This method allows callers to output strings with specific lengths.
It's useful both for strings with embedded NULs (which JSON can
represent, though parser support is apparently spotty), and
non-terminated strings.
fputc ('\n', spj->stream);
}
+/* This implementation supports embedded NULs as allowed by the JSON
+ * specification and Unicode. Support for *parsing* embedded NULs
+ * varies, but is generally not a problem outside of C-based parsers
+ * (Python's json module and Emacs' json.el take embedded NULs in
+ * stride). */
static void
-json_string (struct sprinter *sp, const char *val)
+json_string_len (struct sprinter *sp, const char *val, size_t len)
{
static const char *const escapes[] = {
['\"'] = "\\\"", ['\\'] = "\\\\", ['\b'] = "\\b",
struct sprinter_json *spj = json_begin_value (sp);
fputc ('"', spj->stream);
- for (; *val; ++val) {
+ for (; len; ++val, --len) {
unsigned char ch = *val;
if (ch < ARRAY_SIZE (escapes) && escapes[ch])
fputs (escapes[ch], spj->stream);
fputc ('"', spj->stream);
}
+static void
+json_string (struct sprinter *sp, const char *val)
+{
+ json_string_len (sp, val, strlen (val));
+}
+
static void
json_integer (struct sprinter *sp, int val)
{
.begin_list = json_begin_list,
.end = json_end,
.string = json_string,
+ .string_len = json_string_len,
.integer = json_integer,
.boolean = json_boolean,
.null = json_null,
};
static void
-text_string (struct sprinter *sp, const char *val)
+text_string_len (struct sprinter *sp, const char *val, size_t len)
{
struct sprinter_text *sptxt = (struct sprinter_text *) sp;
if (sptxt->current_prefix != NULL)
fprintf (sptxt->stream, "%s:", sptxt->current_prefix);
- fputs(val, sptxt->stream);
+ fwrite (val, len, 1, sptxt->stream);
+}
+
+static void
+text_string (struct sprinter *sp, const char *val)
+{
+ text_string_len (sp, val, strlen (val));
}
static void
.begin_list = text_begin_list,
.end = text_end,
.string = text_string,
+ .string_len = text_string_len,
.integer = text_integer,
.boolean = text_boolean,
.null = text_null,
*/
void (*end) (struct sprinter *);
- /* Print one string/integer/boolean/null element (possibly inside a
- * list or map, followed or preceded by separators).
- * For string, the char * must be UTF-8 encoded.
+ /* Print one string/integer/boolean/null element (possibly inside
+ * a list or map, followed or preceded by separators). For string
+ * and string_len, the char * must be UTF-8 encoded. string_len
+ * allows non-terminated strings and strings with embedded NULs
+ * (though the handling of the latter is format-dependent).
*/
void (*string) (struct sprinter *, const char *);
+ void (*string_len) (struct sprinter *, const char *, size_t);
void (*integer) (struct sprinter *, int);
void (*boolean) (struct sprinter *, notmuch_bool_t);
void (*null) (struct sprinter *);