project_files/frontlib/model/cfg.c
changeset 7230 240620f46dd7
parent 7227 1c859f572d72
child 7271 5608ac657362
--- 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);
 	}
 }