#ifndef JSON_H #define JSON_H enum json_type { JSON_TYPE_INVALID, JSON_TYPE_STRING, JSON_TYPE_NULL, JSON_TYPE_BOOL, JSON_TYPE_ARRAY, JSON_TYPE_OBJECT, JSON_TYPE_NUMBER }; struct json_object_entry; struct json_ir_parent_data { u32 child_count; struct json_ir *child_first; struct json_ir *child_last; }; /* Intermediate representation of JSON hierarchy tree in memory. Used for mutating * JSON in parsing stage or for creating new objects. Should be manipulated via the * API. */ struct json_ir { enum json_type type; struct json_ir *next_child; struct string key; union { struct json_ir_parent_data children; b32 boolean; struct string string; f64 number; } val; }; /* Final representation of JSON hierarchy. Should be manipulated via the API. */ struct json_val { enum json_type type; u32 child_count; union { void *object_table; struct json_val *array_children; b32 boolean; struct string *string; f64 number; } val; }; struct json_object_entry { struct string key; struct json_val value; }; /* Parse */ const struct json_ir *json_parse(struct arena *arena, struct buffer bytes, struct string **error); /* Format */ const struct json_val *json_format(struct arena *arena, const struct json_ir *ir); const struct json_val *json_parse_and_format(struct arena *arena, struct buffer bytes, struct string **error); /* Index */ const struct json_val *json_array_get(const struct json_val *a, u32 index); const struct json_val *json_object_get(const struct json_val *obj, struct string key); const struct json_object_entry *json_object_get_index(const struct json_val *obj, u32 index); /* Dump */ struct string json_dump_to_string(struct arena *arena, const struct json_val *val, u32 indent); /* Write */ struct json_ir *json_ir_object(struct arena *arena); struct json_ir *json_ir_number(struct arena *arena, f64 n); struct json_ir *json_ir_bool(struct arena *arena, b32 b); struct json_ir *json_ir_object_set(struct json_ir *obj, struct string key, struct json_ir *value); /* ========================== * * Type util * ========================== */ INLINE b32 json_is_object(const struct json_val *v) { return v && v->type == JSON_TYPE_OBJECT; } INLINE b32 json_is_string(const struct json_val *v) { return v && v->type == JSON_TYPE_STRING; } INLINE b32 json_is_number(const struct json_val *v) { return v && v->type == JSON_TYPE_NUMBER; } INLINE b32 json_is_array(const struct json_val *v) { return v && v->type == JSON_TYPE_ARRAY; } INLINE b32 json_is_bool(const struct json_val *v) { return v && v->type == JSON_TYPE_BOOL; } INLINE b32 json_is_null(const struct json_val *v) { return v && v->type == JSON_TYPE_NULL; } /* ========================== * * Val util * ========================== */ INLINE struct string json_string(const struct json_val *v) { ASSERT(json_is_string(v)); return *v->val.string; } INLINE f64 json_number(const struct json_val *v) { ASSERT(json_is_number(v)); return v->val.number; } INLINE b32 json_bool(const struct json_val *v) { ASSERT(json_is_bool(v)); return v->val.boolean; } /* ========================== * * Parent util * ========================== */ INLINE u32 json_child_count(const struct json_val *v) { ASSERT(json_is_object(v) || json_is_array(v)); return v->child_count; } #endif