]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
strv: introduce strv_split_newlines_full()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 5 Mar 2021 00:29:57 +0000 (09:29 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 5 Mar 2021 00:29:57 +0000 (09:29 +0900)
src/basic/strv.c
src/basic/strv.h
src/test/test-device-nodes.c
src/test/test-strv.c

index 492dfe40023a6056cc686debb3ed36d53c014a0f..765da04a7bd972cc040779c27c07c25c16e71181 100644 (file)
@@ -240,27 +240,28 @@ int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix) {
         return 0;
 }
 
-char **strv_split_newlines(const char *s) {
-        char **l;
+int strv_split_newlines_full(char ***ret, const char *s, ExtractFlags flags) {
+        _cleanup_strv_free_ char **l = NULL;
         size_t n;
+        int r;
 
         assert(s);
 
-        /* Special version of strv_split() that splits on newlines and
-         * suppresses an empty string at the end */
+        /* Special version of strv_split_full() that splits on newlines and
+         * suppresses an empty string at the end. */
 
-        l = strv_split(s, NEWLINE);
-        if (!l)
-                return NULL;
+        r = strv_split_full(&l, s, NEWLINE, flags);
+        if (r < 0)
+                return r;
 
         n = strv_length(l);
-        if (n <= 0)
-                return l;
-
-        if (isempty(l[n - 1]))
+        if (n > 0 && isempty(l[n - 1])) {
                 l[n - 1] = mfree(l[n - 1]);
+                n--;
+        }
 
-        return l;
+        *ret = TAKE_PTR(l);
+        return n;
 }
 
 int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags) {
index 6b3e8e7f8600f57c8e4e99188c8a5b02a03e8136..911528fab495a9d761211ccfd8f7116f168a526b 100644 (file)
@@ -73,15 +73,21 @@ static inline bool strv_isempty(char * const *l) {
         return !l || !*l;
 }
 
-char **strv_split_newlines(const char *s);
-
 int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags);
 static inline char **strv_split(const char *s, const char *separators) {
         char **ret;
-        int r;
 
-        r = strv_split_full(&ret, s, separators, 0);
-        if (r < 0)
+        if (strv_split_full(&ret, s, separators, 0) < 0)
+                return NULL;
+
+        return ret;
+}
+
+int strv_split_newlines_full(char ***ret, const char *s, ExtractFlags flags);
+static inline char **strv_split_newlines(const char *s) {
+        char **ret;
+
+        if (strv_split_newlines_full(&ret, s, 0) < 0)
                 return NULL;
 
         return ret;
index 9efb3fe3b3f9754ab426fb9793f840aa8d86a57a..c914d78324f9b8b6b5288c8298082db0ccb14e89 100644 (file)
@@ -31,6 +31,7 @@ static void test_encode_devnode_name(void) {
         assert_se(expect_encoded_as("s/ash/ng", "s\\x2fash\\x2fng"));
         assert_se(expect_encoded_as("/", "\\x2f"));
         assert_se(expect_encoded_as("!", "\\x21"));
+        assert_se(expect_encoded_as("QEMU    ", "QEMU\\x20\\x20\\x20\\x20"));
 }
 
 int main(int argc, char *argv[]) {
index 6b5005f9fc9cedf6a90d556e48d4585e36a76117..162d8bed951d10a8b3a13dbb6fac120133027609 100644 (file)
@@ -118,6 +118,20 @@ static const char* const input_table_one_empty[] = {
         NULL,
 };
 
+static const char* const input_table_unescape[] = {
+        "ID_VENDOR=QEMU",
+        "ID_VENDOR_ENC=QEMUx20x20x20x20",
+        "ID_MODEL_ENC=QEMUx20HARDDISKx20x20x20",
+        NULL,
+};
+
+static const char* const input_table_retain_escape[] = {
+        "ID_VENDOR=QEMU",
+        "ID_VENDOR_ENC=QEMU\\x20\\x20\\x20\\x20",
+        "ID_MODEL_ENC=QEMU\\x20HARDDISK\\x20\\x20\\x20",
+        NULL,
+};
+
 static void test_strv_find(void) {
         log_info("/* %s */", __func__);
 
@@ -453,6 +467,25 @@ static void test_strv_split_newlines(void) {
                 assert_se(streq(*s, input_table_multiple[i++]));
 }
 
+static void test_strv_split_newlines_full(void) {
+        const char str[] =
+                "ID_VENDOR=QEMU\n"
+                "ID_VENDOR_ENC=QEMU\\x20\\x20\\x20\\x20\n"
+                "ID_MODEL_ENC=QEMU\\x20HARDDISK\\x20\\x20\\x20\n"
+                "\n\n\n";
+        _cleanup_strv_free_ char **l = NULL;
+
+        log_info("/* %s */", __func__);
+
+        assert_se(strv_split_newlines_full(&l, str, 0) == 3);
+        assert_se(strv_equal(l, (char**) input_table_unescape));
+
+        l = strv_free(l);
+
+        assert_se(strv_split_newlines_full(&l, str, EXTRACT_RETAIN_ESCAPE) == 3);
+        assert_se(strv_equal(l, (char**) input_table_retain_escape));
+}
+
 static void test_strv_split_nulstr(void) {
         _cleanup_strv_free_ char **l = NULL;
         const char nulstr[] = "str0\0str1\0str2\0str3\0";
@@ -1031,6 +1064,7 @@ int main(int argc, char *argv[]) {
         test_strv_split_full();
         test_strv_split_colon_pairs();
         test_strv_split_newlines();
+        test_strv_split_newlines_full();
         test_strv_split_nulstr();
         test_strv_parse_nulstr();
         test_strv_overlap();