FILE
json_writer.c
File preview with syntax highlighting.
linux-6.19.14/tools/net/ynl/ynltool/json_writer.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.