summaryrefslogtreecommitdiff
path: root/xs_json.h
diff options
context:
space:
mode:
authordefault <nobody@localhost>2023-08-05 21:57:45 +0200
committerdefault <nobody@localhost>2023-08-05 21:57:45 +0200
commit6949d7df8afecef8dd4eef4f74f0f05dfb711ca4 (patch)
treea223f4748a02410f47083466276b9d130ec3edb2 /xs_json.h
parent15f755960b0b870f5d35105393c65c16d5633e58 (diff)
Backport from xs.
Diffstat (limited to 'xs_json.h')
-rw-r--r--xs_json.h108
1 files changed, 52 insertions, 56 deletions
diff --git a/xs_json.h b/xs_json.h
index 2a7766e..1b6e61c 100644
--- a/xs_json.h
+++ b/xs_json.h
@@ -4,9 +4,10 @@
#define _XS_JSON_H
-xs_str *xs_json_dumps_pp(const xs_val *data, int indent);
int xs_json_dump_pp(const xs_val *data, int indent, FILE *f);
+xs_str *xs_json_dumps_pp(const xs_val *data, int indent);
#define xs_json_dumps(data) xs_json_dumps_pp(data, 0)
+#define xs_json_dump(data, f) xs_json_dumps_pp(data, 0, f)
xs_val *xs_json_loads(const xs_str *json);
xs_val *xs_json_load(FILE *f);
@@ -17,63 +18,55 @@ xs_val *xs_json_load(FILE *f);
/** JSON dumps **/
-static xs_str *_xs_json_dumps_str(xs_str *s, const char *data)
+static void _xs_json_dump_str(const char *data, FILE *f)
/* dumps a string in JSON format */
{
unsigned char c;
- s = xs_str_cat(s, "\"");
+ fputs("\"", f);
while ((c = *data)) {
if (c == '\n')
- s = xs_str_cat(s, "\\n");
+ fputs("\\n", f);
else
if (c == '\r')
- s = xs_str_cat(s, "\\r");
+ fputs("\\r", f);
else
if (c == '\t')
- s = xs_str_cat(s, "\\t");
+ fputs("\\t", f);
else
if (c == '\\')
- s = xs_str_cat(s, "\\\\");
+ fputs("\\\\", f);
else
if (c == '"')
- s = xs_str_cat(s, "\\\"");
+ fputs("\\\"", f);
else
- if (c < 32) {
- char tmp[10];
-
- snprintf(tmp, sizeof(tmp), "\\u%04x", (unsigned int) c);
- s = xs_str_cat(s, tmp);
- }
+ if (c < 32)
+ fprintf(f, "\\u%04x", (unsigned int) c);
else
- s = xs_append_m(s, data, 1);
+ fputc(c, f);
data++;
}
- s = xs_str_cat(s, "\"");
-
- return s;
+ fputs("\"", f);
}
-static xs_str *_xs_json_indent(xs_str *s, int level, int indent)
+static void _xs_json_indent(int level, int indent, FILE *f)
/* adds indentation */
{
if (indent) {
int n;
- s = xs_str_cat(s, "\n");
+ fputc('\n', f);
for (n = 0; n < level * indent; n++)
- s = xs_str_cat(s, " ");
+ fputc(' ', f);
}
-
- return s;
}
-static xs_str *_xs_json_dumps(xs_str *s, const xs_val *s_data, int level, int indent)
+static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f)
/* dumps partial data as JSON */
{
int c = 0;
@@ -82,85 +75,87 @@ static xs_str *_xs_json_dumps(xs_str *s, const xs_val *s_data, int level, int in
switch (xs_type(data)) {
case XSTYPE_NULL:
- s = xs_str_cat(s, "null");
+ fputs("null", f);
break;
case XSTYPE_TRUE:
- s = xs_str_cat(s, "true");
+ fputs("true", f);
break;
case XSTYPE_FALSE:
- s = xs_str_cat(s, "false");
+ fputs("false", f);
break;
case XSTYPE_NUMBER:
- s = xs_str_cat(s, xs_number_str(data));
+ fputs(xs_number_str(data), f);
break;
case XSTYPE_LIST:
- s = xs_str_cat(s, "[");
+ fputc('[', f);
while (xs_list_iter(&data, &v)) {
if (c != 0)
- s = xs_str_cat(s, ",");
+ fputc(',', f);
- s = _xs_json_indent(s, level + 1, indent);
- s = _xs_json_dumps(s, v, level + 1, indent);
+ _xs_json_indent(level + 1, indent, f);
+ _xs_json_dump(v, level + 1, indent, f);
c++;
}
- s = _xs_json_indent(s, level, indent);
- s = xs_str_cat(s, "]");
+ _xs_json_indent(level, indent, f);
+ fputc(']', f);
break;
case XSTYPE_DICT:
- s = xs_str_cat(s, "{");
+ fputc('{', f);
xs_str *k;
while (xs_dict_iter(&data, &k, &v)) {
if (c != 0)
- s = xs_str_cat(s, ",");
+ fputc(',', f);
- s = _xs_json_indent(s, level + 1, indent);
+ _xs_json_indent(level + 1, indent, f);
- s = _xs_json_dumps_str(s, k);
- s = xs_str_cat(s, ":");
+ _xs_json_dump_str(k, f);
+ fputc(':', f);
if (indent)
- s = xs_str_cat(s, " ");
+ fputc(' ', f);
- s = _xs_json_dumps(s, v, level + 1, indent);
+ _xs_json_dump(v, level + 1, indent, f);
c++;
}
- s = _xs_json_indent(s, level, indent);
- s = xs_str_cat(s, "}");
+ _xs_json_indent(level, indent, f);
+ fputc('}', f);
break;
case XSTYPE_STRING:
- s = _xs_json_dumps_str(s, data);
+ _xs_json_dump_str(data, f);
break;
default:
break;
}
-
- return s;
}
xs_str *xs_json_dumps_pp(const xs_val *data, int indent)
-/* dumps a piece of data as JSON */
+/* dumps data as a JSON string */
{
- xstype t = xs_type(data);
xs_str *s = NULL;
+ size_t sz;
+ FILE *f;
- if (t == XSTYPE_LIST || t == XSTYPE_DICT) {
- s = xs_str_new(NULL);
- s = _xs_json_dumps(s, data, 0, indent);
+ if ((f = open_memstream(&s, &sz)) != NULL) {
+ int r = xs_json_dump_pp(data, indent, f);
+ fclose(f);
+
+ if (!r)
+ s = xs_free(s);
}
return s;
@@ -170,13 +165,14 @@ xs_str *xs_json_dumps_pp(const xs_val *data, int indent)
int xs_json_dump_pp(const xs_val *data, int indent, FILE *f)
/* dumps data into a file as JSON */
{
- xs *j = xs_json_dumps_pp(data, indent);
+ xstype t = xs_type(data);
- if (j == NULL)
- return 0;
+ if (t == XSTYPE_LIST || t == XSTYPE_DICT) {
+ _xs_json_dump(data, 0, indent, f);
+ return 1;
+ }
- fwrite(j, strlen(j), 1, f);
- return 1;
+ return 0;
}