-/* $OpenBSD: json.c,v 1.1 2023/04/27 07:57:25 claudio Exp $ */
+/* $OpenBSD: json.c,v 1.2 2023/05/03 07:56:05 claudio Exp $ */
/*
* Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org>
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <ctype.h>
#include <err.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "json.h"
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)
+{
+ unsigned char 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' && !eb) {
+ /* skip escaping '/' since our use case does not require it */
+ switch(c) {
+ case '"':
+ eb = fprintf(jsonfh, "\\\"") < 0;
+ break;
+ case '\\':
+ eb = fprintf(jsonfh, "\\\\") < 0;
+ break;
+ case '\b':
+ eb = fprintf(jsonfh, "\\b") < 0;
+ break;
+ case '\f':
+ eb = fprintf(jsonfh, "\\f") < 0;
+ break;
+ case '\n':
+ eb = fprintf(jsonfh, "\\n") < 0;
+ break;
+ case '\r':
+ eb = fprintf(jsonfh, "\\r") < 0;
+ break;
+ case '\t':
+ eb = fprintf(jsonfh, "\\t") < 0;
+ break;
+ default:
+ if (iscntrl(c))
+ errx(1, "bad control character in string");
+ eb = putc(c, jsonfh) == EOF;
+ break;
+ }
+ }
if (!eb)
eb = fprintf(jsonfh, "\"") < 0;
}
-/* $OpenBSD: json.h,v 1.1 2023/04/27 07:57:25 claudio Exp $ */
+/* $OpenBSD: json.h,v 1.2 2023/05/03 07:56:05 claudio Exp $ */
/*
* Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org>
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);