Files
cworker/clib/jblock.c
2023-08-31 03:26:16 +02:00

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;
}