src/json.c

changeset 946
b428424c0214
parent 944
c26299cc9897
child 954
a1d87e8fff6d
--- 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;
     }

mercurial