aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--sprinter-json.c16
-rw-r--r--sprinter-text.c11
-rw-r--r--sprinter.h9
3 files changed, 29 insertions, 7 deletions
diff --git a/sprinter-json.c b/sprinter-json.c
index 46496551..c9b68353 100644
--- a/sprinter-json.c
+++ b/sprinter-json.c
@@ -88,8 +88,13 @@ json_end (struct sprinter *sp)
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",
@@ -98,7 +103,7 @@ json_string (struct sprinter *sp, const char *val)
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);
@@ -111,6 +116,12 @@ json_string (struct sprinter *sp, const char *val)
}
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)
{
struct sprinter_json *spj = json_begin_value (sp);
@@ -166,6 +177,7 @@ sprinter_json_create (const void *ctx, FILE *stream)
.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,
diff --git a/sprinter-text.c b/sprinter-text.c
index b208840b..dfa54b57 100644
--- a/sprinter-text.c
+++ b/sprinter-text.c
@@ -25,14 +25,20 @@ struct sprinter_text {
};
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
@@ -105,6 +111,7 @@ sprinter_text_create (const void *ctx, FILE *stream)
.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,
diff --git a/sprinter.h b/sprinter.h
index 6680d419..5f431757 100644
--- a/sprinter.h
+++ b/sprinter.h
@@ -23,11 +23,14 @@ typedef struct sprinter {
*/
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 *);