From cceb1aa20d8aacb8e7320b75986ab962d62b3a37 Mon Sep 17 00:00:00 2001 From: "Andrei \"Akari\" Alexeyev" Date: Sat, 11 Mar 2017 23:10:05 +0200 Subject: [PATCH] Converted the config parser into reusable utility functions --- src/config.c | 71 +++++------------------------------- src/util.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 8 ++++ 3 files changed, 118 insertions(+), 62 deletions(-) diff --git a/src/config.c b/src/config.c index 29038734..4ad28beb 100644 --- a/src/config.c +++ b/src/config.c @@ -269,8 +269,12 @@ static void config_delete_unknown_entries(void) { delete_all_elements((void**)&unknowndefs, config_delete_unknown_entry); } +static char* config_path(const char *filename) { + return strjoin(get_config_path(), "/", filename, NULL); +} + static FILE* config_open(const char *filename, const char *mode) { - char *buf = strjoin(get_config_path(), "/", filename, NULL); + char *buf = config_path(filename); FILE *out = fopen(buf, mode); free(buf); @@ -327,7 +331,7 @@ void config_save(const char *filename) { #define INTOF(s) ((int)strtol(s, NULL, 10)) #define FLOATOF(s) ((float)strtod(s, NULL)) -static void config_set(const char *key, const char *val) { +static void config_set(const char *key, const char *val, void *data) { ConfigEntry *e = config_find_entry(key); if(!e) { @@ -367,67 +371,10 @@ static void config_set(const char *key, const char *val) { #undef FLOATOF void config_load(const char *filename) { - FILE *in = config_open(filename, "r"); - int c, i = 0, found, line = 0; - char buf[CONFIG_LOAD_BUFSIZE]; - char key[CONFIG_LOAD_BUFSIZE]; - char val[CONFIG_LOAD_BUFSIZE]; - + char *path = config_path(filename); config_init(); - - if(!in) { - return; - } - - while((c = fgetc(in)) != EOF) { - if(c == '#' && !i) { - i = 0; - while(fgetc(in) != '\n'); - } else if(c == ' ') { - if(!i) SYNTAXERROR - - buf[i] = 0; - i = 0; - strcpy(key, buf); - - found = 0; - while((c = fgetc(in)) != EOF) { - if(c == '=') { - if(++found > 1) SYNTAXERROR - } else if(c != ' ') { - if(!found || c == '\n') SYNTAXERROR - - do { - if(c == '\n') { - if(!i) SYNTAXERROR - - buf[i] = 0; - i = 0; - strcpy(val, buf); - found = 0; - ++line; - - config_set(key, val); - break; - } else { - buf[i++] = c; - if(i == CONFIG_LOAD_BUFSIZE) - BUFFERERROR - } - } while((c = fgetc(in)) != EOF); - - break; - } - } if(found) SYNTAXERROR - } else { - buf[i++] = c; - if(i == CONFIG_LOAD_BUFSIZE) - BUFFERERROR - } - } - -end: - fclose(in); + parse_keyvalue_file_cb(path, config_set, NULL); + free(path); } #undef SYNTAXERROR diff --git a/src/util.c b/src/util.c index 945be006..9079b97d 100644 --- a/src/util.c +++ b/src/util.c @@ -252,6 +252,107 @@ char* read_all(const char *filename, int *outsize) { return text; } +bool parse_keyvalue_stream_cb(SDL_RWops *strm, KVCallback callback, void *data) { + const size_t bufsize = 128; + +#define SYNTAXERROR { warnx("%s(): syntax error on line %i, aborted! [%s:%i]\n", __func__, line, __FILE__, __LINE__); return false; } +#define BUFFERERROR { warnx("%s(): string exceed the limit of %i, aborted! [%s:%i]", __func__, bufsize, __FILE__, __LINE__); return false; } + + int i = 0, found, line = 0; + char c, buf[bufsize], key[bufsize], val[bufsize]; + + while(c = (char)SDL_ReadU8(strm)) { + if(c == '#' && !i) { + i = 0; + while((char)SDL_ReadU8(strm) != '\n'); + } else if(c == ' ') { + if(!i) SYNTAXERROR + + buf[i] = 0; + i = 0; + strcpy(key, buf); + + found = 0; + while(c = (char)SDL_ReadU8(strm)) { + if(c == '=') { + if(++found > 1) SYNTAXERROR + } else if(c != ' ') { + if(!found || c == '\n') SYNTAXERROR + + do { + if(c == '\n') { + if(!i) SYNTAXERROR + + buf[i] = 0; + i = 0; + strcpy(val, buf); + found = 0; + ++line; + + callback(key, val, data); + break; + } else { + buf[i++] = c; + if(i == bufsize) + BUFFERERROR + } + } while(c = (char)SDL_ReadU8(strm)); + + break; + } + } if(found) SYNTAXERROR + } else { + buf[i++] = c; + if(i == bufsize) + BUFFERERROR + } + } + + return true; + +#undef SYNTAXERROR +#undef BUFFERERROR +} + +bool parse_keyvalue_file_cb(const char *filename, KVCallback callback, void *data) { + SDL_RWops *strm = SDL_RWFromFile(filename, "r"); + + if(!strm) { + warnx("parse_keyvalue_file_cb(): SDL_RWFromFile() failed: %s", SDL_GetError()); + return false; + } + + bool status = parse_keyvalue_stream_cb(strm, callback, data); + SDL_RWclose(strm); + return status; +} + +static void kvcallback_hashtable(const char *key, const char *val, Hashtable *ht) { + hashtable_set_string(ht, key, (void*)val); +} + +Hashtable* parse_keyvalue_stream(SDL_RWops *strm) { + Hashtable *ht = hashtable_new_stringkeys(37); + + if(!parse_keyvalue_stream_cb(strm, (KVCallback)kvcallback_hashtable, ht)) { + free(ht); + ht = NULL; + } + + return ht; +} + +Hashtable* parse_keyvalue_file(const char *filename) { + Hashtable *ht = hashtable_new_stringkeys(37); + + if(!parse_keyvalue_file_cb(filename, (KVCallback)kvcallback_hashtable, ht)) { + free(ht); + ht = NULL; + } + + return ht; +} + // // misc utils // diff --git a/src/util.h b/src/util.h index 69b272a8..2bee312d 100644 --- a/src/util.h +++ b/src/util.h @@ -6,6 +6,8 @@ #include #include #include // compiling under mingw may fail without this... +#include +#include "hashtable.h" // // compatibility @@ -92,7 +94,13 @@ void fade_out(float f); // i/o utils // +typedef void (*KVCallback)(const char *key, const char *value, void *data); + char* read_all(const char *filename, int *size); +bool parse_keyvalue_stream_cb(SDL_RWops *strm, KVCallback callback, void *data); +bool parse_keyvalue_file_cb(const char *filename, KVCallback callback, void *data); +Hashtable* parse_keyvalue_stream(SDL_RWops *strm); +Hashtable* parse_keyvalue_file(const char *filename); // // misc utils