]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
string-util: add new helper for finding line starting with specific string in a text...
authorLennart Poettering <lennart@poettering.net>
Fri, 24 Mar 2023 17:02:32 +0000 (18:02 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 24 Mar 2023 17:30:20 +0000 (18:30 +0100)
We have implemented this manually a couple of times, and always wrong.
Hence let's implement this correctly for once and use everywhere.

src/basic/string-util.c
src/basic/string-util.h
src/test/test-string-util.c

index ad8c9863bdda531ac78c93d7f354e612588fdd04..cc2f8ecdabeb3fcd6f775a8c96bb883bee2abf34 100644 (file)
@@ -1260,3 +1260,26 @@ char *strdupcspn(const char *a, const char *reject) {
 
         return strndup(a, strcspn(a, reject));
 }
+
+char *find_line_startswith(const char *haystack, const char *needle) {
+        char *p;
+
+        assert(haystack);
+        assert(needle);
+
+        /* Finds the first line in 'haystack' that starts with the specified string. Returns a pointer to the
+         * first character after it */
+
+        p = strstr(haystack, needle);
+        if (!p)
+                return NULL;
+
+        if (p > haystack)
+                while (p[-1] != '\n') {
+                        p = strstr(p + 1, needle);
+                        if (!p)
+                                return NULL;
+                }
+
+        return p + strlen(needle);
+}
index e0a47a21a97dc1617fccc23225531d86572fcd37..1755b3275ad989f546966cec4c084c9a7193333f 100644 (file)
@@ -253,3 +253,5 @@ size_t strspn_from_end(const char *str, const char *accept);
 
 char *strdupspn(const char *a, const char *accept);
 char *strdupcspn(const char *a, const char *reject);
+
+char *find_line_startswith(const char *haystack, const char *needle);
index b3ff7d65c1cf1ad853ba19b42686097886f66d40..9eb048adfa09d00e72b9d8a35592bdea4203c6de 100644 (file)
@@ -1218,4 +1218,33 @@ TEST(make_cstring) {
         TEST_MAKE_CSTRING_ONE(test8, -EINVAL, MAKE_CSTRING_REQUIRE_TRAILING_NUL, NULL);
 }
 
+TEST(find_line_startswith) {
+        static const char text[] =
+                "foobar\n"
+                "this is a test\n"
+                "foobar: waldo\n"
+                "more\n"
+                "\n"
+                "piff\n"
+                "foobarfoobar\n"
+                "iff\n";
+        static const char emptystring[] = "";
+
+        assert_se(find_line_startswith(text, "") == text);
+        assert_se(find_line_startswith(text, "f") == text+1);
+        assert_se(find_line_startswith(text, "foobar") == text+6);
+        assert_se(!find_line_startswith(text, "foobarx"));
+        assert_se(!find_line_startswith(text, "oobar"));
+        assert_se(find_line_startswith(text, "t") == text + 8);
+        assert_se(find_line_startswith(text, "th") == text + 9);
+        assert_se(find_line_startswith(text, "this") == text + 11);
+        assert_se(find_line_startswith(text, "foobarf") == text + 54);
+        assert_se(find_line_startswith(text, "more\n") == text + 41);
+        assert_se(find_line_startswith(text, "\n") == text + 42);
+        assert_se(find_line_startswith(text, "iff") == text + 63);
+
+        assert_se(find_line_startswith(emptystring, "") == emptystring);
+        assert_se(!find_line_startswith(emptystring, "x"));
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);