#include #include #include #include #include #include #include "internal.h" #include #include #include struct json *json_new(void) { struct json *json = calloc(1, sizeof(*json)); if (!json) return NULL; 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; struct json_children *siblings = json->parent->children; if (json->index != --siblings->nitems) { struct json *tmp; for (size_t i = json->index; i < siblings->nitems; i++) { tmp = siblings->items[i] = siblings->items[i + 1]; tmp->index = i; tmp->prev = i > 0 ? siblings->items[tmp->index - 1] : NULL; tmp->next = i < siblings->nitems ? siblings->items[tmp->index + 1] : NULL; } } json->parent = NULL; } void json_delete(struct json *json) { if (!json) return; json_detach(json); json_clear(json); free(json); } void json_clear(struct json *json) { if (!json) return; switch (json->type) { case JSON_OBJECT: case JSON_ARRAY: for (size_t i = 0; i < json->children->nitems; i++) { json_clear(json->children->items[i]); free(json->children->items[i]); } free(json->children); break; case JSON_STRING: free(json->string); break; default: break; } free(json->key); json->type = JSON_NULL; } struct json *json_object(void) { struct json *json = json_new(); json->type = JSON_OBJECT; init_children(json); return json; } struct json *json_array(void) { struct json *json = json_new(); if (!json) return NULL; json->type = JSON_ARRAY; init_children(json); return json; } struct json *json_bool(bool boolean) { struct json *json = json_new(); if (!json) return NULL; json->type = JSON_BOOL; json->boolean = boolean; return json; } struct json *json_number(double num) { struct json *json = json_new(); if (!json) return NULL; json->type = JSON_NUMBER; json->num = num; return json; } struct json *json_string(const char *string) { struct json *json = json_new(); if (!json) return NULL; json->type = JSON_STRING; json->string = strdup(string); return json; } struct json *json_string_from(char *string) { struct json *json = json_new(); if (!json) return NULL; json->type = JSON_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; enum json_parse_result ret = JSON_PARSE_OK; switch (raw->data[raw->index]) { case '"': ret = parse_string(&json, raw); break; case '{': ret = parse_object(&json, raw, depth); break; case '[': ret = parse_array(&json, raw, depth); break; default: ret = parse_literal(&json, raw); break; } *json_out = json; return ret; } struct json *json_parse(const char *str) { return json_parse_sized(strlen(str), str); } 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 = len }; if (parse_value(&json, &raw, 1) != JSON_PARSE_OK) { return NULL; }; skip_ws(&raw); if (raw.index != raw.size) { json_delete(json); return NULL; } return json; }