Update spec
[platform/framework/web/livebox-viewer.git] / src / desc_parser.c
index 94a22d3..73ec31f 100644 (file)
@@ -1,11 +1,11 @@
 /*
  * Copyright 2013  Samsung Electronics Co., Ltd
  *
- * Licensed under the Flora License, Version 1.0 (the "License");
+ * Licensed under the Flora License, Version 1.1 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org
+ * http://floralicense.org/license/
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
 #include <stdlib.h> /* malloc */
 #include <string.h> /* strdup */
 #include <ctype.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
+#include <gio/gio.h>
 #include <dlog.h>
 #include <livebox-errno.h>
+#include <livebox-service.h>
 
 #include "debug.h"
 #include "livebox.h"
 #include "desc_parser.h"
 #include "dlist.h"
 #include "util.h"
-#include "critical_log.h"
-
-#define TYPE_TEXT "text"
-#define TYPE_IMAGE "image"
-#define TYPE_EDJE "edje"
-#define TYPE_SIGNAL "signal"
-#define TYPE_INFO "info"
-#define TYPE_DRAG "drag"
 
 #define INFO_SIZE "size"
 #define INFO_CATEGORY "category"
 
-struct block {
-       char *type;
-       int type_len;
+static const char *type_list[] = {
+       "access",
+       "access,operation",
+       "color",
+       "drag",
+       "image",
+       "info",
+       "script",
+       "signal",
+       "text",
+       NULL
+};
 
-       char *part;
-       int part_len;
+static const char *field_list[] = {
+       "type",
+       "part",
+       "data",
+       "option",
+       "id",
+       "target",
+       "file",
+       NULL
+};
 
-       char *data;
-       int data_len;
+enum block_type {
+       TYPE_ACCESS,
+       TYPE_ACCESS_OP,
+       TYPE_COLOR,
+       TYPE_DRAG,
+       TYPE_IMAGE,
+       TYPE_INFO,
+       TYPE_SCRIPT,
+       TYPE_SIGNAL,
+       TYPE_TEXT,
+       TYPE_MAX
+};
 
-       char *file;
-       int file_len;
+enum field_type {
+       FIELD_TYPE,
+       FIELD_PART,
+       FIELD_DATA,
+       FIELD_OPTION,
+       FIELD_ID,
+       FIELD_TARGET,
+       FIELD_FILE
+};
 
+struct block {
+       enum block_type type;
+       char *part;
+       char *data;
        char *option;
-       int option_len;
-
        char *id;
-       int id_len;
+       char *target;
+       char *file;
+
+       /* Should be released */
+       char *filebuf;
+       const char *filename;
 };
 
 static int update_text(struct livebox *handle, struct block *block, int is_pd)
@@ -70,9 +109,10 @@ static int update_text(struct livebox *handle, struct block *block, int is_pd)
                return LB_STATUS_ERROR_INVALID;
        }
 
-       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-       if (ops->update_text)
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->update_text) {
                ops->update_text(handle, (const char *)block->id, (const char *)block->part, (const char *)block->data);
+       }
 
        return 0;
 }
@@ -80,14 +120,16 @@ static int update_text(struct livebox *handle, struct block *block, int is_pd)
 static int update_image(struct livebox *handle, struct block *block, int is_pd)
 {
        struct livebox_script_operators *ops;
+
        if (!block || !block->part) {
                ErrPrint("Invalid argument\n");
                return LB_STATUS_ERROR_INVALID;
        }
 
-       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-       if (ops->update_image)
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->update_image) {
                ops->update_image(handle, block->id, block->part, block->data, block->option);
+       }
 
        return 0;
 }
@@ -95,14 +137,16 @@ static int update_image(struct livebox *handle, struct block *block, int is_pd)
 static int update_script(struct livebox *handle, struct block *block, int is_pd)
 {
        struct livebox_script_operators *ops;
+
        if (!block || !block->part) {
                ErrPrint("Invalid argument\n");
                return LB_STATUS_ERROR_INVALID;
        }
 
-       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-       if (ops->update_script)
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->update_script) {
                ops->update_script(handle, block->id, block->part, block->data, block->option);
+       }
 
        return 0;
 }
