aboutsummaryrefslogtreecommitdiffstats
path: root/tools/bpf/bpftool/json_writer.c
diff options
context:
space:
mode:
authorQuentin Monnet <quentin.monnet@netronome.com>2017-10-23 12:24:05 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-23 20:25:08 -0400
commitb66e907cfee240a09a4b5aabf950a0d4c8da8d32 (patch)
tree8e2035f10fa6353f08b85b13a87db87305b405e1 /tools/bpf/bpftool/json_writer.c
parent4c4fde210ce665d400e5d859a62e792dcb1bbf37 (diff)
tools: bpftool: copy JSON writer from iproute2 repository
In prevision of following commits, supposed to add JSON output to the tool, two files are copied from the iproute2 repository (taken at commit 268a9eee985f): lib/json_writer.c and include/json_writer.h. Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools/bpf/bpftool/json_writer.c')
-rw-r--r--tools/bpf/bpftool/json_writer.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/tools/bpf/bpftool/json_writer.c b/tools/bpf/bpftool/json_writer.c
new file mode 100644
index 000000000000..6b77d288cce2
--- /dev/null
+++ b/tools/bpf/bpftool/json_writer.c
@@ -0,0 +1,348 @@
1/*
2 * Simple streaming JSON writer
3 *
4 * This takes care of the annoying bits of JSON syntax like the commas
5 * after elements
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 * Authors: Stephen Hemminger <stephen@networkplumber.org>
13 */
14
15#include <stdio.h>
16#include <stdbool.h>
17#include <stdarg.h>
18#include <assert.h>
19#include <malloc.h>
20#include <inttypes.h>
21#include <stdint.h>
22
23#include "json_writer.h"
24
25struct json_writer {
26 FILE *out; /* output file */
27 unsigned depth; /* nesting */
28 bool pretty; /* optional whitepace */
29 char sep; /* either nul or comma */
30};
31
32/* indentation for pretty print */
33static void jsonw_indent(json_writer_t *self)
34{
35 unsigned i;
36 for (i = 0; i < self->depth; ++i)
37 fputs(" ", self->out);
38}
39
40/* end current line and indent if pretty printing */
41static void jsonw_eol(json_writer_t *self)
42{
43 if (!self->pretty)
44 return;
45
46 putc('\n', self->out);
47 jsonw_indent(self);
48}
49
50/* If current object is not empty print a comma */
51static void jsonw_eor(json_writer_t *self)
52{
53 if (self->sep != '\0')
54 putc(self->sep, self->out);
55 self->sep = ',';
56}
57
58
59/* Output JSON encoded string */
60/* Handles C escapes, does not do Unicode */
61static void jsonw_puts(json_writer_t *self, const char *str)
62{
63 putc('"', self->out);
64 for (; *str; ++str)
65 switch (*str) {
66 case '\t':
67 fputs("\\t", self->out);
68 break;
69 case '\n':
70 fputs("\\n", self->out);
71 break;
72 case '\r':
73 fputs("\\r", self->out);
74 break;
75 case '\f':
76 fputs("\\f", self->out);
77 break;
78 case '\b':
79 fputs("\\b", self->out);
80 break;
81 case '\\':
82 fputs("\\n", self->out);
83 break;
84 case '"':
85 fputs("\\\"", self->out);
86 break;
87 case '\'':
88 fputs("\\\'", self->out);
89 break;
90 default:
91 putc(*str, self->out);
92 }
93 putc('"', self->out);
94}
95
96/* Create a new JSON stream */
97json_writer_t *jsonw_new(FILE *f)
98{
99 json_writer_t *self = malloc(sizeof(*self));
100 if (self) {
101 self->out = f;
102 self->depth = 0;
103 self->pretty = false;
104 self->sep = '\0';
105 }
106 return self;
107}
108
109/* End output to JSON stream */
110void jsonw_destroy(json_writer_t **self_p)
111{
112 json_writer_t *self = *self_p;
113
114 assert(self->depth == 0);
115 fputs("\n", self->out);
116 fflush(self->out);
117 free(self);
118 *self_p = NULL;
119}
120
121void jsonw_pretty(json_writer_t *self, bool on)
122{
123 self->pretty = on;
124}
125
126/* Basic blocks */
127static void jsonw_begin(json_writer_t *self, int c)
128{
129 jsonw_eor(self);
130 putc(c, self->out);
131 ++self->depth;
132 self->sep = '\0';
133}
134
135static void jsonw_end(json_writer_t *self, int c)
136{
137 assert(self->depth > 0);
138
139 --self->depth;
140 if (self->sep != '\0')
141 jsonw_eol(self);
142 putc(c, self->out);
143 self->sep = ',';
144}
145
146
147/* Add a JSON property name */
148void jsonw_name(json_writer_t *self, const char *name)
149{
150 jsonw_eor(self);
151 jsonw_eol(self);
152 self->sep = '\0';
153 jsonw_puts(self, name);
154 putc(':', self->out);
155 if (self->pretty)
156 putc(' ', self->out);
157}
158
159void jsonw_printf(json_writer_t *self, const char *fmt, ...)
160{
161 va_list ap;
162
163 va_start(ap, fmt);
164 jsonw_eor(self);
165 vfprintf(self->out, fmt, ap);
166 va_end(ap);
167}
168
169/* Collections */
170void jsonw_start_object(json_writer_t *self)
171{
172 jsonw_begin(self, '{');
173}
174
175void jsonw_end_object(json_writer_t *self)
176{
177 jsonw_end(self, '}');
178}
179
180void jsonw_start_array(json_writer_t *self)
181{
182 jsonw_begin(self, '[');
183}
184
185void jsonw_end_array(json_writer_t *self)
186{
187 jsonw_end(self, ']');
188}
189
190/* JSON value types */
191void jsonw_string(json_writer_t *self, const char *value)
192{
193 jsonw_eor(self);
194 jsonw_puts(self, value);
195}
196
197void jsonw_bool(json_writer_t *self, bool val)
198{
199 jsonw_printf(self, "%s", val ? "true" : "false");
200}
201
202void jsonw_null(json_writer_t *self)
203{
204 jsonw_printf(self, "null");
205}
206
207void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num)
208{
209 jsonw_printf(self, fmt, num);
210}
211
212#ifdef notused
213void jsonw_float(json_writer_t *self, double num)
214{
215 jsonw_printf(self, "%g", num);
216}
217#endif
218
219void jsonw_hu(json_writer_t *self, unsigned short num)
220{
221 jsonw_printf(self, "%hu", num);
222}
223
224void jsonw_uint(json_writer_t *self, uint64_t num)
225{
226 jsonw_printf(self, "%"PRIu64, num);
227}
228
229void jsonw_lluint(json_writer_t *self, unsigned long long int num)
230{
231 jsonw_printf(self, "%llu", num);
232}
233
234void jsonw_int(json_writer_t *self, int64_t num)
235{
236 jsonw_printf(self, "%"PRId64, num);
237}
238
239/* Basic name/value objects */
240void jsonw_string_field(json_writer_t *self, const char *prop, const char *val)
241{
242 jsonw_name(self, prop);
243 jsonw_string(self, val);
244}
245
246void jsonw_bool_field(json_writer_t *self, const char *prop, bool val)
247{
248 jsonw_name(self, prop);
249 jsonw_bool(self, val);
250}
251
252#ifdef notused
253void jsonw_float_field(json_writer_t *self, const char *prop, double val)
254{
255 jsonw_name(self, prop);
256 jsonw_float(self, val);
257}
258#endif
259
260void jsonw_float_field_fmt(json_writer_t *self,
261 const char *prop,
262 const char *fmt,
263 double val)
264{
265 jsonw_name(self, prop);
266 jsonw_float_fmt(self, fmt, val);
267}
268
269void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num)
270{
271 jsonw_name(self, prop);
272 jsonw_uint(self, num);
273}
274
275void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num)
276{
277 jsonw_name(self, prop);
278 jsonw_hu(self, num);
279}
280
281void jsonw_lluint_field(json_writer_t *self,
282 const char *prop,
283 unsigned long long int num)
284{
285 jsonw_name(self, prop);
286 jsonw_lluint(self, num);
287}
288
289void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num)
290{
291 jsonw_name(self, prop);
292 jsonw_int(self, num);
293}
294
295void jsonw_null_field(json_writer_t *self, const char *prop)
296{
297 jsonw_name(self, prop);
298 jsonw_null(self);
299}
300
301#ifdef TEST
302int main(int argc, char **argv)
303{
304 json_writer_t *wr = jsonw_new(stdout);
305
306 jsonw_start_object(wr);
307 jsonw_pretty(wr, true);
308 jsonw_name(wr, "Vyatta");
309 jsonw_start_object(wr);
310 jsonw_string_field(wr, "url", "http://vyatta.com");
311 jsonw_uint_field(wr, "downloads", 2000000ul);
312 jsonw_float_field(wr, "stock", 8.16);
313
314 jsonw_name(wr, "ARGV");
315 jsonw_start_array(wr);
316 while (--argc)
317 jsonw_string(wr, *++argv);
318 jsonw_end_array(wr);
319
320 jsonw_name(wr, "empty");
321 jsonw_start_array(wr);
322 jsonw_end_array(wr);
323
324 jsonw_name(wr, "NIL");
325 jsonw_start_object(wr);
326 jsonw_end_object(wr);
327
328 jsonw_null_field(wr, "my_null");
329
330 jsonw_name(wr, "special chars");
331 jsonw_start_array(wr);
332 jsonw_string_field(wr, "slash", "/");
333 jsonw_string_field(wr, "newline", "\n");
334 jsonw_string_field(wr, "tab", "\t");
335 jsonw_string_field(wr, "ff", "\f");
336 jsonw_string_field(wr, "quote", "\"");
337 jsonw_string_field(wr, "tick", "\'");
338 jsonw_string_field(wr, "backslash", "\\");
339 jsonw_end_array(wr);
340
341 jsonw_end_object(wr);
342
343 jsonw_end_object(wr);
344 jsonw_destroy(&wr);
345 return 0;
346}
347
348#endif