mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-25 04:18:08 +01:00
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.
This commit is contained in:
parent
624d1897ce
commit
14883b0700
3 changed files with 29 additions and 7 deletions
|
@ -88,8 +88,13 @@ json_end (struct sprinter *sp)
|
||||||
fputc ('\n', spj->stream);
|
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
|
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[] = {
|
static const char *const escapes[] = {
|
||||||
['\"'] = "\\\"", ['\\'] = "\\\\", ['\b'] = "\\b",
|
['\"'] = "\\\"", ['\\'] = "\\\\", ['\b'] = "\\b",
|
||||||
|
@ -98,7 +103,7 @@ json_string (struct sprinter *sp, const char *val)
|
||||||
struct sprinter_json *spj = json_begin_value (sp);
|
struct sprinter_json *spj = json_begin_value (sp);
|
||||||
|
|
||||||
fputc ('"', spj->stream);
|
fputc ('"', spj->stream);
|
||||||
for (; *val; ++val) {
|
for (; len; ++val, --len) {
|
||||||
unsigned char ch = *val;
|
unsigned char ch = *val;
|
||||||
if (ch < ARRAY_SIZE (escapes) && escapes[ch])
|
if (ch < ARRAY_SIZE (escapes) && escapes[ch])
|
||||||
fputs (escapes[ch], spj->stream);
|
fputs (escapes[ch], spj->stream);
|
||||||
|
@ -110,6 +115,12 @@ json_string (struct sprinter *sp, const char *val)
|
||||||
fputc ('"', spj->stream);
|
fputc ('"', spj->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
json_string (struct sprinter *sp, const char *val)
|
||||||
|
{
|
||||||
|
json_string_len (sp, val, strlen (val));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
json_integer (struct sprinter *sp, int val)
|
json_integer (struct sprinter *sp, int val)
|
||||||
{
|
{
|
||||||
|
@ -166,6 +177,7 @@ sprinter_json_create (const void *ctx, FILE *stream)
|
||||||
.begin_list = json_begin_list,
|
.begin_list = json_begin_list,
|
||||||
.end = json_end,
|
.end = json_end,
|
||||||
.string = json_string,
|
.string = json_string,
|
||||||
|
.string_len = json_string_len,
|
||||||
.integer = json_integer,
|
.integer = json_integer,
|
||||||
.boolean = json_boolean,
|
.boolean = json_boolean,
|
||||||
.null = json_null,
|
.null = json_null,
|
||||||
|
|
|
@ -25,14 +25,20 @@ struct sprinter_text {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
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;
|
struct sprinter_text *sptxt = (struct sprinter_text *) sp;
|
||||||
|
|
||||||
if (sptxt->current_prefix != NULL)
|
if (sptxt->current_prefix != NULL)
|
||||||
fprintf (sptxt->stream, "%s:", sptxt->current_prefix);
|
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
|
static void
|
||||||
|
@ -105,6 +111,7 @@ sprinter_text_create (const void *ctx, FILE *stream)
|
||||||
.begin_list = text_begin_list,
|
.begin_list = text_begin_list,
|
||||||
.end = text_end,
|
.end = text_end,
|
||||||
.string = text_string,
|
.string = text_string,
|
||||||
|
.string_len = text_string_len,
|
||||||
.integer = text_integer,
|
.integer = text_integer,
|
||||||
.boolean = text_boolean,
|
.boolean = text_boolean,
|
||||||
.null = text_null,
|
.null = text_null,
|
||||||
|
|
|
@ -23,11 +23,14 @@ typedef struct sprinter {
|
||||||
*/
|
*/
|
||||||
void (*end) (struct sprinter *);
|
void (*end) (struct sprinter *);
|
||||||
|
|
||||||
/* Print one string/integer/boolean/null element (possibly inside a
|
/* Print one string/integer/boolean/null element (possibly inside
|
||||||
* list or map, followed or preceded by separators).
|
* a list or map, followed or preceded by separators). For string
|
||||||
* For string, the char * must be UTF-8 encoded.
|
* 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) (struct sprinter *, const char *);
|
||||||
|
void (*string_len) (struct sprinter *, const char *, size_t);
|
||||||
void (*integer) (struct sprinter *, int);
|
void (*integer) (struct sprinter *, int);
|
||||||
void (*boolean) (struct sprinter *, notmuch_bool_t);
|
void (*boolean) (struct sprinter *, notmuch_bool_t);
|
||||||
void (*null) (struct sprinter *);
|
void (*null) (struct sprinter *);
|
||||||
|
|
Loading…
Reference in a new issue