From da909e4f79db634446292ab7b96a2d2d6e9dde6f Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Tue, 8 May 2018 23:04:49 +0900 Subject: [PATCH] Add confreader library --- apps/test-conf.c | 18 ++++ base/etc/demo.conf | 7 ++ base/usr/include/toaru/confreader.h | 18 ++++ lib/confreader.c | 147 ++++++++++++++++++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 apps/test-conf.c create mode 100644 base/etc/demo.conf create mode 100644 base/usr/include/toaru/confreader.h create mode 100644 lib/confreader.c diff --git a/apps/test-conf.c b/apps/test-conf.c new file mode 100644 index 00000000..69b88e0a --- /dev/null +++ b/apps/test-conf.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include + + +int main(int argc, char * argv[]) { + confreader_t * conf = confreader_load("/etc/demo.conf"); + + fprintf(stderr, "test 1\n"); + assert(confreader_get(conf, "", "test") != NULL); + assert(!strcmp(confreader_get(conf, "", "test"),"hello")); + + fprintf(stderr, "test 2\n"); + assert(!strcmp(confreader_get(conf,"sec","tion"),"test")); + + return 0; +} diff --git a/base/etc/demo.conf b/base/etc/demo.conf new file mode 100644 index 00000000..5b1e9d8a --- /dev/null +++ b/base/etc/demo.conf @@ -0,0 +1,7 @@ +; this is a comment +test=hello + +[sec] +tion=test + +; this is also a comment diff --git a/base/usr/include/toaru/confreader.h b/base/usr/include/toaru/confreader.h new file mode 100644 index 00000000..f1fcb934 --- /dev/null +++ b/base/usr/include/toaru/confreader.h @@ -0,0 +1,18 @@ +/* vim: tabstop=4 shiftwidth=4 noexpandtab + */ + +#pragma once + +#include + +typedef struct { + hashmap_t * sections; +} confreader_t; + +confreader_t * confreader_load(const char * file); +char * confreader_get(confreader_t * ctx, char * section, char * value); +char * confreader_getd(confreader_t * ctx, char * section, char * value, char * def); +int confreader_int(confreader_t * ctx, char * section, char * value); +int confreader_intd(confreader_t * ctx, char * section, char * value, int def); +void confreader_free(confreader_t * conf); + diff --git a/lib/confreader.c b/lib/confreader.c new file mode 100644 index 00000000..8bb4384e --- /dev/null +++ b/lib/confreader.c @@ -0,0 +1,147 @@ +/* vim: tabstop=4 shiftwidth=4 noexpandtab + * This file is part of ToaruOS and is released under the terms + * of the NCSA / University of Illinois License - see LICENSE.md + * Copyright (C) 2018 K. Lange + * + * Configuration File Reader + * + * Reads an implementation of the INI "standard". Note that INI + * isn't actually a standard. We support the following: + * - ; comments + * - foo=bar keyword assignment + * - [sections] + */ +#include +#include +#include + +#define TRACE_APP_NAME "confreader" +#define TRACE(...) +//#include + +static void free_hashmap(void * h) { + hashmap_free(h); + free(h); +} + +confreader_t * confreader_load(const char * file) { + + confreader_t * out = malloc(sizeof(confreader_t)); + + out->sections = hashmap_create(10); + + FILE * f = fopen(file, "r"); + + hashmap_t * current_section = hashmap_create(10); + current_section->hash_val_free = free_hashmap; + + hashmap_set(out->sections, "", current_section); + + if (!f) { + /* File does not exist, no configuration values, but continue normally. */ + return out; + } + + char tmp[1024]; + char tmp2[1024]; + + while (!feof(f)) { + char c = fgetc(f); + tmp[0] = '\0'; + tmp2[0] = '\0'; + if (c == ';') { + TRACE("Comment"); + while (!feof(f) && fgetc(f) != '\n'); + TRACE("Done"); + } else if (c == '\n' || c == EOF) { + TRACE("blank line or EOF: %d", c); + continue; + } else if (c == '[') { + TRACE("section"); + char * foo = tmp; + int i; + while ((i = fgetc(f)) >= 0) { + if (i == ']') break; + *foo = i; + foo++; + *foo = '\0'; + } + while (!feof(f) && fgetc(f) != '\n'); + current_section = hashmap_create(10); + TRACE("adding section %s", tmp); + hashmap_set(out->sections, tmp, current_section); + TRACE("section is over"); + } else { + TRACE("value"); + char * foo = tmp; + *foo = c; + foo++; + int i; + while ((i = fgetc(f)) >= 0) { + if (i == '=') break; + *foo = i; + foo++; + *foo = '\0'; + } + if (i != '=') { + TRACE("no equals sign"); + while (!feof(f) && fgetc(f) != '\n'); + continue; + } + TRACE("="); + foo = tmp2; + while ((i = fgetc(f)) >= 0) { + if (i == '\n') break; + *foo = i; + foo++; + *foo = '\0'; + } + TRACE("setting value %s to %s", tmp, tmp2); + hashmap_set(current_section, tmp, strdup(tmp2)); + } + } + + fclose(f); + + TRACE("done reading"); + + return out; +} + +void confreader_free(confreader_t * conf) { + free_hashmap(conf->sections); + free(conf); +} + +char * confreader_get(confreader_t * ctx, char * section, char * value) { + if (!ctx) return NULL; + + hashmap_t * s = hashmap_get(ctx->sections, section); + + if (!s) { + TRACE("section doesn't exist: %s", section); + return NULL; + } + + return hashmap_get(s, value); +} + +char * confreader_getd(confreader_t * ctx, char * section, char * value, char * def) { + char * result = confreader_get(ctx, section, value); + return result ? result : def; +} + +int confreader_int(confreader_t * ctx, char * section, char * value) { + char * result = confreader_get(ctx, section, value); + if (!result) return 0; + return atoi(result); +} + +int confreader_intd(confreader_t * ctx, char * section, char * value, int def) { + char * result = confreader_get(ctx, section, value); + if (!result) return def; + return atoi(result); +} + + +