2 #include "json-writer.h"
4 void jw_init(struct json_writer
*jw
)
6 struct json_writer blank
= JSON_WRITER_INIT
;
7 memcpy(jw
, &blank
, sizeof(*jw
));;
10 void jw_release(struct json_writer
*jw
)
12 strbuf_release(&jw
->json
);
13 strbuf_release(&jw
->open_stack
);
17 * Append JSON-quoted version of the given string to 'out'.
19 static void append_quoted_string(struct strbuf
*out
, const char *in
)
23 strbuf_addch(out
, '"');
24 while ((c
= *in
++) != '\0') {
26 strbuf_addstr(out
, "\\\"");
28 strbuf_addstr(out
, "\\\\");
30 strbuf_addstr(out
, "\\n");
32 strbuf_addstr(out
, "\\r");
34 strbuf_addstr(out
, "\\t");
36 strbuf_addstr(out
, "\\f");
38 strbuf_addstr(out
, "\\b");
40 strbuf_addf(out
, "\\u%04x", c
);
44 strbuf_addch(out
, '"');
47 static void indent_pretty(struct json_writer
*jw
)
51 for (k
= 0; k
< jw
->open_stack
.len
; k
++)
52 strbuf_addstr(&jw
->json
, " ");
56 * Begin an object or array (either top-level or nested within the currently
57 * open object or array).
59 static void begin(struct json_writer
*jw
, char ch_open
, int pretty
)
63 strbuf_addch(&jw
->json
, ch_open
);
65 strbuf_addch(&jw
->open_stack
, ch_open
);
70 * Assert that the top of the open-stack is an object.
72 static void assert_in_object(const struct json_writer
*jw
, const char *key
)
74 if (!jw
->open_stack
.len
)
75 BUG("json-writer: object: missing jw_object_begin(): '%s'", key
);
76 if (jw
->open_stack
.buf
[jw
->open_stack
.len
- 1] != '{')
77 BUG("json-writer: object: not in object: '%s'", key
);
81 * Assert that the top of the open-stack is an array.
83 static void assert_in_array(const struct json_writer
*jw
)
85 if (!jw
->open_stack
.len
)
86 BUG("json-writer: array: missing jw_array_begin()");
87 if (jw
->open_stack
.buf
[jw
->open_stack
.len
- 1] != '[')
88 BUG("json-writer: array: not in array");
92 * Add comma if we have already seen a member at this level.
94 static void maybe_add_comma(struct json_writer
*jw
)
97 strbuf_addch(&jw
->json
, ',');
102 static void fmt_double(struct json_writer
*jw
, int precision
,
106 strbuf_addf(&jw
->json
, "%f", value
);
108 struct strbuf fmt
= STRBUF_INIT
;
109 strbuf_addf(&fmt
, "%%.%df", precision
);
110 strbuf_addf(&jw
->json
, fmt
.buf
, value
);
111 strbuf_release(&fmt
);
115 static void object_common(struct json_writer
*jw
, const char *key
)
117 assert_in_object(jw
, key
);
121 strbuf_addch(&jw
->json
, '\n');
125 append_quoted_string(&jw
->json
, key
);
126 strbuf_addch(&jw
->json
, ':');
128 strbuf_addch(&jw
->json
, ' ');
131 static void array_common(struct json_writer
*jw
)
137 strbuf_addch(&jw
->json
, '\n');
143 * Assert that the given JSON object or JSON array has been properly
144 * terminated. (Has closing bracket.)
146 static void assert_is_terminated(const struct json_writer
*jw
)
148 if (jw
->open_stack
.len
)
149 BUG("json-writer: object: missing jw_end(): '%s'",
153 void jw_object_begin(struct json_writer
*jw
, int pretty
)
155 begin(jw
, '{', pretty
);
158 void jw_object_string(struct json_writer
*jw
, const char *key
, const char *value
)
160 object_common(jw
, key
);
161 append_quoted_string(&jw
->json
, value
);
164 void jw_object_intmax(struct json_writer
*jw
, const char *key
, intmax_t value
)
166 object_common(jw
, key
);
167 strbuf_addf(&jw
->json
, "%"PRIdMAX
, value
);
170 void jw_object_double(struct json_writer
*jw
, const char *key
, int precision
,
173 object_common(jw
, key
);
174 fmt_double(jw
, precision
, value
);
177 void jw_object_true(struct json_writer
*jw
, const char *key
)
179 object_common(jw
, key
);
180 strbuf_addstr(&jw
->json
, "true");
183 void jw_object_false(struct json_writer
*jw
, const char *key
)
185 object_common(jw
, key
);
186 strbuf_addstr(&jw
->json
, "false");
189 void jw_object_bool(struct json_writer
*jw
, const char *key
, int value
)
192 jw_object_true(jw
, key
);
194 jw_object_false(jw
, key
);
197 void jw_object_null(struct json_writer
*jw
, const char *key
)
199 object_common(jw
, key
);
200 strbuf_addstr(&jw
->json
, "null");
203 static void increase_indent(struct strbuf
*sb
,
204 const struct json_writer
*jw
,
210 for (k
= 0; k
< jw
->json
.len
; k
++) {
211 char ch
= jw
->json
.buf
[k
];
212 strbuf_addch(sb
, ch
);
214 strbuf_addchars(sb
, ' ', indent
);
218 static void kill_indent(struct strbuf
*sb
,
219 const struct json_writer
*jw
)
225 for (k
= 0; k
< jw
->json
.len
; k
++) {
226 char ch
= jw
->json
.buf
[k
];
227 if (eat_it
&& ch
== ' ')
234 strbuf_addch(sb
, ch
);
238 static void append_sub_jw(struct json_writer
*jw
,
239 const struct json_writer
*value
)
242 * If both are pretty, increase the indentation of the sub_jw
243 * to better fit under the super.
245 * If the super is pretty, but the sub_jw is compact, leave the
246 * sub_jw compact. (We don't want to parse and rebuild the sub_jw
247 * for this debug-ish feature.)
249 * If the super is compact, and the sub_jw is pretty, convert
250 * the sub_jw to compact.
252 * If both are compact, keep the sub_jw compact.
254 if (jw
->pretty
&& jw
->open_stack
.len
&& value
->pretty
) {
255 struct strbuf sb
= STRBUF_INIT
;
256 increase_indent(&sb
, value
, jw
->open_stack
.len
* 2);
257 strbuf_addbuf(&jw
->json
, &sb
);
261 if (!jw
->pretty
&& value
->pretty
) {
262 struct strbuf sb
= STRBUF_INIT
;
263 kill_indent(&sb
, value
);
264 strbuf_addbuf(&jw
->json
, &sb
);
269 strbuf_addbuf(&jw
->json
, &value
->json
);
273 * Append existing (properly terminated) JSON sub-data (object or array)
274 * as-is onto the given JSON data.
276 void jw_object_sub_jw(struct json_writer
*jw
, const char *key
,
277 const struct json_writer
*value
)
279 assert_is_terminated(value
);
281 object_common(jw
, key
);
282 append_sub_jw(jw
, value
);
285 void jw_object_inline_begin_object(struct json_writer
*jw
, const char *key
)
287 object_common(jw
, key
);
289 jw_object_begin(jw
, jw
->pretty
);
292 void jw_object_inline_begin_array(struct json_writer
*jw
, const char *key
)
294 object_common(jw
, key
);
296 jw_array_begin(jw
, jw
->pretty
);
299 void jw_array_begin(struct json_writer
*jw
, int pretty
)
301 begin(jw
, '[', pretty
);
304 void jw_array_string(struct json_writer
*jw
, const char *value
)
307 append_quoted_string(&jw
->json
, value
);
310 void jw_array_intmax(struct json_writer
*jw
, intmax_t value
)
313 strbuf_addf(&jw
->json
, "%"PRIdMAX
, value
);
316 void jw_array_double(struct json_writer
*jw
, int precision
, double value
)
319 fmt_double(jw
, precision
, value
);
322 void jw_array_true(struct json_writer
*jw
)
325 strbuf_addstr(&jw
->json
, "true");
328 void jw_array_false(struct json_writer
*jw
)
331 strbuf_addstr(&jw
->json
, "false");
334 void jw_array_bool(struct json_writer
*jw
, int value
)
342 void jw_array_null(struct json_writer
*jw
)
345 strbuf_addstr(&jw
->json
, "null");
348 void jw_array_sub_jw(struct json_writer
*jw
, const struct json_writer
*value
)
350 assert_is_terminated(value
);
353 append_sub_jw(jw
, value
);
356 void jw_array_argc_argv(struct json_writer
*jw
, int argc
, const char **argv
)
360 for (k
= 0; k
< argc
; k
++)
361 jw_array_string(jw
, argv
[k
]);
364 void jw_array_argv(struct json_writer
*jw
, const char **argv
)
367 jw_array_string(jw
, *argv
++);
370 void jw_array_inline_begin_object(struct json_writer
*jw
)
374 jw_object_begin(jw
, jw
->pretty
);
377 void jw_array_inline_begin_array(struct json_writer
*jw
)
381 jw_array_begin(jw
, jw
->pretty
);
384 int jw_is_terminated(const struct json_writer
*jw
)
386 return !jw
->open_stack
.len
;
389 void jw_end(struct json_writer
*jw
)
394 if (!jw
->open_stack
.len
)
395 BUG("json-writer: too many jw_end(): '%s'", jw
->json
.buf
);
397 len
= jw
->open_stack
.len
- 1;
398 ch_open
= jw
->open_stack
.buf
[len
];
400 strbuf_setlen(&jw
->open_stack
, len
);
404 strbuf_addch(&jw
->json
, '\n');
409 strbuf_addch(&jw
->json
, '}');
411 strbuf_addch(&jw
->json
, ']');