2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <stdlib.h> /* malloc */
20 #include <string.h> /* strdup */
23 #include <sys/types.h>
29 #include <livebox-errno.h>
30 #include <livebox-service.h>
34 #include "livebox_internal.h"
35 #include "desc_parser.h"
39 #define INFO_SIZE "size"
40 #define INFO_CATEGORY "category"
42 static const char *type_list[] = {
55 static const char *field_list[] = {
98 /* Should be released */
100 const char *filename;
103 static int update_text(struct livebox *handle, struct block *block, int is_pd)
105 struct livebox_script_operators *ops;
107 if (!block || !block->part || !block->data) {
108 ErrPrint("Invalid argument\n");
109 return LB_STATUS_ERROR_INVALID;
112 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
113 if (ops->update_text) {
114 ops->update_text(handle, (const char *)block->id, (const char *)block->part, (const char *)block->data);
120 static int update_image(struct livebox *handle, struct block *block, int is_pd)
122 struct livebox_script_operators *ops;
124 if (!block || !block->part) {
125 ErrPrint("Invalid argument\n");
126 return LB_STATUS_ERROR_INVALID;
129 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
130 if (ops->update_image) {
131 ops->update_image(handle, block->id, block->part, block->data, block->option);
137 static int update_script(struct livebox *handle, struct block *block, int is_pd)
139 struct livebox_script_operators *ops;
141 if (!block || !block->part) {
142 ErrPrint("Invalid argument\n");
143 return LB_STATUS_ERROR_INVALID;
146 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
147 if (ops->update_script) {
148 ops->update_script(handle, block->id, block->target, block->part, block->data, block->option);
154 static int update_signal(struct livebox *handle, struct block *block, int is_pd)
156 struct livebox_script_operators *ops;
159 ErrPrint("Invalid argument\n");
160 return LB_STATUS_ERROR_INVALID;
163 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
164 if (ops->update_signal) {
165 ops->update_signal(handle, block->id, block->data, block->part);
171 static int update_drag(struct livebox *handle, struct block *block, int is_pd)
174 struct livebox_script_operators *ops;
176 if (!block || !block->data || !block->part) {
177 ErrPrint("Invalid argument\n");
178 return LB_STATUS_ERROR_INVALID;
181 if (sscanf(block->data, "%lfx%lf", &dx, &dy) != 2) {
182 ErrPrint("Invalid format of data\n");
183 return LB_STATUS_ERROR_INVALID;
186 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
187 if (ops->update_drag) {
188 ops->update_drag(handle, block->id, block->part, dx, dy);
194 static int update_info(struct livebox *handle, struct block *block, int is_pd)
196 struct livebox_script_operators *ops;
198 if (!block || !block->part || !block->data) {
199 ErrPrint("Invalid argument\n");
200 return LB_STATUS_ERROR_INVALID;
203 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
204 if (!strcasecmp(block->part, INFO_SIZE)) {
207 if (sscanf(block->data, "%dx%d", &w, &h) != 2) {
208 ErrPrint("Invalid format (%s)\n", block->data);
209 return LB_STATUS_ERROR_INVALID;
212 if (ops->update_info_size) {
213 ops->update_info_size(handle, block->id, w, h);
215 } else if (!strcasecmp(block->part, INFO_CATEGORY)) {
216 if (ops->update_info_category) {
217 ops->update_info_category(handle, block->id, block->data);
224 static int update_access(struct livebox *handle, struct block *block, int is_pd)
226 struct livebox_script_operators *ops;
229 ErrPrint("Invalid argument\n");
230 return LB_STATUS_ERROR_INVALID;
233 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
234 if (ops->update_access) {
235 ops->update_access(handle, block->id, block->part, block->data, block->option);
241 static int operate_access(struct livebox *handle, struct block *block, int is_pd)
243 struct livebox_script_operators *ops;
246 ErrPrint("Invalid argument\n");
247 return LB_STATUS_ERROR_INVALID;
250 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
251 if (ops->operate_access) {
252 ops->operate_access(handle, block->id, block->part, block->data, block->option);
258 static int update_color(struct livebox *handle, struct block *block, int is_pd)
260 struct livebox_script_operators *ops;
263 ErrPrint("Invalid argument\n");
264 return LB_STATUS_ERROR_INVALID;
267 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
268 if (ops->update_color) {
269 ops->update_color(handle, block->id, block->part, block->data);
275 static inline int update_begin(struct livebox *handle, int is_pd)
277 struct livebox_script_operators *ops;
279 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
280 if (ops->update_begin) {
281 ops->update_begin(handle);
287 static inline int update_end(struct livebox *handle, int is_pd)
289 struct livebox_script_operators *ops;
291 ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
292 if (ops->update_end) {
293 ops->update_end(handle);
299 static inline void delete_block(struct block *block)
301 free(block->filebuf);
305 static inline void consuming_parsed_block(struct livebox *handle, int is_pd, struct block *block)
307 typedef int (*update_function_t)(struct livebox *handle, struct block *block, int is_pd);
308 static update_function_t updators[] = {
321 if (block->type >= 0 || block->type < TYPE_MAX) {
322 (void)updators[block->type](handle, block, is_pd);
324 ErrPrint("Block type[%d] is not valid\n", block->type);
328 static inline char *load_file(const char *filename)
330 char *filebuf = NULL;
336 fd = open(filename, O_RDONLY);
338 ErrPrint("open: %s\n", strerror(errno));
342 filesize = lseek(fd, 0L, SEEK_END);
343 if (filesize == (off_t)-1) {
344 ErrPrint("lseek: %s\n", strerror(errno));
348 if (lseek(fd, 0L, SEEK_SET) < 0) {
349 ErrPrint("lseek: %s\n", strerror(errno));
353 filebuf = malloc(filesize + 1);
355 ErrPrint("malloc: %s\n", strerror(errno));
359 while (readsize < filesize) {
360 ret = read(fd, filebuf + readsize, (size_t)filesize - readsize);
362 if (errno == EINTR) {
363 DbgPrint("Read is interrupted\n");
367 ErrPrint("read: %s\n", strerror(errno));
377 filebuf[readsize] = '\0';
382 * Now, we are ready to parse the filebuf.
387 ErrPrint("close: %s\n", strerror(errno));
393 int parse_desc(struct livebox_common *common, const char *filename, int is_pd)
402 struct block *block = NULL;
403 struct dlist *block_list = NULL;
406 struct dlist *handle_iterator;
407 struct livebox *handler;
417 filebuf = load_file(filename);
419 return LB_STATUS_ERROR_IO;
425 while (*fileptr && state != ERROR) {
428 if (*fileptr == '{') {
429 block = calloc(1, sizeof(*block));
431 ErrPrint("calloc: %s\n", strerror(errno));
440 if (isspace(*fileptr)) {
444 } else if (*fileptr == '=') {
448 } else if (ptr == NULL) {
453 while (field_list[field_idx]) {
454 if (field_list[field_idx][field_len] == *fileptr) {
460 if (!field_list[field_idx]) {
461 ErrPrint("Invalid field\n");
468 if (field_list[field_idx][field_len] != *fileptr) {
470 while (field_list[field_idx]) {
471 if (!strncmp(field_list[field_idx], fileptr - field_len, field_len)) {
478 if (!field_list[field_idx]) {
480 ErrPrint("field is not valid\n");
492 if (isspace(*fileptr)) {
496 if (*fileptr == '\0') {
498 ErrPrint("Type is not valid\n");
507 if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
511 if (type_list[type_idx][type_len] != *fileptr) {
513 while (type_list[type_idx]) {
514 if (!strncmp(type_list[type_idx], fileptr - type_len, type_len)) {
521 if (!type_list[type_idx]) {
523 ErrPrint("type is not valid (%s)\n", fileptr - type_len);
529 block->type = type_idx;
541 if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
556 if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
571 if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
586 if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
601 if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
616 if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
631 if (isspace(*fileptr)) {
632 } else if (*fileptr == '}') {
634 block->filename = filename;
635 block_list = dlist_append(block_list, block);
650 if (state != BEGIN) {
653 ErrPrint("State %d\n", state);
658 dlist_foreach_safe(block_list, l, n, block) {
660 block_list = dlist_remove(block_list, l);
663 return LB_STATUS_ERROR_FAULT;
667 block = dlist_data(dlist_prev(block_list));
669 block->filebuf = filebuf;
671 ErrPrint("Last block is not exists (There is no parsed block)\n");
675 ErrPrint("Begin: Set content for object\n");
676 dlist_foreach(common->livebox_list, l, handler) {
677 update_begin(handler, is_pd);
680 dlist_foreach_safe(block_list, l, n, block) {
681 dlist_foreach(common->livebox_list, handle_iterator, handler) {
682 consuming_parsed_block(handler, is_pd, block);
685 block_list = dlist_remove(block_list, l);
689 dlist_foreach(common->livebox_list, l, handler) {
690 update_end(handler, is_pd);
692 ErrPrint("End: Set content for object\n");
694 return LB_STATUS_SUCCESS;