File Index
Files and directories
Sign in
FILE

json_writer.c

File preview with syntax highlighting.

linux-6.19.14/tools/net/ynl/ynltool/json_writer.c C
  1// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
  2/*
  3 * Simple streaming JSON writer
  4 *
  5 * This takes care of the annoying bits of JSON syntax like the commas
  6 * after elements
  7 *
  8 * Authors:	Stephen Hemminger <stephen@networkplumber.org>
  9 */
 10
 11#include <stdio.h>
 12#include <stdbool.h>
 13#include <stdarg.h>
 14#include <assert.h>
 15#include <malloc.h>
 16#include <inttypes.h>
 17#include <stdint.h>
 18
 19#include "json_writer.h"
 20
 21struct json_writer {
 22	FILE		*out;
 23	unsigned	depth;
 24	bool		pretty;
 25	char		sep;
 26};
 27
 28static void jsonw_indent(json_writer_t *self)
 29{
 30	unsigned i;
 31	for (i = 0; i < self->depth; ++i)
 32		fputs("    ", self->out);
 33}
 34
 35static void jsonw_eol(json_writer_t *self)
 36{
 37	if (!self->pretty)
 38		return;
 39
 40	putc('\n', self->out);
 41	jsonw_indent(self);
 42}
 43
 44static void jsonw_eor(json_writer_t *self)
 45{
 46	if (self->sep != '\0')
 47		putc(self->sep, self->out);
 48	self->sep = ',';
 49}
 50
 51static void jsonw_puts(json_writer_t *self, const char *str)
 52{
 53	putc('"', self->out);
 54	for (; *str; ++str)
 55		switch (*str) {
 56		case '\t':
 57			fputs("\\t", self->out);
 58			break;
 59		case '\n':
 60			fputs("\\n", self->out);
 61			break;
 62		case '\r':
 63			fputs("\\r", self->out);
 64			break;
 65		case '\f':
 66			fputs("\\f", self->out);
 67			break;
 68		case '\b':
 69			fputs("\\b", self->out);
 70			break;
 71		case '\\':
 72			fputs("\\\\", self->out);
 73			break;
 74		case '"':
 75			fputs("\\\"", self->out);
 76			break;
 77		default:
 78			putc(*str, self->out);
 79		}
 80	putc('"', self->out);
 81}
 82
 83json_writer_t *jsonw_new(FILE *f)
 84{
 85	json_writer_t *self = malloc(sizeof(*self));
 86	if (self) {
 87		self->out = f;
 88		self->depth = 0;
 89		self->pretty = false;
 90		self->sep = '\0';
 91	}
 92	return self;
 93}
 94
 95void jsonw_destroy(json_writer_t **self_p)
 96{
 97	json_writer_t *self = *self_p;
 98
 99	assert(self->depth == 0);
100	fputs("\n", self->out);
101	fflush(self->out);
102	free(self);
103	*self_p = NULL;
104}
105
106void jsonw_pretty(json_writer_t *self, bool on)
107{
108	self->pretty = on;
109}
110
111void jsonw_reset(json_writer_t *self)
112{
113	assert(self->depth == 0);
114	self->sep = '\0';
115}
116
117static void jsonw_begin(json_writer_t *self, int c)
118{
119	jsonw_eor(self);
120	putc(c, self->out);
121	++self->depth;
122	self->sep = '\0';
123}
124
125static void jsonw_end(json_writer_t *self, int c)
126{
127	assert(self->depth > 0);
128
129	--self->depth;
130	if (self->sep != '\0')
131		jsonw_eol(self);
132	putc(c, self->out);
133	self->sep = ',';
134}
135
136void jsonw_name(json_writer_t *self, const char *name)
137{
138	jsonw_eor(self);
139	jsonw_eol(self);
140	self->sep = '\0';
141	jsonw_puts(self, name);
142	putc(':', self->out);
143	if (self->pretty)
144		putc(' ', self->out);
145}
146
147void jsonw_vprintf_enquote(json_writer_t *self, const char *fmt, va_list ap)
148{
149	jsonw_eor(self);
150	putc('"', self->out);
151	vfprintf(self->out, fmt, ap);
152	putc('"', self->out);
153}
154
155void jsonw_printf(json_writer_t *self, const char *fmt, ...)
156{
157	va_list ap;
158
159	va_start(ap, fmt);
160	jsonw_eor(self);
161	vfprintf(self->out, fmt, ap);
162	va_end(ap);
163}
164
165void jsonw_start_object(json_writer_t *self)
166{
167	jsonw_begin(self, '{');
168}
169
170void jsonw_end_object(json_writer_t *self)
171{
172	jsonw_end(self, '}');
173}
174
175void jsonw_start_array(json_writer_t *self)
176{
177	jsonw_begin(self, '[');
178}
179
180void jsonw_end_array(json_writer_t *self)
181{
182	jsonw_end(self, ']');
183}
184
185void jsonw_string(json_writer_t *self, const char *value)
186{
187	jsonw_eor(self);
188	jsonw_puts(self, value);
189}
190
191void jsonw_bool(json_writer_t *self, bool val)
192{
193	jsonw_printf(self, "%s", val ? "true" : "false");
194}
195
196void jsonw_null(json_writer_t *self)
197{
198	jsonw_printf(self, "null");
199}
200
201void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num)
202{
203	jsonw_printf(self, fmt, num);
204}
205
206void jsonw_float(json_writer_t *self, double num)
207{
208	jsonw_printf(self, "%g", num);
209}
210
211void jsonw_hu(json_writer_t *self, unsigned short num)
212{
213	jsonw_printf(self, "%hu", num);
214}
215
216void jsonw_uint(json_writer_t *self, uint64_t num)
217{
218	jsonw_printf(self, "%"PRIu64, num);
219}
220
221void jsonw_lluint(json_writer_t *self, unsigned long long int num)
222{
223	jsonw_printf(self, "%llu", num);
224}
225
226void jsonw_int(json_writer_t *self, int64_t num)
227{
228	jsonw_printf(self, "%"PRId64, num);
229}
230
231void jsonw_string_field(json_writer_t *self, const char *prop, const char *val)
232{
233	jsonw_name(self, prop);
234	jsonw_string(self, val);
235}
236
237void jsonw_bool_field(json_writer_t *self, const char *prop, bool val)
238{
239	jsonw_name(self, prop);
240	jsonw_bool(self, val);
241}
242
243void jsonw_float_field(json_writer_t *self, const char *prop, double val)
244{
245	jsonw_name(self, prop);
246	jsonw_float(self, val);
247}
248
249void jsonw_float_field_fmt(json_writer_t *self,
250			   const char *prop,
251			   const char *fmt,
252			   double val)
253{
254	jsonw_name(self, prop);
255	jsonw_float_fmt(self, fmt, val);
256}
257
258void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num)
259{
260	jsonw_name(self, prop);
261	jsonw_uint(self, num);
262}
263
264void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num)
265{
266	jsonw_name(self, prop);
267	jsonw_hu(self, num);
268}
269
270void jsonw_lluint_field(json_writer_t *self,
271			const char *prop,
272			unsigned long long int num)
273{
274	jsonw_name(self, prop);
275	jsonw_lluint(self, num);
276}
277
278void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num)
279{
280	jsonw_name(self, prop);
281	jsonw_int(self, num);
282}
283
284void jsonw_null_field(json_writer_t *self, const char *prop)
285{
286	jsonw_name(self, prop);
287	jsonw_null(self);
288}
~/ Read-only file preview.