/* * Author, Copyright: Oleg Borodin <onborodin@gmail.com> */ #include <regex.h> #define _WITH_GETLINE #include <stdio.h> #include <stdlib.h> #include <string.h> #include "vector.h" typedef struct keyvalue { char* key; char* value; } keyvalue_t; int config_kvmatch(char* str, keyvalue_t** kv) { size_t nmatch = 4; regmatch_t pmatch[5]; char* pattern = "^[\t ]*([A-Za-z0-9_\\.]+)[\t ]*[=:]+[\t ]*([A-Za-z0-9_\\.]+)[\t #;]*"; regex_t preg; int rc; if ((rc = regcomp(&preg, pattern, REG_EXTENDED)) != 0) { regfree(&preg); return -1; } if ((rc = regexec(&preg, str, nmatch, pmatch, 0)) != 0) { regfree(&preg); return -1; } if (pmatch[1].rm_so < 0 || pmatch[2].rm_so < 0) { regfree(&preg); return -1; } *kv = (keyvalue_t*)malloc(sizeof(keyvalue_t)); if (*kv == NULL) { regfree(&preg); return -1; } (*kv)->value = NULL; (*kv)->key = NULL; size_t ksize = pmatch[1].rm_eo - pmatch[1].rm_so; (*kv)->key = (char*)malloc(ksize); memset((void*)(*kv)->key, 0, ksize); memcpy((*kv)->key, &str[pmatch[1].rm_so], ksize); size_t vsize = pmatch[2].rm_eo - pmatch[2].rm_so; (*kv)->value = (char*)malloc(vsize); memset((*kv)->value, 0, vsize); memcpy((*kv)->value, &str[pmatch[2].rm_so], vsize); regfree(&preg); return 1; } vector_t* config_read(char* filename) { if (filename == NULL) return NULL; FILE* fp = fopen(filename, "r"); if (fp == NULL) return NULL; char *line = NULL; size_t linecap = 0; ssize_t linelen; vector_t* v = vector_create(); if (v == NULL) return NULL; while ((linelen = getline(&line, &linecap, fp)) > 0) { keyvalue_t* kv = NULL; if (config_kvmatch(line, &kv) < 0) continue; vector_add(v, kv); } free(line); fclose(fp); return v; } char* config_getv(vector_t* v, char* key) { if (key == NULL || v == NULL) return NULL; for(int i = 0; i < vector_size(v); i++) { keyvalue_t* kv = vector_get(v, i); if (kv->key != NULL && kv->value != NULL) { if (strcmp(key, kv->key) == 0) { return kv->value; } } } return NULL; } void config_free(vector_t* v) { if (v == NULL) return; for(int i = 0; i < vector_size(v); i++) { keyvalue_t* kv = vector_get(v, i); if (kv->key != NULL) free(kv->key); if (kv->value != NULL) free(kv->value); if (kv != NULL) free(kv); } vector_free(v); } int main(int argc, char **argv) { vector_t* confv = config_read("sample.conf"); if (confv == NULL) return 1; for(int i = 0; i < vector_size(confv); i++) { keyvalue_t* kv = vector_get(confv, i); printf("%s=%s;\n", kv->key, kv->value); } printf("get some: %s\n", config_getv(confv, "some")); config_free(confv); return 0; }
/* * Author, Copyright: Oleg Borodin <onborodin@gmail.com> */ #ifndef VECTOR_H_QWE #define VECTOR_H_QWE #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #define VECTOR_INIT_CAPACITY 4 typedef struct vector { void **items; int capacity; int size; } vector_t; vector_t* vector_create() { vector_t* v = malloc(sizeof(vector_t)); if (v == NULL) return NULL; v->capacity = VECTOR_INIT_CAPACITY; v->size = 0; v->items = malloc(sizeof(void*) * v->capacity); return v; } int vector_size(vector_t *v) { return v->size; } int vector_resize(vector_t *v, int capacity) { void **newitems = realloc(v->items, sizeof(void*) * capacity); if (newitems != NULL) { v->items = newitems; v->capacity = capacity; return 1; } return -1; } int vector_add(vector_t *v, void *item) { if (v->capacity == v->size) { if (vector_resize(v, v->capacity * 2) < 0) { return -1; } } v->items[v->size++] = item; return 1; } int vector_set(vector_t *v, int index, void *item) { if (index >= 0 && index < v->size) { v->items[index] = item; return 1; } return -1; } void* vector_get(vector_t *v, int index) { if (index >= 0 && index < v->size) { return v->items[index]; } return NULL; } int vector_delete(vector_t *v, int index) { if (index < 0 || index >= v->size) { return -1; } v->items[index] = NULL; for (int i = index; i < v->size - 1; i++) { v->items[i] = v->items[i + 1]; v->items[i + 1] = NULL; } v->size--; if (v->size > 0 && v->size == v->capacity / 4) { vector_resize(v, v->capacity / 2); } return 1; } void vector_free(vector_t *v) { if (v->items != NULL) free(v->items); if (v != NULL) free(v); } #endif
# comment = badvalue; some = bare foo = qwerty #comment rur=krewr; oldv : uio; avert = 456; // avert2 = 789 // #end
$ ./config some=bare; foo=qwerty; rur=krewr; oldv=uio; avert=456; avert2=789; get some: bare $
==57064== LEAK SUMMARY: ==57064== definitely lost: 0 bytes in 0 blocks ==57064== indirectly lost: 0 bytes in 0 blocks ==57064== possibly lost: 0 bytes in 0 blocks ==57064== still reachable: 1,184 bytes in 2 blocks ==57064== suppressed: 0 bytes in 0 blocks
[<>]