project_files/frontlib/model/weapon.c
changeset 7230 240620f46dd7
parent 7227 1c859f572d72
child 7269 5b0aeef8ba2a
--- 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);
+	}
+}