aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Clements <amdragon@MIT.EDU>2012-08-02 21:14:49 -0400
committerDavid Bremner <bremner@debian.org>2012-08-03 20:21:29 -0300
commit14883b07003b9ed4223cd8f2c03b301fddae07bd (patch)
tree216ab7263c82a84aff4a03aa1ce759148cc07080
parent624d1897ce70fde8a41f2ea245db2a5e27f16ce1 (diff)
sprinter: Add a string_len method
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.
-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 4649655..c9b6835 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 b208840..dfa54b5 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 6680d41..5f43175 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 *);