Converted the config parser into reusable utility functions
This commit is contained in:
parent
c82928a8da
commit
cceb1aa20d
3 changed files with 118 additions and 62 deletions
71
src/config.c
71
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
|
||||
|
|
101
src/util.c
101
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
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue