summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2015-06-23 17:00:40 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2015-08-07 15:50:42 +0000
commit206644aedeb8859801051ac170ec562c6a113a79 (patch)
tree88ba118333423abc16871dc490a74cd911218b3d /src
parent12ba2c44dde4d7cfc0e531dbc3cbd0581c323637 (diff)
util: Allow non-separator coalescing parsing in extract_first_word
If EXTRACT_DONT_COALESCE_SEPARATORS is passed, then leading separators, trailing separators and spans of multiple separators aren't skipped, and empty arguments from before, after or between separators may be extracted.
Diffstat (limited to 'src')
-rw-r--r--src/basic/util.c28
-rw-r--r--src/basic/util.h1
-rw-r--r--src/test/test-util.c32
3 files changed, 55 insertions, 6 deletions
diff --git a/src/basic/util.c b/src/basic/util.c
index d4c385fcef..0b974b2ab5 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -5735,10 +5735,20 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
switch (state) {
case START:
- if (c == 0)
+ if (c == 0) {
+ if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
+ if (!GREEDY_REALLOC(s, allocated, sz+1))
+ return -ENOMEM;
goto finish_force_terminate;
- else if (strchr(separators, c))
+ } else if (strchr(separators, c)) {
+ if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
+ if (!GREEDY_REALLOC(s, allocated, sz+1))
+ return -ENOMEM;
+ (*p) ++;
+ goto finish_force_next;
+ }
break;
+ }
state = VALUE;
/* fallthrough */
@@ -5758,9 +5768,13 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
return -ENOMEM;
state = DOUBLE_QUOTE;
- } else if (strchr(separators, c))
+ } else if (strchr(separators, c)) {
+ if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
+ (*p) ++;
+ goto finish_force_next;
+ }
state = SEPARATOR;
- else {
+ } else {
if (!GREEDY_REALLOC(s, allocated, sz+2))
return -ENOMEM;
@@ -5857,10 +5871,11 @@ end_escape:
case SEPARATOR:
if (c == 0)
- goto finish;
+ goto finish_force_terminate;
+ if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
+ goto finish_force_next;
if (!strchr(separators, c))
goto finish;
-
break;
}
@@ -5876,6 +5891,7 @@ finish:
return 0;
}
+finish_force_next:
s[sz] = 0;
*ret = s;
s = NULL;
diff --git a/src/basic/util.h b/src/basic/util.h
index 82fb771e20..4d6a8abb57 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -859,6 +859,7 @@ typedef enum ExtractFlags {
EXTRACT_CUNESCAPE = 2,
EXTRACT_CUNESCAPE_RELAX = 4,
EXTRACT_QUOTES = 8,
+ EXTRACT_DONT_COALESCE_SEPARATORS = 16,
} ExtractFlags;
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 40f5d34de3..fc7a3de106 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -1744,6 +1744,38 @@ static void test_extract_first_word(void) {
assert_se(streq(t, ""));
free(t);
assert_se(isempty(p));
+
+ p = original = ":foo\\:bar::waldo:";
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(t);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == original + 1);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(streq(t, "foo:bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(t);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == original + 11);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(p == original + 17);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == NULL);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0);
+ assert_se(!t);
+ assert_se(!p);
}
static void test_extract_first_word_and_warn(void) {