/* * * Copyright 2023 Oleg Borodin * */ #include #include #include #include #include #include #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; 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; }