root/tools/bpf/bpftool/json_writer.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. jsonw_indent
  2. jsonw_eol
  3. jsonw_eor
  4. jsonw_puts
  5. jsonw_new
  6. jsonw_destroy
  7. jsonw_pretty
  8. jsonw_begin
  9. jsonw_end
  10. jsonw_name
  11. jsonw_vprintf_enquote
  12. jsonw_printf
  13. jsonw_start_object
  14. jsonw_end_object
  15. jsonw_start_array
  16. jsonw_end_array
  17. jsonw_string
  18. jsonw_bool
  19. jsonw_null
  20. jsonw_float_fmt
  21. jsonw_float
  22. jsonw_hu
  23. jsonw_uint
  24. jsonw_lluint
  25. jsonw_int
  26. jsonw_string_field
  27. jsonw_bool_field
  28. jsonw_float_field
  29. jsonw_float_field_fmt
  30. jsonw_uint_field
  31. jsonw_hu_field
  32. jsonw_lluint_field
  33. jsonw_int_field
  34. jsonw_null_field
  35. main

   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 
  21 struct json_writer {
  22         FILE            *out;   /* output file */
  23         unsigned        depth;  /* nesting */
  24         bool            pretty; /* optional whitepace */
  25         char            sep;    /* either nul or comma */
  26 };
  27 
  28 /* indentation for pretty print */
  29 static void jsonw_indent(json_writer_t *self)
  30 {
  31         unsigned i;
  32         for (i = 0; i < self->depth; ++i)
  33                 fputs("    ", self->out);
  34 }
  35 
  36 /* end current line and indent if pretty printing */
  37 static void jsonw_eol(json_writer_t *self)
  38 {
  39         if (!self->pretty)
  40                 return;
  41 
  42         putc('\n', self->out);
  43         jsonw_indent(self);
  44 }
  45 
  46 /* If current object is not empty print a comma */
  47 static void jsonw_eor(json_writer_t *self)
  48 {
  49         if (self->sep != '\0')
  50                 putc(self->sep, self->out);
  51         self->sep = ',';
  52 }
  53 
  54 
  55 /* Output JSON encoded string */
  56 /* Handles C escapes, does not do Unicode */
  57 static void jsonw_puts(json_writer_t *self, const char *str)
  58 {
  59         putc('"', self->out);
  60         for (; *str; ++str)
  61                 switch (*str) {
  62                 case '\t':
  63                         fputs("\\t", self->out);
  64                         break;
  65                 case '\n':
  66                         fputs("\\n", self->out);
  67                         break;
  68                 case '\r':
  69                         fputs("\\r", self->out);
  70                         break;
  71                 case '\f':
  72                         fputs("\\f", self->out);
  73                         break;
  74                 case '\b':
  75                         fputs("\\b", self->out);
  76                         break;
  77                 case '\\':
  78                         fputs("\\n", self->out);
  79                         break;
  80                 case '"':
  81                         fputs("\\\"", self->out);
  82                         break;
  83                 case '\'':
  84                         fputs("\\\'", self->out);
  85                         break;
  86                 default:
  87                         putc(*str, self->out);
  88                 }
  89         putc('"', self->out);
  90 }
  91 
  92 /* Create a new JSON stream */
  93 json_writer_t *jsonw_new(FILE *f)
  94 {
  95         json_writer_t *self = malloc(sizeof(*self));
  96         if (self) {
  97                 self->out = f;
  98                 self->depth = 0;
  99                 self->pretty = false;
 100                 self->sep = '\0';
 101         }
 102         return self;
 103 }
 104 
 105 /* End output to JSON stream */
 106 void jsonw_destroy(json_writer_t **self_p)
 107 {
 108         json_writer_t *self = *self_p;
 109 
 110         assert(self->depth == 0);
 111         fputs("\n", self->out);
 112         fflush(self->out);
 113         free(self);
 114         *self_p = NULL;
 115 }
 116 
 117 void jsonw_pretty(json_writer_t *self, bool on)
 118 {
 119         self->pretty = on;
 120 }
 121 
 122 /* Basic blocks */
 123 static void jsonw_begin(json_writer_t *self, int c)
 124 {
 125         jsonw_eor(self);
 126         putc(c, self->out);
 127         ++self->depth;
 128         self->sep = '\0';
 129 }
 130 
 131 static void jsonw_end(json_writer_t *self, int c)
 132 {
 133         assert(self->depth > 0);
 134 
 135         --self->depth;
 136         if (self->sep != '\0')
 137                 jsonw_eol(self);
 138         putc(c, self->out);
 139         self->sep = ',';
 140 }
 141 
 142 
 143 /* Add a JSON property name */
 144 void jsonw_name(json_writer_t *self, const char *name)
 145 {
 146         jsonw_eor(self);
 147         jsonw_eol(self);
 148         self->sep = '\0';
 149         jsonw_puts(self, name);
 150         putc(':', self->out);
 151         if (self->pretty)
 152                 putc(' ', self->out);
 153 }
 154 
 155 void jsonw_vprintf_enquote(json_writer_t *self, const char *fmt, va_list ap)
 156 {
 157         jsonw_eor(self);
 158         putc('"', self->out);
 159         vfprintf(self->out, fmt, ap);
 160         putc('"', self->out);
 161 }
 162 
 163 void jsonw_printf(json_writer_t *self, const char *fmt, ...)
 164 {
 165         va_list ap;
 166 
 167         va_start(ap, fmt);
 168         jsonw_eor(self);
 169         vfprintf(self->out, fmt, ap);
 170         va_end(ap);
 171 }
 172 
 173 /* Collections */
 174 void jsonw_start_object(json_writer_t *self)
 175 {
 176         jsonw_begin(self, '{');
 177 }
 178 
 179 void jsonw_end_object(json_writer_t *self)
 180 {
 181         jsonw_end(self, '}');
 182 }
 183 
 184 void jsonw_start_array(json_writer_t *self)
 185 {
 186         jsonw_begin(self, '[');
 187 }
 188 
 189 void jsonw_end_array(json_writer_t *self)
 190 {
 191         jsonw_end(self, ']');
 192 }
 193 
 194 /* JSON value types */
 195 void jsonw_string(json_writer_t *self, const char *value)
 196 {
 197         jsonw_eor(self);
 198         jsonw_puts(self, value);
 199 }
 200 
 201 void jsonw_bool(json_writer_t *self, bool val)
 202 {
 203         jsonw_printf(self, "%s", val ? "true" : "false");
 204 }
 205 
 206 void jsonw_null(json_writer_t *self)
 207 {
 208         jsonw_printf(self, "null");
 209 }
 210 
 211 void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num)
 212 {
 213         jsonw_printf(self, fmt, num);
 214 }
 215 
 216 #ifdef notused
 217 void jsonw_float(json_writer_t *self, double num)
 218 {
 219         jsonw_printf(self, "%g", num);
 220 }
 221 #endif
 222 
 223 void jsonw_hu(json_writer_t *self, unsigned short num)
 224 {
 225         jsonw_printf(self, "%hu", num);
 226 }
 227 
 228 void jsonw_uint(json_writer_t *self, uint64_t num)
 229 {
 230         jsonw_printf(self, "%"PRIu64, num);
 231 }
 232 
 233 void jsonw_lluint(json_writer_t *self, unsigned long long int num)
 234 {
 235         jsonw_printf(self, "%llu", num);
 236 }
 237 
 238 void jsonw_int(json_writer_t *self, int64_t num)
 239 {
 240         jsonw_printf(self, "%"PRId64, num);
 241 }
 242 
 243 /* Basic name/value objects */
 244 void jsonw_string_field(json_writer_t *self, const char *prop, const char *val)
 245 {
 246         jsonw_name(self, prop);
 247         jsonw_string(self, val);
 248 }
 249 
 250 void jsonw_bool_field(json_writer_t *self, const char *prop, bool val)
 251 {
 252         jsonw_name(self, prop);
 253         jsonw_bool(self, val);
 254 }
 255 
 256 #ifdef notused
 257 void jsonw_float_field(json_writer_t *self, const char *prop, double val)
 258 {
 259         jsonw_name(self, prop);
 260         jsonw_float(self, val);
 261 }
 262 #endif
 263 
 264 void jsonw_float_field_fmt(json_writer_t *self,
 265                            const char *prop,
 266                            const char *fmt,
 267                            double val)
 268 {
 269         jsonw_name(self, prop);
 270         jsonw_float_fmt(self, fmt, val);
 271 }
 272 
 273 void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num)
 274 {
 275         jsonw_name(self, prop);
 276         jsonw_uint(self, num);
 277 }
 278 
 279 void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num)
 280 {
 281         jsonw_name(self, prop);
 282         jsonw_hu(self, num);
 283 }
 284 
 285 void jsonw_lluint_field(json_writer_t *self,
 286                         const char *prop,
 287                         unsigned long long int num)
 288 {
 289         jsonw_name(self, prop);
 290         jsonw_lluint(self, num);
 291 }
 292 
 293 void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num)
 294 {
 295         jsonw_name(self, prop);
 296         jsonw_int(self, num);
 297 }
 298 
 299 void jsonw_null_field(json_writer_t *self, const char *prop)
 300 {
 301         jsonw_name(self, prop);
 302         jsonw_null(self);
 303 }
 304 
 305 #ifdef TEST
 306 int main(int argc, char **argv)
 307 {
 308         json_writer_t *wr = jsonw_new(stdout);
 309 
 310         jsonw_start_object(wr);
 311         jsonw_pretty(wr, true);
 312         jsonw_name(wr, "Vyatta");
 313         jsonw_start_object(wr);
 314         jsonw_string_field(wr, "url", "http://vyatta.com");
 315         jsonw_uint_field(wr, "downloads", 2000000ul);
 316         jsonw_float_field(wr, "stock", 8.16);
 317 
 318         jsonw_name(wr, "ARGV");
 319         jsonw_start_array(wr);
 320         while (--argc)
 321                 jsonw_string(wr, *++argv);
 322         jsonw_end_array(wr);
 323 
 324         jsonw_name(wr, "empty");
 325         jsonw_start_array(wr);
 326         jsonw_end_array(wr);
 327 
 328         jsonw_name(wr, "NIL");
 329         jsonw_start_object(wr);
 330         jsonw_end_object(wr);
 331 
 332         jsonw_null_field(wr, "my_null");
 333 
 334         jsonw_name(wr, "special chars");
 335         jsonw_start_array(wr);
 336         jsonw_string_field(wr, "slash", "/");
 337         jsonw_string_field(wr, "newline", "\n");
 338         jsonw_string_field(wr, "tab", "\t");
 339         jsonw_string_field(wr, "ff", "\f");
 340         jsonw_string_field(wr, "quote", "\"");
 341         jsonw_string_field(wr, "tick", "\'");
 342         jsonw_string_field(wr, "backslash", "\\");
 343         jsonw_end_array(wr);
 344 
 345         jsonw_end_object(wr);
 346 
 347         jsonw_end_object(wr);
 348         jsonw_destroy(&wr);
 349         return 0;
 350 }
 351 
 352 #endif

/* [<][>][^][v][top][bottom][index][help] */