project_files/frontlib/model/cfg.c
changeset 7230 240620f46dd7
parent 7227 1c859f572d72
child 7271 5608ac657362
equal deleted inserted replaced
7227:1c859f572d72 7230:240620f46dd7
     1 #include "cfg.h"
     1 #include "cfg.h"
     2 
     2 
     3 #include "../util/inihelper.h"
     3 #include "../util/inihelper.h"
     4 #include "../util/logging.h"
     4 #include "../util/logging.h"
     5 #include "../util/util.h"
     5 #include "../util/util.h"
       
     6 #include "../util/refcounter.h"
     6 
     7 
     7 #include <stdio.h>
     8 #include <stdio.h>
     8 #include <stdlib.h>
     9 #include <stdlib.h>
       
    10 #include <limits.h>
       
    11 #include <string.h>
     9 
    12 
    10 static flib_cfg_meta *flib_cfg_meta_from_ini_handleError(flib_cfg_meta *result, flib_ini *settingfile, flib_ini *modfile) {
    13 static void flib_cfg_meta_destroy(flib_cfg_meta *cfg) {
    11 	flib_cfg_meta_destroy(result);
       
    12 	flib_ini_destroy(settingfile);
       
    13 	flib_ini_destroy(modfile);
       
    14 	return NULL;
       
    15 }
       
    16 
       
    17 flib_cfg_meta *flib_cfg_meta_from_ini(const char *settingpath, const char *modpath) {
       
    18 	if(!settingpath || !modpath) {
       
    19 		flib_log_e("null parameter in flib_cfg_meta_from_ini");
       
    20 		return NULL;
       
    21 	}
       
    22 	flib_cfg_meta *result = flib_calloc(1, sizeof(flib_cfg_meta));
       
    23 	flib_ini *settingfile = flib_ini_load(settingpath);
       
    24 	flib_ini *modfile = flib_ini_load(modpath);
       
    25 
       
    26 	if(!result || !settingfile || !modfile) {
       
    27 		return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
       
    28 	}
       
    29 
       
    30 	result->settingCount = flib_ini_get_sectioncount(settingfile);
       
    31 	result->modCount = flib_ini_get_sectioncount(modfile);
       
    32 	result->settings = flib_calloc(result->settingCount, sizeof(flib_cfg_setting_meta));
       
    33 	result->mods = flib_calloc(result->modCount, sizeof(flib_cfg_mod_meta));
       
    34 
       
    35 	if(!result->settings || !result->mods) {
       
    36 		return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
       
    37 	}
       
    38 
       
    39 	for(int i=0; i<result->settingCount; i++) {
       
    40 		result->settings[i].iniName = flib_ini_get_sectionname(settingfile, i);
       
    41 		if(!result->settings[i].iniName) {
       
    42 			return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
       
    43 		}
       
    44 
       
    45 		bool error = false;
       
    46 		error |= flib_ini_enter_section(settingfile, result->settings[i].iniName);
       
    47 		error |= flib_ini_get_str(settingfile, &result->settings[i].title, "title");
       
    48 		error |= flib_ini_get_str(settingfile, &result->settings[i].engineCommand, "command");
       
    49 		error |= flib_ini_get_str(settingfile, &result->settings[i].image, "image");
       
    50 		error |= flib_ini_get_bool(settingfile, &result->settings[i].checkOverMax, "checkOverMax");
       
    51 		error |= flib_ini_get_bool(settingfile, &result->settings[i].times1000, "times1000");
       
    52 		error |= flib_ini_get_int(settingfile, &result->settings[i].min, "min");
       
    53 		error |= flib_ini_get_int(settingfile, &result->settings[i].max, "max");
       
    54 		error |= flib_ini_get_int(settingfile, &result->settings[i].def, "default");
       
    55 
       
    56 		if(error) {
       
    57 			flib_log_e("Missing or malformed ini parameter in file %s, section %s", settingpath, result->settings[i].iniName);
       
    58 			return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
       
    59 		}
       
    60 	}
       
    61 
       
    62 	for(int i=0; i<result->modCount; i++) {
       
    63 		result->mods[i].iniName = flib_ini_get_sectionname(modfile, i);
       
    64 		if(!result->mods[i].iniName) {
       
    65 			return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
       
    66 		}
       
    67 
       
    68 		bool error = false;
       
    69 		error |= flib_ini_enter_section(modfile, result->mods[i].iniName);
       
    70 		error |= flib_ini_get_int(modfile, &result->mods[i].bitmaskIndex, "bitmaskIndex");
       
    71 		if(error) {
       
    72 			flib_log_e("Missing or malformed ini parameter in file %s, section %s", modpath, result->mods[i].iniName);
       
    73 			return flib_cfg_meta_from_ini_handleError(result, settingfile, modfile);
       
    74 		}
       
    75 	}
       
    76 
       
    77 	flib_ini_destroy(settingfile);
       
    78 	flib_ini_destroy(modfile);
       
    79 	return result;
       
    80 }
       
    81 
       
    82 void flib_cfg_meta_destroy(flib_cfg_meta *cfg) {
       
    83 	if(cfg) {
    14 	if(cfg) {
    84 		if(cfg->settings) {
    15 		if(cfg->settings) {
    85 			for(int i=0; i<cfg->settingCount; i++) {
    16 			for(int i=0; i<cfg->settingCount; i++) {
    86 				free(cfg->settings[i].iniName);
    17 				free(cfg->settings[i].name);
    87 				free(cfg->settings[i].title);
       
    88 				free(cfg->settings[i].engineCommand);
    18 				free(cfg->settings[i].engineCommand);
    89 				free(cfg->settings[i].image);
       
    90 			}
    19 			}
    91 			free(cfg->settings);
    20 			free(cfg->settings);
    92 		}
    21 		}
    93 		if(cfg->mods) {
    22 		if(cfg->mods) {
    94 			for(int i=0; i<cfg->modCount; i++) {
    23 			for(int i=0; i<cfg->modCount; i++) {
    95 				free(cfg->mods[i].iniName);
    24 				free(cfg->mods[i].name);
    96 			}
    25 			}
    97 			free(cfg->mods);
    26 			free(cfg->mods);
    98 		}
    27 		}
    99 		free(cfg);
    28 		free(cfg);
   100 	}
    29 	}
   101 }
    30 }
   102 
    31 
   103 flib_cfg *flib_cfg_create(const flib_cfg_meta *meta, const char *schemeName) {
    32 static void flib_cfg_destroy(flib_cfg* cfg) {
   104 	flib_cfg *result = flib_calloc(1, sizeof(flib_cfg));
    33 	if(cfg) {
       
    34 		flib_cfg_meta_release(cfg->meta);
       
    35 		free(cfg->mods);
       
    36 		free(cfg->settings);
       
    37 		free(cfg->schemeName);
       
    38 		free(cfg);
       
    39 	}
       
    40 }
       
    41 
       
    42 static flib_cfg_meta *flib_cfg_meta_from_ini_handleError(flib_cfg_meta *result, flib_ini *ini) {
       
    43 	flib_cfg_meta_destroy(result);
       
    44 	flib_ini_destroy(ini);
       
    45 	return NULL;
       
    46 }
       
    47 
       
    48 static int readMetaSettingSections(flib_ini *ini, flib_cfg_meta *result, int limit) {
       
    49 	while(result->settingCount<limit) {
       
    50 		char sectionName[32];
       
    51 		if(snprintf(sectionName, sizeof(sectionName), "setting%i", result->settingCount) <= 0) {
       
    52 			return -1;
       
    53 		}
       
    54 		if(!flib_ini_enter_section(ini, sectionName)) {
       
    55 			flib_cfg_setting_meta *metasetting = &result->settings[result->settingCount];
       
    56 			result->settingCount++;
       
    57 
       
    58 			bool error = false;
       
    59 			error |= flib_ini_get_str(ini, &metasetting->name, "name");
       
    60 			error |= flib_ini_get_str_opt(ini, &metasetting->engineCommand, "command", NULL);
       
    61 			error |= flib_ini_get_bool(ini, &metasetting->times1000, "times1000");
       
    62 			error |= flib_ini_get_bool(ini, &metasetting->maxMeansInfinity, "maxmeansinfinity");
       
    63 			error |= flib_ini_get_int(ini, &metasetting->min, "min");
       
    64 			error |= flib_ini_get_int(ini, &metasetting->max, "max");
       
    65 			error |= flib_ini_get_int(ini, &metasetting->def, "default");
       
    66 			if(error) {
       
    67 				flib_log_e("Missing or malformed ini parameter in metaconfig, section %s", sectionName);
       
    68 				return -1;
       
    69 			}
       
    70 		} else {
       
    71 			return 0;
       
    72 		}
       
    73 	}
       
    74 	return 0;
       
    75 }
       
    76 
       
    77 static int readMetaModSections(flib_ini *ini, flib_cfg_meta *result, int limit) {
       
    78 	while(result->modCount<limit) {
       
    79 		char sectionName[32];
       
    80 		if(snprintf(sectionName, sizeof(sectionName), "mod%i", result->modCount) <= 0) {
       
    81 			return -1;
       
    82 		}
       
    83 		if(!flib_ini_enter_section(ini, sectionName)) {
       
    84 			flib_cfg_mod_meta *metamod = &result->mods[result->modCount];
       
    85 			result->modCount++;
       
    86 
       
    87 			bool error = false;
       
    88 			error |= flib_ini_get_str(ini, &metamod->name, "name");
       
    89 			error |= flib_ini_get_int(ini, &metamod->bitmaskIndex, "bitmaskIndex");
       
    90 			if(error) {
       
    91 				flib_log_e("Missing or malformed ini parameter in metaconfig, section %s", sectionName);
       
    92 				return -1;
       
    93 			}
       
    94 		} else {
       
    95 			return 0;
       
    96 		}
       
    97 	}
       
    98 	return 0;
       
    99 }
       
   100 
       
   101 flib_cfg_meta *flib_cfg_meta_from_ini(const char *filename) {
       
   102 	if(!filename) {
       
   103 		flib_log_e("null parameter in flib_cfg_meta_from_ini");
       
   104 		return NULL;
       
   105 	}
       
   106 	flib_cfg_meta *result = flib_cfg_meta_retain(flib_calloc(1, sizeof(flib_cfg_meta)));
       
   107 	flib_ini *ini = flib_ini_load(filename);
       
   108 
       
   109 	if(!result || !ini) {
       
   110 		return flib_cfg_meta_from_ini_handleError(result, ini);
       
   111 	}
       
   112 
       
   113 	// We're overallocating here for simplicity
       
   114 	int sectionCount = flib_ini_get_sectioncount(ini);
       
   115 	result->settingCount = 0;
       
   116 	result->modCount = 0;
       
   117 	result->settings = flib_calloc(sectionCount, sizeof(flib_cfg_setting_meta));
       
   118 	result->mods = flib_calloc(sectionCount, sizeof(flib_cfg_mod_meta));
       
   119 
       
   120 	if(!result->settings || !result->mods) {
       
   121 		return flib_cfg_meta_from_ini_handleError(result, ini);
       
   122 	}
       
   123 
       
   124 	if(readMetaSettingSections(ini, result, sectionCount) || readMetaModSections(ini, result, sectionCount)) {
       
   125 		return flib_cfg_meta_from_ini_handleError(result, ini);
       
   126 	}
       
   127 
       
   128 	if(result->settingCount+result->modCount != sectionCount) {
       
   129 		flib_log_e("Unknown or non-contiguous sections headers in metaconfig.");
       
   130 		return flib_cfg_meta_from_ini_handleError(result, ini);
       
   131 	}
       
   132 
       
   133 	flib_ini_destroy(ini);
       
   134 	return result;
       
   135 }
       
   136 
       
   137 flib_cfg_meta *flib_cfg_meta_retain(flib_cfg_meta *metainfo) {
       
   138 	if(metainfo) {
       
   139 		flib_retain(&metainfo->_referenceCount, "flib_cfg_meta");
       
   140 	}
       
   141 	return metainfo;
       
   142 }
       
   143 
       
   144 void flib_cfg_meta_release(flib_cfg_meta *cfg) {
       
   145 	if(cfg && flib_release(&cfg->_referenceCount, "flib_cfg_meta")) {
       
   146 		flib_cfg_meta_destroy(cfg);
       
   147 	}
       
   148 }
       
   149 
       
   150 flib_cfg *flib_cfg_create(flib_cfg_meta *meta, const char *schemeName) {
       
   151 	flib_cfg *result = flib_cfg_retain(flib_calloc(1, sizeof(flib_cfg)));
   105 	if(!meta || !result || !schemeName) {
   152 	if(!meta || !result || !schemeName) {
   106 		flib_log_e("null parameter in flib_cfg_create");
   153 		flib_log_e("null parameter in flib_cfg_create");
   107 		return NULL;
   154 		return NULL;
   108 	}
   155 	}
   109 
   156 
   110 	result->modCount = meta->modCount;
   157 	result->meta = flib_cfg_meta_retain(meta);
   111 	result->settingCount = meta->settingCount;
       
   112 	result->schemeName = flib_strdupnull(schemeName);
   158 	result->schemeName = flib_strdupnull(schemeName);
   113 	result->mods = flib_calloc(meta->modCount, sizeof(*result->mods));
   159 	result->mods = flib_calloc(meta->modCount, sizeof(*result->mods));
   114 	result->settings = flib_calloc(meta->settingCount, sizeof(*result->settings));
   160 	result->settings = flib_calloc(meta->settingCount, sizeof(*result->settings));
   115 
   161 
   116 	if(!result->mods || !result->settings || !result->schemeName) {
   162 	if(!result->mods || !result->settings || !result->schemeName) {
   122 		result->settings[i] = meta->settings[i].def;
   168 		result->settings[i] = meta->settings[i].def;
   123 	}
   169 	}
   124 	return result;
   170 	return result;
   125 }
   171 }
   126 
   172 
   127 flib_cfg *flib_cfg_from_ini_handleError(flib_cfg *result, flib_ini *settingfile) {
   173 flib_cfg *flib_cfg_copy(flib_cfg *cfg) {
   128 	flib_ini_destroy(settingfile);
   174 	flib_cfg *result = NULL;
   129 	flib_cfg_destroy(result);
   175 	if(cfg) {
   130 	return NULL;
   176 		result = flib_cfg_create(cfg->meta, cfg->schemeName);
   131 }
   177 		if(result) {
   132 
   178 			memcpy(result->mods, cfg->mods, cfg->meta->modCount * sizeof(*cfg->mods));
   133 flib_cfg *flib_cfg_from_ini(const flib_cfg_meta *meta, const char *filename) {
   179 			memcpy(result->settings, cfg->settings, cfg->meta->settingCount * sizeof(*cfg->settings));
   134 	if(!meta || !filename) {
       
   135 		flib_log_e("null parameter in flib_cfg_from_ini");
       
   136 		return NULL;
       
   137 	}
       
   138 	flib_ini *settingfile = flib_ini_load(filename);
       
   139 	if(!settingfile) {
       
   140 		return NULL;
       
   141 	}
       
   142 
       
   143 	char *schemename = NULL;
       
   144 	if(flib_ini_enter_section(settingfile, "Scheme")) {
       
   145 		flib_log_e("Missing section \"Scheme\" in config file %s.", filename);
       
   146 		return flib_cfg_from_ini_handleError(NULL, settingfile);
       
   147 	}
       
   148 	if(flib_ini_get_str(settingfile, &schemename, "name")) {
       
   149 		flib_log_e("Missing scheme name in config file %s.", filename);
       
   150 		return flib_cfg_from_ini_handleError(NULL, settingfile);
       
   151 	}
       
   152 
       
   153 	flib_cfg *result = flib_cfg_create(meta, schemename);
       
   154 
       
   155 	if(flib_ini_enter_section(settingfile, "BasicSettings")) {
       
   156 		flib_log_w("Missing section \"BasicSettings\" in config file %s, using defaults.", filename);
       
   157 	} else {
       
   158 		for(int i=0; i<meta->settingCount; i++) {
       
   159 			if(flib_ini_get_int_opt(settingfile, &result->settings[i], meta->settings[i].iniName, meta->settings[i].def)) {
       
   160 				flib_log_e("Error reading BasicSetting %s in config file %s.", meta->settings[i].iniName, filename);
       
   161 				return flib_cfg_from_ini_handleError(result, settingfile);
       
   162 			}
       
   163 		}
   180 		}
   164 	}
       
   165 
       
   166 	if(flib_ini_enter_section(settingfile, "GameMods")) {
       
   167 		flib_log_w("Missing section \"GameMods\" in config file %s, using defaults.", filename);
       
   168 	} else {
       
   169 		for(int i=0; i<meta->modCount; i++) {
       
   170 			if(flib_ini_get_bool_opt(settingfile, &result->mods[i], meta->mods[i].iniName, false)) {
       
   171 				flib_log_e("Error reading GameMod %s in config file %s.", meta->mods[i].iniName, filename);
       
   172 				return flib_cfg_from_ini_handleError(result, settingfile);
       
   173 			}
       
   174 		}
       
   175 	}
       
   176 	flib_ini_destroy(settingfile);
       
   177 	return result;
       
   178 }
       
   179 
       
   180 int flib_cfg_to_ini(const flib_cfg_meta *meta, const char *filename, const flib_cfg *config) {
       
   181 	int result = -1;
       
   182 	if(!meta || !filename || !config || config->modCount!=meta->modCount || config->settingCount!=meta->settingCount) {
       
   183 		flib_log_e("Invalid parameter in flib_cfg_to_ini");
       
   184 	} else {
       
   185 		flib_ini *ini = flib_ini_create(filename);
       
   186 		if(ini) {
       
   187 			bool error = false;
       
   188 
       
   189 			// Add the values
       
   190 			error |= flib_ini_create_section(ini, "Scheme");
       
   191 			if(!error) {
       
   192 				error |= flib_ini_set_str(ini, "name", config->schemeName);
       
   193 			}
       
   194 
       
   195 
       
   196 			error |= flib_ini_create_section(ini, "BasicSettings");
       
   197 			if(!error) {
       
   198 				for(int i=0; i<config->settingCount; i++) {
       
   199 					error |= flib_ini_set_int(ini, meta->settings[i].iniName, config->settings[i]);
       
   200 				}
       
   201 			}
       
   202 
       
   203 			error |= flib_ini_create_section(ini, "GameMods");
       
   204 			if(!error) {
       
   205 				for(int i=0; i<config->modCount; i++) {
       
   206 					error |= flib_ini_set_bool(ini, meta->mods[i].iniName, config->mods[i]);
       
   207 				}
       
   208 			}
       
   209 
       
   210 			if(!error) {
       
   211 				result = flib_ini_save(ini, filename);
       
   212 			}
       
   213 		}
       
   214 		flib_ini_destroy(ini);
       
   215 	}
   181 	}
   216 	return result;
   182 	return result;
   217 }
   183 }
   218 
   184 
   219 void flib_cfg_destroy(flib_cfg* cfg) {
   185 flib_cfg *flib_cfg_retain(flib_cfg *cfg) {
   220 	if(cfg) {
   186 	if(cfg) {
   221 		free(cfg->mods);
   187 		flib_retain(&cfg->_referenceCount, "flib_cfg");
   222 		free(cfg->settings);
   188 	}
   223 		free(cfg->schemeName);
   189 	return cfg;
   224 		free(cfg);
   190 }
       
   191 
       
   192 void flib_cfg_release(flib_cfg *cfg) {
       
   193 	if(cfg && flib_release(&cfg->_referenceCount, "flib_cfg")) {
       
   194 		flib_cfg_destroy(cfg);
   225 	}
   195 	}
   226 }
   196 }