// Written by retoor@molodetz.nl // A C library for creating and manipulating JSON structures. It provides functions to build JSON strings recursively, including starting // and closing JSON objects and arrays, adding key-value pairs (for strings, integers, numbers, booleans, and durations), and freeing JSON // objects. // Includes for memory management, string manipulation, time handling, and testing utilities: rmalloc.h, rtypes.h, rstring.h, rtemp.h, // rtime.h, rtest.h // MIT License #ifndef RJSON_H #define RJSON_H #include "rmalloc.h" #include "rtypes.h" #include "rstring.h" #include "rtemp.h" #include "rtime.h" #include "rtest.h" typedef struct rjson_t { char *content; size_t length; size_t size; } rjson_t; rjson_t *rjson() { rjson_t *json = rmalloc(sizeof(rjson_t)); json->size = 1024; json->length = 0; json->content = rmalloc(json->size); json->content[0] = 0; return json; } void rjson_write(rjson_t *rjs, char *content) { size_t len = strlen(content); while (rjs->size < rjs->length + len + 1) { rjs->content = realloc(rjs->content, rjs->size + 1024); rjs->size += 1024; } strcat(rjs->content, content); rjs->length += len; } void rjson_object_start(rjson_t *rjs) { if (rstrendswith(rjs->content, "}")) { rjson_write(rjs, ","); } rjson_write(rjs, "{"); } void rjson_object_close(rjson_t *rjs) { if (rstrendswith(rjs->content, ",")) { rjs->content[rjs->length - 1] = 0; rjs->length--; } rjson_write(rjs, "}"); } void rjson_array_start(rjson_t *rjs) { if (rjs->length && (rstrendswith(rjs->content, "}") || rstrendswith(rjs->content, "]"))) { rjson_write(rjs, ","); } rjson_write(rjs, "["); } void rjson_array_close(rjson_t *rjs) { if (rstrendswith(rjs->content, ",")) { rjs->content[rjs->length - 1] = 0; rjs->length--; } rjson_write(rjs, "]"); } void rjson_kv_string(rjson_t *rjs, char *key, char *value) { if (rjs->length && !rstrendswith(rjs->content, "{") && !rstrendswith(rjs->content, "[")) { rjson_write(rjs, ","); } rjson_write(rjs, "\""); rjson_write(rjs, key); rjson_write(rjs, "\":\""); char *value_str = rmalloc(strlen(value) + 4096); rstraddslashes(value, value_str); rjson_write(rjs, value_str); free(value_str); rjson_write(rjs, "\""); } void rjson_kv_int(rjson_t *rjs, char *key, ulonglong value) { if (rjs->length && !rstrendswith(rjs->content, "{") && !rstrendswith(rjs->content, "[")) { rjson_write(rjs, ","); } rjson_write(rjs, "\""); rjson_write(rjs, key); rjson_write(rjs, "\":"); char value_str[100] = {0}; sprintf(value_str, "%lld", value); rjson_write(rjs, value_str); } void rjson_kv_number(rjson_t *rjs, char *key, ulonglong value) { if (rjs->length && !rstrendswith(rjs->content, "{") && !rstrendswith(rjs->content, "[")) { rjson_write(rjs, ","); } rjson_write(rjs, "\""); rjson_write(rjs, key); rjson_write(rjs, "\":\""); rjson_write(rjs, sbuf(rformat_number(value))); rjson_write(rjs, "\""); } void rjson_kv_bool(rjson_t *rjs, char *key, int value) { if (rjs->length && !rstrendswith(rjs->content, "{") && !rstrendswith(rjs->content, "[")) { rjson_write(rjs, ","); } rjson_write(rjs, "\""); rjson_write(rjs, key); rjson_write(rjs, "\":"); rjson_write(rjs, value > 0 ? "true" : "false"); } void rjson_kv_duration(rjson_t *rjs, char *key, nsecs_t value) { if (rjs->length && !rstrendswith(rjs->content, "{") && !rstrendswith(rjs->content, "[")) { rjson_write(rjs, ","); } rjson_write(rjs, "\""); rjson_write(rjs, key); rjson_write(rjs, "\":\""); rjson_write(rjs, sbuf(format_time(value))); rjson_write(rjs, "\""); } void rjson_free(rjson_t *rsj) { free(rsj->content); free(rsj); } void rjson_key(rjson_t *rsj, char *key) { rjson_write(rsj, "\""); rjson_write(rsj, key); rjson_write(rsj, "\":"); } #endif