212 lines
5.4 KiB
C
212 lines
5.4 KiB
C
/*
|
|
*
|
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
|
*
|
|
*/
|
|
|
|
#include <jblock.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
|
|
#define INIT_CAPA 64
|
|
|
|
static void* jstring_init(jstring_t* str);
|
|
static void* jstring_append(jstring_t* str, char* add);
|
|
static char* jstring_getref(jstring_t* str);
|
|
static char* strcopy(char* src);
|
|
|
|
void jblock_init(jblock_t* jb) {
|
|
jb->kvsize = 0;
|
|
jb->kvcapa = INIT_CAPA;
|
|
jb->kvarr = malloc(sizeof(jkeyval_t) * INIT_CAPA);
|
|
}
|
|
|
|
static void* jblock_checkalloc(jblock_t* jb) {
|
|
if (jb->kvsize == jb->kvcapa) {
|
|
size_t newsize = jb->kvcapa * 2;
|
|
jkeyval_t* newarr = realloc(jb->kvarr, sizeof(jkeyval_t) * newsize);
|
|
if (newarr == NULL) {
|
|
return NULL;
|
|
}
|
|
jb->kvarr = newarr;
|
|
jb->kvcapa = newsize;
|
|
}
|
|
return jb->kvarr;
|
|
}
|
|
|
|
static bool jblock_keyexists(jblock_t* jb, char* key) {
|
|
for (int i = 0; i < jb->kvsize; i++) {
|
|
if (strcmp(key, jb->kvarr[i].key) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
int jblock_addint(jblock_t* jb, char* key, int64_t val) {
|
|
if (jblock_keyexists(jb, key)) {
|
|
return -2;
|
|
}
|
|
if (jblock_checkalloc(jb) == NULL) {
|
|
return -1;
|
|
}
|
|
jb->kvarr[jb->kvsize].key = strcopy(key);
|
|
jb->kvarr[jb->kvsize].num = val;
|
|
jb->kvarr[jb->kvsize].type = JKVTYPE_INT;
|
|
return ++jb->kvsize;
|
|
}
|
|
|
|
int jblock_addfloat(jblock_t* jb, char* key, double val) {
|
|
if (jblock_keyexists(jb, key)) {
|
|
return -2;
|
|
}
|
|
if (jblock_checkalloc(jb) == NULL) {
|
|
return -1;
|
|
}
|
|
jb->kvarr[jb->kvsize].key = strcopy(key);
|
|
jb->kvarr[jb->kvsize].flt = val;
|
|
jb->kvarr[jb->kvsize].type = JKVTYPE_FLT;
|
|
return ++jb->kvsize;
|
|
}
|
|
|
|
int jblock_addbool(jblock_t* jb, char* key, bool val) {
|
|
if (jblock_keyexists(jb, key)) {
|
|
return -2;
|
|
}
|
|
if (jblock_checkalloc(jb) == NULL) {
|
|
return -1;
|
|
}
|
|
jb->kvarr[jb->kvsize].key = strcopy(key);
|
|
jb->kvarr[jb->kvsize].flag = val;
|
|
jb->kvarr[jb->kvsize].type = JKVTYPE_BOOL;
|
|
return ++jb->kvsize;
|
|
}
|
|
|
|
int jblock_addstr(jblock_t* jb, char* key, char* val) {
|
|
if (jblock_keyexists(jb, key)) {
|
|
return -2;
|
|
}
|
|
if (jblock_checkalloc(jb) == NULL) {
|
|
return -1;
|
|
}
|
|
jb->kvarr[jb->kvsize].key = strcopy(key);
|
|
jb->kvarr[jb->kvsize].str = strcopy(val);
|
|
jb->kvarr[jb->kvsize].type = JKVTYPE_STR;
|
|
return ++jb->kvsize;
|
|
}
|
|
|
|
void jblock_outjson(jblock_t* jb, char** res) {
|
|
jstring_t jstr;
|
|
jstring_init(&jstr);
|
|
jstring_append(&jstr, "{");
|
|
for (int i = 0; i < jb->kvsize; i++) {
|
|
switch (jb->kvarr[i].type) {
|
|
case JKVTYPE_STR:
|
|
case JKVTYPE_BOOL:
|
|
case JKVTYPE_FLT:
|
|
case JKVTYPE_INT: {
|
|
char* buffer = NULL;
|
|
asprintf(&buffer, "\"%s\":", jb->kvarr[i].key);
|
|
jstring_append(&jstr, buffer);
|
|
free(buffer);
|
|
break;
|
|
}
|
|
default: {
|
|
continue;
|
|
}
|
|
}
|
|
switch (jb->kvarr[i].type) {
|
|
case JKVTYPE_INT: {
|
|
char* buffer = NULL;
|
|
asprintf(&buffer, "%ld", jb->kvarr[i].num);
|
|
jstring_append(&jstr, buffer);
|
|
free(buffer);
|
|
break;
|
|
}
|
|
case JKVTYPE_FLT: {
|
|
char* buffer = NULL;
|
|
asprintf(&buffer, "%e", jb->kvarr[i].flt);
|
|
jstring_append(&jstr, buffer);
|
|
free(buffer);
|
|
break;
|
|
}
|
|
case JKVTYPE_BOOL: {
|
|
if (jb->kvarr[i].flag) {
|
|
jstring_append(&jstr, "true");
|
|
} else {
|
|
jstring_append(&jstr, "false");
|
|
}
|
|
break;
|
|
}
|
|
case JKVTYPE_STR: {
|
|
char* buffer = NULL;
|
|
asprintf(&buffer, "\"%s\"", jb->kvarr[i].str);
|
|
jstring_append(&jstr, buffer);
|
|
free(buffer);
|
|
break;
|
|
}
|
|
}
|
|
if (i < jb->kvsize - 1) {
|
|
jstring_append(&jstr, ",");
|
|
}
|
|
}
|
|
jstring_append(&jstr, "}");
|
|
*res = jstring_getref(&jstr);
|
|
}
|
|
|
|
|
|
void jblock_destroy(jblock_t* jb) {
|
|
if (jb == NULL) return;
|
|
for (int i = 0; i < jb->kvsize; i++) {
|
|
free(jb->kvarr[i].key);
|
|
switch (jb->kvarr[i].type) {
|
|
case JKVTYPE_STR: {
|
|
free(jb->kvarr[i].str);
|
|
}
|
|
}
|
|
}
|
|
jb->kvsize = 0;
|
|
jb->kvcapa = 0;
|
|
jb->kvarr = NULL;
|
|
}
|
|
|
|
|
|
static void* jstring_init(jstring_t* str) {
|
|
str->data = malloc(INIT_CAPA + 1);
|
|
if (str->data == NULL) return NULL;
|
|
memset(str->data, '\0', INIT_CAPA + 1);
|
|
str->capa = INIT_CAPA;
|
|
str->size = 0;
|
|
return str->data;
|
|
}
|
|
|
|
|
|
static void* jstring_append(jstring_t* str, char* add) {
|
|
size_t addsize = strlen(add);
|
|
size_t newsize = str->size + addsize;
|
|
if (newsize > str->capa) {
|
|
char* newstr = malloc(newsize + 1);
|
|
if (newstr == NULL) return NULL;
|
|
}
|
|
strcpy(&(str->data[str->size]), add);
|
|
str->data[newsize + 1] = '\0';
|
|
str->capa = newsize;
|
|
str->size = newsize;
|
|
return str->data;
|
|
}
|
|
|
|
static char* jstring_getref(jstring_t* str) {
|
|
return str->data;
|
|
}
|
|
|
|
static char* strcopy(char* src) {
|
|
size_t srcsize = strlen(src) + 1;
|
|
char* dst = malloc(srcsize);
|
|
memset(dst, '\0', srcsize);
|
|
strcpy(dst, src);
|
|
return dst;
|
|
}
|