frontlib: Rewrote the ini helper code, finished ini reading/writing support for all relevant file types
--- a/project_files/frontlib/ipc/ipcconn.c Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/ipc/ipcconn.c Tue Jun 12 21:10:11 2012 +0200
@@ -15,7 +15,7 @@
*
* We don't need to worry about wasting a few kb though, and I like powers of two...
*/
-typedef struct _flib_ipcconn {
+struct _flib_ipcconn {
uint8_t readBuffer[8192];
int readBufferSize;
@@ -23,10 +23,10 @@
uint16_t port;
flib_tcpsocket *sock;
-} _flib_ipcconn;
+};
flib_ipcconn *flib_ipcconn_create() {
- flib_ipcconn *result = flib_malloc(sizeof(_flib_ipcconn));
+ flib_ipcconn *result = flib_malloc(sizeof(flib_ipcconn));
flib_acceptor *acceptor = flib_acceptor_create(0);
if(!result || !acceptor) {
--- a/project_files/frontlib/model/cfg.c Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/model/cfg.c Tue Jun 12 21:10:11 2012 +0200
@@ -1,17 +1,16 @@
#include "cfg.h"
-#include "../iniparser/iniparser.h"
-#include "../iniparser/dictionary.h"
#include "../util/inihelper.h"
#include "../util/logging.h"
#include "../util/util.h"
#include <stdio.h>
+#include <stdlib.h>
-static flib_cfg_meta *flib_cfg_meta_from_ini_handleError(flib_cfg_meta *result, dictionary *settingfile, dictionary *modfile) {
+static flib_cfg_meta *flib_cfg_meta_from_ini_handleError(flib_cfg_meta *result, flib_ini *settingfile, flib_ini *modfile) {
flib_cfg_meta_destroy(result);
- iniparser_freedict(settingfile);
- iniparser_freedict(modfile);
+ flib_ini_destroy(settingfile);
+ flib_ini_destroy(modfile);
return NULL;
}
@@ -21,15 +20,15 @@
return NULL;
}
flib_cfg_meta *result = flib_calloc(1, sizeof(flib_cfg_meta));
- dictionary *settingfile = iniparser_load(settingpath);
- dictionary *modfile = iniparser_load(modpath);
+ flib_ini *settingfile = flib_ini_load(settingpath);
+ flib_ini *modfile = flib_ini_load(modpath);
if(!result || !settingfile || !modfile) {
return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
}
- result->settingCount = iniparser_getnsec(settingfile);
- result->modCount = iniparser_getnsec(modfile);
+ result->settingCount = flib_ini_get_sectioncount(settingfile);
+ result->modCount = flib_ini_get_sectioncount(modfile);
result->settings = flib_calloc(result->settingCount, sizeof(flib_cfg_setting_meta));
result->mods = flib_calloc(result->modCount, sizeof(flib_cfg_mod_meta));
@@ -38,44 +37,45 @@
}
for(int i=0; i<result->settingCount; i++) {
- char *sectionName = iniparser_getsecname(settingfile, i);
- if(!sectionName) {
+ result->settings[i].iniName = flib_ini_get_sectionname(settingfile, i);
+ if(!result->settings[i].iniName) {
return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
}
bool error = false;
- result->settings[i].iniName = flib_strdupnull(sectionName);
- result->settings[i].title = inihelper_getstringdup(settingfile, &error, sectionName, "title");
- result->settings[i].engineCommand = inihelper_getstringdup(settingfile, &error, sectionName, "command");
- result->settings[i].image = inihelper_getstringdup(settingfile, &error, sectionName, "image");
- result->settings[i].checkOverMax = inihelper_getbool(settingfile, &error, sectionName, "checkOverMax");
- result->settings[i].times1000 = inihelper_getbool(settingfile, &error, sectionName, "times1000");
- result->settings[i].min = inihelper_getint(settingfile, &error, sectionName, "min");
- result->settings[i].max = inihelper_getint(settingfile, &error, sectionName, "max");
- result->settings[i].def = inihelper_getint(settingfile, &error, sectionName, "default");
+ error |= flib_ini_enter_section(settingfile, result->settings[i].iniName);
+ error |= flib_ini_get_str(settingfile, &result->settings[i].title, "title");
+ error |= flib_ini_get_str(settingfile, &result->settings[i].engineCommand, "command");
+ error |= flib_ini_get_str(settingfile, &result->settings[i].image, "image");
+ error |= flib_ini_get_bool(settingfile, &result->settings[i].checkOverMax, "checkOverMax");
+ error |= flib_ini_get_bool(settingfile, &result->settings[i].times1000, "times1000");
+ error |= flib_ini_get_int(settingfile, &result->settings[i].min, "min");
+ error |= flib_ini_get_int(settingfile, &result->settings[i].max, "max");
+ error |= flib_ini_get_int(settingfile, &result->settings[i].def, "default");
+
if(error) {
- flib_log_e("Missing or malformed ini parameter in file %s, section %s", settingpath, sectionName);
+ flib_log_e("Missing or malformed ini parameter in file %s, section %s", settingpath, result->settings[i].iniName);
return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
}
}
for(int i=0; i<result->modCount; i++) {
- char *sectionName = iniparser_getsecname(modfile, i);
- if(!sectionName) {
+ result->mods[i].iniName = flib_ini_get_sectionname(modfile, i);
+ if(!result->mods[i].iniName) {
return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
}
bool error = false;
- result->mods[i].iniName = flib_strdupnull(sectionName);
- result->mods[i].bitmaskIndex = inihelper_getint(modfile, &error, sectionName, "bitmaskIndex");
+ error |= flib_ini_enter_section(modfile, result->mods[i].iniName);
+ error |= flib_ini_get_int(modfile, &result->mods[i].bitmaskIndex, "bitmaskIndex");
if(error) {
- flib_log_e("Missing or malformed ini parameter in file %s, section %s", modpath, sectionName);
+ flib_log_e("Missing or malformed ini parameter in file %s, section %s", modpath, result->mods[i].iniName);
return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
}
}
- iniparser_freedict(settingfile);
- iniparser_freedict(modfile);
+ flib_ini_destroy(settingfile);
+ flib_ini_destroy(modfile);
return result;
}
@@ -124,8 +124,8 @@
return result;
}
-flib_cfg *flib_cfg_from_ini_handleError(flib_cfg *result, dictionary *settingfile) {
- iniparser_freedict(settingfile);
+flib_cfg *flib_cfg_from_ini_handleError(flib_cfg *result, flib_ini *settingfile) {
+ flib_ini_destroy(settingfile);
flib_cfg_destroy(result);
return NULL;
}
@@ -135,36 +135,45 @@
flib_log_e("null parameter in flib_cfg_from_ini");
return NULL;
}
- dictionary *settingfile = iniparser_load(filename);
+ flib_ini *settingfile = flib_ini_load(filename);
if(!settingfile) {
return NULL;
}
- bool error = false;
- char *schemename = inihelper_getstring(settingfile, &error, "Scheme", "name");
- if(!schemename) {
+ char *schemename = NULL;
+ if(flib_ini_enter_section(settingfile, "Scheme")) {
+ flib_log_e("Missing section \"Scheme\" in config file %s.", filename);
+ return flib_cfg_from_ini_handleError(NULL, settingfile);
+ }
+ if(flib_ini_get_str(settingfile, &schemename, "name")) {
+ flib_log_e("Missing scheme name in config file %s.", filename);
return flib_cfg_from_ini_handleError(NULL, settingfile);
}
flib_cfg *result = flib_cfg_create(meta, schemename);
- for(int i=0; i<meta->settingCount; i++) {
- char *key = inihelper_createDictKey("BasicSettings", meta->settings[i].iniName);
- if(!key) {
- return flib_cfg_from_ini_handleError(result, settingfile);
+ if(flib_ini_enter_section(settingfile, "BasicSettings")) {
+ flib_log_w("Missing section \"BasicSettings\" in config file %s, using defaults.", filename);
+ } else {
+ for(int i=0; i<meta->settingCount; i++) {
+ if(flib_ini_get_int_opt(settingfile, &result->settings[i], meta->settings[i].iniName, meta->settings[i].def)) {
+ flib_log_e("Error reading BasicSetting %s in config file %s.", meta->settings[i].iniName, filename);
+ return flib_cfg_from_ini_handleError(result, settingfile);
+ }
}
- result->settings[i] = iniparser_getint(settingfile, key, meta->settings[i].def);
- free(key);
}
- for(int i=0; i<meta->modCount; i++) {
- char *key = inihelper_createDictKey("GameMods", meta->mods[i].iniName);
- if(!key) {
- return flib_cfg_from_ini_handleError(result, settingfile);
+
+ if(flib_ini_enter_section(settingfile, "GameMods")) {
+ flib_log_w("Missing section \"GameMods\" in config file %s, using defaults.", filename);
+ } else {
+ for(int i=0; i<meta->modCount; i++) {
+ if(flib_ini_get_bool_opt(settingfile, &result->mods[i], meta->mods[i].iniName, false)) {
+ flib_log_e("Error reading GameMod %s in config file %s.", meta->mods[i].iniName, filename);
+ return flib_cfg_from_ini_handleError(result, settingfile);
+ }
}
- result->mods[i] = iniparser_getboolean(settingfile, key, false);
- free(key);
}
- iniparser_freedict(settingfile);
+ flib_ini_destroy(settingfile);
return result;
}
@@ -173,35 +182,36 @@
if(!meta || !filename || !config || config->modCount!=meta->modCount || config->settingCount!=meta->settingCount) {
flib_log_e("Invalid parameter in flib_cfg_to_ini");
} else {
- dictionary *dict = iniparser_load(filename);
- if(!dict) {
- dict = dictionary_new(0);
- }
- if(dict) {
+ flib_ini *ini = flib_ini_create(filename);
+ if(ini) {
bool error = false;
- // Add the sections
- error |= iniparser_set(dict, "Scheme", NULL);
- error |= iniparser_set(dict, "BasicSettings", NULL);
- error |= iniparser_set(dict, "GameMods", NULL);
// Add the values
- error |= inihelper_setstr(dict, "Scheme", "name", config->schemeName);
- for(int i=0; i<config->settingCount; i++) {
- error |= inihelper_setint(dict, "BasicSettings", meta->settings[i].iniName, config->settings[i]);
- }
- for(int i=0; i<config->modCount; i++) {
- error |= inihelper_setbool(dict, "GameMods", meta->mods[i].iniName, config->mods[i]);
+ error |= flib_ini_create_section(ini, "Scheme");
+ if(!error) {
+ error |= flib_ini_set_str(ini, "name", config->schemeName);
}
+
+
+ error |= flib_ini_create_section(ini, "BasicSettings");
if(!error) {
- FILE *inifile = fopen(filename, "wb");
- if(inifile) {
- iniparser_dump_ini(dict, inifile);
- fclose(inifile);
- result = 0;
+ for(int i=0; i<config->settingCount; i++) {
+ error |= flib_ini_set_int(ini, meta->settings[i].iniName, config->settings[i]);
}
}
- dictionary_del(dict);
+
+ error |= flib_ini_create_section(ini, "GameMods");
+ if(!error) {
+ for(int i=0; i<config->modCount; i++) {
+ error |= flib_ini_set_bool(ini, meta->mods[i].iniName, config->mods[i]);
+ }
+ }
+
+ if(!error) {
+ result = flib_ini_save(ini, filename);
+ }
}
+ flib_ini_destroy(ini);
}
return result;
}
--- a/project_files/frontlib/model/team.c Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/model/team.c Tue Jun 12 21:10:11 2012 +0200
@@ -3,84 +3,189 @@
#include "../util/inihelper.h"
#include "../util/util.h"
#include "../util/logging.h"
+#include <string.h>
+#include <stdlib.h>
-static flib_team *from_ini_handleError(flib_team *result, dictionary *settingfile, char **bindingKeys) {
- if(settingfile) {
- iniparser_freedict(settingfile);
- }
+static flib_team *from_ini_handleError(flib_team *result, flib_ini *settingfile) {
+ flib_ini_destroy(settingfile);
flib_team_destroy(result);
- free(bindingKeys);
return NULL;
}
flib_team *flib_team_from_ini(const char *filename) {
flib_team *result = flib_calloc(1, sizeof(flib_team));
- dictionary *settingfile = NULL;
- char **bindingKeys = NULL;
+ flib_ini *ini = NULL;
if(!filename) {
flib_log_e("null parameter in flib_team_from_ini");
- return from_ini_handleError(result, settingfile, bindingKeys);
+ return from_ini_handleError(result, ini);
}
if(!result) {
- return from_ini_handleError(result, settingfile, bindingKeys);
+ return from_ini_handleError(result, ini);
+ }
+
+ ini = flib_ini_load(filename);
+ if(!ini) {
+ flib_log_e("Error loading team file %s", filename);
+ return from_ini_handleError(result, ini);
}
- settingfile = iniparser_load(filename);
- if(!settingfile) {
- flib_log_e("Error loading team file %s", filename);
- return from_ini_handleError(result, settingfile, bindingKeys);
+ if(flib_ini_enter_section(ini, "team")) {
+ flib_log_e("Missing section \"Team\" in team file %s", filename);
+ return from_ini_handleError(result, ini);
+ }
+ bool error = false;
+ error |= flib_ini_get_str(ini, &result->name, "name");
+ error |= flib_ini_get_str(ini, &result->grave, "grave");
+ error |= flib_ini_get_str(ini, &result->fort, "fort");
+ error |= flib_ini_get_str(ini, &result->voicepack, "voicepack");
+ error |= flib_ini_get_str(ini, &result->flag, "flag");
+ error |= flib_ini_get_int(ini, &result->rounds, "rounds");
+ error |= flib_ini_get_int(ini, &result->wins, "wins");
+ error |= flib_ini_get_int(ini, &result->campaignProgress, "campaignprogress");
+
+ int difficulty = 0;
+ error |= flib_ini_get_int(ini, &difficulty, "difficulty");
+
+ if(error) {
+ flib_log_e("Missing or malformed entry in section \"Team\" in file %s", filename);
+ return from_ini_handleError(result, ini);
}
- bool error = false;
- result->name = inihelper_getstringdup(settingfile, &error, "team", "name");
- result->grave = inihelper_getstringdup(settingfile, &error, "team", "grave");
- result->fort = inihelper_getstringdup(settingfile, &error, "team", "fort");
- result->voicepack = inihelper_getstringdup(settingfile, &error, "team", "voicepack");
- result->flag = inihelper_getstringdup(settingfile, &error, "team", "flag");
- result->rounds = inihelper_getint(settingfile, &error, "team", "rounds");
- result->wins = inihelper_getint(settingfile, &error, "team", "wins");
- result->campaignProgress = inihelper_getint(settingfile, &error, "team", "campaignprogress");
- int difficulty = inihelper_getint(settingfile, &error, "team", "difficulty");
-
- char sectionName[10];
- strcpy(sectionName, "hedgehog0");
for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
- sectionName[8] = '0'+i;
- result->hogs[i].name = inihelper_getstringdup(settingfile, &error, sectionName, "name");
- result->hogs[i].hat = inihelper_getstringdup(settingfile, &error, sectionName, "hat");
- result->hogs[i].rounds = inihelper_getint(settingfile, &error, sectionName, "rounds");
- result->hogs[i].kills = inihelper_getint(settingfile, &error, sectionName, "kills");
- result->hogs[i].deaths = inihelper_getint(settingfile, &error, sectionName, "deaths");
- result->hogs[i].suicides = inihelper_getint(settingfile, &error, sectionName, "suicides");
+ char sectionName[32];
+ if(snprintf(sectionName, sizeof(sectionName), "hedgehog%i", i) <= 0) {
+ return from_ini_handleError(result, ini);
+ }
+ if(flib_ini_enter_section(ini, sectionName)) {
+ flib_log_e("Missing section \"%s\" in team file %s", sectionName, filename);
+ return from_ini_handleError(result, ini);
+ }
+ flib_hog *hog = &result->hogs[i];
+ error |= flib_ini_get_str(ini, &hog->name, "name");
+ error |= flib_ini_get_str(ini, &hog->hat, "hat");
+ error |= flib_ini_get_int(ini, &hog->rounds, "rounds");
+ error |= flib_ini_get_int(ini, &hog->kills, "kills");
+ error |= flib_ini_get_int(ini, &hog->deaths, "deaths");
+ error |= flib_ini_get_int(ini, &hog->suicides, "suicides");
result->hogs[i].difficulty = difficulty;
result->hogs[i].initialHealth = TEAM_DEFAULT_HEALTH;
+
+ if(error) {
+ flib_log_e("Missing or malformed entry in section \"%s\" in file %s", sectionName, filename);
+ return from_ini_handleError(result, ini);
+ }
}
- result->bindingCount = iniparser_getsecnkeys(settingfile, "binds");
- result->bindings = flib_calloc(result->bindingCount, sizeof(flib_binding));
- bindingKeys = iniparser_getseckeys(settingfile, "binds");
- if(!result->bindings || !bindingKeys) {
- return from_ini_handleError(result, settingfile, bindingKeys);
- }
-
- for(int i=0; i<result->bindingCount; i++) {
- result->bindings[i].binding = flib_strdupnull(iniparser_getstring(settingfile, bindingKeys[i], NULL));
- // The key names all start with "binds:", so we skip that.
- result->bindings[i].action = inihelper_urldecode(bindingKeys[i]+strlen("binds:"));
- if(!result->bindings[i].action || !result->bindings[i].binding) {
- error = true;
+ if(!flib_ini_enter_section(ini, "binds")) {
+ result->bindingCount = flib_ini_get_keycount(ini);
+ if(result->bindingCount<0) {
+ flib_log_e("Error reading bindings from file %s", filename);
+ result->bindingCount = 0;
+ }
+ result->bindings = flib_calloc(result->bindingCount, sizeof(flib_binding));
+ if(!result->bindings) {
+ return from_ini_handleError(result, ini);
+ }
+ for(int i=0; i<result->bindingCount; i++) {
+ char *keyname = flib_ini_get_keyname(ini, i);
+ if(!keyname) {
+ error = true;
+ } else {
+ result->bindings[i].action = flib_urldecode(keyname);
+ error |= !result->bindings[i].action;
+ error |= flib_ini_get_str(ini, &result->bindings[i].binding, keyname);
+ }
+ free(keyname);
}
}
if(error) {
flib_log_e("Error reading team file %s", filename);
- return from_ini_handleError(result, settingfile, bindingKeys);
+ return from_ini_handleError(result, ini);
}
- iniparser_freedict(settingfile);
- free(bindingKeys);
+ flib_ini_destroy(ini);
+ return result;
+}
+
+static int writeTeamSection(const flib_team *team, flib_ini *ini) {
+ if(flib_ini_create_section(ini, "team")) {
+ return -1;
+ }
+ bool error = false;
+ error |= flib_ini_set_str(ini, "name", team->name);
+ error |= flib_ini_set_str(ini, "grave", team->grave);
+ error |= flib_ini_set_str(ini, "fort", team->fort);
+ error |= flib_ini_set_str(ini, "voicepack", team->voicepack);
+ error |= flib_ini_set_str(ini, "flag", team->flag);
+ error |= flib_ini_set_int(ini, "rounds", team->rounds);
+ error |= flib_ini_set_int(ini, "wins", team->wins);
+ error |= flib_ini_set_int(ini, "campaignprogress", team->campaignProgress);
+ error |= flib_ini_set_int(ini, "difficulty", team->hogs[0].difficulty);
+ return error;
+}
+
+static int writeHogSections(const flib_team *team, flib_ini *ini) {
+ for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
+ const flib_hog *hog = &team->hogs[i];
+ char sectionName[32];
+ if(snprintf(sectionName, sizeof(sectionName), "hedgehog%i", i) <= 0) {
+ return -1;
+ }
+ if(flib_ini_create_section(ini, sectionName)) {
+ return -1;
+ }
+ bool error = false;
+ error |= flib_ini_set_str(ini, "name", hog->name);
+ error |= flib_ini_set_str(ini, "hat", hog->hat);
+ error |= flib_ini_set_int(ini, "rounds", hog->rounds);
+ error |= flib_ini_set_int(ini, "kills", hog->kills);
+ error |= flib_ini_set_int(ini, "deaths", hog->deaths);
+ error |= flib_ini_set_int(ini, "suicides", hog->suicides);
+ if(error) {
+ return error;
+ }
+ }
+ return 0;
+}
+
+static int writeBindingSection(const flib_team *team, flib_ini *ini) {
+ if(flib_ini_create_section(ini, "binds")) {
+ return -1;
+ }
+ for(int i=0; i<team->bindingCount; i++) {
+ bool error = false;
+ char *action = flib_urlencode(team->bindings[i].action);
+ if(action) {
+ error |= flib_ini_set_str(ini, action, team->bindings[i].binding);
+ free(action);
+ } else {
+ error = true;
+ }
+ if(error) {
+ return error;
+ }
+ }
+ return 0;
+}
+
+int flib_team_to_ini(const char *filename, const flib_team *team) {
+ int result = -1;
+ if(!filename || !team) {
+ flib_log_e("null parameter in flib_team_to_ini");
+ } else {
+ flib_ini *ini = flib_ini_create(filename);
+ bool error = false;
+ error |= writeTeamSection(team, ini);
+ error |= writeHogSections(team, ini);
+ error |= writeBindingSection(team, ini);
+ if(!error) {
+ result = flib_ini_save(ini, filename);
+ }
+ flib_ini_destroy(ini);
+ }
return result;
}
--- a/project_files/frontlib/model/team.h Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/model/team.h Tue Jun 12 21:10:11 2012 +0200
@@ -79,6 +79,10 @@
* that were already present. Note that not all fields of a team struct
* are stored in the ini, some are only used intermittently to store
* information about a team in the context of a game.
+ *
+ * The flib_team can handle "difficulty" on a per-hog basis, but it
+ * is only written per-team in the team file. The difficulty of the
+ * first hog is used for the entire team when writing.
*/
int flib_team_to_ini(const char *filename, const flib_team *team);
void flib_team_destroy(flib_team *team);
--- a/project_files/frontlib/model/weapon.c Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/model/weapon.c Tue Jun 12 21:10:11 2012 +0200
@@ -1,6 +1,5 @@
#include "weapon.h"
-#include "../iniparser/iniparser.h"
#include "../util/inihelper.h"
#include "../util/logging.h"
#include "../util/util.h"
@@ -75,23 +74,30 @@
if(!filename) {
flib_log_e("null parameter in flib_weaponset_from_ini");
} else {
- dictionary *settingfile = iniparser_load(filename);
- if(!settingfile) {
+ flib_ini *ini = flib_ini_load(filename);
+ if(!ini) {
flib_log_e("Error loading weapon scheme file %s", filename);
- } else {
+ } else if(!flib_ini_enter_section(ini, "weaponset")) {
bool error = false;
- char *name = inihelper_getstring(settingfile, &error, "weaponset", "name");
- char *loadout = inihelper_getstring(settingfile, &error, "weaponset", "loadout");
- char *crateprob = inihelper_getstring(settingfile, &error, "weaponset", "crateprob");
- char *crateammo = inihelper_getstring(settingfile, &error, "weaponset", "crateammo");
- char *delay = inihelper_getstring(settingfile, &error, "weaponset", "delay");
+ char *name = NULL, *loadout = NULL, *crateprob = NULL, *crateammo = NULL, *delay = NULL;
+ error |= flib_ini_get_str(ini, &name, "name");
+ error |= flib_ini_get_str(ini, &loadout, "loadout");
+ error |= flib_ini_get_str(ini, &crateprob, "crateprob");
+ error |= flib_ini_get_str(ini, &crateammo, "crateammo");
+ error |= flib_ini_get_str(ini, &delay, "delay");
+
if(error) {
flib_log_e("Missing key in weapon scheme file %s", filename);
} else {
result = flib_weaponset_create_str(name, loadout, crateprob, crateammo, delay);
}
+ free(name);
+ free(loadout);
+ free(crateprob);
+ free(crateammo);
+ free(delay);
}
- iniparser_freedict(settingfile);
+ flib_ini_destroy(ini);
}
return result;
}
@@ -101,31 +107,19 @@
if(!filename || !set) {
flib_log_e("null parameter in flib_weaponset_to_ini");
} else {
- dictionary *dict = iniparser_load(filename);
- if(!dict) {
- dict = dictionary_new(0);
- }
- if(dict) {
+ flib_ini *ini = flib_ini_create(filename);
+ if(!flib_ini_create_section(ini, "weaponset")) {
bool error = false;
- // Add the sections
- error |= iniparser_set(dict, "weaponset", NULL);
-
- // Add the values
- error |= inihelper_setstr(dict, "weaponset", "name", set->name);
- error |= inihelper_setstr(dict, "weaponset", "loadout", set->loadout);
- error |= inihelper_setstr(dict, "weaponset", "crateprob", set->crateprob);
- error |= inihelper_setstr(dict, "weaponset", "crateammo", set->crateammo);
- error |= inihelper_setstr(dict, "weaponset", "delay", set->delay);
+ error |= flib_ini_set_str(ini, "name", set->name);
+ error |= flib_ini_set_str(ini, "loadout", set->loadout);
+ error |= flib_ini_set_str(ini, "crateprob", set->crateprob);
+ error |= flib_ini_set_str(ini, "crateammo", set->crateammo);
+ error |= flib_ini_set_str(ini, "delay", set->delay);
if(!error) {
- FILE *inifile = fopen(filename, "wb");
- if(inifile) {
- iniparser_dump_ini(dict, inifile);
- fclose(inifile);
- result = 0;
- }
+ result = flib_ini_save(ini, filename);
}
- dictionary_del(dict);
}
+ flib_ini_destroy(ini);
}
return result;
}
--- a/project_files/frontlib/test.c Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/test.c Tue Jun 12 21:10:11 2012 +0200
@@ -104,7 +104,7 @@
flib_gamesetup setup;
setup.gamescheme = flib_cfg_from_ini(metaconf, "scheme_shoppa.ini");
setup.map = flib_map_create_maze("Jungle", MAZE_SIZE_MEDIUM_TUNNELS);
- setup.seed = "apsfooasdgnds";
+ setup.seed = "asparagus";
setup.script = NULL;
setup.teamcount = 2;
setup.teams = calloc(2, sizeof(flib_team*));
@@ -166,12 +166,37 @@
}
}
+void testSave() {
+ FILE *demofile = fopen("testsave.42.hws", "rb");
+ assert(demofile);
+ flib_vector *vec = flib_vector_create();
+ uint8_t demobuf[512];
+ int len;
+ while((len=fread(demobuf, 1, 512, demofile))>0) {
+ flib_vector_append(vec, demobuf, len);
+ }
+ fclose(demofile);
+ flib_constbuffer constbuf = flib_vector_as_constbuffer(vec);
+ flib_gameconn *gameconn = flib_gameconn_create_loadgame("Medo42", constbuf.data, constbuf.size);
+ flib_vector_destroy(vec);
+ assert(gameconn);
+ flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
+ flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
+ startEngineGame(flib_gameconn_getport(gameconn));
+
+ while(gameconn) {
+ flib_gameconn_tick(gameconn);
+ }
+}
+
int main(int argc, char *argv[]) {
flib_init(0);
flib_log_setLevel(FLIB_LOGLEVEL_ALL);
//testMapPreview();
- testDemo();
+ //testDemo();
+ //testSave();
+ testGame();
flib_quit();
return 0;
--- a/project_files/frontlib/util/inihelper.c Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/util/inihelper.c Tue Jun 12 21:10:11 2012 +0200
@@ -1,4 +1,7 @@
#include "inihelper.h"
+#include "../iniparser/dictionary.h"
+#include "../iniparser/iniparser.h"
+
#include "logging.h"
#include "util.h"
@@ -9,167 +12,309 @@
#include <errno.h>
#include <stdarg.h>
-static bool keychar_needs_urlencoding(char c) {
- return !isalnum(c);
-}
-
-char *inihelper_urlencode(const char *inbuf) {
- if(!inbuf) {
- return NULL;
- }
- size_t insize = strlen(inbuf);
- if(insize > SIZE_MAX/4) {
- return NULL;
- }
-
- char *outbuf = flib_malloc(insize*3+1);
- if(!outbuf) {
- return NULL;
- }
+struct _flib_ini {
+ dictionary *inidict;
+ char *currentSection;
+};
- size_t inpos = 0, outpos = 0;
- while(inbuf[inpos]) {
- if(!keychar_needs_urlencoding(inbuf[inpos])) {
- outbuf[outpos++] = inbuf[inpos++];
- } else {
- if(snprintf(outbuf+outpos, 4, "%%%02X", (unsigned)((uint8_t*)inbuf)[inpos])<0) {
- free(outbuf);
- return NULL;
- }
- inpos++;
- outpos += 3;
- }
- }
- outbuf[outpos] = 0;
- char *shrunk = realloc(outbuf, outpos+1);
- return shrunk ? shrunk : outbuf;
-}
-
-char *inihelper_urldecode(const char *inbuf) {
- char *outbuf = flib_malloc(strlen(inbuf)+1);
- if(!outbuf) {
- return NULL;
- }
-
- size_t inpos = 0, outpos = 0;
- while(inbuf[inpos]) {
- if(inbuf[inpos] == '%' && isxdigit(inbuf[inpos+1]) && isxdigit(inbuf[inpos+2])) {
- char temp[3] = {inbuf[inpos+1],inbuf[inpos+2],0};
- outbuf[outpos++] = strtol(temp, NULL, 16);
- inpos += 3;
- } else {
- outbuf[outpos++] = inbuf[inpos++];
- }
- }
- outbuf[outpos] = 0;
- char *shrunk = realloc(outbuf, outpos+1);
- return shrunk ? shrunk : outbuf;
-}
-
-char *inihelper_createDictKey(const char *sectionName, const char *keyName) {
- if(!sectionName || !keyName) {
- flib_log_e("null parameter in inihelper_createDictKey");
- return NULL;
- }
+static char *createDictKey(const char *sectionName, const char *keyName) {
return flib_asprintf("%s:%s", sectionName, keyName);
}
-char *inihelper_getstring(dictionary *inifile, bool *error, const char *sectionName, const char *keyName) {
- if(!inifile || !sectionName || !keyName) {
- flib_log_e("null parameter in inihelper_getstring");
- *error = true;
- return NULL;
+/**
+ * Turns a string into a lowercase string, in-place.
+ */
+static void strToLower(char *str) {
+ if(str) {
+ while(*str) {
+ *str = tolower(*str);
+ str++;
+ }
}
- char *extendedkey = inihelper_createDictKey(sectionName, keyName);
- if(!extendedkey) {
- *error = true;
- return NULL;
+}
+
+flib_ini *flib_ini_create(const char *filename) {
+ flib_ini *result = NULL;
+ flib_ini *tmpIni = flib_calloc(1, sizeof(flib_ini));
+ if(tmpIni) {
+ if(filename) {
+ tmpIni->inidict = iniparser_load(filename);
+ }
+ if(!tmpIni->inidict) {
+ tmpIni->inidict = dictionary_new(0);
+ }
+ if(tmpIni->inidict) {
+ result = tmpIni;
+ tmpIni = NULL;
+ }
}
- char *result = iniparser_getstring(inifile, extendedkey, NULL);
- free(extendedkey);
- if(!result) {
- flib_log_d("Missing ini setting: %s/%s", sectionName, keyName);
- *error = true;
+ flib_ini_destroy(tmpIni);
+ return result;
+}
+
+flib_ini *flib_ini_load(const char *filename) {
+ flib_ini *result = NULL;
+ if(!filename) {
+ flib_log_e("null parameter in flib_ini_load");
+ } else {
+ flib_ini *tmpIni = flib_calloc(1, sizeof(flib_ini));
+ if(tmpIni) {
+ tmpIni->inidict = iniparser_load(filename);
+ if(tmpIni->inidict) {
+ result = tmpIni;
+ tmpIni = NULL;
+ }
+ }
+ flib_ini_destroy(tmpIni);
}
return result;
}
-char *inihelper_getstringdup(dictionary *inifile, bool *error, const char *sectionName, const char *keyName) {
- return flib_strdupnull(inihelper_getstring(inifile, error, sectionName, keyName));
-}
-
-int inihelper_getint(dictionary *inifile, bool *error, const char *sectionName, const char *keyName) {
- char *value = inihelper_getstring(inifile, error, sectionName, keyName);
- if(!value) {
- return 0;
+int flib_ini_save(flib_ini *ini, const char *filename) {
+ int result = INI_ERROR_OTHER;
+ if(!ini || !filename) {
+ flib_log_e("null parameter in flib_ini_save");
} else {
- errno = 0;
- long val = strtol(value, NULL, 10);
- if(errno!=0) {
- flib_log_w("Cannot parse ini setting %s/%s = \"%s\" as integer.", sectionName, keyName, value);
- *error = true;
- return 0;
- }
- if(val<INT_MIN || val>INT_MAX) {
- flib_log_w("ini setting %s/%s = \"%s\" is too large or too small.", sectionName, keyName, value);
- *error = true;
- return 0;
+ FILE *file = fopen(filename, "wb");
+ if(!file) {
+ flib_log_e("Error opening file \"%s\" for writing.", filename);
+ } else {
+ iniparser_dump_ini(ini->inidict, file);
+ if(fclose(file)) {
+ flib_log_e("Write error on ini file \"%s\"", filename);
+ } else {
+ result = 0;
+ }
}
- return (int)val;
- }
-}
-
-bool inihelper_getbool(dictionary *inifile, bool *error, const char *sectionName, const char *keyName) {
- char *value = inihelper_getstring(inifile, error, sectionName, keyName);
- if(!value) {
- return false;
- } else {
- bool trueval = strchr("1tTyY", value[0]);
- bool falseval = strchr("0fFnN", value[0]);
- if(!trueval && !falseval) {
- flib_log_w("ini setting %s/%s = \"%s\" is not a recognized truth value.", sectionName, keyName, value);
- *error = true;
- return false;
- } else {
- return trueval;
- }
- }
-}
-
-int inihelper_setstr(dictionary *dict, const char *sectionName, const char *keyName, const char *value) {
- int result = -1;
- if(!dict || !sectionName || !keyName || !value) {
- flib_log_e("null parameter in inihelper_setstr");
- } else {
- char *extendedkey = inihelper_createDictKey(sectionName, keyName);
- if(extendedkey) {
- result = iniparser_set(dict, extendedkey, value);
- }
- free(extendedkey);
}
return result;
}
-int inihelper_setint(dictionary *dict, const char *sectionName, const char *keyName, int value) {
- int result = -1;
- if(!dict || !sectionName || !keyName) {
- flib_log_e("null parameter in inihelper_setint");
+void flib_ini_destroy(flib_ini *ini) {
+ if(ini) {
+ if(ini->inidict) {
+ iniparser_freedict(ini->inidict);
+ }
+ free(ini->currentSection);
+ free(ini);
+ }
+}
+
+int flib_ini_enter_section(flib_ini *ini, const char *section) {
+ int result = INI_ERROR_OTHER;
+ if(ini) {
+ free(ini->currentSection);
+ ini->currentSection = NULL;
+ }
+ if(!ini || !section) {
+ flib_log_e("null parameter in flib_ini_enter_section");
} else {
- char *strvalue = flib_asprintf("%i", value);
- if(strvalue) {
- result = inihelper_setstr(dict, sectionName, keyName, strvalue);
- free(strvalue);
+ if(!iniparser_find_entry(ini->inidict, section)) {
+ result = INI_ERROR_NOTFOUND;
+ } else {
+ ini->currentSection = flib_strdupnull(section);
+ if(ini->currentSection) {
+ // Usually iniparser ignores case, but some section-handling functions don't,
+ // so we set it to lowercase manually
+ strToLower(ini->currentSection);
+ result = 0;
+ }
+ }
+ }
+ return result;
+}
+
+int flib_ini_create_section(flib_ini *ini, const char *section) {
+ int result = INI_ERROR_OTHER;
+ if(!ini || !section) {
+ flib_log_e("null parameter in flib_ini_create_section");
+ } else {
+ result = flib_ini_enter_section(ini, section);
+ if(result == INI_ERROR_NOTFOUND) {
+ if(iniparser_set(ini->inidict, section, NULL)) {
+ result = INI_ERROR_OTHER;
+ } else {
+ result = flib_ini_enter_section(ini, section);
+ }
}
}
return result;
}
-int inihelper_setbool(dictionary *dict, const char *sectionName, const char *keyName, bool value) {
- int result = -1;
- if(!dict || !sectionName || !keyName) {
- flib_log_e("null parameter in inihelper_setbool");
+/**
+ * The result is an internal string of the iniparser, don't free it.
+ */
+static char *findValue(dictionary *dict, const char *section, const char *key) {
+ char *result = NULL;
+ char *dictKey = createDictKey(section, key);
+ if(dictKey) {
+ result = iniparser_getstring(dict, dictKey, NULL);
+ }
+ free(dictKey);
+ return result;
+}
+
+int flib_ini_get_str(flib_ini *ini, char **outVar, const char *key) {
+ char *tmpValue = NULL;
+ int result = flib_ini_get_str_opt(ini, &tmpValue, key, NULL);
+ if(result==0) {
+ if(tmpValue == NULL) {
+ result = INI_ERROR_NOTFOUND;
+ } else {
+ *outVar = tmpValue;
+ tmpValue = NULL;
+ }
+ }
+ free(tmpValue);
+ return result;
+}
+
+int flib_ini_get_str_opt(flib_ini *ini, char **outVar, const char *key, const char *def) {
+ int result = INI_ERROR_OTHER;
+ if(!ini || !outVar || !key || !ini->currentSection) {
+ flib_log_e("null parameter or no current section in flib_ini_get_str_opt");
} else {
- result = inihelper_setstr(dict, sectionName, keyName, value ? "true" : "false");
+ const char *value = findValue(ini->inidict, ini->currentSection, key);
+ if(!value) {
+ value = def;
+ }
+ char *valueDup = flib_strdupnull(value);
+ if(valueDup) {
+ *outVar = valueDup;
+ result = 0;
+ }
+ }
+ return result;
+}
+
+int flib_ini_get_int(flib_ini *ini, int *outVar, const char *key) {
+ char *tmpValue = NULL;
+ int result = flib_ini_get_str(ini, &tmpValue, key);
+ if(result==0) {
+ errno = 0;
+ long val = strtol(tmpValue, NULL, 10);
+ if(errno!=0 || val<INT_MIN || val>INT_MAX) {
+ flib_log_w("Cannot parse ini setting %s/%s = \"%s\" as integer.", ini->currentSection, key, tmpValue);
+ result = INI_ERROR_FORMAT;
+ } else {
+ *outVar = val;
+ }
+ }
+ free(tmpValue);
+ return result;
+}
+
+int flib_ini_get_int_opt(flib_ini *ini, int *outVar, const char *key, int def) {
+ int tmpValue;
+ int result = flib_ini_get_int(ini, &tmpValue, key);
+ if(result == 0) {
+ *outVar = tmpValue;
+ } else if(result == INI_ERROR_NOTFOUND) {
+ *outVar = def;
+ result = 0;
}
return result;
}
+
+int flib_ini_get_bool(flib_ini *ini, bool *outVar, const char *key) {
+ char *tmpValue = NULL;
+ int result = flib_ini_get_str(ini, &tmpValue, key);
+ if(result==0) {
+ bool trueval = strchr("1tTyY", tmpValue[0]);
+ bool falseval = strchr("0fFnN", tmpValue[0]);
+ if(!trueval && !falseval) {
+ flib_log_w("ini setting %s/%s = \"%s\" is not a recognized truth value.", ini->currentSection, key, tmpValue);
+ result = INI_ERROR_FORMAT;
+ } else {
+ *outVar = trueval;
+ }
+ }
+ free(tmpValue);
+ return result;
+}
+
+int flib_ini_get_bool_opt(flib_ini *ini, bool *outVar, const char *key, bool def) {
+ bool tmpValue;
+ int result = flib_ini_get_bool(ini, &tmpValue, key);
+ if(result == 0) {
+ *outVar = tmpValue;
+ } else if(result == INI_ERROR_NOTFOUND) {
+ *outVar = def;
+ result = 0;
+ }
+ return result;
+}
+
+int flib_ini_set_str(flib_ini *ini, const char *key, const char *value) {
+ int result = INI_ERROR_OTHER;
+ if(!ini || !key || !value || !ini->currentSection) {
+ flib_log_e("null parameter or no current section in flib_ini_set_str");
+ } else {
+ char *dictKey = createDictKey(ini->currentSection, key);
+ if(dictKey) {
+ result = iniparser_set(ini->inidict, dictKey, value);
+ }
+ free(dictKey);
+ }
+ return result;
+}
+
+int flib_ini_set_int(flib_ini *ini, const char *key, int value) {
+ int result = INI_ERROR_OTHER;
+ char *strvalue = flib_asprintf("%i", value);
+ if(strvalue) {
+ result = flib_ini_set_str(ini, key, strvalue);
+ }
+ free(strvalue);
+ return result;
+}
+
+int flib_ini_set_bool(flib_ini *ini, const char *key, bool value) {
+ return flib_ini_set_str(ini, key, value ? "true" : "false");
+}
+
+int flib_ini_get_sectioncount(flib_ini *ini) {
+ int result = INI_ERROR_OTHER;
+ if(!ini) {
+ flib_log_e("null parameter in flib_ini_get_sectioncount");
+ } else {
+ result = iniparser_getnsec(ini->inidict);
+ }
+ return result;
+}
+
+char *flib_ini_get_sectionname(flib_ini *ini, int number) {
+ char *result = NULL;
+ if(!ini || number<0) {
+ flib_log_e("bad parameter in flib_ini_get_sectionname");
+ } else {
+ result = flib_strdupnull(iniparser_getsecname(ini->inidict, number));
+ }
+ return result;
+}
+
+int flib_ini_get_keycount(flib_ini *ini) {
+ int result = INI_ERROR_OTHER;
+ if(!ini || !ini->currentSection) {
+ flib_log_e("null parameter or no current section in flib_ini_get_keycount");
+ } else {
+ result = iniparser_getsecnkeys(ini->inidict, ini->currentSection);
+ }
+ return result;
+}
+
+char *flib_ini_get_keyname(flib_ini *ini, int number) {
+ char *result = NULL;
+ if(!ini || number<0 || !ini->currentSection) {
+ flib_log_e("bad parameter or no current section in flib_ini_get_keyname");
+ } else {
+ int keyCount = iniparser_getsecnkeys(ini->inidict, ini->currentSection);
+ char **keys = iniparser_getseckeys(ini->inidict, ini->currentSection);
+ if(keys && keyCount>number) {
+ // The keys are in the format section:key, so we have to skip the section and colon.
+ result = flib_strdupnull(keys[number]+strlen(ini->currentSection)+1);
+ }
+ free(keys);
+ }
+ return result;
+}
--- a/project_files/frontlib/util/inihelper.h Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/util/inihelper.h Tue Jun 12 21:10:11 2012 +0200
@@ -9,65 +9,152 @@
#ifndef INIHELPER_H_
#define INIHELPER_H_
-#include "../iniparser/iniparser.h"
+#include <stdbool.h>
-#include <stdbool.h>
+#define INI_ERROR_NOTFOUND -1
+#define INI_ERROR_FORMAT -2
+#define INI_ERROR_OTHER -100
struct _flib_ini;
-typedef struct _flib_inihelper flib_ini;
+typedef struct _flib_ini flib_ini;
/**
- * Returned buffer must be free()d
+ * Create a new ini data structure, pre-filled with the contents of
+ * the file "filename" if it exists. If filename is null, or the file
+ * is not found, an empty ini will be created. However, if an error
+ * occurs while reading the ini file (or any other error), null
+ * is returned.
+ *
+ * This behavior is useful for modifying an existing ini file without
+ * discarding unknown keys.
*/
-char *inihelper_urlencode(const char *inbuf);
+flib_ini *flib_ini_create(const char *filename);
+
+/**
+ * Similar to flib_ini_create, but fails if the file is not found
+ * or if filename is null.
+ */
+flib_ini *flib_ini_load(const char *filename);
/**
- * Returned buffer must be free()d
+ * Store the ini to the file "filename", overwriting
+ * the previous contents. Returns 0 on success.
*/
-char *inihelper_urldecode(const char *inbuf);
+int flib_ini_save(flib_ini *ini, const char *filename);
+
+void flib_ini_destroy(flib_ini *ini);
+
+/**
+ * Enter the section with the specified name. Returns 0 on
+ * success, INI_ERROR_NOTFOUND if the section does not exist
+ * and a different value if another error occurs.
+ * If an error occurs, there is no current section.
+ *
+ * The section name should only consist of letters and
+ * numbers.
+ */
+int flib_ini_enter_section(flib_ini *ini, const char *section);
/**
- * Create a key in the format "sectionName:keyName"
- * Returned buffer must be free()d
+ * Creates and enters the section with the specified name. Simply
+ * enters the section if it exists already. Returns 0 on success
+ * and a different value if another error occurs.
+ * If an error occurs, there is no current section.
*/
-char *inihelper_createDictKey(const char *sectionName, const char *keyName);
+int flib_ini_create_section(flib_ini *ini, const char *section);
/**
- * Returns an internal buffer, don't modify or free
- * Sets error to true if something goes wrong, leaves it unchanged otherwise.
+ * Find a key in the current section and store the value in outVar
+ * as a newly allocated string. Returns 0 on success, INI_ERROR_NOTFOUND
+ * if the key was not found and a different value for other errors,
+ * e.g. if there is no current section.
*/
-char *inihelper_getstring(dictionary *inifile, bool *error, const char *sectionName, const char *keyName);
+int flib_ini_get_str(flib_ini *ini, char **outVar, const char *key);
+
+/**
+ * Find a key in the current section and store the value in outVar
+ * as a newly allocated string. If the key is not found, the default
+ * value will be used instead. Returns 0 on success.
+ */
+int flib_ini_get_str_opt(flib_ini *ini, char **outVar, const char *key, const char *def);
/**
- * Returned buffer must be free()d
- * Sets error to true if something goes wrong, leaves it unchanged otherwise.
+ * Find a key in the current section and store the value in outVar
+ * as an int. Returns 0 on success, INI_ERROR_NOTFOUND
+ * if the key was not found, INI_ERROR_FORMAT if it was found but
+ * could not be converted to an int, and a different value for other
+ * errors, e.g. if there is no current section.
*/
-char *inihelper_getstringdup(dictionary *inifile, bool *error, const char *sectionName, const char *keyName);
+int flib_ini_get_int(flib_ini *ini, int *outVar, const char *key);
+
+/**
+ * Find a key in the current section and store the value in outVar
+ * as an int. If the key is not found, the default value will be used instead.
+ * Returns 0 on success, INI_ERROR_FORMAT if the value was found but
+ * could not be converted to int, and another value otherwise.
+ */
+int flib_ini_get_int_opt(flib_ini *ini, int *outVar, const char *key, int def);
/**
- * Sets error to true if something goes wrong, leaves it unchanged otherwise.
+ * Find a key in the current section and store the value in outVar
+ * as a bool. Treats everything beginning with "Y", "T" or "1" as true,
+ * everything starting with "N", "F" or "1" as false.
+ *
+ * Returns 0 on success, INI_ERROR_NOTFOUND if the key was not found,
+ * INI_ERROR_FORMAT if the value could not be interpreted as boolean,
+ * and another value otherwise.
*/
-int inihelper_getint(dictionary *inifile, bool *error, const char *sectionName, const char *keyName);
+int flib_ini_get_bool(flib_ini *ini, bool *outVar, const char *key);
/**
- * Sets error to true if something goes wrong, leaves it unchanged otherwise.
+ * Find a key in the current section and store the value in outVar
+ * as a bool. If the key is not found, the default value will be
+ * used instead. Returns 0 on success, INI_ERROR_FORMAT if the
+ * value could not be interpreted as boolean, and another value otherwise.
*/
-bool inihelper_getbool(dictionary *inifile, bool *error, const char *sectionName, const char *keyName);
+int flib_ini_get_bool_opt(flib_ini *ini, bool *outVar, const char *key, bool def);
/**
- * Returns a nonzero value on error.
+ * In the current section, associate key with value. Returns 0 on success.
+ */
+int flib_ini_set_str(flib_ini *ini, const char *key, const char *value);
+
+/**
+ * In the current section, associate key with value. Returns 0 on success.
*/
-int inihelper_setstr(dictionary *dict, const char *sectionName, const char *keyName, const char *value);
+int flib_ini_set_int(flib_ini *ini, const char *key, int value);
+
+/**
+ * In the current section, associate key with value. Returns 0 on success.
+ */
+int flib_ini_set_bool(flib_ini *ini, const char *key, bool value);
+
+/**
+ * Returns the number of sections in the ini file, or a negative value on error.
+ */
+int flib_ini_get_sectioncount(flib_ini *ini);
/**
- * Returns a nonzero value on error.
+ * Returns the name of the section, or NULL on error. The returned string must
+ * be free()d.
+ *
+ * Note: There is no guarantee that the order of the sections
+ * will remain stable if the ini is modified.
*/
-int inihelper_setint(dictionary *dict, const char *sectionName, const char *keyName, int value);
+char *flib_ini_get_sectionname(flib_ini *ini, int number);
/**
- * Set an ini setting to "true" or "false".
- * Returns a nonzero value on error.
+ * Returns the number of keys in the current section, or -1 on error.
*/
-int inihelper_setbool(dictionary *dict, const char *sectionName, const char *keyName, bool value);
+int flib_ini_get_keycount(flib_ini *ini);
+
+/**
+ * Returns the name of the key in the current section, or NULL on error.
+ * The returned string must be free()d.
+ *
+ * Note: There is no guarantee that the order of the keys in a section
+ * will remain stable if the ini is modified.
+ */
+char *flib_ini_get_keyname(flib_ini *ini, int number);
#endif /* INIHELPER_H_ */
--- a/project_files/frontlib/util/util.c Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/util/util.c Tue Jun 12 21:10:11 2012 +0200
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <ctype.h>
char *flib_asprintf(const char *fmt, ...) {
va_list argp;
@@ -68,3 +69,62 @@
}
return result;
}
+
+static bool isAsciiAlnum(char c) {
+ return (c>='0' && c<='9') || (c>='a' && c <='z') || (c>='A' && c <='Z');
+}
+
+char *flib_urlencode(const char *inbuf) {
+ if(!inbuf) {
+ return NULL;
+ }
+ size_t insize = strlen(inbuf);
+ if(insize > SIZE_MAX/4) {
+ flib_log_e("String too long in flib_urlencode: %zu bytes.", insize);
+ return NULL;
+ }
+
+ char *outbuf = flib_malloc(insize*3+1);
+ if(!outbuf) {
+ return NULL;
+ }
+
+ size_t inpos = 0, outpos = 0;
+ while(inbuf[inpos]) {
+ if(isAsciiAlnum(inbuf[inpos])) {
+ outbuf[outpos++] = inbuf[inpos++];
+ } else {
+ if(snprintf(outbuf+outpos, 4, "%%%02X", (unsigned)((uint8_t*)inbuf)[inpos])<0) {
+ flib_log_e("printf error in flib_urlencode");
+ free(outbuf);
+ return NULL;
+ }
+ inpos++;
+ outpos += 3;
+ }
+ }
+ outbuf[outpos] = 0;
+ char *shrunk = realloc(outbuf, outpos+1);
+ return shrunk ? shrunk : outbuf;
+}
+
+char *flib_urldecode(const char *inbuf) {
+ char *outbuf = flib_malloc(strlen(inbuf)+1);
+ if(!outbuf) {
+ return NULL;
+ }
+
+ size_t inpos = 0, outpos = 0;
+ while(inbuf[inpos]) {
+ if(inbuf[inpos] == '%' && isxdigit(inbuf[inpos+1]) && isxdigit(inbuf[inpos+2])) {
+ char temp[3] = {inbuf[inpos+1],inbuf[inpos+2],0};
+ outbuf[outpos++] = strtol(temp, NULL, 16);
+ inpos += 3;
+ } else {
+ outbuf[outpos++] = inbuf[inpos++];
+ }
+ }
+ outbuf[outpos] = 0;
+ char *shrunk = realloc(outbuf, outpos+1);
+ return shrunk ? shrunk : outbuf;
+}
--- a/project_files/frontlib/util/util.h Tue Jun 12 11:25:05 2012 +0200
+++ b/project_files/frontlib/util/util.h Tue Jun 12 21:10:11 2012 +0200
@@ -45,4 +45,22 @@
*/
void *flib_calloc(size_t count, size_t elementsize);
+/**
+ * Replace all non-alphanumeric and non-ascii bytes with escape
+ * sequences in the form %XX. Does not modify the original string,
+ * but returns a newly allocated one that must be free()d. Returns
+ * null on failure or if null was passed as argument.
+ *
+ * This should work fine with all ASCII-based charsets including UTF-8.
+ */
+char *flib_urlencode(const char *str);
+
+/**
+ * Replace escape sequences of the form %XX with their byte values.
+ * Does not modify the original string, but returns a newly allocated
+ * one that must be free()d. Returns null on failure or if null was
+ * passed as argument.
+ */
+char *flib_urldecode(const char *str);
+
#endif