X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=util%2Fstring-util.c;h=de8430b2add34dea3fdf52507cf442c420cd170f;hp=b0108811903b27153dcaece1fa10b893234c3b9f;hb=HEAD;hpb=040c3236afcf95bead0324a48c2e0b9cd7934993 diff --git a/util/string-util.c b/util/string-util.c index b0108811..03d7648d 100644 --- a/util/string-util.c +++ b/util/string-util.c @@ -24,6 +24,7 @@ #include #include +#include char * strtok_len (char *s, const char *delim, size_t *len) @@ -37,12 +38,36 @@ strtok_len (char *s, const char *delim, size_t *len) return *len ? s : NULL; } +const char * +strsplit_len (const char *s, char delim, size_t *len) +{ + bool escaping = false; + size_t count = 0, last_nonspace = 0; + + /* Skip initial unescaped delimiters and whitespace */ + while (*s && (*s == delim || isspace (*s))) + s++; + + while (s[count] && (escaping || s[count] != delim)) { + if (! isspace (s[count])) + last_nonspace = count; + escaping = (s[count] == '\\'); + count++; + } + + if (count == 0) + return NULL; + + *len = last_nonspace + 1; + return s; +} + const char * strtok_len_c (const char *s, const char *delim, size_t *len) { /* strtok_len is already const-safe, but we can't express both * versions in the C type system. */ - return strtok_len ((char*)s, delim, len); + return strtok_len ((char *) s, delim, len); } char * @@ -60,7 +85,7 @@ sanitize_string (const void *ctx, const char *str) for (loop = out; *loop; loop++) { if (*loop == '\t' || *loop == '\n') *loop = ' '; - else if ((unsigned char)(*loop) < 32) + else if ((unsigned char) (*loop) < 32) *loop = '?'; } @@ -87,9 +112,9 @@ make_boolean_term (void *ctx, const char *prefix, const char *term, * beginning, and anything containing non-ASCII text. */ if (! term[0]) need_quoting = 1; - for (in = term; *in && !need_quoting; in++) + for (in = term; *in && ! need_quoting; in++) if (is_unquoted_terminator (*in) || *in == '"' || *in == '(' - || (unsigned char)*in > 127) + || (unsigned char) *in > 127) need_quoting = 1; if (need_quoting) @@ -141,7 +166,7 @@ make_boolean_term (void *ctx, const char *prefix, const char *term, return 0; } -static const char* +const char * skip_space (const char *str) { while (*str && isspace ((unsigned char) *str)) @@ -154,11 +179,13 @@ parse_boolean_term (void *ctx, const char *str, char **prefix_out, char **term_out) { int err = EINVAL; + *prefix_out = *term_out = NULL; /* Parse prefix */ str = skip_space (str); const char *pos = strchr (str, ':'); + if (! pos || pos == str) goto FAIL; *prefix_out = talloc_strndup (ctx, str, pos - str); @@ -193,7 +220,7 @@ parse_boolean_term (void *ctx, const char *str, } /* Did the term terminate without a closing quote or is there * trailing text after the closing quote? */ - if (!closed || *pos) + if (! closed || *pos) goto FAIL; *out = '\0'; } else { @@ -215,7 +242,7 @@ parse_boolean_term (void *ctx, const char *str, } return 0; - FAIL: + FAIL: talloc_free (*prefix_out); talloc_free (*term_out); errno = err; @@ -230,9 +257,9 @@ strcmp_null (const char *s1, const char *s2) else if (! s1 && ! s2) return 0; else if (s1) - return 1; /* s1 (non-NULL) is greater than s2 (NULL) */ + return 1; /* s1 (non-NULL) is greater than s2 (NULL) */ else - return -1; /* s1 (NULL) is less than s2 (non-NULL) */ + return -1; /* s1 (NULL) is less than s2 (non-NULL) */ } int @@ -248,6 +275,7 @@ strcase_hash (const void *ptr) /* This is the djb2 hash. */ unsigned int hash = 5381; + while (s && *s) { hash = ((hash << 5) + hash) + tolower (*s); s++;