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 }