commit 8535fc8
default
·
2023-09-03 18:22:32 +0000 UTC
parent e3fbb80
Backport from xs.
3 files changed,
+119,
-69
M
xs.h
+2,
-5
1@@ -28,9 +28,6 @@ typedef enum {
2 } xstype;
3
4
5-/* dynamic strings */
6-typedef char d_char;
7-
8 /* types */
9 typedef char xs_val;
10 typedef char xs_str;
11@@ -157,7 +154,7 @@ xs_val xs_stock_dict[] = { XSTYPE_DICT, 0, 0, 5, XSTYPE_EOM };
12
13 void *_xs_realloc(void *ptr, size_t size, const char *file, int line, const char *func)
14 {
15- d_char *ndata = realloc(ptr, size);
16+ xs_val *ndata = realloc(ptr, size);
17
18 if (ndata == NULL) {
19 fprintf(stderr, "**OUT OF MEMORY**\n");
20@@ -530,7 +527,7 @@ int xs_starts_and_ends(const char *prefix, const char *str, const char *suffix)
21
22
23 xs_str *xs_crop_i(xs_str *str, int start, int end)
24-/* crops the d_char to be only from start to end */
25+/* crops the string to be only from start to end */
26 {
27 XS_ASSERT_TYPE(str, XSTYPE_STRING);
28
+116,
-63
1@@ -6,8 +6,13 @@
2
3 int xs_json_dump(const xs_val *data, int indent, FILE *f);
4 xs_str *xs_json_dumps(const xs_val *data, int indent);
5-xs_val *xs_json_loads(const xs_str *json);
6+
7 xs_val *xs_json_load(FILE *f);
8+xs_val *xs_json_loads(const xs_str *json);
9+
10+xstype xs_json_load_type(FILE *f);
11+int xs_json_load_array_iter(FILE *f, xs_val **value, int *c);
12+int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, int *c);
13
14
15 #ifdef XS_IMPLEMENTATION
16@@ -176,8 +181,6 @@ int xs_json_dump(const xs_val *data, int indent, FILE *f)
17
18 /** JSON loads **/
19
20-/* this code comes mostly from the Minimum Profit Text Editor (MPDM) */
21-
22 typedef enum {
23 JS_ERROR = -1,
24 JS_INCOMPLETE,
25@@ -326,6 +329,40 @@ static xs_val *_xs_json_load_lexer(FILE *f, js_type *t)
26 static xs_list *_xs_json_load_array(FILE *f);
27 static xs_dict *_xs_json_load_object(FILE *f);
28
29+int xs_json_load_array_iter(FILE *f, xs_val **value, int *c)
30+{
31+ js_type t;
32+
33+ *value = _xs_json_load_lexer(f, &t);
34+
35+ if (t == JS_ERROR)
36+ return -1;
37+
38+ if (t == JS_CBRACK)
39+ return 0;
40+
41+ if (*c > 0) {
42+ if (t == JS_COMMA)
43+ *value = _xs_json_load_lexer(f, &t);
44+ else
45+ return -1;
46+ }
47+
48+ if (t == JS_OBRACK)
49+ *value = _xs_json_load_array(f);
50+ else
51+ if (t == JS_OCURLY)
52+ *value = _xs_json_load_object(f);
53+
54+ if (*value == NULL)
55+ return -1;
56+
57+ *c = *c + 1;
58+
59+ return 1;
60+}
61+
62+
63 static xs_list *_xs_json_load_array(FILE *f)
64 /* parses a JSON array */
65 {
66@@ -333,36 +370,63 @@ static xs_list *_xs_json_load_array(FILE *f)
67 int c = 0;
68
69 for (;;) {
70- js_type tt;
71- xs *v = _xs_json_load_lexer(f, &tt);
72+ xs *v = NULL;
73+ int r = xs_json_load_array_iter(f, &v, &c);
74+
75+ if (r == -1)
76+ l = xs_free(l);
77
78- if (tt == JS_ERROR)
79+ if (r == 1)
80+ l = xs_list_append(l, v);
81+ else
82 break;
83+ }
84
85- if (tt == JS_CBRACK)
86- return l;
87+ return l;
88+}
89
90- if (c > 0) {
91- if (tt == JS_COMMA)
92- v = _xs_json_load_lexer(f, &tt);
93- else
94- break;
95- }
96
97- if (tt == JS_OBRACK)
98- v = _xs_json_load_array(f);
99- else
100- if (tt == JS_OCURLY)
101- v = _xs_json_load_object(f);
102+int xs_json_load_object_iter(FILE *f, xs_str **key, xs_val **value, int *c)
103+{
104+ js_type t;
105
106- if (v == NULL)
107- break;
108+ *key = _xs_json_load_lexer(f, &t);
109+
110+ if (t == JS_ERROR)
111+ return -1;
112
113- l = xs_list_append(l, v);
114- c++;
115+ if (t == JS_CCURLY)
116+ return 0;
117+
118+ if (*c > 0) {
119+ if (t == JS_COMMA)
120+ *key = _xs_json_load_lexer(f, &t);
121+ else
122+ return -1;
123 }
124
125- return xs_free(l);
126+ if (t != JS_STRING)
127+ return -1;
128+
129+ xs_free(_xs_json_load_lexer(f, &t));
130+
131+ if (t != JS_COLON)
132+ return -1;
133+
134+ *value = _xs_json_load_lexer(f, &t);
135+
136+ if (t == JS_OBRACK)
137+ *value = _xs_json_load_array(f);
138+ else
139+ if (t == JS_OCURLY)
140+ *value = _xs_json_load_object(f);
141+
142+ if (*value == NULL)
143+ return -1;
144+
145+ *c = *c + 1;
146+
147+ return 1;
148 }
149
150
151@@ -375,47 +439,20 @@ static xs_dict *_xs_json_load_object(FILE *f)
152 d = xs_dict_new();
153
154 for (;;) {
155- js_type tt;
156- xs *k = _xs_json_load_lexer(f, &tt);
157+ xs *k = NULL;
158 xs *v = NULL;
159+ int r = xs_json_load_object_iter(f, &k, &v, &c);
160
161- if (tt == JS_ERROR)
162- break;
163-
164- if (tt == JS_CCURLY)
165- return d;
166-
167- if (c > 0) {
168- if (tt == JS_COMMA)
169- k = _xs_json_load_lexer(f, &tt);
170- else
171- break;
172- }
173-
174- if (tt != JS_STRING)
175- break;
176-
177- xs_free(_xs_json_load_lexer(f, &tt));
178+ if (r == -1)
179+ d = xs_free(d);
180
181- if (tt != JS_COLON)
182- break;
183-
184- v = _xs_json_load_lexer(f, &tt);
185-
186- if (tt == JS_OBRACK)
187- v = _xs_json_load_array(f);
188+ if (r == 1)
189+ d = xs_dict_append(d, k, v);
190 else
191- if (tt == JS_OCURLY)
192- v = _xs_json_load_object(f);
193-
194- if (v == NULL)
195 break;
196-
197- d = xs_dict_append(d, k, v);
198- c++;
199 }
200
201- return xs_free(d);
202+ return d;
203 }
204
205
206@@ -434,18 +471,34 @@ xs_val *xs_json_loads(const xs_str *json)
207 }
208
209
210+xstype xs_json_load_type(FILE *f)
211+/* identifies the type of a JSON stream */
212+{
213+ xstype t = XSTYPE_NULL;
214+ js_type jt;
215+
216+ xs_free(_xs_json_load_lexer(f, &jt));
217+
218+ if (jt == JS_OBRACK)
219+ t = XSTYPE_LIST;
220+ else
221+ if (jt == JS_OCURLY)
222+ t = XSTYPE_DICT;
223+
224+ return t;
225+}
226+
227+
228 xs_val *xs_json_load(FILE *f)
229 /* loads a JSON file */
230 {
231 xs_val *v = NULL;
232- js_type t;
233+ xstype t = xs_json_load_type(f);
234
235- xs_free(_xs_json_load_lexer(f, &t));
236-
237- if (t == JS_OBRACK)
238+ if (t == XSTYPE_LIST)
239 v = _xs_json_load_array(f);
240 else
241- if (t == JS_OCURLY)
242+ if (t == XSTYPE_DICT)
243 v = _xs_json_load_object(f);
244
245 return v;
+1,
-1
1@@ -1 +1 @@
2-/* ce9e43569a7dd29a85c807e496c335cc4999bafd */
3+/* 9a2b91d7713c862ce8753721da2ab5867abb80fd */