From: Michael Tremer Date: Fri, 16 Apr 2021 13:04:01 +0000 (+0000) Subject: config: Add function to parse files X-Git-Tag: 0.9.28~1285^2~352 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bbebb7174ba17299fc61c57ec402f9f767303630;p=pakfire.git config: Add function to parse files Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/config.c b/src/libpakfire/config.c index 148887253..1171ff1e6 100644 --- a/src/libpakfire/config.c +++ b/src/libpakfire/config.c @@ -18,6 +18,7 @@ # # #############################################################################*/ +#include #include #include #include @@ -26,15 +27,20 @@ #include #include +#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; +} diff --git a/src/libpakfire/include/pakfire/config.h b/src/libpakfire/include/pakfire/config.h index 9edeeb15a..31fc5666b 100644 --- a/src/libpakfire/include/pakfire/config.h +++ b/src/libpakfire/include/pakfire/config.h @@ -23,6 +23,8 @@ #ifdef PAKFIRE_PRIVATE +#include + 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 */ diff --git a/tests/libpakfire/config.c b/tests/libpakfire/config.c index f4b04ca3e..235297549 100644 --- a/tests/libpakfire/config.c +++ b/tests/libpakfire/config.c @@ -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(); }