1 #define DISABLE_SIGN_COMPARE_WARNINGS
3 #include "git-compat-util.h"
4 #include "json-writer.h"
6 void jw_init(struct json_writer
*jw
)
8 struct json_writer blank
= JSON_WRITER_INIT
;
9 memcpy(jw
, &blank
, sizeof(*jw
));;
12 void jw_release(struct json_writer
*jw
)
14 strbuf_release(&jw
->json
);
15 strbuf_release(&jw
->open_stack
);
19 * Append JSON-quoted version of the given string to 'out'.
21 static void append_quoted_string(struct strbuf
*out
, const char *in
)
25 strbuf_addch(out
, '"');
26 while ((c
= *in
++) != '\0') {
28 strbuf_addstr(out
, "\\\"");
30 strbuf_addstr(out
, "\\\\");
32 strbuf_addstr(out
, "\\n");
34 strbuf_addstr(out
, "\\r");
36 strbuf_addstr(out
, "\\t");
38 strbuf_addstr(out
, "\\f");
40 strbuf_addstr(out
, "\\b");
42 strbuf_addf(out
, "\\u%04x", c
);
46 strbuf_addch(out
, '"');
49 static void indent_pretty(struct json_writer
*jw
)
51 strbuf_addstrings(&jw
->json
, " ", jw
->open_stack
.len
);
55 * Begin an object or array (either top-level or nested within the currently
56 * open object or array).
58 static void begin(struct json_writer
*jw
, char ch_open
, int pretty
)
62 strbuf_addch(&jw
->json
, ch_open
);
64 strbuf_addch(&jw
->open_stack
, ch_open
);
69 * Assert that the top of the open-stack is an object.
71 static void assert_in_object(const struct json_writer
*jw
, const char *key
)
73 if (!jw
->open_stack
.len
)
74 BUG("json-writer: object: missing jw_object_begin(): '%s'", key
);
75 if (jw
->open_stack
.buf
[jw
->open_stack
.len
- 1] != '{')
76 BUG("json-writer: object: not in object: '%s'", key
);
80 * Assert that the top of the open-stack is an array.
82 static void assert_in_array(const struct json_writer
*jw
)
84 if (!jw
->open_stack
.len
)
85 BUG("json-writer: array: missing jw_array_begin()");
86 if (jw
->open_stack
.buf
[jw
->open_stack
.len
- 1] != '[')
87 BUG("json-writer: array: not in array");
91 * Add comma if we have already seen a member at this level.
93 static void maybe_add_comma(struct json_writer
*jw
)
96 strbuf_addch(&jw
->json
, ',');
101 static void fmt_double(struct json_writer
*jw
, int precision
,
105 strbuf_addf(&jw
->json
, "%f", value
);
107 struct strbuf fmt
= STRBUF_INIT
;
108 strbuf_addf(&fmt
, "%%.%df", precision
);
109 strbuf_addf(&jw
->json
, fmt
.buf
, value
);
110 strbuf_release(&fmt
);
114 static void object_common(struct json_writer
*jw
, const char *key
)
116 assert_in_object(jw
, key
);
120 strbuf_addch(&jw
->json
, '\n');
124 append_quoted_string(&jw
->json
, key
);
125 strbuf_addch(&jw
->json
, ':');
127 strbuf_addch(&jw
->json
, ' ');
130 static void array_common(struct json_writer
*jw
)
136 strbuf_addch(&jw
->json
, '\n');
142 * Assert that the given JSON object or JSON array has been properly
143 * terminated. (Has closing bracket.)
145 static void assert_is_terminated(const struct json_writer
*jw
)
147 if (jw
->open_stack
.len
)
148 BUG("json-writer: object: missing jw_end(): '%s'",
152 void jw_object_begin(struct json_writer
*jw
, int pretty
)
154 begin(jw
, '{', pretty
);
157 void jw_object_string(struct json_writer
*jw
, const char *key
, const char *value
)
159 object_common(jw
, key
);
160 append_quoted_string(&jw
->json
, value
);
163 void jw_object_intmax(struct json_writer
*jw
, const char *key
, intmax_t value
)
165 object_common(jw
, key
);
166 strbuf_addf(&jw
->json
, "%"PRIdMAX
, value
);
169 void jw_object_double(struct json_writer
*jw
, const char *key
, int precision
,
172 object_common(jw
, key
);
173 fmt_double(jw
, precision
, value
);
176 void jw_object_true(struct json_writer
*jw
, const char *key
)
178 object_common(jw
, key
);
179 strbuf_addstr(&jw
->json
, "true");
182 void jw_object_false(struct json_writer
*jw
, const char *key
)
184 object_common(jw
, key
);
185 strbuf_addstr(&jw
->json
, "false");
188 void jw_object_bool(struct json_writer
*jw
, const char *key
, int value
)
191 jw_object_true(jw
, key
);
193 jw_object_false(jw
, key
);
196 void jw_object_null(struct json_writer
*jw
, const char *key
)
198 object_common(jw
, key
);
199 strbuf_addstr(&jw
->json
, "null");
202 static void increase_indent(struct strbuf
*sb
,
203 const struct json_writer
*jw
,
209 for (k
= 0; k
< jw
->json
.len
; k
++) {
210 char ch
= jw
->json
.buf
[k
];
211 strbuf_addch(sb
, ch
);
213 strbuf_addchars(sb
, ' ', indent
);
217 static void kill_indent(struct strbuf
*sb
,
218 const struct json_writer
*jw
)
224 for (k
= 0; k
< jw
->json
.len
; k
++) {
225 char ch
= jw
->json
.buf
[k
];
226 if (eat_it
&& ch
== ' ')
233 strbuf_addch(sb
, ch
);
237 static void append_sub_jw(struct json_writer
*jw
,
238 const struct json_writer
*value
)
241 * If both are pretty, increase the indentation of the sub_jw
242 * to better fit under the super.
244 * If the super is pretty, but the sub_jw is compact, leave the
245 * sub_jw compact. (We don't want to parse and rebuild the sub_jw
246 * for this debug-ish feature.)
248 * If the super is compact, and the sub_jw is pretty, convert
249 * the sub_jw to compact.
251 * If both are compact, keep the sub_jw compact.
253 if (jw
->pretty
&& jw
->open_stack
.len
&& value
->pretty
) {
254 struct strbuf sb
= STRBUF_INIT
;
255 increase_indent(&sb
, value
, jw
->open_stack
.len
* 2);
256 strbuf_addbuf(&jw
->json
, &sb
);
260 if (!jw
->pretty
&& value
->pretty
) {
261 struct strbuf sb
= STRBUF_INIT
;
262 kill_indent(&sb
, value
);
263 strbuf_addbuf(&jw
->json
, &sb
);
268 strbuf_addbuf(&jw
->json
, &value
->json
);
272 * Append existing (properly terminated) JSON sub-data (object or array)
273 * as-is onto the given JSON data.
275 void jw_object_sub_jw(struct json_writer
*jw
, const char *key
,
276 const struct json_writer
*value
)
278 assert_is_terminated(value
);
280 object_common(jw
, key
);
281 append_sub_jw(jw
, value
);
284 void jw_object_inline_begin_object(struct json_writer
*jw
, const char *key
)
286 object_common(jw
, key
);
288 jw_object_begin(jw
, jw
->pretty
);
291 void jw_object_inline_begin_array(struct json_writer
*jw
, const char *key
)
293 object_common(jw
, key
);
295 jw_array_begin(jw
, jw
->pretty
);
298 void jw_array_begin(struct json_writer
*jw
, int pretty
)
300 begin(jw
, '[', pretty
);
303 void jw_array_string(struct json_writer
*jw
, const char *value
)
306 append_quoted_string(&jw
->json
, value
);
309 void jw_array_intmax(struct json_writer
*jw
, intmax_t value
)
312 strbuf_addf(&jw
->json
, "%"PRIdMAX
, value
);
315 void jw_array_double(struct json_writer
*jw
, int precision
, double value
)
318 fmt_double(jw
, precision
, value
);
321 void jw_array_true(struct json_writer
*jw
)
324 strbuf_addstr(&jw
->json
, "true");
327 void jw_array_false(struct json_writer
*jw
)
330 strbuf_addstr(&jw
->json
, "false");
333 void jw_array_bool(struct json_writer
*jw
, int value
)
341 void jw_array_null(struct json_writer
*jw
)
344 strbuf_addstr(&jw
->json
, "null");
347 void jw_array_sub_jw(struct json_writer
*jw
, const struct json_writer
*value
)
349 assert_is_terminated(value
);
352 append_sub_jw(jw
, value
);
355 void jw_array_argc_argv(struct json_writer
*jw
, int argc
, const char **argv
)
359 for (k
= 0; k
< argc
; k
++)
360 jw_array_string(jw
, argv
[k
]);
363 void jw_array_argv(struct json_writer
*jw
, const char **argv
)
366 jw_array_string(jw
, *argv
++);
369 void jw_array_inline_begin_object(struct json_writer
*jw
)
373 jw_object_begin(jw
, jw
->pretty
);
376 void jw_array_inline_begin_array(struct json_writer
*jw
)
380 jw_array_begin(jw
, jw
->pretty
);
383 int jw_is_terminated(const struct json_writer
*jw
)
385 return !jw
->open_stack
.len
;
388 void jw_end(struct json_writer
*jw
)
393 if (!jw
->open_stack
.len
)
394 BUG("json-writer: too many jw_end(): '%s'", jw
->json
.buf
);
396 len
= jw
->open_stack
.len
- 1;
397 ch_open
= jw
->open_stack
.buf
[len
];
399 strbuf_setlen(&jw
->open_stack
, len
);
403 strbuf_addch(&jw
->json
, '\n');
408 strbuf_addch(&jw
->json
, '}');
410 strbuf_addch(&jw
->json
, ']');