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