@@ -116,9 +160,10 @@ static int update_signal(struct livebox *handle, struct block *block, int is_pd)
                return LB_STATUS_ERROR_INVALID;
        }
 
-       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-       if (ops->update_signal)
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->update_signal) {
                ops->update_signal(handle, block->id, block->data, block->part);
+       }
 
        return 0;
 }
@@ -133,15 +178,15 @@ static int update_drag(struct livebox *handle, struct block *block, int is_pd)
                return LB_STATUS_ERROR_INVALID;
        }
 
-       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-
        if (sscanf(block->data, "%lfx%lf", &dx, &dy) != 2) {
                ErrPrint("Invalid format of data\n");
                return LB_STATUS_ERROR_INVALID;
        }
 
-       if (ops->update_drag)
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->update_drag) {
                ops->update_drag(handle, block->id, block->part, dx, dy);
+       }
 
        return 0;
 }
@@ -155,8 +200,7 @@ static int update_info(struct livebox *handle, struct block *block, int is_pd)
                return LB_STATUS_ERROR_INVALID;
        }
 
-       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
        if (!strcasecmp(block->part, INFO_SIZE)) {
                int w, h;
 
@@ -165,25 +209,77 @@ static int update_info(struct livebox *handle, struct block *block, int is_pd)
                        return LB_STATUS_ERROR_INVALID;
                }
 
-               if (ops->update_info_size)
+               if (ops->update_info_size) {
                        ops->update_info_size(handle, block->id, w, h);
-
+               }
        } else if (!strcasecmp(block->part, INFO_CATEGORY)) {
-               if (ops->update_info_category)
+               if (ops->update_info_category) {
                        ops->update_info_category(handle, block->id, block->data);
+               }
        }
 
        return 0;
 }
 
