On Tue, May 02, 2023 at 02:13:27PM +0200, Claudio Jeker wrote: > Add a json_do_string() a function to print a JSON string. > This function does the needed encoding of control chars and escape chars. > I skipped the optional encoding of the forward slash (/) since this is > only needed if the json output is embedded in HTML/SGML/XML. > People putting JSON into such documents need to pass this through an extra > step. > > This implements json_do_printf() now as a wrapper around json_do_string(). > All users of json_do_printf(name, "%s", value) can be converted to > json_do_string(). I will do this is a subsequent step.
I'm ok with this. Some comments below. > -- > :wq Claudio > > Index: json.c > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/json.c,v > retrieving revision 1.1 > diff -u -p -r1.1 json.c > --- json.c 27 Apr 2023 07:57:25 -0000 1.1 > +++ json.c 1 May 2023 20:07:26 -0000 > @@ -19,6 +19,7 @@ > #include <err.h> > #include <stdarg.h> > #include <stdint.h> > +#include <stdlib.h> I'd move this below stdio.h > #include <stdio.h> > #include <string.h> > > @@ -179,16 +180,64 @@ void > json_do_printf(const char *name, const char *fmt, ...) > { > va_list ap; > + char *str; > > - do_comma_indent(); > + va_start(ap, fmt); > + if (!eb) { > + if (vasprintf(&str, fmt, ap) == -1) > + errx(1, "json printf failed"); > + json_do_string(name, str); > + free(str); > + } > + va_end(ap); > +} > > +void > +json_do_string(const char *name, const char *v) > +{ > + int c; > + > + do_comma_indent(); > do_name(name); > if (!eb) > eb = fprintf(jsonfh, "\"") < 0; > - va_start(ap, fmt); > - if (!eb) > - eb = vfprintf(jsonfh, fmt, ap) < 0; > - va_end(ap); > + while ((c = *v++) != '\0') { Should this include && !eb? > + /* skip escaping '/' since our use case does not require it */ > + switch(c) { > + case '"': > + if (!eb) > + eb = fprintf(jsonfh, "\\\"") < 0; It's fine as it is, but the repetition could be avoided by assigning the escaped string or c to a temporary variable and do the printing after the switch. Your call. > + break; > + case '\\': > + if (!eb) > + eb = fprintf(jsonfh, "\\\\") < 0; > + break; > + case '\b': > + if (!eb) > + eb = fprintf(jsonfh, "\\b") < 0; > + break; > + case '\f': > + if (!eb) > + eb = fprintf(jsonfh, "\\f") < 0; > + break; > + case '\n': > + if (!eb) > + eb = fprintf(jsonfh, "\\n") < 0; > + break; > + case '\r': > + if (!eb) > + eb = fprintf(jsonfh, "\\r") < 0; > + break; > + case '\t': > + if (!eb) > + eb = fprintf(jsonfh, "\\t") < 0; > + break; > + default: > + if (!eb) > + eb = putc(c, jsonfh) == EOF; > + break; > + } > + } > if (!eb) > eb = fprintf(jsonfh, "\"") < 0; > } > Index: json.h > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/json.h,v > retrieving revision 1.1 > diff -u -p -r1.1 json.h > --- json.h 27 Apr 2023 07:57:25 -0000 1.1 > +++ json.h 30 Apr 2023 15:11:36 -0000 > @@ -26,6 +26,7 @@ void json_do_object(const char *); > void json_do_end(void); > void json_do_printf(const char *, const char *, ...) > __attribute__((__format__ (printf, 2, 3))); > +void json_do_string(const char *, const char *); > void json_do_hexdump(const char *, void *, size_t); > void json_do_bool(const char *, int); > void json_do_uint(const char *, unsigned long long); >