7 struct sprinter vtable;
9 /* Top of the state stack, or NULL if the printer is not currently
10 * inside any aggregate types. */
11 struct json_state *state;
13 /* A flag to signify that a separator should be inserted in the
14 * output as soon as possible.
16 bool insert_separator;
20 struct json_state *parent;
21 /* True if nothing has been printed in this aggregate yet.
22 * Suppresses the comma before a value. */
24 /* The character that closes the current aggregate. */
28 /* Helper function to set up the stream to print a value. If this
29 * value follows another value, prints a comma. */
30 static struct sprinter_json *
31 json_begin_value (struct sprinter *sp)
33 struct sprinter_json *spj = (struct sprinter_json *) sp;
36 if (! spj->state->first) {
37 fputc (',', spj->stream);
38 if (spj->insert_separator) {
39 fputc ('\n', spj->stream);
40 spj->insert_separator = false;
42 fputc (' ', spj->stream);
45 spj->state->first = false;
51 /* Helper function to begin an aggregate type. Prints the open
52 * character and pushes a new state frame. */
54 json_begin_aggregate (struct sprinter *sp, char open, char close)
56 struct sprinter_json *spj = json_begin_value (sp);
57 struct json_state *state = talloc (spj, struct json_state);
59 fputc (open, spj->stream);
60 state->parent = spj->state;
67 json_begin_map (struct sprinter *sp)
69 json_begin_aggregate (sp, '{', '}');
73 json_begin_list (struct sprinter *sp)
75 json_begin_aggregate (sp, '[', ']');
79 json_end (struct sprinter *sp)
81 struct sprinter_json *spj = (struct sprinter_json *) sp;
82 struct json_state *state = spj->state;
84 fputc (spj->state->close, spj->stream);
85 spj->state = state->parent;
87 if (spj->state == NULL)
88 fputc ('\n', spj->stream);
91 /* This implementation supports embedded NULs as allowed by the JSON
92 * specification and Unicode. Support for *parsing* embedded NULs
93 * varies, but is generally not a problem outside of C-based parsers
94 * (Python's json module and Emacs' json.el take embedded NULs in
97 json_string_len (struct sprinter *sp, const char *val, size_t len)
99 static const char *const escapes[] = {
100 ['\"'] = "\\\"", ['\\'] = "\\\\", ['\b'] = "\\b",
101 ['\f'] = "\\f", ['\n'] = "\\n", ['\t'] = "\\t"
103 struct sprinter_json *spj = json_begin_value (sp);
105 fputc ('"', spj->stream);
106 for (; len; ++val, --len) {
107 unsigned char ch = *val;
108 if (ch < ARRAY_SIZE (escapes) && escapes[ch])
109 fputs (escapes[ch], spj->stream);
111 fputc (ch, spj->stream);
113 fprintf (spj->stream, "\\u%04x", ch);
115 fputc ('"', spj->stream);
119 json_string (struct sprinter *sp, const char *val)
123 json_string_len (sp, val, strlen (val));
127 json_integer (struct sprinter *sp, int val)
129 struct sprinter_json *spj = json_begin_value (sp);
131 fprintf (spj->stream, "%d", val);
135 json_boolean (struct sprinter *sp, bool val)
137 struct sprinter_json *spj = json_begin_value (sp);
139 fputs (val ? "true" : "false", spj->stream);
143 json_null (struct sprinter *sp)
145 struct sprinter_json *spj = json_begin_value (sp);
147 fputs ("null", spj->stream);
151 json_map_key (struct sprinter *sp, const char *key)
153 struct sprinter_json *spj = (struct sprinter_json *) sp;
155 json_string (sp, key);
156 fputs (": ", spj->stream);
157 spj->state->first = true;
161 json_set_prefix (unused (struct sprinter *sp), unused (const char *name))
166 json_separator (struct sprinter *sp)
168 struct sprinter_json *spj = (struct sprinter_json *) sp;
170 spj->insert_separator = true;
174 sprinter_json_create (const void *ctx, FILE *stream)
176 static const struct sprinter_json template = {
178 .begin_map = json_begin_map,
179 .begin_list = json_begin_list,
181 .string = json_string,
182 .string_len = json_string_len,
183 .integer = json_integer,
184 .boolean = json_boolean,
186 .map_key = json_map_key,
187 .separator = json_separator,
188 .set_prefix = json_set_prefix,
189 .is_text_printer = false,
192 struct sprinter_json *res;
194 res = talloc (ctx, struct sprinter_json);
199 res->stream = stream;