222 lines
5.5 KiB
C
222 lines
5.5 KiB
C
/*
|
|
*
|
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
|
*
|
|
*/
|
|
|
|
|
|
#ifdef __linux__
|
|
#define _GNU_SOURCE
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include <cstring.h>
|
|
#include <cdynarr.h>
|
|
#include <jblock.h>
|
|
|
|
#define INIT_CAPA 64
|
|
|
|
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);
|
|
}
|
|
|
|
jblock_t* new_jblock() {
|
|
jblock_t* jb = malloc(sizeof(jblock_t));
|
|
if (jb == NULL) return NULL;
|
|
jblock_init(jb);
|
|
return jb;
|
|
}
|
|
|
|
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) {
|
|
cstring_t jstr;
|
|
cstring_init(&jstr);
|
|
cstring_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);
|
|
cstring_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);
|
|
cstring_append(&jstr, buffer);
|
|
free(buffer);
|
|
break;
|
|
}
|
|
case JKVTYPE_FLT: {
|
|
char* buffer = NULL;
|
|
asprintf(&buffer, "%e", jb->kvarr[i].flt);
|
|
cstring_append(&jstr, buffer);
|
|
free(buffer);
|
|
break;
|
|
}
|
|
case JKVTYPE_BOOL: {
|
|
if (jb->kvarr[i].flag) {
|
|
cstring_append(&jstr, "true");
|
|
} else {
|
|
cstring_append(&jstr, "false");
|
|
}
|
|
break;
|
|
}
|
|
case JKVTYPE_STR: {
|
|
char* buffer = NULL;
|
|
asprintf(&buffer, "\"%s\"", jb->kvarr[i].str);
|
|
cstring_append(&jstr, buffer);
|
|
free(buffer);
|
|
break;
|
|
}
|
|
}
|
|
if (i < jb->kvsize - 1) {
|
|
cstring_append(&jstr, ",");
|
|
}
|
|
}
|
|
cstring_append(&jstr, "}");
|
|
*res = cstring_getref(&jstr);
|
|
}
|
|
|
|
|
|
void jblock_destroy(jblock_t* jb) {
|
|
if (jb == NULL) return;
|
|
for (int i = 0; i < jb->kvsize; i++) {
|
|
switch (jb->kvarr[i].type) {
|
|
case JKVTYPE_BLK: {
|
|
jblock_destroy(jb->kvarr[i].blk);
|
|
break;
|
|
}
|
|
//case JKVTYPE_BLKARR: {
|
|
// break;
|
|
//}
|
|
case JKVTYPE_STR: {
|
|
free(jb->kvarr[i].str);
|
|
break;
|
|
}
|
|
case JKVTYPE_INTARR: {
|
|
//free(jb->kvarr[i].numarr);
|
|
break;
|
|
}
|
|
case JKVTYPE_BOOLARR: {
|
|
//free(jb->kvarr[i].flagarr);
|
|
break;
|
|
}
|
|
case JKVTYPE_FLTARR: {
|
|
//free(jb->kvarr[i].fltarr);
|
|
break;
|
|
}
|
|
}
|
|
free(jb->kvarr[i].key);
|
|
}
|
|
|
|
jb->kvsize = 0;
|
|
jb->kvcapa = 0;
|
|
free(jb->kvarr);
|
|
jb->kvarr = NULL;
|
|
}
|
|
|
|
void jblock_free(jblock_t* jb) {
|
|
jblock_destroy(jb);
|
|
free(jb);
|
|
}
|
|
|
|
/* Tools */
|
|
static char* strcopy(char* src) {
|
|
size_t srcsize = strlen(src) + 1;
|
|
char* dst = malloc(srcsize);
|
|
memset(dst, '\0', srcsize);
|
|
strcpy(dst, src);
|
|
return dst;
|
|
}
|