commit 6949d7d

default  ·  2023-08-05 19:57:45 +0000 UTC
parent 15f7559
Backport from xs.
2 files changed,  +53, -57
+52, -56
  1@@ -4,9 +4,10 @@
  2 
  3 #define _XS_JSON_H
  4 
  5-xs_str *xs_json_dumps_pp(const xs_val *data, int indent);
  6 int xs_json_dump_pp(const xs_val *data, int indent, FILE *f);
  7+xs_str *xs_json_dumps_pp(const xs_val *data, int indent);
  8 #define xs_json_dumps(data) xs_json_dumps_pp(data, 0)
  9+#define xs_json_dump(data, f) xs_json_dumps_pp(data, 0, f)
 10 xs_val *xs_json_loads(const xs_str *json);
 11 xs_val *xs_json_load(FILE *f);
 12 
 13@@ -17,63 +18,55 @@ xs_val *xs_json_load(FILE *f);
 14 
 15 /** JSON dumps **/
 16 
 17-static xs_str *_xs_json_dumps_str(xs_str *s, const char *data)
 18+static void _xs_json_dump_str(const char *data, FILE *f)
 19 /* dumps a string in JSON format */
 20 {
 21     unsigned char c;
 22-    s = xs_str_cat(s, "\"");
 23+    fputs("\"", f);
 24 
 25     while ((c = *data)) {
 26         if (c == '\n')
 27-            s = xs_str_cat(s, "\\n");
 28+            fputs("\\n", f);
 29         else
 30         if (c == '\r')
 31-            s = xs_str_cat(s, "\\r");
 32+            fputs("\\r", f);
 33         else
 34         if (c == '\t')
 35-            s = xs_str_cat(s, "\\t");
 36+            fputs("\\t", f);
 37         else
 38         if (c == '\\')
 39-            s = xs_str_cat(s, "\\\\");
 40+            fputs("\\\\", f);
 41         else
 42         if (c == '"')
 43-            s = xs_str_cat(s, "\\\"");
 44+            fputs("\\\"", f);
 45         else
 46-        if (c < 32) {
 47-            char tmp[10];
 48-
 49-            snprintf(tmp, sizeof(tmp), "\\u%04x", (unsigned int) c);
 50-            s = xs_str_cat(s, tmp);
 51-        }
 52+        if (c < 32)
 53+            fprintf(f, "\\u%04x", (unsigned int) c);
 54         else
 55-            s = xs_append_m(s, data, 1);
 56+            fputc(c, f);
 57 
 58         data++;
 59     }
 60 
 61-    s = xs_str_cat(s, "\"");
 62-
 63-    return s;
 64+    fputs("\"", f);
 65 }
 66 
 67 
 68-static xs_str *_xs_json_indent(xs_str *s, int level, int indent)
 69+static void _xs_json_indent(int level, int indent, FILE *f)
 70 /* adds indentation */
 71 {
 72     if (indent) {
 73         int n;
 74 
 75-        s = xs_str_cat(s, "\n");
 76+        fputc('\n', f);
 77 
 78         for (n = 0; n < level * indent; n++)
 79-            s = xs_str_cat(s, " ");
 80+            fputc(' ', f);
 81     }
 82-
 83-    return s;
 84 }
 85 
 86 
 87-static xs_str *_xs_json_dumps(xs_str *s, const xs_val *s_data, int level, int indent)
 88+static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f)
 89 /* dumps partial data as JSON */
 90 {
 91     int c = 0;
 92@@ -82,85 +75,87 @@ static xs_str *_xs_json_dumps(xs_str *s, const xs_val *s_data, int level, int in
 93 
 94     switch (xs_type(data)) {
 95     case XSTYPE_NULL:
 96-        s = xs_str_cat(s, "null");
 97+        fputs("null", f);
 98         break;
 99 
100     case XSTYPE_TRUE:
101-        s = xs_str_cat(s, "true");
102+        fputs("true", f);
103         break;
104 
105     case XSTYPE_FALSE:
106-        s = xs_str_cat(s, "false");
107+        fputs("false", f);
108         break;
109 
110     case XSTYPE_NUMBER:
111-        s = xs_str_cat(s, xs_number_str(data));
112+        fputs(xs_number_str(data), f);
113         break;
114 
115     case XSTYPE_LIST:
116-        s = xs_str_cat(s, "[");
117+        fputc('[', f);
118 
119         while (xs_list_iter(&data, &v)) {
120             if (c != 0)
121-                s = xs_str_cat(s, ",");
122+                fputc(',', f);
123 
124-            s = _xs_json_indent(s, level + 1, indent);
125-            s = _xs_json_dumps(s, v, level + 1, indent);
126+            _xs_json_indent(level + 1, indent, f);
127+            _xs_json_dump(v, level + 1, indent, f);
128 
129             c++;
130         }
131 
132-        s = _xs_json_indent(s, level, indent);
133-        s = xs_str_cat(s, "]");
134+        _xs_json_indent(level, indent, f);
135+        fputc(']', f);
136 
137         break;
138 
139     case XSTYPE_DICT:
140-        s = xs_str_cat(s, "{");
141+        fputc('{', f);
142 
143         xs_str *k;
144         while (xs_dict_iter(&data, &k, &v)) {
145             if (c != 0)
146-                s = xs_str_cat(s, ",");
147+                fputc(',', f);
148 
149-            s = _xs_json_indent(s, level + 1, indent);
150+            _xs_json_indent(level + 1, indent, f);
151 
152-            s = _xs_json_dumps_str(s, k);
153-            s = xs_str_cat(s, ":");
154+            _xs_json_dump_str(k, f);
155+            fputc(':', f);
156 
157             if (indent)
158-                s = xs_str_cat(s, " ");
159+                fputc(' ', f);
160 
161-            s = _xs_json_dumps(s, v, level + 1, indent);
162+            _xs_json_dump(v, level + 1, indent, f);
163 
164             c++;
165         }
166 
167-        s = _xs_json_indent(s, level, indent);
168-        s = xs_str_cat(s, "}");
169+        _xs_json_indent(level, indent, f);
170+        fputc('}', f);
171         break;
172 
173     case XSTYPE_STRING:
174-        s = _xs_json_dumps_str(s, data);
175+        _xs_json_dump_str(data, f);
176         break;
177 
178     default:
179         break;
180     }
181-
182-    return s;
183 }
184 
185 
186 xs_str *xs_json_dumps_pp(const xs_val *data, int indent)
187-/* dumps a piece of data as JSON */
188+/* dumps data as a JSON string */
189 {
190-    xstype t = xs_type(data);
191     xs_str *s = NULL;
192+    size_t sz;
193+    FILE *f;
194 
195-    if (t == XSTYPE_LIST || t == XSTYPE_DICT) {
196-        s = xs_str_new(NULL);
197-        s = _xs_json_dumps(s, data, 0, indent);
198+    if ((f = open_memstream(&s, &sz)) != NULL) {
199+        int r = xs_json_dump_pp(data, indent, f);
200+        fclose(f);
201+
202+        if (!r)
203+            s = xs_free(s);
204     }
205 
206     return s;
207@@ -170,13 +165,14 @@ xs_str *xs_json_dumps_pp(const xs_val *data, int indent)
208 int xs_json_dump_pp(const xs_val *data, int indent, FILE *f)
209 /* dumps data into a file as JSON */
210 {
211-    xs *j = xs_json_dumps_pp(data, indent);
212+    xstype t = xs_type(data);
213 
214-    if (j == NULL)
215-        return 0;
216+    if (t == XSTYPE_LIST || t == XSTYPE_DICT) {
217+        _xs_json_dump(data, 0, indent, f);
218+        return 1;
219+    }
220 
221-    fwrite(j, strlen(j), 1, f);
222-    return 1;
223+    return 0;
224 }
225 
226 
+1, -1
1@@ -1 +1 @@
2-/* 5ad148b1c1dbbf7b4550c9fcd13d96ac6def2d21 */
3+/* 7ee8d1e20f4adc0a1cddd64b290efee94e055f32 */