]> git.ipfire.org Git - pakfire.git/commitdiff
config: Extend parser to support multiline files
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 11 Oct 2022 13:00:48 +0000 (13:00 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 11 Oct 2022 13:00:48 +0000 (13:00 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/config.c
tests/libpakfire/config.c

index ac1e26d56be69fe4c9458d187cf08cdbfe29068f..22fbe892b8cdb1dd02a4678321c1656be8eb6aeb 100644 (file)
@@ -169,6 +169,32 @@ int pakfire_config_set(struct pakfire_config* config,
        return pakfire_string_set(entry->value, value);
 }
 
+static int pakfire_config_append(struct pakfire_config* config,
+               const char* section, const char* key, const char* value2) {
+       char* buffer = NULL;
+       int r;
+
+       // Fetch the current value
+       const char* value1 = pakfire_config_get(config, section, key, NULL);
+
+       // Short cut if value1 is empty
+       if (!value1 || !*value1)
+               return pakfire_config_set(config, section, key, value2);
+
+       // Join both values together
+       r = asprintf(&buffer, "%s\n%s", value1, value2);
+       if (r < 0)
+               return 1;
+
+       // Set the new value
+       r = pakfire_config_set(config, section, key, buffer);
+
+       if (buffer)
+               free(buffer);
+
+       return r;
+}
+
 const char* pakfire_config_get(struct pakfire_config* config,
                const char* section, const char* key, const char* _default) {
        struct pakfire_config_entry* entry = pakfire_config_find(config, section, key);
@@ -287,7 +313,7 @@ int pakfire_config_has_section(struct pakfire_config* config, const char* sectio
        return 0;
 }
 
-static ssize_t strip(char* s) {
+static ssize_t lstrip(char* s) {
        if (!s)
                return 0;
 
@@ -297,6 +323,15 @@ static ssize_t strip(char* s) {
        while (isspace(s[0]))
                memmove(s, s + 1, l--);
 
+       return l;
+}
+
+static ssize_t rstrip(char* s) {
+       if (!s)
+               return 0;
+
+       size_t l = strlen(s);
+
        // Remove trailing space
        while (isspace(s[l - 1]))
                s[l-- - 1] = '\0';
@@ -304,8 +339,19 @@ static ssize_t strip(char* s) {
        return l;
 }
 
+static ssize_t strip(char* s) {
+       ssize_t l = lstrip(s);
+
+       if (l)
+               l = rstrip(s);
+
+       return l;
+}
+
 int pakfire_config_read(struct pakfire_config* config, FILE* f) {
        char section[SECTION_MAX_LENGTH] = "";
+       char key[KEY_MAX_LENGTH] = "";
+       int r;
 
        char* line = NULL;
        size_t l = 0;
@@ -327,7 +373,7 @@ int pakfire_config_read(struct pakfire_config* config, FILE* f) {
                }
 
                // Remove trailing space
-               length = strip(line);
+               length = rstrip(line);
 
                // Skip empty lines
                if (*line == '\0')
@@ -337,13 +383,34 @@ int pakfire_config_read(struct pakfire_config* config, FILE* f) {
                if (line[0] == '[' && line[length - 1] == ']') {
                        line[length - 1] = '\0';
 
-                       int r = pakfire_string_set(section, line + 1);
+                       // Clear the previous key
+                       *key = '\0';
+
+                       r = pakfire_string_set(section, line + 1);
                        if (r)
-                               return r;
+                               goto ERROR;
 
                        continue;
                }
 
+               // Check if this is a multiline value
+               if (isspace(*line)) {
+                       // We cannot assign this value anywhere
+                       if (!*key) {
+                               errno = EINVAL;
+                               r = 1;
+                               goto ERROR;
+                       }
+
+                       // Strip any leading whitespace
+                       lstrip(line);
+
+                       // Append the value to the existing one
+                       r = pakfire_config_append(config, section, key, line);
+                       if (r)
+                               goto ERROR;
+               }
+
                // Handle any assignments
 
                // Find the separator
@@ -358,13 +425,18 @@ int pakfire_config_read(struct pakfire_config* config, FILE* f) {
                strip(line);
                strip(value);
 
-               int r = pakfire_config_set(config, section, line, value);
+               // Update the key
+               pakfire_string_set(key, line);
+
+               // Store the value
+               r = pakfire_config_set(config, section, key, value);
                if (r)
-                       return r;
+                       goto ERROR;
        }
 
+ERROR:
        if (line)
                free(line);
 
-       return 0;
+       return r;
 }
index 9773224d31a67f0aa5f76cd79e7bc3df0f4e44b0..8ac2571d9fb216d8812659ebf7140c6cfe2cdf82 100644 (file)
@@ -144,9 +144,42 @@ FAIL:
        return r;
 }
 
+static int test_parse_multiline(const struct test* t) {
+       int r = EXIT_FAILURE;
+
+       char* TEST_INPUT =
+               "key1 =\n"
+               " value1\n"
+               " value2\n"
+               "\n"
+               "key2 = value1\n";
+
+       FILE* f = fmemopen(TEST_INPUT, strlen(TEST_INPUT), "r");
+       ASSERT(f);
+
+       struct pakfire_config* config = NULL;
+
+       ASSERT_SUCCESS(pakfire_config_create(&config));
+       ASSERT_SUCCESS(pakfire_config_read(config, f));
+
+       ASSERT_STRING_EQUALS(pakfire_config_get(config, "", "key1", NULL), "value1\nvalue2");
+       ASSERT_STRING_EQUALS(pakfire_config_get(config, "", "key2", NULL), "value1");
+
+       // Everything passed
+       r = EXIT_SUCCESS;
+
+FAIL:
+       if (f)
+               fclose(f);
+       pakfire_config_unref(config);
+
+       return r;
+}
+
 int main(int argc, const char* argv[]) {
        testsuite_add_test(test_get_and_set);
        testsuite_add_test(test_parse);
+       testsuite_add_test(test_parse_multiline);
 
        return testsuite_run(argc, argv);
 }