project_files/frontlib/model/schemelist.c
changeset 7230 240620f46dd7
child 7269 5b0aeef8ba2a
equal deleted inserted replaced
7227:1c859f572d72 7230:240620f46dd7
       
     1 #include "schemelist.h"
       
     2 
       
     3 #include "../util/inihelper.h"
       
     4 #include "../util/logging.h"
       
     5 #include "../util/util.h"
       
     6 #include "../util/refcounter.h"
       
     7 
       
     8 #include <stdio.h>
       
     9 #include <stdlib.h>
       
    10 #include <limits.h>
       
    11 #include <string.h>
       
    12 
       
    13 static void flib_schemelist_destroy(flib_schemelist *list) {
       
    14 	if(list) {
       
    15 		for(int i=0; i<list->schemeCount; i++) {
       
    16 			flib_cfg_release(list->schemes[i]);
       
    17 		}
       
    18 		free(list);
       
    19 	}
       
    20 }
       
    21 
       
    22 static char *makePrefixedName(int schemeIndex, const char *settingName) {
       
    23 	return flib_asprintf("%i\\%s", schemeIndex, settingName);
       
    24 }
       
    25 
       
    26 static int readSettingsFromIni(flib_ini *ini, flib_cfg *scheme, int index) {
       
    27 	flib_cfg_meta *meta = scheme->meta;
       
    28 	bool error = false;
       
    29 	for(int i=0; i<meta->settingCount && !error; i++) {
       
    30 		char *key = makePrefixedName(index, meta->settings[i].name);
       
    31 		if(!key) {
       
    32 			error = true;
       
    33 		} else if(flib_ini_get_int_opt(ini, &scheme->settings[i], key, meta->settings[i].def)) {
       
    34 			flib_log_e("Error reading setting %s in schemes file.", key);
       
    35 			error = true;
       
    36 		}
       
    37 		free(key);
       
    38 	}
       
    39 	return error;
       
    40 }
       
    41 
       
    42 static int readModsFromIni(flib_ini *ini, flib_cfg *scheme, int index) {
       
    43 	flib_cfg_meta *meta = scheme->meta;
       
    44 	bool error = false;
       
    45 	for(int i=0; i<meta->modCount && !error; i++) {
       
    46 		char *key = makePrefixedName(index, meta->mods[i].name);
       
    47 		if(!key) {
       
    48 			error = true;
       
    49 		} else if(flib_ini_get_bool_opt(ini, &scheme->mods[i], key, false)) {
       
    50 			flib_log_e("Error reading mod %s in schemes file.", key);
       
    51 			error = true;
       
    52 		}
       
    53 		free(key);
       
    54 	}
       
    55 	return error;
       
    56 }
       
    57 
       
    58 static flib_cfg *readSchemeFromIni(flib_cfg_meta *meta, flib_ini *ini, int index) {
       
    59 	flib_cfg *result = NULL;
       
    60 	char *schemeNameKey = makePrefixedName(index+1, "name");
       
    61 	if(schemeNameKey) {
       
    62 		char *schemeName = NULL;
       
    63 		if(!flib_ini_get_str_opt(ini, &schemeName, schemeNameKey, "Unnamed")) {
       
    64 			flib_cfg *scheme = flib_cfg_create(meta, schemeName);
       
    65 			if(scheme) {
       
    66 				if(!readSettingsFromIni(ini, scheme, index) && !readModsFromIni(ini, scheme, index)) {
       
    67 					result = flib_cfg_retain(scheme);
       
    68 				}
       
    69 			}
       
    70 			flib_cfg_release(scheme);
       
    71 		}
       
    72 		free(schemeName);
       
    73 	}
       
    74 	free(schemeNameKey);
       
    75 	return result;
       
    76 }
       
    77 
       
    78 static flib_schemelist *fromIniHandleError(flib_schemelist *result, flib_ini *ini) {
       
    79 	flib_ini_destroy(ini);
       
    80 	flib_schemelist_destroy(result);
       
    81 	return NULL;
       
    82 }
       
    83 
       
    84 flib_schemelist *flib_schemelist_from_ini(flib_cfg_meta *meta, const char *filename) {
       
    85 	flib_schemelist *list = NULL;
       
    86 	if(!meta || !filename) {
       
    87 		flib_log_e("null parameter in flib_schemelist_from_ini");
       
    88 		return NULL;
       
    89 	}
       
    90 	flib_ini *ini = flib_ini_load(filename);
       
    91 	if(!ini || flib_ini_enter_section(ini, "schemes")) {
       
    92 		flib_log_e("Missing file or missing section \"schemes\" in file %s.", filename);
       
    93 		return fromIniHandleError(list, ini);
       
    94 	}
       
    95 
       
    96 	list = flib_schemelist_create();
       
    97 	if(!list) {
       
    98 		return fromIniHandleError(list, ini);
       
    99 	}
       
   100 
       
   101 	int schemeCount = 0;
       
   102 	if(flib_ini_get_int(ini, &schemeCount, "size")) {
       
   103 		flib_log_e("Missing or malformed scheme count in config file %s.", filename);
       
   104 		return fromIniHandleError(list, ini);
       
   105 	}
       
   106 
       
   107 	for(int i=0; i<schemeCount; i++) {
       
   108 		flib_cfg *scheme = readSchemeFromIni(meta, ini, i);
       
   109 		if(!scheme || flib_schemelist_insert(list, scheme, i)) {
       
   110 			flib_cfg_release(scheme);
       
   111 			flib_log_e("Error reading scheme %i from config file %s.", i, filename);
       
   112 			return fromIniHandleError(list, ini);
       
   113 		}
       
   114 		flib_cfg_release(scheme);
       
   115 	}
       
   116 
       
   117 
       
   118 	flib_ini_destroy(ini);
       
   119 	return list;
       
   120 }
       
   121 
       
   122 static int writeSchemeToIni(flib_cfg *scheme, flib_ini *ini, int index) {
       
   123 	flib_cfg_meta *meta = scheme->meta;
       
   124 	bool error = false;
       
   125 
       
   126 	char *key = makePrefixedName(index+1, "name");
       
   127 	error |= !key || flib_ini_set_str(ini, key, scheme->schemeName);
       
   128 	free(key);
       
   129 
       
   130 	for(int i=0; i<meta->modCount && !error; i++) {
       
   131 		char *key = makePrefixedName(index+1, meta->mods[i].name);
       
   132 		error |= !key || flib_ini_set_bool(ini, key, scheme->mods[i]);
       
   133 		free(key);
       
   134 	}
       
   135 
       
   136 	for(int i=0; i<meta->settingCount && !error; i++) {
       
   137 		char *key = makePrefixedName(index+1, meta->settings[i].name);
       
   138 		error |= !key || flib_ini_set_int(ini, key, scheme->settings[i]);
       
   139 		free(key);
       
   140 	}
       
   141 	return error;
       
   142 }
       
   143 
       
   144 int flib_schemelist_to_ini(const char *filename, const flib_schemelist *schemes) {
       
   145 	int result = -1;
       
   146 	if(!filename || !schemes) {
       
   147 		flib_log_e("null parameter in flib_schemelist_to_ini");
       
   148 	} else {
       
   149 		flib_ini *ini = flib_ini_create(NULL);
       
   150 		if(ini && !flib_ini_create_section(ini, "schemes")) {
       
   151 			bool error = false;
       
   152 			error |= flib_ini_set_int(ini, "size", schemes->schemeCount);
       
   153 			for(int i=0; i<schemes->schemeCount && !error; i++) {
       
   154 				error |= writeSchemeToIni(schemes->schemes[i], ini, i);
       
   155 			}
       
   156 
       
   157 			if(!error) {
       
   158 				result = flib_ini_save(ini, filename);
       
   159 			}
       
   160 		}
       
   161 		flib_ini_destroy(ini);
       
   162 	}
       
   163 	return result;
       
   164 }
       
   165 
       
   166 flib_schemelist *flib_schemelist_create() {
       
   167 	return flib_schemelist_retain(flib_calloc(1, sizeof(flib_schemelist)));
       
   168 }
       
   169 
       
   170 flib_schemelist *flib_schemelist_retain(flib_schemelist *list) {
       
   171 	if(list) {
       
   172 		flib_retain(&list->_referenceCount, "flib_schemelist");
       
   173 	}
       
   174 	return list;
       
   175 }
       
   176 
       
   177 void flib_schemelist_release(flib_schemelist *list) {
       
   178 	if(list && flib_release(&list->_referenceCount, "flib_schemelist")) {
       
   179 		flib_schemelist_destroy(list);
       
   180 	}
       
   181 }
       
   182 
       
   183 flib_cfg *flib_schemelist_find(flib_schemelist *list, const char *name) {
       
   184 	if(list && name) {
       
   185 		for(int i=0; i<list->schemeCount; i++) {
       
   186 			if(!strcmp(name, list->schemes[i]->schemeName)) {
       
   187 				return list->schemes[i];
       
   188 			}
       
   189 		}
       
   190 	}
       
   191 	return NULL;
       
   192 }
       
   193 
       
   194 int flib_schemelist_insert(flib_schemelist *list, flib_cfg *cfg, int pos) {
       
   195 	int result = -1;
       
   196 	if(!list || !cfg || pos < 0 || pos > list->schemeCount) {
       
   197 		flib_log_e("Invalid parameter in flib_schemelist_insert");
       
   198 	} else {
       
   199 		flib_cfg **newSchemes = flib_realloc(list->schemes, (list->schemeCount+1)*sizeof(*list->schemes));
       
   200 		if(newSchemes) {
       
   201 			list->schemes = newSchemes;
       
   202 			memmove(list->schemes+pos+1, list->schemes+pos, (list->schemeCount-pos)*sizeof(*list->schemes));
       
   203 			list->schemes[pos] = flib_cfg_retain(cfg);
       
   204 			list->schemeCount++;
       
   205 			result = 0;
       
   206 		}
       
   207 	}
       
   208 	return result;
       
   209 }
       
   210 
       
   211 int flib_schemelist_delete(flib_schemelist *list, int pos) {
       
   212 	int result = -1;
       
   213 	if(!list || pos < 0 || pos >= list->schemeCount) {
       
   214 		flib_log_e("Invalid parameter in flib_schemelist_delete");
       
   215 	} else {
       
   216 		flib_cfg_release(list->schemes[pos]);
       
   217 		memmove(list->schemes+pos, list->schemes+pos+1, (list->schemeCount-(pos+1))*sizeof(*list->schemes));
       
   218 		list->schemes[list->schemeCount-1] = NULL;
       
   219 		list->schemeCount--;
       
   220 
       
   221 		// If the realloc fails, just keep using the old buffer...
       
   222 		flib_cfg **newSchemes = flib_realloc(list->schemes, list->schemeCount*sizeof(*list->schemes));
       
   223 		if(newSchemes || list->schemeCount==1) {
       
   224 			list->schemes = newSchemes;
       
   225 		}
       
   226 		result = 0;
       
   227 	}
       
   228 	return result;
       
   229 }