]> git.ipfire.org Git - pakfire.git/commitdiff
config: Add function to parse files
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 16 Apr 2021 13:04:01 +0000 (13:04 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 16 Apr 2021 13:39:53 +0000 (13:39 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/config.c
src/libpakfire/include/pakfire/config.h
tests/libpakfire/config.c

index 14888725397408fc518fb0b56747708155d58533..1171ff1e6efd0f078c23b0a97ee8daa0cf8bc6a0 100644 (file)
@@ -18,6 +18,7 @@
 #                                                                             #
 #############################################################################*/
 
+#include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <pakfire/config.h>
 #include <pakfire/util.h>
 
+#define KEY_MAX_LENGTH         32
+#define VALUE_MAX_LENGTH       1024
+#define SECTION_MAX_LENGTH     32
+#define LINE_MAX_LENGTH                1024
+
 struct pakfire_config_entry {
        STAILQ_ENTRY(pakfire_config_entry) nodes;
 
        // Section name
-       char section[32];
+       char section[SECTION_MAX_LENGTH];
 
        // Key & Value
-       char key[32];
-       char value[1024];
+       char key[KEY_MAX_LENGTH];
+       char value[VALUE_MAX_LENGTH];
 };
 
 struct pakfire_config {
@@ -199,3 +205,85 @@ int pakfire_config_get_bool(struct pakfire_config* config,
        // Otherwise return the default value
        return _default;
 }
+
+static ssize_t strip(char* s) {
+       if (!s)
+               return 0;
+
+       size_t l = strlen(s);
+
+       // Remove leading space
+       while (isspace(s[0]))
+               memmove(s, s + 1, l--);
+
+       // Remove trailing space
+       while (isspace(s[l - 1]))
+               s[l-- - 1] = '\0';
+
+       return l;
+}
+
+int pakfire_config_read(struct pakfire_config* config, FILE* f) {
+       char section[SECTION_MAX_LENGTH] = "";
+
+       char* line = NULL;
+       size_t l = 0;
+
+       while (!feof(f)) {
+               ssize_t length = getline(&line, &l, f);
+               if (length < 0)
+                       break;
+
+               // Break if there was an error
+               if (ferror(f))
+                       break;
+
+               // Terminate line after comment sign
+               char* comment = strchr(line, '#');
+               if (comment) {
+                       *comment = '\0';
+                       length = comment - line;
+               }
+
+               // Remove trailing space
+               length = strip(line);
+
+               // Skip empty lines
+               if (*line == '\0')
+                       continue;
+
+               // Is this a new section?
+               if (line[0] == '[' && line[length - 1] == ']') {
+                       line[length - 1] = '\0';
+
+                       int r = snprintf(section, sizeof(section) - 1, "%s", line + 1);
+                       if (r == sizeof(section))
+                               return ENOBUFS;
+
+                       continue;
+               }
+
+               // Handle any assignments
+
+               // Find the separator
+               char* value = strchr(line, '=');
+               if (!value)
+                       continue;
+
+               // Split the string
+               *value++ = '\0';
+
+               // Remove trailing space
+               strip(line);
+               strip(value);
+
+               int r = pakfire_config_set(config, section, line, value);
+               if (r)
+                       return r;
+       }
+
+       if (line)
+               free(line);
+
+       return 0;
+}
index 9edeeb15a26d8d2a98f6bdbb72cdf1db3778e072..31fc5666bf0b4b2ff44765d8670a74ea6317c2ac 100644 (file)
@@ -23,6 +23,8 @@
 
 #ifdef PAKFIRE_PRIVATE
 
+#include <stdio.h>
+
 struct pakfire_config;
 
 int pakfire_config_create(struct pakfire_config** config);
@@ -38,6 +40,8 @@ long int pakfire_config_get_int(struct pakfire_config* config,
 int pakfire_config_get_bool(struct pakfire_config* config,
        const char* section, const char* key, int _default);
 
+int pakfire_config_read(struct pakfire_config* config, FILE* f);
+
 #endif
 
 #endif /* PAKFIRE_CONFIG_H */
index f4b04ca3e447b63622cbabbe3f9b6225552123d1..235297549cd357e3ebb415fa55f0e5fd3711aee9 100644 (file)
@@ -64,8 +64,43 @@ static int test_get_and_set(const struct test* t) {
        return EXIT_SUCCESS;
 }
 
+
+static int test_parse(const struct test* t) {
+       char* TEST_INPUT =
+               "key1 = value1\n"
+               "\n"
+               "# This is a comment\n"
+               "[section1]\n"
+               "key1 = value1\n"
+               "key2 = value2\n"
+               "[section2]\n"
+               "key1 = value1\n"
+               "key2 = value2\n";
+
+       FILE* f = fmemopen(TEST_INPUT, strlen(TEST_INPUT), "r");
+       ASSERT(f);
+
+       struct pakfire_config* config;
+
+       ASSERT_SUCCESS(pakfire_config_create(&config));
+       ASSERT_SUCCESS(pakfire_config_read(config, f));
+
+       ASSERT_STRING_EQUALS(pakfire_config_get(config, "", "key1", NULL), "value1");
+       ASSERT_STRING_EQUALS(pakfire_config_get(config, "section1", "key1", NULL), "value1");
+       ASSERT_STRING_EQUALS(pakfire_config_get(config, "section1", "key2", NULL), "value2");
+       ASSERT_STRING_EQUALS(pakfire_config_get(config, "section2", "key1", NULL), "value1");
+       ASSERT_STRING_EQUALS(pakfire_config_get(config, "section2", "key2", NULL), "value2");
+
+       pakfire_config_free(config);
+
+       fclose(f);
+
+       return EXIT_SUCCESS;
+}
+
 int main(int argc, char** argv) {
        testsuite_add_test(test_get_and_set);
+       testsuite_add_test(test_parse);
 
        return testsuite_run();
 }