diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-03-18 22:25:27 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-03-18 22:25:27 -0400 |
commit | ccaeb7092b5ad40b1b3833c987ba3ec4d47f0bb8 (patch) | |
tree | ae167772a9a2343aa77bf8944b56abe853f6a2ec /src/config.c | |
parent | 3731bb4679ee8716d4f579d5744c36a2d1b4a257 (diff) | |
download | spmc-ccaeb7092b5ad40b1b3833c987ba3ec4d47f0bb8.tar.gz |
Refactor project: build/install libspm[_static.a].so to make unit testing possible
Diffstat (limited to 'src/config.c')
-rw-r--r-- | src/config.c | 227 |
1 files changed, 0 insertions, 227 deletions
diff --git a/src/config.c b/src/config.c deleted file mode 100644 index 88c96fd..0000000 --- a/src/config.c +++ /dev/null @@ -1,227 +0,0 @@ -/** - * @file config.c - */ -#include "spm.h" - -/** - * Parse a basic configuration file - * - * NOTE: All values are stored as strings. You need to convert non-string values yourself. - * - * Example: - * ~~~{.c} - * ConfigItem **items = config_read("example.cfg"); - * if (!items) { - * // handle error - * } - * config_free(items); - * ~~~ - * - * - * @param filename - * @return success=`ConfigItem` array, failure=NULL - */ -ConfigItem **config_read(const char *filename) { - const char sep = '='; - size_t record = 0; - char *line = NULL; - FILE *fp = NULL; - - if (SPM_GLOBAL.verbose) { - printf("Reading configuration file: %s\n", filename); - } - - fp = fopen(filename, "r"); - if (!fp) { - // errno will be set, so die, and let the caller handle it - return NULL; - } - - ConfigItem **config = (ConfigItem **) calloc(record + 1, sizeof(ConfigItem *)); - if (!config) { - perror("ConfigItem"); - fprintf(SYSERROR); - fclose(fp); - return NULL; - } - - line = (char *)calloc(CONFIG_BUFFER_SIZE, sizeof(char)); - if (!line) { - perror("config line buffer"); - fprintf(SYSERROR); - return NULL; - } - - while (fgets(line, CONFIG_BUFFER_SIZE - 1, fp) != NULL) { - char *lptr = line; - // Remove trailing space and newlines - lptr = strip(lptr); - - // Remove leading space and newlines - lptr = lstrip(lptr); - - // Skip empty lines - if (isempty(lptr)) { - continue; - } - - // Skip comment-only lines - if (*lptr == '#' || *lptr == ';') { - continue; - } - - // Get a pointer to the key pair separator - char *sep_pos = strchr(lptr, sep); - if (!sep_pos) { - printf("invalid entry on line %zu: missing '%c': '%s'\n", record, sep, lptr); - continue; - } - - // These values are approximations. The real length(s) are recorded using strlen below. - // At most we'll lose a few heap bytes to whitespace, but it's better than allocating PATH_MAX or BUFSIZ - // for a measly ten byte string. - size_t key_length = strcspn(lptr, &sep); - size_t value_length = strlen(sep_pos); - - // Allocate a ConfigItem record - config[record] = (ConfigItem *)calloc(1, sizeof(ConfigItem)); - config[record]->key = (char *)calloc(key_length + 1, sizeof(char)); - config[record]->value = (char *)calloc(value_length + 1, sizeof(char)); - - if (!config[record] || !config[record]->key || !config[record]->value) { - perror("ConfigItem record"); - fprintf(SYSERROR); - return NULL; - } - - // Shortcut our array at this point. Things get pretty ugly otherwise. - char *key = config[record]->key; - char *value = config[record]->value; - - // Copy the array pointers (used to populate config->key/value_length - char *key_orig = key; - char *value_orig = value; - - // Populate the key and remove any trailing space - while (lptr != sep_pos) { - *key++ = *lptr++; - } - key = strip(key_orig); - - // We're at the separator now, so skip over it - lptr++; - // and remove any leading space - lptr = lstrip(lptr); - - // Determine whether the string is surrounded by quotes, if so, get rid of them - if (isquoted(lptr)) { - // Move pointer beyond quote - lptr = strpbrk(lptr, "'\"") + 1; - // Terminate on closing quote - char *tmp = strpbrk(lptr, "'\""); - *tmp = '\0'; - } - - // Populate the value, and ignore any inline comments - while (*lptr) { - if (*lptr == '#' || *lptr == ';') { - // strip trailing whitespace where the comment is and stop processing - value = strip(value); - break; - } - *value++ = *lptr++; - } - - // Populate length data - config[record]->key_length = strlen(key_orig); - config[record]->value_length = strlen(value_orig); - - // Destroy contents of line buffer - memset(line, '\0', CONFIG_BUFFER_SIZE); - - if (SPM_GLOBAL.verbose) { - printf("CONFIG RECORD=%zu, PTR='%p', KEY='%s', VALUE='%s'\n", - record, config[record], config[record]->key, config[record]->value); - } - - // increment record count - record++; - - // Expand config by another record - config = (ConfigItem **)reallocarray(config, record + 1, sizeof(ConfigItem *)); - if (!config) { - perror("ConfigItem array"); - fprintf(SYSERROR); - free(line); - return NULL; - } - - config[record] = NULL; - } - free(line); - return config; -} - -/** - * Free memory allocated by `config_read` - * @param item `ConfigItem` array - */ -void config_free(ConfigItem **item) { - for (size_t i = 0; item[i] != NULL; i++) { - free(item[i]->key); - free(item[i]->value); - free(item[i]); - } - free(item); -} - -/** - * If the `ConfigItem` array contains `key`, return a pointer to that record - * - * Example: - * ~~~{.c} - * char *nptr = NULL; - * ConfigItem *item = config_get(items, "a_number"); - * if (!item) { - * // handle error - * } - * int the_number = strtol(item->value, &nptr, 10); - * printf("%s = %d\n", item->key, the_number); - * ~~~ - * - * @param item pointer to array of config records - * @param key search for key in config records - * @return success=pointer to record, failure=NULL - */ -ConfigItem *config_get(ConfigItem **item, const char *key) { - if (!item) { - return NULL; - } - for (size_t i = 0; item[i] != NULL; i++) { - if (!strcmp(item[i]->key, key)) { - return item[i]; - } - } - return NULL; -} - -void config_test(void) { - ConfigItem **config = config_read("program.conf"); - printf("Data Parsed:\n"); - for (int i = 0; config[i] != NULL; i++) { - printf("key: '%s', value: '%s'\n", config[i]->key, config[i]->value); - } - - printf("Testing config_get():\n"); - ConfigItem *cptr = NULL; - if ((cptr = config_get(config, "integer_value"))) { - printf("%s = %d\n", cptr->key, atoi(cptr->value)); - } - if ((cptr = config_get(config, "float_value"))) { - printf("%s = %.3f\n", cptr->key, atof(cptr->value)); - } - if ((cptr = config_get(config, "string_value"))) { - printf("%s = %s\n", cptr->key, cptr->value); - } - config_free(config); -} |