--- a/project_files/frontlib/hwconsts.h Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/hwconsts.h Fri Jun 15 19:57:25 2012 +0200
@@ -13,9 +13,5 @@
#define GAMEMOD_SHAREDAMMO_MASKBIT 16
#define WEAPONS_COUNT 55
-#define AMMOLINE_DEFAULT_QT "9391929422199121032235111001201000000211110101011111011"
-#define AMMOLINE_DEFAULT_PROB "0405040541600655546554464776576666666155510101115411011"
-#define AMMOLINE_DEFAULT_DELAY "0000000000000205500000040007004000000000220000000600000"
-#define AMMOLINE_DEFAULT_CRATE "1311110312111111123114111111111111111211111101111111010"
#endif
--- a/project_files/frontlib/ipc/gameconn.c Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/ipc/gameconn.c Fri Jun 15 19:57:25 2012 +0200
@@ -63,43 +63,6 @@
conn->onNetMessageCb = &defaultCallback_onNetMessage;
}
-static bool getGameMod(flib_cfg_meta *meta, flib_cfg *conf, int maskbit) {
- for(int i=0; i<meta->modCount; i++) {
- if(meta->mods[i].bitmaskIndex == maskbit) {
- return conf->mods[i];
- }
- }
- flib_log_e("Unable to find game mod with mask bit %i", maskbit);
- return false;
-}
-
-static int fillConfigBuffer(flib_vector *configBuffer, const char *playerName, flib_cfg_meta *metaconf, flib_gamesetup *setup, bool netgame) {
- bool error = false;
- bool perHogAmmo = false;
- bool sharedAmmo = false;
-
- error |= flib_ipc_append_message(configBuffer, netgame ? "TN" : "TL");
- error |= flib_ipc_append_seed(configBuffer, setup->seed);
- if(setup->map) {
- error |= flib_ipc_append_mapconf(configBuffer, setup->map, false);
- }
- if(setup->script) {
- error |= flib_ipc_append_message(configBuffer, "escript %s", setup->script);
- }
- if(setup->gamescheme) {
- error |= flib_ipc_append_gamescheme(configBuffer, setup->gamescheme, metaconf);
- perHogAmmo = getGameMod(metaconf, setup->gamescheme, GAMEMOD_PERHOGAMMO_MASKBIT);
- sharedAmmo = getGameMod(metaconf, setup->gamescheme, GAMEMOD_SHAREDAMMO_MASKBIT);
- }
- if(setup->teams) {
- for(int i=0; i<setup->teamcount; i++) {
- error |= flib_ipc_append_addteam(configBuffer, setup->teams[i], perHogAmmo, sharedAmmo);
- }
- }
- error |= flib_ipc_append_message(configBuffer, "!");
- return error ? -1 : 0;
-}
-
static flib_gameconn *flib_gameconn_create_partial(bool record, const char *playerName, bool netGame) {
flib_gameconn *result = NULL;
flib_gameconn *tempConn = flib_calloc(1, sizeof(flib_gameconn));
@@ -122,11 +85,11 @@
return result;
}
-flib_gameconn *flib_gameconn_create(const char *playerName, flib_cfg_meta *metaconf, flib_gamesetup *setup, bool netgame) {
+flib_gameconn *flib_gameconn_create(const char *playerName, flib_gamesetup *setup, bool netgame) {
flib_gameconn *result = NULL;
flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, netgame);
if(tempConn) {
- if(fillConfigBuffer(tempConn->configBuffer, playerName, metaconf, setup, netgame) == 0) {
+ if(!flib_ipc_append_fullconfig(tempConn->configBuffer, setup, netgame)) {
result = tempConn;
tempConn = NULL;
}
--- a/project_files/frontlib/ipc/gameconn.h Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/ipc/gameconn.h Fri Jun 15 19:57:25 2012 +0200
@@ -16,7 +16,7 @@
struct _flib_gameconn;
typedef struct _flib_gameconn flib_gameconn;
-flib_gameconn *flib_gameconn_create(const char *playerName, flib_cfg_meta *metaconf, flib_gamesetup *setup, bool netgame);
+flib_gameconn *flib_gameconn_create(const char *playerName, flib_gamesetup *setup, bool netgame);
flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demo, int size);
flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *save, int size);
void flib_gameconn_destroy(flib_gameconn *conn);
@@ -75,4 +75,6 @@
*/
void flib_gameconn_onNetMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, int size), void* context);
+// TODO efinish
+
#endif
--- a/project_files/frontlib/ipc/ipcprotocol.c Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/ipc/ipcprotocol.c Fri Jun 15 19:57:25 2012 +0200
@@ -6,6 +6,7 @@
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
+#include <stdlib.h>
int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...) {
int result = -1;
@@ -38,7 +39,7 @@
return result;
}
-int flib_ipc_append_mapconf(flib_vector *vec, flib_map *map, bool mappreview) {
+int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview) {
int result = -1;
flib_vector *tempvector = flib_vector_create();
if(!vec || !map) {
@@ -96,12 +97,13 @@
}
}
-int flib_ipc_append_gamescheme(flib_vector *vec, flib_cfg *scheme, flib_cfg_meta *meta) {
+int flib_ipc_append_gamescheme(flib_vector *vec, const flib_cfg *scheme) {
int result = -1;
flib_vector *tempvector = flib_vector_create();
- if(!vec || !scheme || !meta) {
+ if(!vec || !scheme) {
flib_log_e("null parameter in flib_ipc_append_gamescheme");
} else if(tempvector) {
+ const flib_cfg_meta *meta = scheme->meta;
bool error = false;
uint32_t gamemods = 0;
for(int i=0; i<meta->modCount; i++) {
@@ -112,8 +114,8 @@
error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, gamemods);
for(int i=0; i<meta->settingCount; i++) {
int value = scheme->settings[i];
- if(meta->settings[i].checkOverMax) {
- value = value>meta->settings[i].max ? meta->settings[i].max : value;
+ if(meta->settings[i].maxMeansInfinity) {
+ value = value>=meta->settings[i].max ? 9999 : value;
}
if(meta->settings[i].times1000) {
value *= 1000;
@@ -133,19 +135,23 @@
return result;
}
-// FIXME shared ammo will break per-team ammo
-int flib_ipc_append_addteam(flib_vector *vec, flib_team *team, bool perHogAmmo, bool sharedAmmo) {
+static int appendWeaponSet(flib_vector *vec, flib_weaponset *set) {
+ return flib_ipc_append_message(vec, "eammloadt %s", set->loadout)
+ || flib_ipc_append_message(vec, "eammprob %s", set->crateprob)
+ || flib_ipc_append_message(vec, "eammdelay %s", set->delay)
+ || flib_ipc_append_message(vec, "eammreinf %s", set->crateammo);
+}
+
+int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore) {
int result = -1;
flib_vector *tempvector = flib_vector_create();
- if(!vec || !team || !team->weaponset) {
+ if(!vec || !team) {
flib_log_e("invalid parameter in flib_ipc_append_addteam");
} else if(tempvector) {
bool error = false;
- error |= flib_ipc_append_message(tempvector, "eammloadt %s", team->weaponset->loadout);
- error |= flib_ipc_append_message(tempvector, "eammprob %s", team->weaponset->crateprob);
- error |= flib_ipc_append_message(tempvector, "eammdelay %s", team->weaponset->delay);
- error |= flib_ipc_append_message(tempvector, "eammreinf %s", team->weaponset->crateammo);
- if(!perHogAmmo) {
+
+ if(!perHogAmmo && !noAmmoStore) {
+ error |= appendWeaponSet(tempvector, team->hogs[0].weaponset);
error |= flib_ipc_append_message(tempvector, "eammstore");
}
@@ -166,6 +172,9 @@
}
for(int i=0; i<team->hogsInGame; i++) {
+ if(perHogAmmo && !noAmmoStore) {
+ error |= appendWeaponSet(tempvector, team->hogs[i].weaponset);
+ }
error |= flib_ipc_append_message(tempvector, "eaddhh %i %i %s", team->hogs[i].difficulty, team->hogs[i].initialHealth, team->hogs[i].name);
error |= flib_ipc_append_message(tempvector, "ehat %s", team->hogs[i].hat);
}
@@ -181,3 +190,80 @@
flib_vector_destroy(tempvector);
return result;
}
+
+static bool getGameMod(const flib_cfg *conf, int maskbit) {
+ for(int i=0; i<conf->meta->modCount; i++) {
+ if(conf->meta->mods[i].bitmaskIndex == maskbit) {
+ return conf->mods[i];
+ }
+ }
+ flib_log_e("Unable to find game mod with mask bit %i", maskbit);
+ return false;
+}
+
+int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame) {
+ int result = -1;
+ flib_vector *tempvector = flib_vector_create();
+ if(!vec || !setup) {
+ flib_log_e("null parameter in flib_ipc_append_fullconfig");
+ } else if(tempvector) {
+ bool error = false;
+ bool perHogAmmo = false;
+ bool sharedAmmo = false;
+
+ error |= flib_ipc_append_message(vec, netgame ? "TN" : "TL");
+ error |= flib_ipc_append_seed(vec, setup->seed);
+ if(setup->map) {
+ error |= flib_ipc_append_mapconf(tempvector, setup->map, false);
+ }
+ if(setup->script) {
+ error |= flib_ipc_append_message(tempvector, "escript %s", setup->script);
+ }
+ if(setup->gamescheme) {
+ error |= flib_ipc_append_gamescheme(tempvector, setup->gamescheme);
+ sharedAmmo = getGameMod(setup->gamescheme, GAMEMOD_SHAREDAMMO_MASKBIT);
+ // Shared ammo has priority over per-hog ammo
+ perHogAmmo = !sharedAmmo && getGameMod(setup->gamescheme, GAMEMOD_PERHOGAMMO_MASKBIT);
+ }
+ if(setup->teams && setup->teamcount>0) {
+ uint32_t *clanColors = flib_calloc(setup->teamcount, sizeof(uint32_t));
+ if(!clanColors) {
+ error = true;
+ } else {
+ int clanCount = 0;
+ for(int i=0; i<setup->teamcount; i++) {
+ flib_team *team = setup->teams[i];
+ bool newClan = false;
+
+ // Find the clan index of this team (clans are identified by color).
+ // The upper 8 bits (alpha) are ignored in the engine as well.
+ uint32_t color = team->color&UINT32_C(0x00ffffff);
+ int clan = 0;
+ while(clan<clanCount && clanColors[clan] != color) {
+ clan++;
+ }
+ if(clan==clanCount) {
+ newClan = true;
+ clanCount++;
+ clanColors[clan] = color;
+ }
+
+ // If shared ammo is active, only add an ammo store for the first team in each clan.
+ bool noAmmoStore = sharedAmmo&&!newClan;
+ error |= flib_ipc_append_addteam(tempvector, setup->teams[i], perHogAmmo, noAmmoStore);
+ }
+ }
+ free(clanColors);
+ }
+ error |= flib_ipc_append_message(tempvector, "!");
+
+ if(!error) {
+ // Message created, now we can copy everything.
+ flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector);
+ if(flib_vector_append(vec, constbuf.data, constbuf.size) == constbuf.size) {
+ result = 0;
+ }
+ }
+ }
+ return result;
+}
--- a/project_files/frontlib/ipc/ipcprotocol.h Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/ipc/ipcprotocol.h Fri Jun 15 19:57:25 2012 +0200
@@ -5,6 +5,7 @@
#include "../model/map.h"
#include "../model/team.h"
#include "../model/cfg.h"
+#include "../model/gamesetup.h"
#include <stdbool.h>
@@ -27,7 +28,7 @@
* Returns nonzero if something goes wrong. In that case the buffer
* contents are unaffected.
*/
-int flib_ipc_append_mapconf(flib_vector *vec, flib_map *map, bool mappreview);
+int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview);
/**
* Append a seed message to the buffer.
@@ -43,8 +44,10 @@
* Returns nonzero if something goes wrong. In that case the buffer
* contents are unaffected.
*/
-int flib_ipc_append_gamescheme(flib_vector *vec, flib_cfg *seed, flib_cfg_meta *meta);
+int flib_ipc_append_gamescheme(flib_vector *vec, const flib_cfg *cfg);
-int flib_ipc_append_addteam(flib_vector *vec, flib_team *team, bool perHogAmmo, bool sharedAmmo);
+int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore);
+
+int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame);
#endif /* IPCPROTOCOL_H_ */
--- a/project_files/frontlib/model/cfg.c Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/model/cfg.c Fri Jun 15 19:57:25 2012 +0200
@@ -3,96 +3,25 @@
#include "../util/inihelper.h"
#include "../util/logging.h"
#include "../util/util.h"
+#include "../util/refcounter.h"
#include <stdio.h>
#include <stdlib.h>
-
-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);
- flib_ini_destroy(settingfile);
- flib_ini_destroy(modfile);
- return NULL;
-}
-
-flib_cfg_meta *flib_cfg_meta_from_ini(const char *settingpath, const char *modpath) {
- if(!settingpath || !modpath) {
- flib_log_e("null parameter in flib_cfg_meta_from_ini");
- return NULL;
- }
- flib_cfg_meta *result = flib_calloc(1, sizeof(flib_cfg_meta));
- 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 = 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));
-
- if(!result->settings || !result->mods) {
- return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
- }
-
- for(int i=0; i<result->settingCount; i++) {
- 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);
- }
+#include <limits.h>
+#include <string.h>
- bool error = false;
- 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, result->settings[i].iniName);
- return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
- }
- }
-
- for(int i=0; i<result->modCount; i++) {
- 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;
- 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, result->mods[i].iniName);
- return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
- }
- }
-
- flib_ini_destroy(settingfile);
- flib_ini_destroy(modfile);
- return result;
-}
-
-void flib_cfg_meta_destroy(flib_cfg_meta *cfg) {
+static void flib_cfg_meta_destroy(flib_cfg_meta *cfg) {
if(cfg) {
if(cfg->settings) {
for(int i=0; i<cfg->settingCount; i++) {
- free(cfg->settings[i].iniName);
- free(cfg->settings[i].title);
+ free(cfg->settings[i].name);
free(cfg->settings[i].engineCommand);
- free(cfg->settings[i].image);
}
free(cfg->settings);
}
if(cfg->mods) {
for(int i=0; i<cfg->modCount; i++) {
- free(cfg->mods[i].iniName);
+ free(cfg->mods[i].name);
}
free(cfg->mods);
}
@@ -100,15 +29,132 @@
}
}
-flib_cfg *flib_cfg_create(const flib_cfg_meta *meta, const char *schemeName) {
- flib_cfg *result = flib_calloc(1, sizeof(flib_cfg));
+static void flib_cfg_destroy(flib_cfg* cfg) {
+ if(cfg) {
+ flib_cfg_meta_release(cfg->meta);
+ free(cfg->mods);
+ free(cfg->settings);
+ free(cfg->schemeName);
+ free(cfg);
+ }
+}
+
+static flib_cfg_meta *flib_cfg_meta_from_ini_handleError(flib_cfg_meta *result, flib_ini *ini) {
+ flib_cfg_meta_destroy(result);
+ flib_ini_destroy(ini);
+ return NULL;
+}
+
+static int readMetaSettingSections(flib_ini *ini, flib_cfg_meta *result, int limit) {
+ while(result->settingCount<limit) {
+ char sectionName[32];
+ if(snprintf(sectionName, sizeof(sectionName), "setting%i", result->settingCount) <= 0) {
+ return -1;
+ }
+ if(!flib_ini_enter_section(ini, sectionName)) {
+ flib_cfg_setting_meta *metasetting = &result->settings[result->settingCount];
+ result->settingCount++;
+
+ bool error = false;
+ error |= flib_ini_get_str(ini, &metasetting->name, "name");
+ error |= flib_ini_get_str_opt(ini, &metasetting->engineCommand, "command", NULL);
+ error |= flib_ini_get_bool(ini, &metasetting->times1000, "times1000");
+ error |= flib_ini_get_bool(ini, &metasetting->maxMeansInfinity, "maxmeansinfinity");
+ error |= flib_ini_get_int(ini, &metasetting->min, "min");
+ error |= flib_ini_get_int(ini, &metasetting->max, "max");
+ error |= flib_ini_get_int(ini, &metasetting->def, "default");
+ if(error) {
+ flib_log_e("Missing or malformed ini parameter in metaconfig, section %s", sectionName);
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static int readMetaModSections(flib_ini *ini, flib_cfg_meta *result, int limit) {
+ while(result->modCount<limit) {
+ char sectionName[32];
+ if(snprintf(sectionName, sizeof(sectionName), "mod%i", result->modCount) <= 0) {
+ return -1;
+ }
+ if(!flib_ini_enter_section(ini, sectionName)) {
+ flib_cfg_mod_meta *metamod = &result->mods[result->modCount];
+ result->modCount++;
+
+ bool error = false;
+ error |= flib_ini_get_str(ini, &metamod->name, "name");
+ error |= flib_ini_get_int(ini, &metamod->bitmaskIndex, "bitmaskIndex");
+ if(error) {
+ flib_log_e("Missing or malformed ini parameter in metaconfig, section %s", sectionName);
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+flib_cfg_meta *flib_cfg_meta_from_ini(const char *filename) {
+ if(!filename) {
+ flib_log_e("null parameter in flib_cfg_meta_from_ini");
+ return NULL;
+ }
+ flib_cfg_meta *result = flib_cfg_meta_retain(flib_calloc(1, sizeof(flib_cfg_meta)));
+ flib_ini *ini = flib_ini_load(filename);
+
+ if(!result || !ini) {
+ return flib_cfg_meta_from_ini_handleError(result, ini);
+ }
+
+ // We're overallocating here for simplicity
+ int sectionCount = flib_ini_get_sectioncount(ini);
+ result->settingCount = 0;
+ result->modCount = 0;
+ result->settings = flib_calloc(sectionCount, sizeof(flib_cfg_setting_meta));
+ result->mods = flib_calloc(sectionCount, sizeof(flib_cfg_mod_meta));
+
+ if(!result->settings || !result->mods) {
+ return flib_cfg_meta_from_ini_handleError(result, ini);
+ }
+
+ if(readMetaSettingSections(ini, result, sectionCount) || readMetaModSections(ini, result, sectionCount)) {
+ return flib_cfg_meta_from_ini_handleError(result, ini);
+ }
+
+ if(result->settingCount+result->modCount != sectionCount) {
+ flib_log_e("Unknown or non-contiguous sections headers in metaconfig.");
+ return flib_cfg_meta_from_ini_handleError(result, ini);
+ }
+
+ flib_ini_destroy(ini);
+ return result;
+}
+
+flib_cfg_meta *flib_cfg_meta_retain(flib_cfg_meta *metainfo) {
+ if(metainfo) {
+ flib_retain(&metainfo->_referenceCount, "flib_cfg_meta");
+ }
+ return metainfo;
+}
+
+void flib_cfg_meta_release(flib_cfg_meta *cfg) {
+ if(cfg && flib_release(&cfg->_referenceCount, "flib_cfg_meta")) {
+ flib_cfg_meta_destroy(cfg);
+ }
+}
+
+flib_cfg *flib_cfg_create(flib_cfg_meta *meta, const char *schemeName) {
+ flib_cfg *result = flib_cfg_retain(flib_calloc(1, sizeof(flib_cfg)));
if(!meta || !result || !schemeName) {
flib_log_e("null parameter in flib_cfg_create");
return NULL;
}
- result->modCount = meta->modCount;
- result->settingCount = meta->settingCount;
+ result->meta = flib_cfg_meta_retain(meta);
result->schemeName = flib_strdupnull(schemeName);
result->mods = flib_calloc(meta->modCount, sizeof(*result->mods));
result->settings = flib_calloc(meta->settingCount, sizeof(*result->settings));
@@ -124,103 +170,27 @@
return result;
}
-flib_cfg *flib_cfg_from_ini_handleError(flib_cfg *result, flib_ini *settingfile) {
- flib_ini_destroy(settingfile);
- flib_cfg_destroy(result);
- return NULL;
-}
-
-flib_cfg *flib_cfg_from_ini(const flib_cfg_meta *meta, const char *filename) {
- if(!meta || !filename) {
- flib_log_e("null parameter in flib_cfg_from_ini");
- return NULL;
- }
- flib_ini *settingfile = flib_ini_load(filename);
- if(!settingfile) {
- return NULL;
- }
-
- 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);
-
- 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);
- }
+flib_cfg *flib_cfg_copy(flib_cfg *cfg) {
+ flib_cfg *result = NULL;
+ if(cfg) {
+ result = flib_cfg_create(cfg->meta, cfg->schemeName);
+ if(result) {
+ memcpy(result->mods, cfg->mods, cfg->meta->modCount * sizeof(*cfg->mods));
+ memcpy(result->settings, cfg->settings, cfg->meta->settingCount * sizeof(*cfg->settings));
}
}
-
- 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);
- }
- }
- }
- flib_ini_destroy(settingfile);
- return result;
-}
-
-int flib_cfg_to_ini(const flib_cfg_meta *meta, const char *filename, const flib_cfg *config) {
- int result = -1;
- if(!meta || !filename || !config || config->modCount!=meta->modCount || config->settingCount!=meta->settingCount) {
- flib_log_e("Invalid parameter in flib_cfg_to_ini");
- } else {
- flib_ini *ini = flib_ini_create(filename);
- if(ini) {
- bool error = false;
-
- // Add the values
- 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) {
- for(int i=0; i<config->settingCount; i++) {
- error |= flib_ini_set_int(ini, meta->settings[i].iniName, config->settings[i]);
- }
- }
-
- 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;
}
-void flib_cfg_destroy(flib_cfg* cfg) {
+flib_cfg *flib_cfg_retain(flib_cfg *cfg) {
if(cfg) {
- free(cfg->mods);
- free(cfg->settings);
- free(cfg->schemeName);
- free(cfg);
+ flib_retain(&cfg->_referenceCount, "flib_cfg");
+ }
+ return cfg;
+}
+
+void flib_cfg_release(flib_cfg *cfg) {
+ if(cfg && flib_release(&cfg->_referenceCount, "flib_cfg")) {
+ flib_cfg_destroy(cfg);
}
}
--- a/project_files/frontlib/model/cfg.h Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/model/cfg.h Fri Jun 15 19:57:25 2012 +0200
@@ -1,9 +1,5 @@
/**
* Data structures for game scheme information.
- *
- * Important conventions:
- * - All data structures own what they point to.
- * - Strings are never null pointers.
*/
#ifndef CFG_H_
@@ -11,66 +7,79 @@
#include <stdbool.h>
+// TODO: cfg/config -> scheme
+
typedef struct {
- char *iniName;
- char *title;
+ char *name;
char *engineCommand;
- char *image;
- int netplayIndex;
- bool checkOverMax;
+ bool maxMeansInfinity;
bool times1000;
- int def;
int min;
int max;
+ int def;
} flib_cfg_setting_meta;
typedef struct {
- char *iniName;
+ char *name;
int bitmaskIndex;
} flib_cfg_mod_meta;
typedef struct {
- int settingCount;
- int modCount;
+ int _referenceCount;
+ int settingCount;
+ int modCount;
flib_cfg_setting_meta *settings;
flib_cfg_mod_meta *mods;
} flib_cfg_meta;
typedef struct {
- int settingCount;
- int modCount;
+ int _referenceCount;
+ flib_cfg_meta *meta;
+
char *schemeName;
int *settings;
bool *mods;
} flib_cfg;
/**
- * Read the meta-configuration from the relevant .ini files (e.g. which settings exist,
+ * Read the meta-configuration from a .ini file (e.g. which settings exist,
* what are their defaults etc.)
*
- * Returns the meta-configuration or NULL. Destroy the meta-configuration with
- * flib_cfg_meta_destroy.
+ * Returns the meta-configuration or NULL.
*/
-flib_cfg_meta *flib_cfg_meta_from_ini(const char *settingpath, const char *modpath);
-void flib_cfg_meta_destroy(flib_cfg_meta *metainfo);
+flib_cfg_meta *flib_cfg_meta_from_ini(const char *filename);
/**
- * Create a new configuration with default settings.
+ * Increase the reference count of the object. Call this if you store a pointer to it somewhere.
+ * Returns the parameter.
+ */
+flib_cfg_meta *flib_cfg_meta_retain(flib_cfg_meta *metainfo);
+
+/**
+ * Decrease the reference count of the object and free it if this was the last reference.
+ */
+void flib_cfg_meta_release(flib_cfg_meta *metainfo);
+
+/**
+ * Create a new configuration with everything set to default or false
* Returns NULL on error.
*/
-flib_cfg *flib_cfg_create(const flib_cfg_meta *meta, const char *schemeName);
+flib_cfg *flib_cfg_create(flib_cfg_meta *meta, const char *schemeName);
+
+/**
+ * Create a copy of the scheme. Returns NULL on error or if NULL was passed.
+ */
+flib_cfg *flib_cfg_copy(flib_cfg *cfg);
/**
- * Load a configuration from the ini file.
- * Returns NULL on error.
+ * Increase the reference count of the object. Call this if you store a pointer to it somewhere.
+ * Returns the parameter.
*/
-flib_cfg *flib_cfg_from_ini(const flib_cfg_meta *meta, const char *filename);
+flib_cfg *flib_cfg_retain(flib_cfg *cfg);
/**
- * Store the configuration to an ini file.
- * Returns NULL on error.
+ * Decrease the reference count of the object and free it if this was the last reference.
*/
-int flib_cfg_to_ini(const flib_cfg_meta *meta, const char *filename, const flib_cfg *config);
-void flib_cfg_destroy(flib_cfg* cfg);
+void flib_cfg_release(flib_cfg* cfg);
#endif /* CFG_H_ */
--- a/project_files/frontlib/model/map.c Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/model/map.c Fri Jun 15 19:57:25 2012 +0200
@@ -3,9 +3,19 @@
#include "../util/inihelper.h"
#include "../util/util.h"
#include "../util/logging.h"
+#include "../util/refcounter.h"
#include <stdlib.h>
+static void flib_map_destroy(flib_map *map) {
+ if(map) {
+ free(map->drawData);
+ free(map->name);
+ free(map->theme);
+ free(map);
+ }
+}
+
flib_map *flib_map_create_regular(const char *theme, int templateFilter) {
flib_map *result = NULL;
if(!theme) {
@@ -13,6 +23,7 @@
} else {
flib_map *newmap = flib_calloc(1, sizeof(flib_map));
if(newmap) {
+ newmap->_referenceCount = 1;
newmap->mapgen = MAPGEN_REGULAR;
newmap->templateFilter = templateFilter;
newmap->theme = flib_strdupnull(theme);
@@ -33,6 +44,7 @@
} else {
flib_map *newmap = flib_calloc(1, sizeof(flib_map));
if(newmap) {
+ newmap->_referenceCount = 1;
newmap->mapgen = MAPGEN_MAZE;
newmap->mazeSize = mazeSize;
newmap->theme = flib_strdupnull(theme);
@@ -53,6 +65,7 @@
} else {
flib_map *newmap = flib_calloc(1, sizeof(flib_map));
if(newmap) {
+ newmap->_referenceCount = 1;
newmap->mapgen = MAPGEN_NAMED;
newmap->name = flib_strdupnull(name);
if(newmap->name) {
@@ -72,6 +85,7 @@
} else {
flib_map *newmap = flib_calloc(1, sizeof(flib_map));
if(newmap) {
+ newmap->_referenceCount = 1;
newmap->mapgen = MAPGEN_DRAWN;
newmap->drawData = flib_bufdupnull(drawData, drawDataSize);
newmap->drawDataSize = drawDataSize;
@@ -85,11 +99,15 @@
return result;
}
-void flib_map_destroy(flib_map *map) {
+flib_map *flib_map_retain(flib_map *map) {
if(map) {
- free(map->drawData);
- free(map->name);
- free(map->theme);
- free(map);
+ flib_retain(&map->_referenceCount, "flib_map");
+ }
+ return map;
+}
+
+void flib_map_release(flib_map *map) {
+ if(map && flib_release(&map->_referenceCount, "flib_map")) {
+ flib_map_destroy(map);
}
}
--- a/project_files/frontlib/model/map.h Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/model/map.h Fri Jun 15 19:57:25 2012 +0200
@@ -30,6 +30,7 @@
#define MAZE_SIZE_LARGE_ISLANDS 5
typedef struct {
+ int _referenceCount;
int mapgen; // Always one of the MAPGEN_ constants
char *theme; // Used for all except MAPGEN_NAMED
char *name; // Used for MAPGEN_NAMED
@@ -79,9 +80,15 @@
flib_map *flib_map_create_drawn(const char *theme, const uint8_t *drawData, int drawDataSize);
/**
- * Free the memory taken up by the map. Passing NULL is allowed and does nothing.
+ * Increase the reference count of the object. Call this if you store a pointer to it somewhere.
+ * Returns the parameter.
*/
-void flib_map_destroy(flib_map *map);
+flib_map *flib_map_retain(flib_map *map);
+
+/**
+ * Decrease the reference count of the object and free it if this was the last reference.
+ */
+void flib_map_release(flib_map *map);
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/model/schemelist.c Fri Jun 15 19:57:25 2012 +0200
@@ -0,0 +1,229 @@
+#include "schemelist.h"
+
+#include "../util/inihelper.h"
+#include "../util/logging.h"
+#include "../util/util.h"
+#include "../util/refcounter.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+static void flib_schemelist_destroy(flib_schemelist *list) {
+ if(list) {
+ for(int i=0; i<list->schemeCount; i++) {
+ flib_cfg_release(list->schemes[i]);
+ }
+ free(list);
+ }
+}
+
+static char *makePrefixedName(int schemeIndex, const char *settingName) {
+ return flib_asprintf("%i\\%s", schemeIndex, settingName);
+}
+
+static int readSettingsFromIni(flib_ini *ini, flib_cfg *scheme, int index) {
+ flib_cfg_meta *meta = scheme->meta;
+ bool error = false;
+ for(int i=0; i<meta->settingCount && !error; i++) {
+ char *key = makePrefixedName(index, meta->settings[i].name);
+ if(!key) {
+ error = true;
+ } else if(flib_ini_get_int_opt(ini, &scheme->settings[i], key, meta->settings[i].def)) {
+ flib_log_e("Error reading setting %s in schemes file.", key);
+ error = true;
+ }
+ free(key);
+ }
+ return error;
+}
+
+static int readModsFromIni(flib_ini *ini, flib_cfg *scheme, int index) {
+ flib_cfg_meta *meta = scheme->meta;
+ bool error = false;
+ for(int i=0; i<meta->modCount && !error; i++) {
+ char *key = makePrefixedName(index, meta->mods[i].name);
+ if(!key) {
+ error = true;
+ } else if(flib_ini_get_bool_opt(ini, &scheme->mods[i], key, false)) {
+ flib_log_e("Error reading mod %s in schemes file.", key);
+ error = true;
+ }
+ free(key);
+ }
+ return error;
+}
+
+static flib_cfg *readSchemeFromIni(flib_cfg_meta *meta, flib_ini *ini, int index) {
+ flib_cfg *result = NULL;
+ char *schemeNameKey = makePrefixedName(index+1, "name");
+ if(schemeNameKey) {
+ char *schemeName = NULL;
+ if(!flib_ini_get_str_opt(ini, &schemeName, schemeNameKey, "Unnamed")) {
+ flib_cfg *scheme = flib_cfg_create(meta, schemeName);
+ if(scheme) {
+ if(!readSettingsFromIni(ini, scheme, index) && !readModsFromIni(ini, scheme, index)) {
+ result = flib_cfg_retain(scheme);
+ }
+ }
+ flib_cfg_release(scheme);
+ }
+ free(schemeName);
+ }
+ free(schemeNameKey);
+ return result;
+}
+
+static flib_schemelist *fromIniHandleError(flib_schemelist *result, flib_ini *ini) {
+ flib_ini_destroy(ini);
+ flib_schemelist_destroy(result);
+ return NULL;
+}
+
+flib_schemelist *flib_schemelist_from_ini(flib_cfg_meta *meta, const char *filename) {
+ flib_schemelist *list = NULL;
+ if(!meta || !filename) {
+ flib_log_e("null parameter in flib_schemelist_from_ini");
+ return NULL;
+ }
+ flib_ini *ini = flib_ini_load(filename);
+ if(!ini || flib_ini_enter_section(ini, "schemes")) {
+ flib_log_e("Missing file or missing section \"schemes\" in file %s.", filename);
+ return fromIniHandleError(list, ini);
+ }
+
+ list = flib_schemelist_create();
+ if(!list) {
+ return fromIniHandleError(list, ini);
+ }
+
+ int schemeCount = 0;
+ if(flib_ini_get_int(ini, &schemeCount, "size")) {
+ flib_log_e("Missing or malformed scheme count in config file %s.", filename);
+ return fromIniHandleError(list, ini);
+ }
+
+ for(int i=0; i<schemeCount; i++) {
+ flib_cfg *scheme = readSchemeFromIni(meta, ini, i);
+ if(!scheme || flib_schemelist_insert(list, scheme, i)) {
+ flib_cfg_release(scheme);
+ flib_log_e("Error reading scheme %i from config file %s.", i, filename);
+ return fromIniHandleError(list, ini);
+ }
+ flib_cfg_release(scheme);
+ }
+
+
+ flib_ini_destroy(ini);
+ return list;
+}
+
+static int writeSchemeToIni(flib_cfg *scheme, flib_ini *ini, int index) {
+ flib_cfg_meta *meta = scheme->meta;
+ bool error = false;
+
+ char *key = makePrefixedName(index+1, "name");
+ error |= !key || flib_ini_set_str(ini, key, scheme->schemeName);
+ free(key);
+
+ for(int i=0; i<meta->modCount && !error; i++) {
+ char *key = makePrefixedName(index+1, meta->mods[i].name);
+ error |= !key || flib_ini_set_bool(ini, key, scheme->mods[i]);
+ free(key);
+ }
+
+ for(int i=0; i<meta->settingCount && !error; i++) {
+ char *key = makePrefixedName(index+1, meta->settings[i].name);
+ error |= !key || flib_ini_set_int(ini, key, scheme->settings[i]);
+ free(key);
+ }
+ return error;
+}
+
+int flib_schemelist_to_ini(const char *filename, const flib_schemelist *schemes) {
+ int result = -1;
+ if(!filename || !schemes) {
+ flib_log_e("null parameter in flib_schemelist_to_ini");
+ } else {
+ flib_ini *ini = flib_ini_create(NULL);
+ if(ini && !flib_ini_create_section(ini, "schemes")) {
+ bool error = false;
+ error |= flib_ini_set_int(ini, "size", schemes->schemeCount);
+ for(int i=0; i<schemes->schemeCount && !error; i++) {
+ error |= writeSchemeToIni(schemes->schemes[i], ini, i);
+ }
+
+ if(!error) {
+ result = flib_ini_save(ini, filename);
+ }
+ }
+ flib_ini_destroy(ini);
+ }
+ return result;
+}
+
+flib_schemelist *flib_schemelist_create() {
+ return flib_schemelist_retain(flib_calloc(1, sizeof(flib_schemelist)));
+}
+
+flib_schemelist *flib_schemelist_retain(flib_schemelist *list) {
+ if(list) {
+ flib_retain(&list->_referenceCount, "flib_schemelist");
+ }
+ return list;
+}
+
+void flib_schemelist_release(flib_schemelist *list) {
+ if(list && flib_release(&list->_referenceCount, "flib_schemelist")) {
+ flib_schemelist_destroy(list);
+ }
+}
+
+flib_cfg *flib_schemelist_find(flib_schemelist *list, const char *name) {
+ if(list && name) {
+ for(int i=0; i<list->schemeCount; i++) {
+ if(!strcmp(name, list->schemes[i]->schemeName)) {
+ return list->schemes[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+int flib_schemelist_insert(flib_schemelist *list, flib_cfg *cfg, int pos) {
+ int result = -1;
+ if(!list || !cfg || pos < 0 || pos > list->schemeCount) {
+ flib_log_e("Invalid parameter in flib_schemelist_insert");
+ } else {
+ flib_cfg **newSchemes = flib_realloc(list->schemes, (list->schemeCount+1)*sizeof(*list->schemes));
+ if(newSchemes) {
+ list->schemes = newSchemes;
+ memmove(list->schemes+pos+1, list->schemes+pos, (list->schemeCount-pos)*sizeof(*list->schemes));
+ list->schemes[pos] = flib_cfg_retain(cfg);
+ list->schemeCount++;
+ result = 0;
+ }
+ }
+ return result;
+}
+
+int flib_schemelist_delete(flib_schemelist *list, int pos) {
+ int result = -1;
+ if(!list || pos < 0 || pos >= list->schemeCount) {
+ flib_log_e("Invalid parameter in flib_schemelist_delete");
+ } else {
+ flib_cfg_release(list->schemes[pos]);
+ memmove(list->schemes+pos, list->schemes+pos+1, (list->schemeCount-(pos+1))*sizeof(*list->schemes));
+ list->schemes[list->schemeCount-1] = NULL;
+ list->schemeCount--;
+
+ // If the realloc fails, just keep using the old buffer...
+ flib_cfg **newSchemes = flib_realloc(list->schemes, list->schemeCount*sizeof(*list->schemes));
+ if(newSchemes || list->schemeCount==1) {
+ list->schemes = newSchemes;
+ }
+ result = 0;
+ }
+ return result;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/model/schemelist.h Fri Jun 15 19:57:25 2012 +0200
@@ -0,0 +1,67 @@
+/**
+ * Functions for managing a list of schemes.
+ * This is in here because the scheme config file of the QtFrontend (which we are staying compatble with) contains
+ * all the schemes at once, so we need functions to work with a list like that.
+ */
+
+#ifndef SCHEMELIST_H_
+#define SCHEMELIST_H_
+
+#include "cfg.h"
+
+typedef struct {
+ int _referenceCount;
+ int schemeCount;
+ flib_cfg **schemes;
+} flib_schemelist;
+
+/**
+ * Load a list of configurations from the ini file.
+ * Returns NULL on error.
+ */
+flib_schemelist *flib_schemelist_from_ini(flib_cfg_meta *meta, const char *filename);
+
+/**
+ * Store the list of configurations to an ini file.
+ * Returns NULL on error.
+ */
+int flib_schemelist_to_ini(const char *filename, const flib_schemelist *config);
+
+/**
+ * Create an empty scheme list. Returns NULL on error.
+ */
+flib_schemelist *flib_schemelist_create();
+
+/**
+ * Insert a new scheme into the list at position pos, moving all higher schemes to make place.
+ * pos must be at least 0 (insert at the start) and at most list->schemeCount (insert at the end).
+ * The scheme is retained automatically.
+ * Returns 0 on success.
+ */
+int flib_schemelist_insert(flib_schemelist *list, flib_cfg *cfg, int pos);
+
+/**
+ * Delete a cfg from the list at position pos, moving down all higher schemes.
+ * The scheme is released automatically.
+ * Returns 0 on success.
+ */
+int flib_schemelist_delete(flib_schemelist *list, int pos);
+
+/**
+ * Find the scheme with a specific name
+ */
+flib_cfg *flib_schemelist_find(flib_schemelist *list, const char *name);
+
+/**
+ * Increase the reference count of the object. Call this if you store a pointer to it somewhere.
+ * Returns the parameter.
+ */
+flib_schemelist *flib_schemelist_retain(flib_schemelist *list);
+
+/**
+ * Decrease the reference count of the object and free it if this was the last reference.
+ */
+void flib_schemelist_release(flib_schemelist *list);
+
+
+#endif /* SCHEMELIST_H_ */
--- a/project_files/frontlib/model/team.c Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/model/team.c Fri Jun 15 19:57:25 2012 +0200
@@ -194,6 +194,7 @@
for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
free(team->hogs[i].name);
free(team->hogs[i].hat);
+ flib_weaponset_release(team->hogs[i].weaponset);
}
free(team->name);
free(team->grave);
@@ -208,7 +209,15 @@
}
free(team->bindings);
free(team->hash);
- flib_weaponset_destroy(team->weaponset);
free(team);
}
}
+
+void flib_team_set_weaponset(flib_team *team, flib_weaponset *set) {
+ if(team) {
+ for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
+ flib_weaponset_release(team->hogs[i].weaponset);
+ team->hogs[i].weaponset = flib_weaponset_retain(set);
+ }
+ }
+}
--- a/project_files/frontlib/model/team.h Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/model/team.h Fri Jun 15 19:57:25 2012 +0200
@@ -34,6 +34,7 @@
// Transient setting used in game setup
int initialHealth;
+ flib_weaponset *weaponset;
} flib_hog;
typedef struct {
@@ -57,9 +58,7 @@
uint32_t color;
int hogsInGame;
bool remoteDriven;
- char *hash; // TODO calculate
-
- flib_weaponset *weaponset;
+ char *hash; // TODO calculate at the appropriate time... i.e. before trying to send the config to the engine
} flib_team;
/**
@@ -85,6 +84,12 @@
* first hog is used for the entire team when writing.
*/
int flib_team_to_ini(const char *filename, const flib_team *team);
+
+/**
+ * Set the same weaponset for every hog in the team
+ */
+void flib_team_set_weaponset(flib_team *team, flib_weaponset *set);
+
void flib_team_destroy(flib_team *team);
#endif /* TEAM_H_ */
--- a/project_files/frontlib/model/weapon.c Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/model/weapon.c Fri Jun 15 19:57:25 2012 +0200
@@ -3,118 +3,177 @@
#include "../util/inihelper.h"
#include "../util/logging.h"
#include "../util/util.h"
+#include "../util/refcounter.h"
#include <stdlib.h>
#include <ctype.h>
-
-int set_field(char field[WEAPONS_COUNT+1], const char *line, bool no9) {
- // Validate the new string
- for(int i=0; i<WEAPONS_COUNT && line[i]; i++) {
- if(line[i] < '0' || line[i] > '9' || (no9 && line[i] == '9')) {
- flib_log_e("Invalid character in weapon config string \"%.*s\", position %i", WEAPONS_COUNT, line, i);
- return -1;
- }
- }
-
- bool lineEnded = false;
- for(int i=0; i<WEAPONS_COUNT; i++) {
- if(!lineEnded && !line[i]) {
- flib_log_w("Incomplete weapon config line \"%s\", filling with zeroes.", line);
- lineEnded = true;
- }
- if(lineEnded) {
- field[i] = '0';
- } else {
- field[i] = line[i];
- }
- }
- field[WEAPONS_COUNT] = 0;
- return 0;
-}
+#include <string.h>
-static flib_weaponset *flib_weaponset_create_str(const char *name, const char *loadoutStr, const char *crateProbStr, const char *crateAmmoStr, const char *delayStr) {
- flib_weaponset *result = NULL;
- if(!name || !loadoutStr || !crateProbStr || !crateAmmoStr || !delayStr) {
- flib_log_e("null parameter in flib_weaponset_create_str");
- } else {
- flib_weaponset *newSet = flib_calloc(1, sizeof(flib_weaponset));
- char *nameCopy = flib_strdupnull(name);
- if(newSet && nameCopy) {
- newSet->name = nameCopy;
- nameCopy = NULL;
- bool error = false;
- error |= set_field(newSet->loadout, loadoutStr, false);
- error |= set_field(newSet->crateprob, crateProbStr, false);
- error |= set_field(newSet->crateammo, crateAmmoStr, false);
- error |= set_field(newSet->delay, delayStr, false);
- if(!error) {
- result = newSet;
- newSet = NULL;
- }
- }
- free(nameCopy);
- flib_weaponset_destroy(newSet);
- }
- return result;
-}
-
-void flib_weaponset_destroy(flib_weaponset *cfg) {
+static void flib_weaponset_destroy(flib_weaponset *cfg) {
if(cfg) {
free(cfg->name);
free(cfg);
}
}
+static void setField(char field[WEAPONS_COUNT+1], const char *line, int lineLen, bool no9) {
+ if(lineLen>WEAPONS_COUNT) {
+ lineLen = WEAPONS_COUNT;
+ }
+
+ char min = '0';
+ char max = no9 ? '8' : '9';
+ for(int i=0; i<lineLen; i++) {
+ if(line[i] >= min && line[i] <= max) {
+ field[i] = line[i];
+ } else {
+ flib_log_w("Invalid character in weapon config string \"%.*s\", position %i", lineLen, line, i);
+ field[i] = '0';
+ }
+ }
+ for(int i=lineLen; i<WEAPONS_COUNT; i++) {
+ field[i] = '0';
+ }
+ field[WEAPONS_COUNT] = 0;
+}
+
flib_weaponset *flib_weaponset_create(const char *name) {
- return flib_weaponset_create_str(name, AMMOLINE_DEFAULT_QT, AMMOLINE_DEFAULT_PROB, AMMOLINE_DEFAULT_CRATE, AMMOLINE_DEFAULT_DELAY);
+ flib_weaponset *result = NULL;
+ if(!name) {
+ flib_log_e("null parameter in flib_weaponset_create_str");
+ } else {
+ flib_weaponset *newSet = flib_weaponset_retain(flib_calloc(1, sizeof(flib_weaponset)));
+ if(newSet) {
+ newSet->name = flib_strdupnull(name);
+ if(newSet->name) {
+ setField(newSet->loadout, "", 0, false);
+ setField(newSet->crateprob, "", 0, false);
+ setField(newSet->crateammo, "", 0, false);
+ setField(newSet->delay, "", 0, false);
+ result = flib_weaponset_retain(newSet);
+ }
+ }
+ flib_weaponset_release(newSet);
+ }
+ return result;
+}
+
+flib_weaponset *flib_weaponset_retain(flib_weaponset *weaponset) {
+ if(weaponset) {
+ flib_retain(&weaponset->_referenceCount, "flib_weaponset");
+ }
+ return weaponset;
}
-flib_weaponset *flib_weaponset_from_ini(const char *filename) {
- flib_weaponset *result = NULL;
+void flib_weaponset_release(flib_weaponset *weaponset) {
+ if(weaponset && flib_release(&weaponset->_referenceCount, "flib_weaponset")) {
+ flib_weaponset_destroy(weaponset);
+ }
+}
+
+static void flib_weaponsetlist_destroy(flib_weaponsetlist *list) {
+ if(list) {
+ for(int i=0; i<list->weaponsetCount; i++) {
+ flib_weaponset_release(list->weaponsets[i]);
+ }
+ free(list);
+ }
+}
+
+static int fillWeaponsetFromIni(flib_weaponsetlist *list, flib_ini *ini, int index) {
+ int result = -1;
+ char *keyname = flib_ini_get_keyname(ini, index);
+ char *decodedKeyname = flib_urldecode(keyname);
+
+ if(decodedKeyname) {
+ flib_weaponset *set = flib_weaponset_create(decodedKeyname);
+ if(set) {
+ char *value = NULL;
+ if(!flib_ini_get_str(ini, &value, keyname)) {
+ int fieldlen = strlen(value)/4;
+ setField(set->loadout, value, fieldlen, false);
+ setField(set->crateprob, value+1*fieldlen, fieldlen, true);
+ setField(set->delay, value+2*fieldlen, fieldlen, true);
+ setField(set->crateammo, value+3*fieldlen, fieldlen, true);
+ result = flib_weaponsetlist_insert(list, set, list->weaponsetCount);
+ }
+ free(value);
+ }
+ flib_weaponset_release(set);
+ }
+
+ free(keyname);
+ free(decodedKeyname);
+ return result;
+}
+
+static int fillWeaponsetsFromIni(flib_weaponsetlist *list, flib_ini *ini) {
+ bool error = false;
+ int weaponsets = flib_ini_get_keycount(ini);
+
+ for(int i=0; i<weaponsets && !error; i++) {
+ error |= fillWeaponsetFromIni(list, ini, i);
+ }
+ return error;
+}
+
+flib_weaponsetlist *flib_weaponsetlist_from_ini(const char *filename) {
+ flib_weaponsetlist *result = NULL;
if(!filename) {
- flib_log_e("null parameter in flib_weaponset_from_ini");
+ flib_log_e("null parameter in flib_weaponsetlist_from_ini");
} else {
flib_ini *ini = flib_ini_load(filename);
if(!ini) {
- flib_log_e("Error loading weapon scheme file %s", filename);
- } else if(!flib_ini_enter_section(ini, "weaponset")) {
- bool error = false;
- 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);
+ flib_log_e("Missing file %s.", filename);
+ } else if(flib_ini_enter_section(ini, "General")) {
+ flib_log_e("Missing section \"General\" in file %s.", filename);
+ } else {
+ flib_weaponsetlist *list = flib_weaponsetlist_create();
+ if(list) {
+ if(!fillWeaponsetsFromIni(list, ini)) {
+ result = flib_weaponsetlist_retain(list);
+ }
}
- free(name);
- free(loadout);
- free(crateprob);
- free(crateammo);
- free(delay);
+ flib_weaponsetlist_release(list);
}
flib_ini_destroy(ini);
}
return result;
}
-int flib_weaponset_to_ini(const char *filename, const flib_weaponset *set) {
+static bool needsEscape(char c) {
+ return !((c>='0' && c<='9') || (c>='a' && c <='z'));
+}
+
+
+static int writeWeaponsetToIni(flib_ini *ini, flib_weaponset *set) {
int result = -1;
- if(!filename || !set) {
- flib_log_e("null parameter in flib_weaponset_to_ini");
+ char weaponstring[WEAPONS_COUNT*4+1];
+ strcpy(weaponstring, set->loadout);
+ strcat(weaponstring, set->crateprob);
+ strcat(weaponstring, set->delay);
+ strcat(weaponstring, set->crateammo);
+
+ char *escapedname = flib_urlencode_pred(set->name, needsEscape);
+ if(escapedname) {
+ result = flib_ini_set_str(ini, escapedname, weaponstring);
+ }
+ free(escapedname);
+ return result;
+}
+
+int flib_weaponsetlist_to_ini(const char *filename, const flib_weaponsetlist *list) {
+ int result = -1;
+ if(!filename || !list) {
+ flib_log_e("null parameter in flib_weaponsetlist_to_ini");
} else {
- flib_ini *ini = flib_ini_create(filename);
- if(!flib_ini_create_section(ini, "weaponset")) {
+ flib_ini *ini = flib_ini_create(NULL);
+ if(ini && !flib_ini_create_section(ini, "General")) {
bool error = false;
- 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);
+ for(int i=0; i<list->weaponsetCount && !error; i++) {
+ error |= writeWeaponsetToIni(ini, list->weaponsets[i]);
+ }
+
if(!error) {
result = flib_ini_save(ini, filename);
}
@@ -123,3 +182,57 @@
}
return result;
}
+
+flib_weaponsetlist *flib_weaponsetlist_create() {
+ return flib_weaponsetlist_retain(flib_calloc(1, sizeof(flib_weaponsetlist)));
+}
+
+int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *weaponset, int pos) {
+ int result = -1;
+ if(!list || !weaponset || pos < 0 || pos > list->weaponsetCount) {
+ flib_log_e("Invalid parameter in flib_weaponsetlist_insert");
+ } else {
+ flib_weaponset **newSets = flib_realloc(list->weaponsets, (list->weaponsetCount+1)*sizeof(*list->weaponsets));
+ if(newSets) {
+ list->weaponsets = newSets;
+ memmove(list->weaponsets+pos+1, list->weaponsets+pos, (list->weaponsetCount-pos)*sizeof(*list->weaponsets));
+ list->weaponsets[pos] = flib_weaponset_retain(weaponset);
+ list->weaponsetCount++;
+ result = 0;
+ }
+ }
+ return result;
+}
+
+int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos) {
+ int result = -1;
+ if(!list || pos < 0 || pos >= list->weaponsetCount) {
+ flib_log_e("Invalid parameter in flib_weaponsetlist_delete");
+ } else {
+ flib_weaponset_release(list->weaponsets[pos]);
+ memmove(list->weaponsets+pos, list->weaponsets+pos+1, (list->weaponsetCount-(pos+1))*sizeof(*list->weaponsets));
+ list->weaponsets[list->weaponsetCount-1] = NULL;
+ list->weaponsetCount--;
+
+ // If the realloc fails, just keep using the old buffer...
+ flib_weaponset **newSets = flib_realloc(list->weaponsets, list->weaponsetCount*sizeof(*list->weaponsets));
+ if(newSets || list->weaponsetCount==1) {
+ list->weaponsets = newSets;
+ }
+ result = 0;
+ }
+ return result;
+}
+
+flib_weaponsetlist *flib_weaponsetlist_retain(flib_weaponsetlist *list) {
+ if(list) {
+ flib_retain(&list->_referenceCount, "flib_weaponsetlist");
+ }
+ return list;
+}
+
+void flib_weaponsetlist_release(flib_weaponsetlist *list) {
+ if(list && flib_release(&list->_referenceCount, "flib_weaponsetlist")) {
+ flib_weaponsetlist_destroy(list);
+ }
+}
--- a/project_files/frontlib/model/weapon.h Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/model/weapon.h Fri Jun 15 19:57:25 2012 +0200
@@ -10,6 +10,7 @@
* For the other setting, 9 is invalid.
*/
typedef struct {
+ int _referenceCount;
char loadout[WEAPONS_COUNT+1];
char crateprob[WEAPONS_COUNT+1];
char crateammo[WEAPONS_COUNT+1];
@@ -17,6 +18,12 @@
char *name;
} flib_weaponset;
+typedef struct {
+ int _referenceCount;
+ int weaponsetCount;
+ flib_weaponset **weaponsets;
+} flib_weaponsetlist;
+
/**
* Returns a new weapon set, or NULL on error.
* name must not be NULL.
@@ -27,15 +34,57 @@
flib_weaponset *flib_weaponset_create(const char *name);
/**
- * Loads a weapon set, returns NULL on error.
+ * Increase the reference count of the object. Call this if you store a pointer to it somewhere.
+ * Returns the parameter.
+ */
+flib_weaponset *flib_weaponset_retain(flib_weaponset *weaponset);
+
+/**
+ * Decrease the reference count of the object and free it if this was the last reference.
*/
-flib_weaponset *flib_weaponset_from_ini(const char *filename);
+void flib_weaponset_release(flib_weaponset *weaponset);
+
+/**
+ * Load a list of weaponsets from the ini file.
+ * Returns NULL on error.
+ */
+flib_weaponsetlist *flib_weaponsetlist_from_ini(const char *filename);
+
+/**
+ * Store the list of weaponsets to an ini file.
+ * Returns NULL on error.
+ */
+int flib_weaponsetlist_to_ini(const char *filename, const flib_weaponsetlist *weaponsets);
/**
- * Write the weapon set to an ini file. Attempts to
- * retain extra ini settings that were already present.
+ * Create an empty weaponset list. Returns NULL on error.
+ */
+flib_weaponsetlist *flib_weaponsetlist_create();
+
+/**
+ * Insert a new weaponset into the list at position pos, moving all higher weaponsets to make place.
+ * pos must be at least 0 (insert at the start) and at most list->weaponsetCount (insert at the end).
+ * The weaponset is retained automatically.
+ * Returns 0 on success.
*/
-int flib_weaponset_to_ini(const char *filename, const flib_weaponset *set);
-void flib_weaponset_destroy(flib_weaponset *set);
+int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *weaponset, int pos);
+
+/**
+ * Delete a weaponset from the list at position pos, moving down all higher weaponsets.
+ * The weaponset is released automatically.
+ * Returns 0 on success.
+ */
+int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos);
+
+/**
+ * Increase the reference count of the object. Call this if you store a pointer to it somewhere.
+ * Returns the parameter.
+ */
+flib_weaponsetlist *flib_weaponsetlist_retain(flib_weaponsetlist *list);
+
+/**
+ * Decrease the reference count of the object and free it if this was the last reference.
+ */
+void flib_weaponsetlist_release(flib_weaponsetlist *list);
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/resources/metasettings.ini Fri Jun 15 19:57:25 2012 +0200
@@ -0,0 +1,234 @@
+[mod0]
+name=fortsmode
+bitmaskindex=12
+
+[mod1]
+name=divteams
+bitmaskindex=4
+
+[mod2]
+name=solidland
+bitmaskindex=2
+
+[mod3]
+name=border
+bitmaskindex=3
+
+[mod4]
+name=lowgrav
+bitmaskindex=5
+
+[mod5]
+name=laser
+bitmaskindex=6
+
+[mod6]
+name=invulnerability
+bitmaskindex=7
+
+[mod7]
+name=resethealth
+bitmaskindex=8
+
+[mod8]
+name=vampiric
+bitmaskindex=9
+
+[mod9]
+name=karma
+bitmaskindex=10
+
+[mod10]
+name=artillery
+bitmaskindex=11
+
+[mod11]
+name=randomorder
+bitmaskindex=13
+
+[mod12]
+name=king
+bitmaskindex=14
+
+[mod13]
+name=placehog
+bitmaskindex=15
+
+[mod14]
+name=sharedammo
+bitmaskindex=16
+
+[mod15]
+name=disablegirders
+bitmaskindex=17
+
+[mod16]
+name=disablelandobjects
+bitmaskindex=18
+
+[mod17]
+name=aisurvival
+bitmaskindex=19
+
+[mod18]
+name=infattack
+bitmaskindex=20
+
+[mod19]
+name=resetweps
+bitmaskindex=21
+
+[mod20]
+name=perhogammo
+bitmaskindex=22
+
+[mod21]
+name=disablewind
+bitmaskindex=23
+
+[mod22]
+name=morewind
+bitmaskindex=24
+
+[mod23]
+name=tagteam
+bitmaskindex=25
+
+[mod24]
+name=bottomborder
+bitmaskindex=26
+
+
+[setting0]
+name=damagefactor
+times1000=false
+command=e$damagepct
+maxmeansinfinity=false
+min=10
+max=300
+default=100
+
+[setting1]
+name=turntime
+times1000=true
+command=e$turntime
+maxmeansinfinity=true
+min=1
+max=9999
+default=45
+
+[setting2]
+name=health
+times1000=false
+maxmeansinfinity=false
+min=50
+max=200
+default=100
+
+[setting3]
+name=suddendeath
+times1000=false
+command=e$sd_turns
+maxmeansinfinity=true
+min=0
+max=50
+default=15
+
+[setting4]
+name=caseprobability
+times1000=false
+command=e$casefreq
+maxmeansinfinity=false
+min=0
+max=9
+default=5
+
+[setting5]
+name=minestime
+times1000=true
+command=e$minestime
+maxmeansinfinity=false
+min=-1
+max=5
+default=3
+
+[setting6]
+name=minesnum
+times1000=false
+command=e$minesnum
+maxmeansinfinity=false
+min=0
+max=80
+default=4
+
+[setting7]
+name=minedudpct
+times1000=false
+command=e$minedudpct
+maxmeansinfinity=false
+min=0
+max=100
+default=0
+
+[setting8]
+name=explosives
+times1000=false
+command=e$explosives
+maxmeansinfinity=false
+min=0
+max=40
+default=2
+
+[setting9]
+name=healthprobability
+times1000=false
+command=e$healthprob
+maxmeansinfinity=false
+min=0
+max=100
+default=35
+
+[setting10]
+name=healthcaseamount
+times1000=false
+command=e$hcaseamount
+maxmeansinfinity=false
+min=0
+max=200
+default=25
+
+[setting11]
+name=waterrise
+times1000=false
+command=e$waterrise
+maxmeansinfinity=false
+min=0
+max=100
+default=47
+
+[setting12]
+name=healthdecrease
+times1000=false
+command=e$healthdec
+maxmeansinfinity=false
+min=0
+max=100
+default=5
+
+[setting13]
+name=ropepct
+times1000=false
+command=e$ropepct
+maxmeansinfinity=false
+min=25
+max=999
+default=100
+
+[setting14]
+name=getawaytime
+times1000=false
+command=e$getawaytime
+maxmeansinfinity=false
+min=0
+max=999
+default=100
--- a/project_files/frontlib/test.c Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/test.c Fri Jun 15 19:57:25 2012 +0200
@@ -1,6 +1,8 @@
#include "frontlib.h"
#include "util/logging.h"
#include "model/map.h"
+#include "model/weapon.h"
+#include "model/schemelist.h"
#include "ipc/mapconn.h"
#include "ipc/gameconn.h"
@@ -80,7 +82,7 @@
assert(mapConnection);
// We don't need the map description anymore
- flib_map_destroy(map);
+ flib_map_release(map);
map = NULL;
// Register the callback functions
@@ -99,10 +101,13 @@
}
void testGame() {
- flib_cfg_meta *metaconf = flib_cfg_meta_from_ini("basicsettings.ini", "gamemods.ini");
+ flib_cfg_meta *metaconf = flib_cfg_meta_from_ini("metasettings.ini");
assert(metaconf);
+ flib_weaponset *weapons = flib_weaponset_create("Defaultweaps");
+ flib_schemelist *schemelist = flib_schemelist_from_ini(metaconf, "schemes.ini");
+
flib_gamesetup setup;
- setup.gamescheme = flib_cfg_from_ini(metaconf, "scheme_shoppa.ini");
+ setup.gamescheme = flib_schemelist_find(schemelist, "Default");
setup.map = flib_map_create_maze("Jungle", MAZE_SIZE_MEDIUM_TUNNELS);
setup.seed = "asparagus";
setup.script = NULL;
@@ -116,7 +121,6 @@
setup.teams[0]->hogsInGame = 2;
setup.teams[0]->name = "Team Awesome";
setup.teams[0]->voicepack = "British";
- setup.teams[0]->weaponset = flib_weaponset_create("Defaultweaps");
setup.teams[0]->hogs[0].difficulty = 2;
setup.teams[0]->hogs[0].hat = "NoHat";
setup.teams[0]->hogs[0].initialHealth = 100;
@@ -126,15 +130,17 @@
setup.teams[0]->hogs[1].initialHealth = 100;
setup.teams[0]->hogs[1].name = "Chefkoch";
setup.teams[1] = flib_team_from_ini("Cave Dwellers.hwt");
- setup.teams[1]->color = 0xff0000ff;
+ setup.teams[1]->color = 0xFF0000F0;
setup.teams[1]->hogsInGame = 8;
- setup.teams[1]->weaponset = flib_weaponset_create("Defaultweaps");
+ flib_team_set_weaponset(setup.teams[0], weapons);
+ flib_team_set_weaponset(setup.teams[1], weapons);
+ flib_weaponset_release(weapons);
- flib_gameconn *gameconn = flib_gameconn_create("Medo42", metaconf, &setup, false);
+ flib_gameconn *gameconn = flib_gameconn_create("Medo42", &setup, false);
assert(gameconn);
flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
- flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
+ //flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
startEngineGame(flib_gameconn_getport(gameconn));
@@ -196,7 +202,20 @@
//testMapPreview();
//testDemo();
//testSave();
- testGame();
+ //testGame();
+
+ flib_cfg_meta *meta = flib_cfg_meta_from_ini("metasettings.ini");
+ assert(meta);
+ flib_schemelist *schemelist = flib_schemelist_from_ini(meta, "schemes.ini");
+ assert(schemelist);
+
+ flib_schemelist_to_ini("Copy of Schemelist.ini", schemelist);
+ flib_schemelist_release(schemelist);
+ flib_cfg_meta_release(meta);
+
+ flib_weaponsetlist *weaponsets = flib_weaponsetlist_from_ini("weapons.ini");
+ assert(!flib_weaponsetlist_to_ini("copy of weapons.ini", weaponsets));
+ flib_weaponsetlist_release(weaponsets);
flib_quit();
return 0;
--- a/project_files/frontlib/util/inihelper.c Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/util/inihelper.c Fri Jun 15 19:57:25 2012 +0200
@@ -179,7 +179,7 @@
value = def;
}
char *valueDup = flib_strdupnull(value);
- if(valueDup) {
+ if(valueDup || !def) {
*outVar = valueDup;
result = 0;
}
@@ -209,7 +209,7 @@
int result = flib_ini_get_int(ini, &tmpValue, key);
if(result == 0) {
*outVar = tmpValue;
- } else if(result == INI_ERROR_NOTFOUND) {
+ } else if(result == INI_ERROR_NOTFOUND || result == INI_ERROR_FORMAT) {
*outVar = def;
result = 0;
}
@@ -238,7 +238,7 @@
int result = flib_ini_get_bool(ini, &tmpValue, key);
if(result == 0) {
*outVar = tmpValue;
- } else if(result == INI_ERROR_NOTFOUND) {
+ } else if(result == INI_ERROR_NOTFOUND || result == INI_ERROR_FORMAT) {
*outVar = def;
result = 0;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/frontlib/util/refcounter.h Fri Jun 15 19:57:25 2012 +0200
@@ -0,0 +1,51 @@
+/**
+ * Helper functions for reference counted structs.
+ *
+ * We don't have enough of them to justify going crazy with macros, but I still prefer
+ * to have the logic in one place.
+ *
+ * In particular, these functions handle counter overflow in a sensible way
+ * (log and leak).
+ */
+
+#ifndef REFCOUNTER_H_
+#define REFCOUNTER_H_
+
+#include "logging.h"
+#include <stdbool.h>
+
+static inline void flib_retain(int *referenceCountPtr, const char *objName) {
+ if(!referenceCountPtr || !objName) {
+ flib_log_e("null parameter to flib_retain");
+ } else {
+ if((*referenceCountPtr) >= 0) {
+ (*referenceCountPtr)++;
+ flib_log_d("retaining %s, now %i references", objName, (*referenceCountPtr));
+ }
+ if((*referenceCountPtr) < 0) {
+ flib_log_e("Memory leak: Reference count overflow in %s object!", objName);
+ }
+ }
+}
+
+/**
+ * Returns true if the struct should be freed.
+ */
+static inline bool flib_release(int *referenceCountPtr, const char *objName) {
+ bool result = false;
+ if(!referenceCountPtr) {
+ flib_log_e("null parameter to flib_release");
+ } else if((*referenceCountPtr) > 0) {
+ if(--(*referenceCountPtr) == 0) {
+ flib_log_d("releasing and destroying %s", objName);
+ result = true;
+ } else {
+ flib_log_d("releasing %s, now %i references", objName, (*referenceCountPtr));
+ }
+ } else if((*referenceCountPtr) == 0) {
+ flib_log_e("Attempt to release a %s with zero references!", objName);
+ }
+ return result;
+}
+
+#endif /* REFCOUNTER_H_ */
--- a/project_files/frontlib/util/util.c Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/util/util.c Fri Jun 15 19:57:25 2012 +0200
@@ -56,7 +56,7 @@
void *flib_malloc(size_t size) {
void *result = malloc(size);
- if(!result) {
+ if(!result && size>0) {
flib_log_e("Out of memory trying to malloc %zu bytes.", size);
}
return result;
@@ -64,17 +64,29 @@
void *flib_calloc(size_t count, size_t elementsize) {
void *result = calloc(count, elementsize);
- if(!result) {
+ if(!result && count>0 && elementsize>0) {
flib_log_e("Out of memory trying to calloc %zu objects of %zu bytes each.", count, elementsize);
}
return result;
}
+void *flib_realloc(void *ptr, size_t size) {
+ void *result = realloc(ptr, size);
+ if(!result && size>0) {
+ flib_log_e("Out of memory trying to realloc %zu bytes.", size);
+ }
+ 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) {
+ return flib_urlencode_pred(inbuf, isAsciiAlnum);
+}
+
+char *flib_urlencode_pred(const char *inbuf, bool (*needsEscaping)(char c)) {
if(!inbuf) {
return NULL;
}
@@ -91,7 +103,7 @@
size_t inpos = 0, outpos = 0;
while(inbuf[inpos]) {
- if(isAsciiAlnum(inbuf[inpos])) {
+ if(!needsEscaping(inbuf[inpos])) {
outbuf[outpos++] = inbuf[inpos++];
} else {
if(snprintf(outbuf+outpos, 4, "%%%02X", (unsigned)((uint8_t*)inbuf)[inpos])<0) {
--- a/project_files/frontlib/util/util.h Tue Jun 12 21:10:11 2012 +0200
+++ b/project_files/frontlib/util/util.h Fri Jun 15 19:57:25 2012 +0200
@@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdarg.h>
+#include <stdbool.h>
/**
* Prints a format string to a newly allocated buffer of the required size.
@@ -46,6 +47,12 @@
void *flib_calloc(size_t count, size_t elementsize);
/**
+ * Simple realloc wrapper that automatically logs an error if no memory
+ * is available. Otherwise behaves exactly like realloc.
+ */
+void *flib_realloc(void *ptr, size_t size);
+
+/**
* 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
@@ -56,6 +63,17 @@
char *flib_urlencode(const char *str);
/**
+ * Replace some 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.
+ *
+ * All bytes for which the predicate function returns true are escaped.
+ *
+ * Returns null on failure or if null was passed as argument.
+ */
+char *flib_urlencode_pred(const char *str, bool (*needsEscaping)(char c));
+
+/**
* 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