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);
> 

Reply via email to