-static inline int update_begin(struct livebox *handle, int is_pd)
+static int update_access(struct livebox *handle, struct block *block, int is_pd)
+{
+       struct livebox_script_operators *ops;
+
+       if (!block) {
+               ErrPrint("Invalid argument\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->update_access) {
+               ops->update_access(handle, block->id, block->part, block->data, block->option);
+       }
+
+       return 0;
+}
+
+static int operate_access(struct livebox *handle, struct block *block, int is_pd)
+{
+       struct livebox_script_operators *ops;
+
+       if (!block) {
+               ErrPrint("Invalid argument\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->operate_access) {
+               ops->operate_access(handle, block->id, block->part, block->data, block->option);
+       }
+
+       return 0;
+}
+
+static int update_color(struct livebox *handle, struct block *block, int is_pd)
 {
        struct livebox_script_operators *ops;
 
-       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
+       if (!block) {
+               ErrPrint("Invalid argument\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->update_color) {
+               ops->update_color(handle, block->id, block->part, block->data, block->option);
+       }
+
+       return 0;
+}
+
+static inline int update_begin(struct livebox *handle, int is_pd)
+{
+       struct livebox_script_operators *ops;
 
-       if (ops->update_begin)
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->update_begin) {
                ops->update_begin(handle);
+       }
 
        return 0;
 }
@@ -192,413 +288,410 @@ static inline int update_end(struct livebox *handle, int is_pd)
 {
        struct livebox_script_operators *ops;
 
-       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-
-       if (ops->update_end)
+       ops = is_pd ? &handle->cbs.pd_ops : &handle->cbs.lb_ops;
+       if (ops->update_end) {
                ops->update_end(handle);
+       }
 
        return 0;
 }
 
-int parse_desc(struct livebox *handle, const char *descfile, int is_pd)
+static inline void delete_block(struct block *block)
 {
-       FILE *fp;
-       int ch;
-       enum state {
-               UNKNOWN = 0x10,
-               BLOCK_OPEN = 0x11,
-               FIELD = 0x12,
-               VALUE = 0x13,
-               BLOCK_CLOSE = 0x14,
-
-               VALUE_TYPE = 0x00,
-               VALUE_PART = 0x01,
-               VALUE_DATA = 0x02,
-               VALUE_FILE = 0x03,
-               VALUE_OPTION = 0x04,
-               VALUE_ID = 0x05,
-       };
-       const char *field_name[] = {
-               "type",
-               "part",
-               "data",
-               "file",
-               "option",
-               "id",
+       free(block->filebuf);
+       free(block);
+}
+
+static inline void consuming_parsed_block(struct livebox *handle, int is_pd, struct block *block)
+{
+       typedef int (*update_function_t)(struct livebox *handle, struct block *block, int is_pd);
+       static update_function_t updators[] = {
+               update_access,
+               operate_access,
+               update_color,
+               update_drag,
+               update_image,
+               update_info,
+               update_script,
+               update_signal,
+               update_text,
                NULL
        };
-       enum state state;
-       register int field_idx;
-       register int idx = 0;
-       register int i;
-       struct block *block;
-       struct {
-               const char *type;
-               int (*handler)(struct livebox *handle, struct block *block, int is_pd);
-       } handlers[] = {
-               {
-                       .type = TYPE_TEXT,
-                       .handler = update_text,
-               },
-               {
-                       .type = TYPE_IMAGE,
-                       .handler = update_image,
-               },
-               {
-                       .type = TYPE_EDJE,
-                       .handler = update_script,
-               },
-               {
-                       .type = TYPE_SIGNAL,
-                       .handler = update_signal,
-               },
-               {
-                       .type = TYPE_DRAG,
-                       .handler = update_drag,
-               },
-               {
-                       .type = TYPE_INFO,
-                       .handler = update_info,
-               },
-               {
-                       .type = NULL,
-                       .handler = NULL,
-               },
-       };
 
-       fp = fopen(descfile, "rt");
-       if (!fp) {
-               ErrPrint("Error: %s\n", strerror(errno));
-               return LB_STATUS_ERROR_IO;
+       if (block->type >= 0 || block->type < TYPE_MAX) {
+               (void)updators[block->type](handle, block, is_pd);
+       } else {
+               ErrPrint("Block type[%d] is not valid\n", block->type);
+       }
+}
+
+static inline char *load_file(const char *filename)
+{
+       char *filebuf = NULL;
+       int fd;
+       off_t filesize;
+       int ret;
+       size_t readsize = 0;
+
+       fd = open(filename, O_RDONLY);
+       if (fd < 0) {
+               ErrPrint("open: %s\n", strerror(errno));
+               return NULL;
        }
 
-       update_begin(handle, is_pd);
+       filesize = lseek(fd, 0L, SEEK_END);
+       if (filesize == (off_t)-1) {
+               ErrPrint("lseek: %s\n", strerror(errno));
+               goto errout;
+       }
 
-       state = UNKNOWN;
-       field_idx = 0;
+       if (lseek(fd, 0L, SEEK_SET) < 0) {
+               ErrPrint("lseek: %s\n", strerror(errno));
+               goto errout;
+       }
 
-       block = NULL;
-       while (!feof(fp)) {
-               ch = getc(fp);
+       filebuf = malloc(filesize + 1);
+       if (!filebuf) {
+               ErrPrint("malloc: %s\n", strerror(errno));
+               goto errout;
+       }
 
-               switch (state) {
-               case UNKNOWN:
-                       if (ch == '{') {
-                               state = BLOCK_OPEN;
-                               break;
+       while (readsize < filesize) {
+               ret = read(fd, filebuf + readsize, (size_t)filesize - readsize);
+               if (ret < 0) {
+                       if (errno == EINTR) {
+                               DbgPrint("Read is interrupted\n");
+                               continue;
                        }
 
-                       if (!isspace(ch)) {
-                               update_end(handle, is_pd);
-                               fclose(fp);
-                               return LB_STATUS_ERROR_INVALID;
-                       }
+                       ErrPrint("read: %s\n", strerror(errno));
+                       free(filebuf);
+                       filebuf = NULL;
                        break;
+               }
 
-               case BLOCK_OPEN:
-                       if (isblank(ch))
-                               break;
+               readsize += ret;
+       }
 
-                       if (ch != '\n')
-                               goto errout;
+       if (filebuf) {
+               filebuf[readsize] = '\0';
+       }
 
-                       block = calloc(1, sizeof(*block));
-                       if (!block) {
-                               CRITICAL_LOG("Heap: %s\n", strerror(errno));
-                               update_end(handle, is_pd);
-                               fclose(fp);
-                               return LB_STATUS_ERROR_MEMORY;
-                       }
+       /*!
+        * \note
+        * Now, we are ready to parse the filebuf.
+        */
 
-                       state = FIELD;
-                       idx = 0;
-                       field_idx = 0;
-                       break;
+errout:
+       if (close(fd) < 0) {
+               ErrPrint("close: %s\n", strerror(errno));
+       }
 
-               case FIELD:
-                       if (isspace(ch))
-                               break;
+       return filebuf;
+}
 
-                       if (ch == '}') {
-                               state = BLOCK_CLOSE;
-                               break;
+int parse_desc(struct livebox_common *common, const char *filename, int is_pd)
+{
+       int type_idx = 0;
+       int type_len = 0;
+       int field_idx = 0;
+       int field_len = 0;
+       char *filebuf;
+       char *fileptr;
+       char *ptr = NULL;
+       struct block *block = NULL;
+       struct dlist *block_list = NULL;
+       struct dlist *l;
+       struct dlist *n;
+       struct dlist *handle_iterator;
+       struct livebox *handler;
+       enum state {
+               BEGIN,
+               FIELD,
+               DATA,
+               END,
+               DONE,
+               ERROR,
+       } state;
+
+       filebuf = load_file(filename);
+       if (!filebuf) {
+               return LB_STATUS_ERROR_IO;
+       }
+
+       fileptr = filebuf;
+
+       state = BEGIN;
+       while (*fileptr && state != ERROR) {
+               switch (state) {
+               case BEGIN:
+                       if (*fileptr == '{') {
+                               block = calloc(1, sizeof(*block));
+                               if (!block) {
+                                       ErrPrint("calloc: %s\n", strerror(errno));
+                                       state = ERROR;
+                                       continue;
+                               }
+                               state = FIELD;
+                               ptr = NULL;
                        }
+                       break;
+               case FIELD:
+                       if (isspace(*fileptr)) {
+                               if (ptr != NULL) {
+                                       *fileptr = '\0';
+                               }
+                       } else if (*fileptr == '=') {
+                               *fileptr = '\0';
+                               ptr = NULL;
+                               state = DATA;
+                       } else if (ptr == NULL) {
+                               ptr = fileptr;
+                               field_idx = 0;
+                               field_len = 0;
 
-                       if (ch == '=') {
-                               if (field_name[field_idx][idx] != '\0')
-                                       goto errout;
-
-                               switch (field_idx) {
-                               case 0:
-                                       state = VALUE_TYPE;
-                                       if (block->type) {
-                                               free(block->type);
-                                               block->type = NULL;
-                                               block->type_len = 0;
-                                       }
-                                       idx = 0;
-                                       break;
-                               case 1:
-                                       state = VALUE_PART;
-                                       if (block->part) {
-                                               free(block->part);
-                                               block->part = NULL;
-                                               block->part_len = 0;
-                                       }
-                                       idx = 0;
-                                       break;
-                               case 2:
-                                       state = VALUE_DATA;
-                                       if (block->data) {
-                                               free(block->data);
-                                               block->data = NULL;
-                                               block->data_len = 0;
+                               while (field_list[field_idx]) {
+                                       if (field_list[field_idx][field_len] == *fileptr) {
+                                               break;
                                        }
-                                       idx = 0;
-                                       break;
-                               case 3:
-                                       state = VALUE_FILE;
-                                       if (block->file) {
-                                               free(block->file);
-                                               block->file = NULL;
-                                               block->file_len = 0;
-                                       }
-                                       idx = 0;
-                                       break;
-                               case 4:
-                                       state = VALUE_OPTION;
-                                       if (block->option) {
-                                               free(block->option);
-                                               block->option = NULL;
-                                               block->option_len = 0;
+                                       field_idx++;
+                               }
+
+                               if (!field_list[field_idx]) {
+                                       ErrPrint("Invalid field\n");
+                                       state = ERROR;
+                                       continue;
+                               }
+
+                               field_len++;
+                       } else {
+                               if (field_list[field_idx][field_len] != *fileptr) {
+                                       field_idx++;
+                                       while (field_list[field_idx]) {
+                                               if (!strncmp(field_list[field_idx], fileptr - field_len, field_len)) {
+                                                       break;
+                                               } else {
+                                                       field_idx++;
+                                               }
                                        }
-                                       idx = 0;
-                                       break;
-                               case 5:
-                                       state = VALUE_ID;
-                                       if (block->id) {
-                                               free(block->id);
-                                               block->id = NULL;
-                                               block->id_len = 0;
+
+                                       if (!field_list[field_idx]) {
+                                               state = ERROR;
+                                               ErrPrint("field is not valid\n");
+                                               continue;
                                        }
-                                       idx = 0;
-                                       break;
-                               default:
-                                       goto errout;
                                }
 
-                               break;
+                               field_len++;
                        }
+                       break;
+               case DATA:
+                       switch (field_idx) {
+                       case FIELD_TYPE:
+                               if (ptr == NULL) {
+                                       if (isspace(*fileptr)) {
+                                               break;
+                                       }
 
-                       if (ch == '\n')
-                               goto errout;
+                                       if (*fileptr == '\0') {
+                                               state = ERROR;
+                                               ErrPrint("Type is not valid\n");
+                                               continue;
+                                       }
 
-                       if (field_name[field_idx][idx] != ch) {
-                               ungetc(ch, fp);
-                               while (--idx >= 0)
-                                       ungetc(field_name[field_idx][idx], fp);
+                                       ptr = fileptr;
+                                       type_idx = 0;
+                                       type_len = 0;
+                               }
 
-                               field_idx++;
-                               if (field_name[field_idx] == NULL)
-                                       goto errout;
+                               if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
+                                       *fileptr = '\0';
+                               }
 
-                               idx = 0;
-                               break;
-                       }
+                               if (type_list[type_idx][type_len] != *fileptr) {
+                                       type_idx++;
+                                       while (type_list[type_idx]) {
+                                               if (!strncmp(type_list[type_idx], fileptr - type_len, type_len)) {
+                                                       break;
+                                               } else {
+                                                       type_idx++;
+                                               }
+                                       }
 
-                       idx++;
-                       break;
+                                       if (!type_list[type_idx]) {
+                                               state = ERROR;
+                                               ErrPrint("type is not valid (%s)\n", fileptr - type_len);
+                                               continue;
+                                       }
+                               }
 
-               case VALUE_TYPE:
-                       if (idx == block->type_len) {
-                               block->type_len += 256;
-                               block->type = realloc(block->type, block->type_len);
-                               if (!block->type) {
-                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
-                                       goto errout;
+                               if (!*fileptr) {
+                                       block->type = type_idx;
+                                       state = DONE;
+                                       ptr = NULL;
                                }
-                       }
 
-                       if (ch == '\n') {
-                               block->type[idx] = '\0';
-                               state = FIELD;
-                               idx = 0;
-                               field_idx = 0;
+                               type_len++;
                                break;
-                       }
-
-                       block->type[idx] = ch;
-                       idx++;
-                       break;
+                       case FIELD_PART:
+                               if (ptr == NULL) {
+                                       ptr = fileptr;
+                               }
 
-               case VALUE_PART:
-                       if (idx == block->part_len) {
-                               block->part_len += 256;
-                               block->part = realloc(block->part, block->part_len);
-                               if (!block->part) {
-                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
-                                       goto errout;
+                               if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
+                                       *fileptr = '\0';
                                }
-                       }
 
-                       if (ch == '\n') {
-                               block->part[idx] = '\0';
-                               state = FIELD;
-                               idx = 0;
-                               field_idx = 0;
+                               if (!*fileptr) {
+                                       block->part = ptr;
+                                       state = DONE;
+                                       ptr = NULL;
+                               }
                                break;
-                       }
-
-                       block->part[idx] = ch;
-                       idx++;
-                       break;
+                       case FIELD_DATA:
+                               if (ptr == NULL) {
+                                       ptr = fileptr;
+                               }
 
-               case VALUE_DATA:
-                       if (idx == block->data_len) {
-                               block->data_len += 256;
-                               block->data = realloc(block->data, block->data_len);
-                               if (!block->data) {
-                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
-                                       goto errout;
+                               if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
+                                       *fileptr = '\0';
                                }
-                       }
 
-                       if (ch == '\n') {
-                               block->data[idx] = '\0';
-                               state = FIELD;
-                               idx = 0;
-                               field_idx = 0;
+                               if (!*fileptr) {
+                                       block->data = ptr;
+                                       state = DONE;
+                                       ptr = NULL;
+                               }
                                break;
-                       }
-
-                       block->data[idx] = ch;
-                       idx++;
-                       break;
+                       case FIELD_OPTION:
+                               if (ptr == NULL) {
+                                       ptr = fileptr;
+                               }
 
-               case VALUE_FILE:
-                       if (idx == block->file_len) {
-                               block->file_len += 256;
-                               block->file = realloc(block->file, block->file_len);
-                               if (!block->file) {
-                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
-                                       goto errout;
+                               if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
+                                       *fileptr = '\0';
                                }
-                       }
 
-                       if (ch == '\n') {
-                               block->file[idx] = '\0';
-                               state = FIELD;
-                               idx = 0;
-                               field_idx = 0;
+                               if (!*fileptr) {
+                                       block->option = ptr;
+                                       state = DONE;
+                                       ptr = NULL;
+                               }
                                break;
-                       }
+                       case FIELD_ID:
+                               if (ptr == NULL) {
+                                       ptr = fileptr;
+                               }
 
-                       block->file[idx] = ch;
-                       idx++;
-                       break;
+                               if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
+                                       *fileptr = '\0';
+                               }
 
-               case VALUE_OPTION:
-                       if (idx == block->option_len) {
-                               block->option_len += 256;
-                               block->option = realloc(block->option, block->option_len);
-                               if (!block->option) {
-                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
-                                       goto errout;
+                               if (!*fileptr) {
+                                       block->id = ptr;
+                                       state = DONE;
+                                       ptr = NULL;
+                               }
+                               break;
+                       case FIELD_TARGET:
+                               if (ptr == NULL) {
+                                       ptr = fileptr;
                                }
-                       }
 
-                       if (ch == '\n') {
-                               block->option[idx] = '\0';
-                               state = FIELD;
-                               idx = 0;
-                               field_idx = 0;
+                               if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
+                                       *fileptr = '\0';
+                               }
+
+                               if (!*fileptr) {
+                                       block->target = ptr;
+                                       state = DONE;
+                                       ptr = NULL;
+                               }
                                break;
-                       }
+                       case FIELD_FILE:
+                               if (ptr == NULL) {
+                                       ptr = fileptr;
+                               }
 
-                       block->option[idx] = ch;
-                       idx++;
-                       break;
-               case VALUE_ID:
-                       if (idx == block->id_len) {
-                               block->id_len += 256;
-                               block->id = realloc(block->id, block->id_len);
-                               if (!block->id) {
-                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
-                                       goto errout;
+                               if (*fileptr && (*fileptr == '\n' || *fileptr == '\r' || *fileptr == '\f')) {
+                                       *fileptr = '\0';
                                }
-                       }
 
-                       if (ch == '\n') {
-                               block->id[idx] = '\0';
-                               state = FIELD;
-                               idx = 0;
-                               field_idx = 0;
+                               if (!*fileptr) {
+                                       block->target = ptr;
+                                       state = DONE;
+                                       ptr = NULL;
+                               }
+                       default:
                                break;
                        }
 
-                       block->id[idx] = ch;
-                       idx++;
                        break;
-               case BLOCK_CLOSE:
-                       if (!block->file) {
-                               block->file = strdup(util_uri_to_path(handle->id));
-                               if (!block->file)
-                                       goto errout;
+               case DONE:
+                       if (isspace(*fileptr)) {
+                       } else if (*fileptr == '}') {
+                                       state = BEGIN;
+                                       block->filename = filename;
+                                       block_list = dlist_append(block_list, block);
+                                       block = NULL;
+                       } else {
+                               state = FIELD;
+                               continue;
                        }
+                       break;
+               case END:
+               default:
+                       break;
+               }
 
-                       i = 0;
-                       while (handlers[i].type) {
-                               if (!strcasecmp(handlers[i].type, block->type)) {
-                                       handlers[i].handler(handle, block, is_pd);
-                                       break;
-                               }
-                               i++;
-                       }
+               fileptr++;
+       }
 
-                       if (!handlers[i].type)
-                               ErrPrint("Unknown block type: %s\n", block->type);
+       if (state != BEGIN) {
+               struct dlist *l;
+               struct dlist *n;
+               ErrPrint("State %d\n", state);
 
-                       free(block->file);
-                       free(block->type);
-                       free(block->part);
-                       free(block->data);
-                       free(block->option);
-                       free(block->id);
-                       free(block);
-                       block = NULL;
+               free(filebuf);
+               free(block);
 
-                       state = UNKNOWN;
-                       break;
+               dlist_foreach_safe(block_list, l, n, block) {
+                       free(block);
+                       block_list = dlist_remove(block_list, l);
+               }
 
-               default:
-                       break;
-               } /* switch */
-       } /* while */
+               return LB_STATUS_ERROR_FAULT;
+       }
 
-       if (state != UNKNOWN)
-               goto errout;
+               
+       block = dlist_data(dlist_prev(block_list));
+       if (block) {
+               block->filebuf = filebuf;
+       } else {
+               ErrPrint("Last block is not exists (There is no parsed block)\n");
+               free(filebuf);
+       }
 
-       update_end(handle, is_pd);
+       ErrPrint("Begin: Set content for object\n");
+       dlist_foreach(common->livebox_list, l, handler) {
+               update_begin(handler, is_pd);
+       }
 
-       fclose(fp);
-       return 0;
+       dlist_foreach_safe(block_list, l, n, block) {
+               dlist_foreach(common->livebox_list, handle_iterator, handler) {
+                       consuming_parsed_block(handler, is_pd, block);
+               }
 
-errout:
-       ErrPrint("Parse error\n");
-       if (block) {
-               free(block->file);
-               free(block->type);
-               free(block->part);
-               free(block->data);
-               free(block->option);
-               free(block->id);
-               free(block);
+               block_list = dlist_remove(block_list, l);
+               delete_block(block);
        }
 
-       update_end(handle, is_pd);
+       dlist_foreach(common->livebox_list, l, handler) {
+               update_end(handler, is_pd);
+       }
+       ErrPrint("End: Set content for object\n");
 
-       fclose(fp);
-       return LB_STATUS_ERROR_INVALID;
+       return LB_STATUS_SUCCESS;
 }
 
 /* End of a file */