--- a/src/json.c Tue Oct 22 22:42:48 2024 +0200 +++ b/src/json.c Tue Oct 22 23:10:31 2024 +0200 @@ -38,6 +38,7 @@ */ #define PARSER_STATES_ALLOC 32 +#define PARSER_READVALUE_ALLOC 32 static CxJsonValue cx_json_value_nothing = {.type = CX_JSON_NOTHING}; @@ -339,11 +340,21 @@ } static int add_state(CxJson *p, int state) { + // TODO: this is such a common pattern, try to reuse code here if (p->nstates >= p->states_alloc) { - p->states_alloc += PARSER_STATES_ALLOC; - if (cx_reallocate(&p->states, p->states_alloc * sizeof(int))) { - return 1; + unsigned newcap = PARSER_STATES_ALLOC; + if (p->states == p->states_internal) { + void *mem = malloc(newcap * sizeof(int)); + if (mem == NULL) return 1; + memcpy(mem, p->states, p->nstates * sizeof(int)); + p->states = mem; + } else { + newcap += p->states_alloc; + if (cx_reallocate(&p->states, newcap * sizeof(int))) { + return 1; + } } + p->states_alloc = newcap; } p->states[++p->nstates] = state; return 0; @@ -545,9 +556,9 @@ /* -------------------- read value functions -------------------- */ static int setup_read_value(CxJson *p) { - p->readvalue_alloc = PARSER_STATES_ALLOC; + p->readvalue_alloc = PARSER_READVALUE_ALLOC; p->readvalue_nelm = 0; - p->readvalue_stack = calloc(PARSER_STATES_ALLOC, sizeof(CxJsonValue *)); + p->readvalue_stack = calloc(p->readvalue_alloc, sizeof(CxJsonValue *)); if (!p->readvalue_stack) return -1; p->read_value = NULL; @@ -659,15 +670,16 @@ void cxJsonInit(CxJson *json) { memset(json, 0, sizeof(CxJson)); - // TODO: do not allocate states right away - json->states_alloc = PARSER_STATES_ALLOC; - json->states = calloc(PARSER_STATES_ALLOC, sizeof(int)); + json->states = json->states_internal; + json->states_alloc = cx_nmemb(json->states_internal); // TODO: find better way to configure the initial allocation size for arrays and objects json->reader_array_alloc = 8; } void cxJsonDestroy(CxJson *p) { - free(p->states); + if (p->states != p->states_internal) { + free(p->states); + } free(p->readvalue_stack); cxJsonValueFree(p->read_value); free(p->value_name); @@ -684,7 +696,7 @@ int cxJsonNext(CxJson *p, CxJsonValue **value) { // TODO: replace int with a status enum like in CxProperties - *value = NULL; + *value = NULL; // TODO: maybe better initialize with NOTHING? if (!p->readvalue_stack) { if (setup_read_value(p)) return -1; }