#include "json/json_entities.h" #include "aliases.h" #include "json/dstring.h" #include #include void print_json(const jentity_t *entity, u32 indent) { PERSISTENT i32 indentation = 0; dstr_t *key = NULL; const jval_t *value = NULL; if (entity->type == JENTITY_SINGLE) { value = &(entity->value); } else { key = entity->pair.key; value = &(entity->pair.value); } if (key) { printf("%*s\"%s\": ", indentation * indent, "", dstr_to_cstr(key)); } switch (value->type) { case JVAL_COLLECTION: { const char *open = ""; const char *close = ""; if (value->collection->type == JCOLL_OBJECT) { open = "{"; close = "}"; } else { open = "["; close = "]"; } if (key) { printf("%s\n", open); } else { printf("%*s%s\n", indentation * indent, "", open); } ++indentation; if (value->collection->begin) { print_json(value->collection->begin, indent); } --indentation; printf("\n%*s%s", indentation * indent, "", close); break; } case JVAL_STRING: if (key) { printf("\"%s\"", dstr_to_cstr(value->string)); } else { printf("%*s\"%s\"", indentation * indent, "", dstr_to_cstr(value->string)); } break; case JVAL_INTEGER: if (key) { printf("%llu", (unsigned long long)value->num_int); } else { printf("%*s%llu", indentation * indent, "", (unsigned long long)value->num_int); } break; case JVAL_DOUBLE: if (key) { printf("%f", value->num_dbl); } else { printf("%*s%f", indentation * indent, "", value->num_dbl); } break; case JVAL_BOOLEAN: if (key) { printf("%s", value->boolean ? "true" : "false"); } else { printf("%*s%s", indentation * indent, "", value->boolean ? "true" : "false"); } break; case JVAL_NULL: if (key) { printf("%s", "null"); } else { printf("%*s%s", indentation * indent, "", "null"); } break; case JVAL_EMPTY: break; } if (entity->next) { printf(",\n"); print_json(entity->next, indent); } // Add newline after printing the entire json tree if (indentation == 0 && entity->parent == NULL && entity->next == NULL) { printf("\n"); } } void free_json(jentity_t **entity) { if (!(*entity)) { return; } jentity_t *entt_ptr = *entity; dstr_t *key = NULL; const jval_t *value = NULL; if (entt_ptr->type == JENTITY_SINGLE) { value = &(entt_ptr->value); } else { key = entt_ptr->pair.key; value = &(entt_ptr->pair.value); } if (key) { dstr_free(&(entt_ptr->pair.key)); } switch (value->type) { case JVAL_COLLECTION: if (value->collection->begin) { free_json(&(value->collection->begin)); } free(value->collection); break; case JVAL_STRING: dstr_free(&(entt_ptr->pair.value.string)); break; default: break; } if (entt_ptr->next) { free_json(&(entt_ptr->next)); } free(*entity); *entity = NULL; } jcoll_t *get_collection_from_entity(const jentity_t *entity) { return entity->type == JENTITY_SINGLE ? entity->value.collection : entity->pair.value.collection; } jentity_t *create_new_single_entity(const jval_t value, jentity_t *parent) { jentity_t *entity = (jentity_t *)malloc(sizeof(jentity_t)); if (!entity) { return NULL; } entity->type = JENTITY_SINGLE; entity->value = value; entity->parent = parent; entity->next = NULL; return entity; } jentity_t *create_new_pair_entity(dstr_t *key, const jval_t value, jentity_t *parent) { jentity_t *entity = (jentity_t *)malloc(sizeof(jentity_t)); if (!entity) { return NULL; } entity->type = JENTITY_PAIR; entity->pair.key = key; entity->pair.value = value; entity->parent = parent; entity->next = NULL; return entity; }