summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c102
-rw-r--r--src/internal.h21
-rw-r--r--src/json.c73
-rw-r--r--src/literal.c17
-rw-r--r--src/object.c143
-rw-r--r--src/print.c9
-rw-r--r--src/string.c24
7 files changed, 219 insertions, 170 deletions
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 <signal.h>
-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 <assert.h>
#include <stdlib.h>
#include <string.h>
#include <json.h>
#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 <json.h>
#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);