diff --git a/json_parser.c b/json_parser.c index eeaff2f..75ed576 100644 --- a/json_parser.c +++ b/json_parser.c @@ -788,6 +788,32 @@ static void __destroy_json_value(json_value_t *val) } } +json_value_t *json_value_parse(const char *cursor) +{ + json_value_t *val; + + val = (json_value_t *)malloc(sizeof (json_value_t)); + if (!val) + return NULL; + + while (isspace(*cursor)) + cursor++; + + if (__parse_json_value(cursor, &cursor, 0, val) >= 0) + { + while (isspace(*cursor)) + cursor++; + + if (*cursor == '\0') + return val; + + __destroy_json_value(val); + } + + free(val); + return NULL; +} + static void __move_json_value(json_value_t *src, json_value_t *dest) { switch (src->type) @@ -861,52 +887,145 @@ static int __set_json_value(int type, va_list ap, json_value_t *val) return 0; } -json_value_t *json_value_parse(const char *cursor) +json_value_t *json_value_create(int type, ...) { json_value_t *val; + va_list ap; + int ret; val = (json_value_t *)malloc(sizeof (json_value_t)); if (!val) return NULL; - while (isspace(*cursor)) - cursor++; + va_start(ap, type); + ret = __set_json_value(type, ap, val); + va_end(ap); + if (ret < 0) + { + free(val); + return NULL; + } - if (__parse_json_value(cursor, &cursor, 0, val) >= 0) + return val; +} + +static int __copy_json_value(const json_value_t *src, json_value_t *dest); + +static int __copy_json_members(const json_object_t *src, json_object_t *dest) +{ + struct list_head *pos; + json_member_t *entry; + json_member_t *memb; + int len; + + list_for_each(pos, &src->head) { - while (isspace(*cursor)) - cursor++; + entry = list_entry(pos, json_member_t, list); + len = strlen(entry->name); + memb = (json_member_t *)malloc(offsetof(json_member_t, name) + len + 1); + if (!memb) + return -1; - if (*cursor == '\0') - return val; + if (__copy_json_value(&entry->value, &memb->value) < 0) + { + free(memb); + return -1; + } - __destroy_json_value(val); + memcpy(memb->name, entry->name, len + 1); + __insert_json_member(memb, dest->head.prev, dest); } - free(val); - return NULL; + return src->size; } -json_value_t *json_value_create(int type, ...) +static int __copy_json_elements(const json_array_t *src, json_array_t *dest) { - json_value_t *val; - va_list ap; - int ret; + struct list_head *pos; + json_element_t *entry; + json_element_t *elem; - val = (json_value_t *)malloc(sizeof (json_value_t)); - if (!val) + list_for_each(pos, &src->head) + { + elem = (json_element_t *)malloc(sizeof (json_element_t)); + if (!elem) + return -1; + + entry = list_entry(pos, json_element_t, list); + if (__copy_json_value(&entry->value, &elem->value) < 0) + { + free(elem); + return -1; + } + + list_add_tail(&elem->list, &dest->head); + } + + return src->size; +} + +static int __copy_json_value(const json_value_t *src, json_value_t *dest) +{ + int len; + + switch (src->type) + { + case JSON_VALUE_STRING: + len = strlen(src->value.string); + dest->value.string = (char *)malloc(len + 1); + if (!dest->value.string) + return -1; + + memcpy(dest->value.string, src->value.string, len + 1); + break; + + case JSON_VALUE_NUMBER: + dest->value.number = src->value.number; + break; + + case JSON_VALUE_OBJECT: + INIT_LIST_HEAD(&dest->value.object.head); + dest->value.object.root.rb_node = NULL; + if (__copy_json_members(&src->value.object, &dest->value.object) < 0) + { + __destroy_json_members(&dest->value.object); + return -1; + } + + dest->value.object.size = src->value.object.size; + break; + + case JSON_VALUE_ARRAY: + INIT_LIST_HEAD(&dest->value.array.head); + if (__copy_json_elements(&src->value.array, &dest->value.array) < 0) + { + __destroy_json_elements(&dest->value.array); + return -1; + } + + dest->value.array.size = src->value.array.size; + break; + } + + dest->type = src->type; + return 0; +} + +json_value_t *json_value_copy(const json_value_t *val) +{ + json_value_t *copy; + + copy = (json_value_t *)malloc(sizeof (json_value_t)); + if (!copy) return NULL; - va_start(ap, type); - ret = __set_json_value(type, ap, val); - va_end(ap); - if (ret < 0) + if (__copy_json_value(val, copy) < 0) { - free(val); + free(copy); return NULL; } - return val; + return copy; } void json_value_destroy(json_value_t *val) diff --git a/json_parser.h b/json_parser.h index 3b662b6..f29de69 100644 --- a/json_parser.h +++ b/json_parser.h @@ -22,6 +22,7 @@ extern "C" json_value_t *json_value_parse(const char *text); json_value_t *json_value_create(int type, ...); +json_value_t *json_value_copy(const json_value_t *val); void json_value_destroy(json_value_t *val); int json_value_type(const json_value_t *val);