]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/extract-word: add EXTRACT_RETAIN_SEPARATORS flag
authorLuca Boccassi <luca.boccassi@microsoft.com>
Thu, 17 Jun 2021 12:12:57 +0000 (13:12 +0100)
committerLuca Boccassi <luca.boccassi@microsoft.com>
Thu, 24 Jun 2021 12:41:17 +0000 (13:41 +0100)
Makes the helpers avoid skipping over the separator(s) in the
input string

src/basic/extract-word.c
src/basic/extract-word.h
src/test/test-extract-word.c

index 0c440db691ce107bb12da0e97b37ed37d18c5ef5..9f9bb0c7910cd44629cdf239ea7106ce1b29f2ee 100644 (file)
@@ -51,7 +51,8 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                         goto finish_force_terminate;
                 else if (strchr(separators, c)) {
                         if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
-                                (*p)++;
+                                if (!(flags & EXTRACT_RETAIN_SEPARATORS))
+                                        (*p)++;
                                 goto finish_force_next;
                         }
                 } else {
@@ -153,16 +154,18 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
                                         break;
                                 } else if (strchr(separators, c)) {
                                         if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
-                                                (*p)++;
+                                                if (!(flags & EXTRACT_RETAIN_SEPARATORS))
+                                                        (*p)++;
                                                 goto finish_force_next;
                                         }
-                                        /* Skip additional coalesced separators. */
-                                        for (;; (*p)++, c = **p) {
-                                                if (c == 0)
-                                                        goto finish_force_terminate;
-                                                if (!strchr(separators, c))
-                                                        break;
-                                        }
+                                        if (!(flags & EXTRACT_RETAIN_SEPARATORS))
+                                                /* Skip additional coalesced separators. */
+                                                for (;; (*p)++, c = **p) {
+                                                        if (c == 0)
+                                                                goto finish_force_terminate;
+                                                        if (!strchr(separators, c))
+                                                                break;
+                                                }
                                         goto finish;
 
                                 }
index f415872fac97dc2faa3caf12fdf897f257dae93b..c82ad761efe682936d4363d4a121c870e8a1e7db 100644 (file)
@@ -12,6 +12,7 @@ typedef enum ExtractFlags {
         EXTRACT_UNQUOTE                  = 1 << 5, /* Ignore separators in quoting with "" and '', and remove the quotes. */
         EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 6, /* Don't treat multiple adjacent separators as one */
         EXTRACT_RETAIN_ESCAPE            = 1 << 7, /* Treat escape character '\' as any other character without special meaning */
+        EXTRACT_RETAIN_SEPARATORS        = 1 << 8, /* Do not advance the original string pointer past the separator(s) */
 
         /* Note that if no flags are specified, escaped escape characters will be silently stripped. */
 } ExtractFlags;
index a392ec7588074ac8ec457ee3549504799d465ccc..8cf0b63a4c762f04ef57c8fba7cda0ba216beb5e 100644 (file)
@@ -482,6 +482,58 @@ static void test_extract_first_word(void) {
         assert_se(extract_first_word(&p, &t, ",", EXTRACT_UNQUOTE) > 0);
         assert_se(streq(t, "context=system_u:object_r:svirt_sandbox_file_t:s0:c0,c1"));
         free(t);
+
+        p = "a:b";
+        assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS) == 1);
+        assert_se(streq(t, "a"));
+        assert_se(streq(p, ":b"));
+        free(t);
+        assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS) == 1);
+        assert_se(streq(t, "b"));
+        free(t);
+
+        p = "a>:b";
+        assert_se(extract_first_word(&p, &t, ">:", EXTRACT_RETAIN_SEPARATORS) == 1);
+        assert_se(streq(t, "a"));
+        assert_se(streq(p, ">:b"));
+        free(t);
+        assert_se(extract_first_word(&p, &t, ">:", EXTRACT_RETAIN_SEPARATORS) == 1);
+        assert_se(streq(t, "b"));
+        free(t);
+
+        p = "a>:b";
+        assert_se(extract_first_word(&p, &t, ">:", EXTRACT_RETAIN_SEPARATORS|EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+        assert_se(streq(t, "a"));
+        assert_se(streq(p, ">:b"));
+        free(t);
+        assert_se(extract_first_word(&p, &t, ">:", EXTRACT_RETAIN_SEPARATORS|EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+        assert_se(streq(t, ""));
+        assert_se(streq(p, ">:b"));
+        free(t);
+
+        p = "a\\:b";
+        assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS|EXTRACT_RETAIN_ESCAPE) == 1);
+        assert_se(streq(t, "a\\"));
+        assert_se(streq(p, ":b"));
+        free(t);
+
+        p = "a\\:b";
+        assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS) == 1);
+        assert_se(streq(t, "a:b"));
+        assert_se(!p);
+        free(t);
+
+        p = "a\\:b";
+        assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS|EXTRACT_UNESCAPE_SEPARATORS) == 1);
+        assert_se(streq(t, "a:b"));
+        assert_se(!p);
+        free(t);
+
+        p = "a\\:a:b";
+        assert_se(extract_first_word(&p, &t, ":", EXTRACT_RETAIN_SEPARATORS|EXTRACT_UNESCAPE_SEPARATORS) == 1);
+        assert_se(streq(t, "a:a"));
+        assert_se(streq(p, ":b"));
+        free(t);
 }
 
 static void test_extract_first_word_and_warn(void) {