From 1dd3e1c8d7deb0fa6fe6208b2dd8d236d1f3fc2e Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Fri, 12 Apr 2024 12:18:03 +0200 Subject: libjson: new api a lot... changed... Signed-off-by: Anna (navi) Figueiredo Gomes --- src/array.c | 102 +++++++++++++++++++++++----------------- src/internal.h | 21 ++++++--- src/json.c | 73 +++++++++++++++++++---------- src/literal.c | 17 ++++--- src/object.c | 143 ++++++++++++++++++++++++++++----------------------------- src/print.c | 9 +--- src/string.c | 24 ++++++---- 7 files changed, 219 insertions(+), 170 deletions(-) (limited to 'src') diff --git a/src/array.c b/src/array.c index c34a8e5..de14692 100644 --- a/src/array.c +++ b/src/array.c @@ -15,7 +15,7 @@ enum json_parse_result parse_array(struct json **json_out, struct raw_json *raw, goto err; } - json = json_new_array(); + json = json_array(); if (!json) return JSON_OOM; @@ -36,7 +36,7 @@ enum json_parse_result parse_array(struct json **json_out, struct raw_json *raw, goto err; } - json_array_append(json, obj); + json_append(json, obj); skip_ws(raw); obj = NULL; @@ -59,70 +59,88 @@ end: } -bool json_array_append(struct json *dest, struct json *src) { +bool json_append(struct json *dest, struct json *src) { if (!dest || !src) return false; + json_detach(src); add_children(dest, src); return true; } -struct json *json_array_get_mut(struct json *json, size_t index) { - if (json->type != JSON_ARRAY || index > json->children->nitems) - return NULL; +bool json_insert(struct json *dest, size_t index, struct json *src) { + if (!dest || !src) + return false; + json_detach(src); + if (index >= dest->children->nitems) { + add_children(dest, src); + return true; + } + if (!ensure_size(dest, 1)) + return false; + struct json_children *chld = dest->children; + if (index > 0) { + chld->items[index]->prev = src; + chld->items[index - 1]->next = src; + } + for (size_t i = index; i < chld->nitems - 1; i++) + chld->items[i + 1] = chld->items[i]; + chld->items[index] = src; - return json->children->items[index]; + return true; } -const struct json *json_array_get_const(const struct json *array, size_t index) { - return json_array_get_mut((struct json *) array, index); -} +bool json_replace(struct json *dest, size_t index, struct json *src) { + if (!dest || !src) + return false; + json_detach(src); -struct json *json_array_add_object(struct json *dest) { - struct json *obj = json_new_object(); - json_array_append(dest, obj); - return obj; -} + struct json_children *chld = dest->children; + if (index >= chld->nitems) { + add_children(dest, src); + return true; + } + struct json *old = json_swap_index(dest, index, src); + json_clear(old); + free(old); -struct json *json_array_add_array(struct json *dest) { - struct json *array = json_new_array(); - json_array_append(dest, array); - return array; -} -struct json *json_array_add_number(struct json *dest, double num) { - struct json *number = json_new_number(num); - json_array_append(dest, number); - return number; + return true; } -struct json *json_array_add_string(struct json *dest, const char *string) { - struct json *str = json_new_string_copy(string); - json_array_append(dest, str); - return str; -} +struct json *json_at_mut(struct json *json, size_t index) { + if (!json || json->type != JSON_ARRAY || index > json->children->nitems) + return NULL; -struct json *json_array_add_bool(struct json *dest, bool boolean) { - struct json *b = json_new_bool(boolean); - json_array_append(dest, b); - return b; + return json->children->items[index]; } -struct json *json_array_add_null(struct json *dest) { - struct json *n = json_new_null(); - json_array_append(dest, n); - return n; +const struct json *json_at_const(const struct json *array, size_t index) { + return json_at_mut((struct json *) array, index); } -struct json *json_array_detach(struct json *json, size_t index) { - if (json->type != JSON_ARRAY || index >= json->children->nitems) { +struct json *json_detach_index(struct json *json, size_t index) { + if (!json_is_array(json) || index >= json->children->nitems) return NULL; - } struct json *tmp = json->children->items[index]; json_detach(tmp); return tmp; } -void json_array_delete(struct json *json, size_t index) { - struct json *tmp = json_array_detach(json, index); +struct json *json_swap_index(struct json *json, size_t index, struct json *src) { + if (!json_is_array(json) || index >= json->children->nitems || !src) + return NULL; + json_detach(src); + struct json_children *chld = json->children; + if (index > 0) + chld->items[index - 1]->next = src; + if (index < chld->nitems - 1) + chld->items[index + 1]->prev = src; + struct json *old = chld->items[index]; + chld->items[index] = src; + return old; +} + +void json_delete_index(struct json *json, size_t index) { + struct json *tmp = json_detach_index(json, index); json_delete(tmp); } diff --git a/src/internal.h b/src/internal.h index f1e08dc..812688f 100644 --- a/src/internal.h +++ b/src/internal.h @@ -33,16 +33,23 @@ inline static bool init_children(struct json *obj) { return true; } +inline static bool ensure_size(struct json *dest, size_t to_add) { + struct json_children *chld = dest->children; + while (chld->nitems + to_add >= chld->maxitems) { + chld->maxitems *= 2; + chld = realloc(chld, sizeof(*chld) + (sizeof(*chld->items) * chld->maxitems)); + if (!chld) + return false; + dest->children = chld; + } + return true; +} inline static void add_children(struct json *dest, struct json *src) { + if (!ensure_size(dest, 1)) + return; + struct json_children *children = dest->children; - if (children->nitems + 1 >= children->maxitems) { - children->maxitems += 5; - children = realloc(children, sizeof(*children) + (sizeof(*children->items) * children->maxitems)); - if (!children) - return; - dest->children = children; - } src->parent = dest; src->index = children->nitems; diff --git a/src/json.c b/src/json.c index cf71a90..5d8fb61 100644 --- a/src/json.c +++ b/src/json.c @@ -11,20 +11,39 @@ #include -struct json *json_parse(const char *str) { - return json_parse_len(str, strlen(str)); -} - struct json *json_new(void) { struct json *json = calloc(1, sizeof(*json)); if (!json) return NULL; - json->type = JSON_INVALID; + json->type = JSON_NULL; + return json; +} + +struct json *json_dup(const struct json *src) { + struct json *json = json_new(); + switch (src->type) { + case JSON_OBJECT: + case JSON_ARRAY: + for (size_t i = 0; i < src->children->nitems; i++) { + add_children(json, json_dup(src->children->items[i])); + } + break; + case JSON_STRING: + json->string = strdup(src->string); + break; + case JSON_NUMBER: + json->num = src->num; + break; + default: + break; + } + json->type = src->type; return json; } void json_detach(struct json *json) { - if (!json || !json->parent) return; + if (!json || !json->parent) + return; struct json_children *siblings = json->parent->children; if (json->index != --siblings->nitems) { @@ -66,35 +85,35 @@ void json_clear(struct json *json) { break; } free(json->key); - json->type = JSON_INVALID; + json->type = JSON_NULL; } -struct json *json_new_array(void) { +struct json *json_object(void) { struct json *json = json_new(); - if (!json) - return NULL; - json->type = JSON_ARRAY; + json->type = JSON_OBJECT; init_children(json); return json; } -struct json *json_new_bool(bool boolean) { +struct json *json_array(void) { struct json *json = json_new(); if (!json) return NULL; - json->type = boolean ? JSON_TRUE : JSON_FALSE; + json->type = JSON_ARRAY; + init_children(json); return json; } -struct json *json_new_null(void) { +struct json *json_bool(bool boolean) { struct json *json = json_new(); if (!json) return NULL; - json->type = JSON_NULL; + json->type = JSON_BOOL; + json->boolean = boolean; return json; } -struct json *json_new_number(double num) { +struct json *json_number(double num) { struct json *json = json_new(); if (!json) return NULL; @@ -103,24 +122,30 @@ struct json *json_new_number(double num) { return json; } -struct json *json_new_string(void) { +struct json *json_string(const char *string) { struct json *json = json_new(); if (!json) return NULL; json->type = JSON_STRING; - json->string = NULL; + json->string = strdup(string); return json; } -struct json *json_new_string_copy(const char *string) { +struct json *json_string_from(char *string) { struct json *json = json_new(); if (!json) return NULL; json->type = JSON_STRING; - json->string = strdup(string); + json->string = string; return json; } +size_t json_len(const struct json *json) { + if (!json_check_type(json, JSON_OBJECT | JSON_ARRAY)) + return 0; + return json->children->nitems; +} + enum json_parse_result parse_value(struct json **json_out, struct raw_json *raw, size_t depth) { skip_ws(raw); struct json *json = NULL; @@ -144,17 +169,17 @@ enum json_parse_result parse_value(struct json **json_out, struct raw_json *raw, } struct json *json_parse(const char *str) { - return json_parse_len(strlen(str), str); + return json_parse_sized(strlen(str), str); } -struct json *json_parse_len(size_t size, const char str[size]) { - if (!str || size == 0) +struct json *json_parse_sized(size_t len, const char str[len]) { + if (!str || len == 0) return NULL; struct json *json = NULL; struct raw_json raw = { .index = 0, .data = str, - .size = size + .size = len }; if (parse_value(&json, &raw, 1) != JSON_PARSE_OK) { return NULL; diff --git a/src/literal.c b/src/literal.c index 8723462..66fad7f 100644 --- a/src/literal.c +++ b/src/literal.c @@ -17,15 +17,14 @@ enum json_parse_result parse_literal(struct json **json_out, struct raw_json *ra char *end; /* is probably a number here, strtodl will tell */ double num = strtod(start, &end); - if (end != start) { - if (raw->data[raw->index] == '-') - num = -num; - json = json_new_number(num); - raw->index = end - raw->data; - } else { + if (end == start) { ret = JSON_PARSE_INVALID_NUMBER_ERR; goto err; } + if (raw->data[raw->index] == '-') + num = -num; + json = json_number(num); + raw->index = end - raw->data; } else { size_t end_index; for (end_index = raw->index; end_index < raw->size; end_index++) { @@ -35,11 +34,11 @@ enum json_parse_result parse_literal(struct json **json_out, struct raw_json *ra } size_t len = end_index - raw->index; if (len == 4 && strncmp(raw->data + raw->index, "true", len) == 0) { - json = json_new_bool(true); + json = json_bool(true); } else if (len == 5 && strncmp(raw->data + raw->index, "false", len) == 0) { - json = json_new_bool(false); + json = json_bool(false); } else if (len == 4 && strncmp(raw->data + raw->index, "null", len) == 0) { - json = json_new_null(); + json = json_new(); } else { ret = JSON_PARSE_INVALID_TOKEN_ERR; } diff --git a/src/object.c b/src/object.c index fea4787..0474f27 100644 --- a/src/object.c +++ b/src/object.c @@ -1,18 +1,16 @@ +#define JSON_PRIVATE #include #include #include #include #include "internal.h" -//inline static size_t hash(const char *key) { - //if (!key) - //return 0; - //size_t ret = 5381; - //for (const char *p = key; *p != '\0'; p++) { - //ret = ((ret << 5) + ret) + *p; - //} - //return ret; -//} +inline static void adjust_siblings(struct json *json, struct json *src) { + if (json->prev) + json->prev->next = src; + if (json->next) + json->next->prev = src; +} void add_to_object(struct json *dest, char *key, struct json *src) { assert(dest->type == JSON_OBJECT); @@ -20,7 +18,6 @@ void add_to_object(struct json *dest, char *key, struct json *src) { assert(src); src->key = (free(src->key), key); - //src->index = hash(src->key) % dest->children->maxitems; for (size_t i = 0; i < dest->children->nitems; i++) { struct json *e = dest->children->items[i]; @@ -31,8 +28,7 @@ void add_to_object(struct json *dest, char *key, struct json *src) { src->prev = e->prev; src->next = e->next; - if (e->prev) e->prev->next = src; - if (e->next) e->next->prev = src; + adjust_siblings(e, src); json_clear(e); free(e); @@ -43,13 +39,6 @@ void add_to_object(struct json *dest, char *key, struct json *src) { add_children(dest, src); } -struct json *json_new_object(void) { - struct json *json = json_new(); - json->type = JSON_OBJECT; - init_children(json); - return json; -} - enum json_parse_result parse_object(struct json **json_out, struct raw_json *raw, size_t depth) { assert(raw->data[raw->index] == '{'); enum json_parse_result ret = JSON_PARSE_OK; @@ -63,7 +52,7 @@ enum json_parse_result parse_object(struct json **json_out, struct raw_json *raw goto err; } - json = json_new_object(); + json = json_object(); if (!json) return JSON_OOM; @@ -126,82 +115,90 @@ end: return ret; } -bool json_object_add(struct json *dest, const char *key, struct json *src) { +struct json *json_set(struct json *dest, const char *key, struct json *src) { if (!dest || !key || !src) - return false; + return NULL; + json_detach(src); add_to_object(dest, strdup(key), src); - return true; + return src; } -struct json *json_object_get_mut(struct json *obj, const char *key) { - if (obj->type != JSON_OBJECT) return NULL; - struct json *j = NULL; - json_foreach(j, obj) { +struct json *json_get_mut(struct json *json, const char *key) { + if (!json_is_object(json) || !key) + return NULL; + json_foreach(j, json) { if (strcmp(j->key, key) == 0) - break; + return j; } - return j; + return NULL; } -struct json *json_object_getn_mut(struct json *obj, const char *key, size_t n) { - if (obj->type != JSON_OBJECT) return NULL; - struct json *j = NULL; - json_foreach(j, obj) { - if (strncmp(j->key, key, n) == 0) - break; +struct json *json_get_sized_mut(struct json *json, size_t count, const char key[count]) { + if (!json_is_object(json) || !key) + return NULL; + json_foreach(j, json) { + if (strncmp(j->key, key, count) == 0) + return j; } - return j; -} - -const struct json *json_object_get_const(const struct json *obj, const char *key) { - return json_object_get_mut((struct json *) obj, key); + return NULL; } -const struct json *json_object_getn_const(const struct json *obj, const char *key, size_t n) { - return json_object_getn_mut((struct json *) obj, key, n); +const struct json *json_get_const(const struct json *obj, const char *key) { + return json_get_mut((struct json *) obj, key); } -struct json *json_object_add_object(struct json *dest, const char *key) { - struct json *obj = json_new_object(); - json_object_add(dest, key, obj); - return obj; +const struct json *json_get_sized_const(const struct json *obj, size_t count, const char key[count]) { + return json_get_sized_mut((struct json *) obj, count, key); } -struct json *json_object_add_array(struct json *dest, const char *key) { - struct json *array = json_new_array(); - json_object_add(dest, key, array); - return array; -} -struct json *json_object_add_number(struct json *dest, const char *key, double num) { - struct json *number = json_new_number(num); - json_object_add(dest, key, number); - return number; -} - -struct json *json_object_add_string(struct json *dest, const char *key, const char *string) { - struct json *str = json_new_string_copy(string); - json_object_add(dest, key, str); - return str; +struct json *json_detach_key(struct json *json, const char *key) { + struct json *tmp = json_get(json, key); + json_detach(tmp); + return tmp; } -struct json *json_object_add_bool(struct json *dest, const char *key, bool boolean) { - struct json *b = json_new_bool(boolean); - json_object_add(dest, key, b); - return b; +struct json *json_swap_key(struct json *json, const char *key, struct json *src) { + if (!json_is_object(json) || !key) + return NULL; + json_detach(src); + json_foreach(j, json) { + if (strcmp(j->key, key)) { + json->children->items[j->index] = src; + src->index = j->index; + adjust_siblings(j, src); + return j; + } + } + return NULL; } -struct json *json_object_add_null(struct json *dest, const char *key) { - struct json *n = json_new_null(); - json_object_add(dest, key, n); - return n; +void json_delete_key(struct json *json, const char *key) { + struct json *tmp = json_detach_key(json, key); + json_delete(tmp); } -struct json *json_object_detach(struct json *json, const char *key) { - struct json *tmp = json_object_get(json, key); +struct json *json_detach_key_sized(struct json *json, size_t len, const char key[len]) { + struct json *tmp = json_get_sized(json, len, key); json_detach(tmp); return tmp; } -void json_object_delete(struct json *json, const char *key) { - struct json *tmp = json_object_detach(json, key); + +void json_delete_key_sized(struct json *json, size_t len, const char key[len]) { + struct json *tmp = json_detach_key_sized(json, len, key); json_delete(tmp); } + +struct json *json_swap_key_sized(struct json *json, size_t len, const char key[len], struct json *src) { + if (!json_is_object(json) || !key) + return NULL; + json_detach(src); + json_foreach(j, json) { + if (strncmp(j->key, key, len)) { + json->children->items[j->index] = src; + src->index = j->index; + adjust_siblings(j, src); + return j; + } + } + return NULL; +} diff --git a/src/print.c b/src/print.c index e56d213..13e53d9 100644 --- a/src/print.c +++ b/src/print.c @@ -57,11 +57,8 @@ void print_item(struct json *json, char **str, int64_t *size, int64_t *index) { case JSON_NUMBER: append_printf(str, size, index, "%lf", json->num); break; - case JSON_TRUE: - append_printf(str, size, index, "true"); - break; - case JSON_FALSE: - append_printf(str, size, index, "false"); + case JSON_BOOL: + append_printf(str, size, index, json->boolean ? "true" : "false"); break; case JSON_NULL: append_printf(str, size, index, "null"); @@ -98,8 +95,6 @@ void print_item(struct json *json, char **str, int64_t *size, int64_t *index) { } append_printf(str, size, index, "\""); break; - case JSON_INVALID: - break; } } diff --git a/src/string.c b/src/string.c index 2aea375..e5847b8 100644 --- a/src/string.c +++ b/src/string.c @@ -4,22 +4,28 @@ #include #include "internal.h" -char *json_string_get(const struct json *str) { +char *json_string_get_mut(struct json *str) { if (str->type != JSON_STRING) return NULL; return str->string; } +const char *json_string_get_const(const struct json *string) { + return json_string_get_mut((struct json *)string); +} + enum json_parse_result parse_string(struct json **json_out, struct raw_json *raw) { - struct json *json = json_new_string(); - if (!json) + char *str; + enum json_parse_result ret = parse_raw_string(&str, raw); + if (ret != JSON_PARSE_OK) { + return ret; + } + struct json *json = json_string_from(str); + if (!json) { + free(str); return JSON_OOM; - enum json_parse_result ret = parse_raw_string(&json->string, raw); - if (ret == JSON_PARSE_OK) { - *json_out = json; - } else { - json_delete(json); } + *json_out = json; return ret; } @@ -267,6 +273,8 @@ void json_string_set(struct json *dest, const char *string) { json_clear(dest); dest->key = key; dest->type = JSON_STRING; + dest->string = strdup(string); + return; } free(dest->string); dest->string = strdup(string); -- cgit v1.2.3