X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=util%2Fstring-util.c;h=7a71049a098d70d7788e13098ac6c28c3d33f6e3;hp=44f8cd3a252ae2ba409ad1861202398a76e56c6f;hb=25cf5f5dc45cac42f15643f6df09b46d51d7b5ec;hpb=baca1219af0ef1f81985759e868a68e9dd78e0d1 diff --git a/util/string-util.c b/util/string-util.c index 44f8cd3a..7a71049a 100644 --- a/util/string-util.c +++ b/util/string-util.c @@ -20,6 +20,9 @@ #include "string-util.h" +#include "talloc.h" + +#include char * strtok_len (char *s, const char *delim, size_t *len) @@ -32,3 +35,75 @@ strtok_len (char *s, const char *delim, size_t *len) return *len ? s : NULL; } + +static int +is_unquoted_terminator (unsigned char c) +{ + return c == 0 || c <= ' ' || c == ')'; +} + +int +make_boolean_term (void *ctx, const char *prefix, const char *term, + char **buf, size_t *len) +{ + const char *in; + char *out; + size_t needed = 3; + int need_quoting = 0; + + /* Do we need quoting? To be paranoid, we quote anything + * containing a quote, even though it only matters at the + * beginning, and anything containing non-ASCII text. */ + for (in = term; *in && !need_quoting; in++) + if (is_unquoted_terminator (*in) || *in == '"' + || (unsigned char)*in > 127) + need_quoting = 1; + + if (need_quoting) + for (in = term; *in; in++) + needed += (*in == '"') ? 2 : 1; + else + needed = strlen (term) + 1; + + /* Reserve space for the prefix */ + if (prefix) + needed += strlen (prefix) + 1; + + if ((*buf == NULL) || (needed > *len)) { + *len = 2 * needed; + *buf = talloc_realloc (ctx, *buf, char, *len); + } + + if (! *buf) { + errno = ENOMEM; + return -1; + } + + out = *buf; + + /* Copy in the prefix */ + if (prefix) { + strcpy (out, prefix); + out += strlen (prefix); + *out++ = ':'; + } + + if (! need_quoting) { + strcpy (out, term); + return 0; + } + + /* Quote term by enclosing it in double quotes and doubling any + * internal double quotes. */ + *out++ = '"'; + in = term; + while (*in) { + if (*in == '"') + *out++ = '"'; + *out++ = *in++; + } + *out++ = '"'; + *out = '\0'; + + return 0; +}