2 #include "json-writer.h"
 
   4 void jw_init(struct json_writer *jw)
 
   6         strbuf_init(&jw->json, 0);
 
   7         strbuf_init(&jw->open_stack, 0);
 
  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)
 
  53         for (k = 0; k < jw->open_stack.len; k++)
 
  54                 strbuf_addstr(&jw->json, "  ");
 
  58  * Begin an object or array (either top-level or nested within the currently
 
  59  * open object or array).
 
  61 static void begin(struct json_writer *jw, char ch_open, int pretty)
 
  65         strbuf_addch(&jw->json, ch_open);
 
  67         strbuf_addch(&jw->open_stack, ch_open);
 
  72  * Assert that the top of the open-stack is an object.
 
  74 static void assert_in_object(const struct json_writer *jw, const char *key)
 
  76         if (!jw->open_stack.len)
 
  77                 BUG("json-writer: object: missing jw_object_begin(): '%s'", key);
 
  78         if (jw->open_stack.buf[jw->open_stack.len - 1] != '{')
 
  79                 BUG("json-writer: object: not in object: '%s'", key);
 
  83  * Assert that the top of the open-stack is an array.
 
  85 static void assert_in_array(const struct json_writer *jw)
 
  87         if (!jw->open_stack.len)
 
  88                 BUG("json-writer: array: missing jw_array_begin()");
 
  89         if (jw->open_stack.buf[jw->open_stack.len - 1] != '[')
 
  90                 BUG("json-writer: array: not in array");
 
  94  * Add comma if we have already seen a member at this level.
 
  96 static void maybe_add_comma(struct json_writer *jw)
 
  99                 strbuf_addch(&jw->json, ',');
 
 104 static void fmt_double(struct json_writer *jw, int precision,
 
 108                 strbuf_addf(&jw->json, "%f", value);
 
 110                 struct strbuf fmt = STRBUF_INIT;
 
 111                 strbuf_addf(&fmt, "%%.%df", precision);
 
 112                 strbuf_addf(&jw->json, fmt.buf, value);
 
 113                 strbuf_release(&fmt);
 
 117 static void object_common(struct json_writer *jw, const char *key)
 
 119         assert_in_object(jw, key);
 
 123                 strbuf_addch(&jw->json, '\n');
 
 127         append_quoted_string(&jw->json, key);
 
 128         strbuf_addch(&jw->json, ':');
 
 130                 strbuf_addch(&jw->json, ' ');
 
 133 static void array_common(struct json_writer *jw)
 
 139                 strbuf_addch(&jw->json, '\n');
 
 145  * Assert that the given JSON object or JSON array has been properly
 
 146  * terminated.  (Has closing bracket.)
 
 148 static void assert_is_terminated(const struct json_writer *jw)
 
 150         if (jw->open_stack.len)
 
 151                 BUG("json-writer: object: missing jw_end(): '%s'",
 
 155 void jw_object_begin(struct json_writer *jw, int pretty)
 
 157         begin(jw, '{', pretty);
 
 160 void jw_object_string(struct json_writer *jw, const char *key, const char *value)
 
 162         object_common(jw, key);
 
 163         append_quoted_string(&jw->json, value);
 
 166 void jw_object_intmax(struct json_writer *jw, const char *key, intmax_t value)
 
 168         object_common(jw, key);
 
 169         strbuf_addf(&jw->json, "%"PRIdMAX, value);
 
 172 void jw_object_double(struct json_writer *jw, const char *key, int precision,
 
 175         object_common(jw, key);
 
 176         fmt_double(jw, precision, value);
 
 179 void jw_object_true(struct json_writer *jw, const char *key)
 
 181         object_common(jw, key);
 
 182         strbuf_addstr(&jw->json, "true");
 
 185 void jw_object_false(struct json_writer *jw, const char *key)
 
 187         object_common(jw, key);
 
 188         strbuf_addstr(&jw->json, "false");
 
 191 void jw_object_bool(struct json_writer *jw, const char *key, int value)
 
 194                 jw_object_true(jw, key);
 
 196                 jw_object_false(jw, key);
 
 199 void jw_object_null(struct json_writer *jw, const char *key)
 
 201         object_common(jw, key);
 
 202         strbuf_addstr(&jw->json, "null");
 
 205 static void increase_indent(struct strbuf *sb,
 
 206                             const struct json_writer *jw,
 
 212         for (k = 0; k < jw->json.len; k++) {
 
 213                 char ch = jw->json.buf[k];
 
 214                 strbuf_addch(sb, ch);
 
 216                         strbuf_addchars(sb, ' ', indent);
 
 220 static void kill_indent(struct strbuf *sb,
 
 221                         const struct json_writer *jw)
 
 227         for (k = 0; k < jw->json.len; k++) {
 
 228                 char ch = jw->json.buf[k];
 
 229                 if (eat_it && ch == ' ')
 
 236                 strbuf_addch(sb, ch);
 
 240 static void append_sub_jw(struct json_writer *jw,
 
 241                           const struct json_writer *value)
 
 244          * If both are pretty, increase the indentation of the sub_jw
 
 245          * to better fit under the super.
 
 247          * If the super is pretty, but the sub_jw is compact, leave the
 
 248          * sub_jw compact.  (We don't want to parse and rebuild the sub_jw
 
 249          * for this debug-ish feature.)
 
 251          * If the super is compact, and the sub_jw is pretty, convert
 
 252          * the sub_jw to compact.
 
 254          * If both are compact, keep the sub_jw compact.
 
 256         if (jw->pretty && jw->open_stack.len && value->pretty) {
 
 257                 struct strbuf sb = STRBUF_INIT;
 
 258                 increase_indent(&sb, value, jw->open_stack.len * 2);
 
 259                 strbuf_addbuf(&jw->json, &sb);
 
 263         if (!jw->pretty && value->pretty) {
 
 264                 struct strbuf sb = STRBUF_INIT;
 
 265                 kill_indent(&sb, value);
 
 266                 strbuf_addbuf(&jw->json, &sb);
 
 271         strbuf_addbuf(&jw->json, &value->json);
 
 275  * Append existing (properly terminated) JSON sub-data (object or array)
 
 276  * as-is onto the given JSON data.
 
 278 void jw_object_sub_jw(struct json_writer *jw, const char *key,
 
 279                       const struct json_writer *value)
 
 281         assert_is_terminated(value);
 
 283         object_common(jw, key);
 
 284         append_sub_jw(jw, value);
 
 287 void jw_object_inline_begin_object(struct json_writer *jw, const char *key)
 
 289         object_common(jw, key);
 
 291         jw_object_begin(jw, jw->pretty);
 
 294 void jw_object_inline_begin_array(struct json_writer *jw, const char *key)
 
 296         object_common(jw, key);
 
 298         jw_array_begin(jw, jw->pretty);
 
 301 void jw_array_begin(struct json_writer *jw, int pretty)
 
 303         begin(jw, '[', pretty);
 
 306 void jw_array_string(struct json_writer *jw, const char *value)
 
 309         append_quoted_string(&jw->json, value);
 
 312 void jw_array_intmax(struct json_writer *jw, intmax_t value)
 
 315         strbuf_addf(&jw->json, "%"PRIdMAX, value);
 
 318 void jw_array_double(struct json_writer *jw, int precision, double value)
 
 321         fmt_double(jw, precision, value);
 
 324 void jw_array_true(struct json_writer *jw)
 
 327         strbuf_addstr(&jw->json, "true");
 
 330 void jw_array_false(struct json_writer *jw)
 
 333         strbuf_addstr(&jw->json, "false");
 
 336 void jw_array_bool(struct json_writer *jw, int value)
 
 344 void jw_array_null(struct json_writer *jw)
 
 347         strbuf_addstr(&jw->json, "null");
 
 350 void jw_array_sub_jw(struct json_writer *jw, const struct json_writer *value)
 
 352         assert_is_terminated(value);
 
 355         append_sub_jw(jw, value);
 
 358 void jw_array_argc_argv(struct json_writer *jw, int argc, const char **argv)
 
 362         for (k = 0; k < argc; k++)
 
 363                 jw_array_string(jw, argv[k]);
 
 366 void jw_array_argv(struct json_writer *jw, const char **argv)
 
 369                 jw_array_string(jw, *argv++);
 
 372 void jw_array_inline_begin_object(struct json_writer *jw)
 
 376         jw_object_begin(jw, jw->pretty);
 
 379 void jw_array_inline_begin_array(struct json_writer *jw)
 
 383         jw_array_begin(jw, jw->pretty);
 
 386 int jw_is_terminated(const struct json_writer *jw)
 
 388         return !jw->open_stack.len;
 
 391 void jw_end(struct json_writer *jw)
 
 396         if (!jw->open_stack.len)
 
 397                 BUG("json-writer: too many jw_end(): '%s'", jw->json.buf);
 
 399         len = jw->open_stack.len - 1;
 
 400         ch_open = jw->open_stack.buf[len];
 
 402         strbuf_setlen(&jw->open_stack, len);
 
 406                 strbuf_addch(&jw->json, '\n');
 
 411                 strbuf_addch(&jw->json, '}');
 
 413                 strbuf_addch(&jw->json, ']');