Converted the config parser into reusable utility functions

This commit is contained in:
Andrei "Akari" Alexeyev 2017-03-11 23:10:05 +02:00
parent c82928a8da
commit cceb1aa20d
3 changed files with 118 additions and 62 deletions

View file

@ -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

View file

@ -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
//

View file

@ -6,6 +6,8 @@
#include <string.h>
#include <stdio.h>
#include <zlib.h> // compiling under mingw may fail without this...
#include <SDL.h>
#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