+void wrbuf_puts_escaped(WRBUF b, const char *str)
+{
+ wrbuf_write_escaped(b, str, strlen(str));
+}
+
+void wrbuf_write_escaped(WRBUF b, const char *str, size_t len)
+{
+ size_t i;
+ for (i = 0; i < len; i++)
+ if (str[i] < ' ' || str[i] > 126)
+ wrbuf_printf(b, "\\x%02X", str[i] & 0xff);
+ else
+ wrbuf_putc(b, str[i]);
+}
+
+void wrbuf_json_write(WRBUF b, const char *cp, size_t sz)
+{
+ size_t i;
+ for (i = 0; i < sz; i++)
+ {
+ if (cp[i] > 0 && cp[i] < 32)
+ {
+ wrbuf_putc(b, '\\');
+ switch (cp[i])
+ {
+ case '\b': wrbuf_putc(b, 'b'); break;
+ case '\f': wrbuf_putc(b, 'f'); break;
+ case '\n': wrbuf_putc(b, 'n'); break;
+ case '\r': wrbuf_putc(b, 'r'); break;
+ case '\t': wrbuf_putc(b, 't'); break;
+ default:
+ wrbuf_printf(b, "u%04x", cp[i]);
+ }
+ }
+ else if (cp[i] == '"')
+ {
+ wrbuf_putc(b, '\\'); wrbuf_putc(b, '"');
+ }
+ else if (cp[i] == '\\')
+ {
+ wrbuf_putc(b, '\\'); wrbuf_putc(b, '\\');
+ }
+ else
+ { /* leave encoding as raw UTF-8 */
+ wrbuf_putc(b, cp[i]);
+ }
+ }
+
+}
+
+void wrbuf_json_puts(WRBUF b, const char *str)
+{
+ wrbuf_json_write(b, str, strlen(str));
+}
+