commit abf4279

default  ·  2024-03-25 07:55:30 +0000 UTC
parent 8ff9d84
Backport from xs.
1 files changed,  +74, -33
+74, -33
  1@@ -11,8 +11,10 @@ xs_val *xs_json_load(FILE *f);
  2 xs_val *xs_json_loads(const xs_str *json);
  3 
  4 xstype xs_json_load_type(FILE *f);
  5-int xs_json_load_array_iter(FILE *f, xs_val **value, int *c);
  6-int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, int *c);
  7+int xs_json_load_array_iter(FILE *f, xs_val **value, xstype *pt, int *c);
  8+int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, xstype *pt, int *c);
  9+xs_list *xs_json_load_array(FILE *f);
 10+xs_dict *xs_json_load_object(FILE *f);
 11 
 12 
 13 #ifdef XS_IMPLEMENTATION
 14@@ -324,10 +326,9 @@ static xs_val *_xs_json_load_lexer(FILE *f, js_type *t)
 15 }
 16 
 17 
 18-static xs_list *_xs_json_load_array(FILE *f);
 19-static xs_dict *_xs_json_load_object(FILE *f);
 20-
 21-int xs_json_load_array_iter(FILE *f, xs_val **value, int *c)
 22+int xs_json_load_array_iter(FILE *f, xs_val **value, xstype *pt, int *c)
 23+/* loads the next scalar value from the JSON stream */
 24+/* if the value ahead is complex, value is NULL and pt is filled */
 25 {
 26     js_type t;
 27 
 28@@ -346,14 +347,16 @@ int xs_json_load_array_iter(FILE *f, xs_val **value, int *c)
 29             return -1;
 30     }
 31 
 32-    if (t == JS_OBRACK)
 33-        *value = _xs_json_load_array(f);
 34-    else
 35-    if (t == JS_OCURLY)
 36-        *value = _xs_json_load_object(f);
 37-
 38-    if (*value == NULL)
 39-        return -1;
 40+    if (*value == NULL) {
 41+        /* possible complex type ahead */
 42+        if (t == JS_OBRACK)
 43+            *pt = XSTYPE_LIST;
 44+        else
 45+        if (t == JS_OCURLY)
 46+            *pt = XSTYPE_DICT;
 47+        else
 48+            return -1;
 49+    }
 50 
 51     *c = *c + 1;
 52 
 53@@ -361,21 +364,38 @@ int xs_json_load_array_iter(FILE *f, xs_val **value, int *c)
 54 }
 55 
 56 
 57-static xs_list *_xs_json_load_array(FILE *f)
 58-/* parses a JSON array */
 59+xs_list *xs_json_load_array(FILE *f)
 60+/* loads a JSON array (after the initial OBRACK) */
 61 {
 62+    xstype t;
 63     xs_list *l = xs_list_new();
 64     int c = 0;
 65 
 66     for (;;) {
 67         xs *v = NULL;
 68-        int r = xs_json_load_array_iter(f, &v, &c);
 69+        int r = xs_json_load_array_iter(f, &v, &t, &c);
 70 
 71         if (r == -1)
 72             l = xs_free(l);
 73 
 74-        if (r == 1)
 75+        if (r == 1) {
 76+            /* partial load? */
 77+            if (v == NULL) {
 78+                if (t == XSTYPE_LIST)
 79+                    v = xs_json_load_array(f);
 80+                else
 81+                if (t == XSTYPE_DICT)
 82+                    v = xs_json_load_object(f);
 83+            }
 84+
 85+            /* still null? fail */
 86+            if (v == NULL) {
 87+                l = xs_free(l);
 88+                break;
 89+            }
 90+
 91             l = xs_list_append(l, v);
 92+        }
 93         else
 94             break;
 95     }
 96@@ -384,7 +404,9 @@ static xs_list *_xs_json_load_array(FILE *f)
 97 }
 98 
 99 
100-int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, int *c)
101+int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, xstype *pt, int *c)
102+/* loads the next key and scalar value from the JSON stream */
103+/* if the value ahead is complex, value is NULL and pt is filled */
104 {
105     js_type t;
106 
107@@ -413,14 +435,16 @@ int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, int *c)
108 
109     *value = _xs_json_load_lexer(f, &t);
110 
111-    if (t == JS_OBRACK)
112-        *value = _xs_json_load_array(f);
113-    else
114-    if (t == JS_OCURLY)
115-        *value = _xs_json_load_object(f);
116-
117-    if (*value == NULL)
118-        return -1;
119+    if (*value == NULL) {
120+        /* possible complex type ahead */
121+        if (t == JS_OBRACK)
122+            *pt = XSTYPE_LIST;
123+        else
124+        if (t == JS_OCURLY)
125+            *pt = XSTYPE_DICT;
126+        else
127+            return -1;
128+    }
129 
130     *c = *c + 1;
131 
132@@ -428,22 +452,39 @@ int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, int *c)
133 }
134 
135 
136-static xs_dict *_xs_json_load_object(FILE *f)
137-/* parses a JSON object */
138+xs_dict *xs_json_load_object(FILE *f)
139+/* loads a JSON object (after the initial OCURLY) */
140 {
141+    xstype t;
142     xs_dict *d = xs_dict_new();
143     int c = 0;
144 
145     for (;;) {
146         xs *k = NULL;
147         xs *v = NULL;
148-        int r = xs_json_load_object_iter(f, &k, &v, &c);
149+        int r = xs_json_load_object_iter(f, &k, &v, &t, &c);
150 
151         if (r == -1)
152             d = xs_free(d);
153 
154-        if (r == 1)
155+        if (r == 1) {
156+            /* partial load? */
157+            if (v == NULL) {
158+                if (t == XSTYPE_LIST)
159+                    v = xs_json_load_array(f);
160+                else
161+                if (t == XSTYPE_DICT)
162+                    v = xs_json_load_object(f);
163+            }
164+
165+            /* still null? fail */
166+            if (v == NULL) {
167+                d = xs_free(d);
168+                break;
169+            }
170+
171             d = xs_dict_append(d, k, v);
172+        }
173         else
174             break;
175     }
176@@ -492,10 +533,10 @@ xs_val *xs_json_load(FILE *f)
177     xstype t = xs_json_load_type(f);
178 
179     if (t == XSTYPE_LIST)
180-        v = _xs_json_load_array(f);
181+        v = xs_json_load_array(f);
182     else
183     if (t == XSTYPE_DICT)
184-        v = _xs_json_load_object(f);
185+        v = xs_json_load_object(f);
186 
187     return v;
188 }