Back to project.

Raw source file available here .

// 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