diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/string-util.c | 75 | ||||
-rw-r--r-- | util/string-util.h | 15 |
2 files changed, 90 insertions, 0 deletions
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 <errno.h> 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; +} diff --git a/util/string-util.h b/util/string-util.h index ac7676c8..719c276a 100644 --- a/util/string-util.h +++ b/util/string-util.h @@ -19,4 +19,19 @@ char *strtok_len (char *s, const char *delim, size_t *len); +/* Construct a boolean term query with the specified prefix (e.g., + * "id") and search term, quoting term as necessary. Specifically, if + * term contains any non-printable ASCII characters, non-ASCII + * characters, close parenthesis or double quotes, it will be enclosed + * in double quotes and any internal double quotes will be doubled + * (e.g. a"b -> "a""b"). The result will be a valid notmuch query and + * can be parsed by parse_boolean_term. + * + * Output is into buf; it may be talloc_realloced. + * Return: 0 on success, -1 on error. errno will be set to ENOMEM if + * there is an allocation failure. + */ +int make_boolean_term (void *talloc_ctx, const char *prefix, const char *term, + char **buf, size_t *len); + #endif |