2 * UCW JSON Library -- Formatter
4 * (c) 2015 Martin Mares <mj@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
11 #include <ucw/fastbuf.h>
13 #include <ucw/ff-unicode.h>
14 #include <ucw/unicode.h>
15 #include <ucw-json/json.h>
21 void json_set_output(struct json_context *js, struct fastbuf *fb)
26 static void write_string(struct json_context *js, const char *p)
28 struct fastbuf *fb = js->out_fb;
34 p = utf8_32_get(p, &u);
37 if (u == '"' || u == '\\')
44 // We avoid "\f" nor "\b" and use "\uXXXX" instead
47 case 0x09: bputs(fb, "\\t"); break;
48 case 0x0a: bputs(fb, "\\n"); break;
49 case 0x0d: bputs(fb, "\\r"); break;
51 bprintf(fb, "\\u%04x", u);
54 else if (u >= 0x007f && (js->format_options & JSON_FORMAT_ESCAPE_NONASCII))
57 bprintf(fb, "\\u%04x", u);
58 else if (u < 0x110000)
59 bprintf(fb, "\\u%04x\\u%04x", 0xd800 + ((u - 0x10000) >> 10), 0xdc00 + (u & 0x3ff));
69 static void write_number(struct fastbuf *fb, double val)
71 ASSERT(isfinite(val));
72 bprintf(fb, "%.*g", DBL_DIG, val);
75 static bool want_indent_p(struct json_context *js)
77 return (js->format_options & JSON_FORMAT_INDENT);
80 static void write_space(struct json_context *js)
82 struct fastbuf *fb = js->out_fb;
84 if (want_indent_p(js))
87 for (uint i=0; i < js->out_indent; i++)
94 void json_write_value(struct json_context *js, struct json_node *n)
96 struct fastbuf *fb = js->out_fb;
104 bputs(fb, (n->boolean ? "true" : "false"));
107 write_number(fb, n->number);
110 write_string(js, n->string);
114 if (!GARY_SIZE(n->elements))
120 for (size_t i=0; i < GARY_SIZE(n->elements); i++)
125 json_write_value(js, n->elements[i]);
135 if (!GARY_SIZE(n->pairs))
139 for (size_t i=0; i < GARY_SIZE(n->pairs); i++)
144 struct json_pair *p = &n->pairs[i];
145 write_string(js, p->key);
147 json_write_value(js, p->value);
159 void json_write(struct json_context *js, struct fastbuf *fb, struct json_node *n)
161 json_set_output(js, fb);
162 json_write_value(js, n);