#include #include #include #include #include "uconfig.h" struct uconfig_pair_s { char *key; char *value; struct uconfig_pair_s *next; }; struct uconfig_s { struct uconfig_pair_s *head; struct uconfig_pair_s *tail; }; static struct uconfig_pair_s *uconfig_pair_new(char *line, int sep_idx) { assert(line[sep_idx] == '='); line[sep_idx] = '\0'; struct uconfig_pair_s *pair = malloc(sizeof(struct uconfig_pair_s)); pair->key = strdup(line); pair->value = strdup(line + sep_idx + 1); pair->next = NULL; return pair; } static void uconfig_add_tail(struct uconfig_s *uconfig, struct uconfig_pair_s *pair) { if (!uconfig->head) { /* first pair in the config handle */ uconfig->head = pair; uconfig->tail = pair; } else { uconfig->tail->next = pair; uconfig->tail = pair; } } static int uconfig_parse_line(struct uconfig_s *uconfig, const char *file, int line_number, char *line, ssize_t line_len) { /* Remove trailing newline, if any */ if (line[line_len - 1] == '\n') { line[line_len - 1] = '\0'; line_len--; } /* Find index of '=' character in the line */ int sep_idx = 0; while ((sep_idx < line_len) && (line[sep_idx] != '=')) { sep_idx++; } if (sep_idx == line_len) { fprintf(stderr, "%s: %s:%d: no '=' character found\n", __func__, file, line_number); return -1; } struct uconfig_pair_s *pair = uconfig_pair_new(line, sep_idx); uconfig_add_tail(uconfig, pair); return 0; } struct uconfig_s *uconfig_new(const char*file) { FILE *input = fopen(file, "r"); struct uconfig_s *uconfig = NULL; ssize_t line_len; size_t line_size = 128; char *line = NULL; int line_number = 1; int rc; if (input == NULL) { fprintf(stderr, "%s: fopen: %s: ", __func__, file); perror(""); goto err; } uconfig = calloc(1, sizeof(struct uconfig_s)); line = malloc(line_size); while ((line_len = getline(&line, &line_size, input)) != -1) { rc = uconfig_parse_line(uconfig, file, line_number, line, line_len); if (rc == -1) goto err; line_number++; } if (ferror(input)) { fprintf(stderr, "%s: getline: %s: ", __func__, file); perror(""); goto err; } free(line); fclose(input); return uconfig; err: if (input) fclose(input); if (line) free(line); if (uconfig) uconfig_destroy(uconfig); return NULL; } const char *uconfig_get(const struct uconfig_s *uconfig, const char *key) { struct uconfig_pair_s *pair = uconfig->head; while (pair) { if (strcmp(pair->key, key) == 0) return pair->value; pair = pair->next; } return NULL; } static void uconfig_destroy_pairs(struct uconfig_pair_s *pair) { if (pair->next) uconfig_destroy_pairs(pair->next); free(pair->key); free(pair->value); free(pair); } void uconfig_destroy(struct uconfig_s *uconfig) { uconfig_destroy_pairs(uconfig->head); }