project_files/frontlib/model/schemelist.c
branchhedgeroid
changeset 7857 2bc61f8841a1
parent 7497 7e1d72fc03c7
child 10017 de822cd3df3a
equal deleted inserted replaced
7855:ddcdedd3330b 7857:2bc61f8841a1
       
     1 /*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU General Public License
       
     7  * as published by the Free Software Foundation; either version 2
       
     8  * of the License, or (at your option) any later version.
       
     9  *
       
    10  * This program is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13  * GNU General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License
       
    16  * along with this program; if not, write to the Free Software
       
    17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
       
    18  */
       
    19 
       
    20 #include "schemelist.h"
       
    21 
       
    22 #include "../util/inihelper.h"
       
    23 #include "../util/logging.h"
       
    24 #include "../util/util.h"
       
    25 #include "../util/list.h"
       
    26 
       
    27 #include <stdio.h>
       
    28 #include <stdlib.h>
       
    29 #include <limits.h>
       
    30 #include <string.h>
       
    31 
       
    32 static char *makePrefixedName(int schemeIndex, const char *settingName) {
       
    33 	return flib_asprintf("%i\\%s", schemeIndex, settingName);
       
    34 }
       
    35 
       
    36 static int readSettingsFromIni(flib_ini *ini, flib_scheme *scheme, int index) {
       
    37 	bool error = false;
       
    38 	for(int i=0; i<flib_meta.settingCount && !error; i++) {
       
    39 		char *key = makePrefixedName(index, flib_meta.settings[i].name);
       
    40 		if(!key) {
       
    41 			error = true;
       
    42 		} else if(flib_ini_get_int_opt(ini, &scheme->settings[i], key, flib_meta.settings[i].def)) {
       
    43 			flib_log_e("Error reading setting %s in schemes file.", key);
       
    44 			error = true;
       
    45 		}
       
    46 		free(key);
       
    47 	}
       
    48 	return error;
       
    49 }
       
    50 
       
    51 static int readModsFromIni(flib_ini *ini, flib_scheme *scheme, int index) {
       
    52 	bool error = false;
       
    53 	for(int i=0; i<flib_meta.modCount && !error; i++) {
       
    54 		char *key = makePrefixedName(index, flib_meta.mods[i].name);
       
    55 		if(!key) {
       
    56 			error = true;
       
    57 		} else if(flib_ini_get_bool_opt(ini, &scheme->mods[i], key, false)) {
       
    58 			flib_log_e("Error reading mod %s in schemes file.", key);
       
    59 			error = true;
       
    60 		}
       
    61 		free(key);
       
    62 	}
       
    63 	return error;
       
    64 }
       
    65 
       
    66 static flib_scheme *readSchemeFromIni(flib_ini *ini, int index) {
       
    67 	flib_scheme *result = NULL;
       
    68 	char *schemeNameKey = makePrefixedName(index+1, "name");
       
    69 	if(schemeNameKey) {
       
    70 		char *schemeName = NULL;
       
    71 		if(!flib_ini_get_str_opt(ini, &schemeName, schemeNameKey, "Unnamed")) {
       
    72 			flib_scheme *tmpScheme = flib_scheme_create(schemeName);
       
    73 			if(tmpScheme) {
       
    74 				if(!readSettingsFromIni(ini, tmpScheme, index) && !readModsFromIni(ini, tmpScheme, index)) {
       
    75 					result = tmpScheme;
       
    76 					tmpScheme = NULL;
       
    77 				}
       
    78 			}
       
    79 			flib_scheme_destroy(tmpScheme);
       
    80 		}
       
    81 		free(schemeName);
       
    82 	}
       
    83 	free(schemeNameKey);
       
    84 	return result;
       
    85 }
       
    86 
       
    87 static flib_schemelist *fromIniHandleError(flib_schemelist *result, flib_ini *ini) {
       
    88 	flib_ini_destroy(ini);
       
    89 	flib_schemelist_destroy(result);
       
    90 	return NULL;
       
    91 }
       
    92 
       
    93 flib_schemelist *flib_schemelist_from_ini(const char *filename) {
       
    94 	if(log_badargs_if(filename==NULL)) {
       
    95 		return NULL;
       
    96 	}
       
    97 
       
    98 	flib_schemelist *list = NULL;
       
    99 	flib_ini *ini = flib_ini_load(filename);
       
   100 	if(!ini || flib_ini_enter_section(ini, "schemes")) {
       
   101 		flib_log_e("Missing file or missing section \"schemes\" in file %s.", filename);
       
   102 		return fromIniHandleError(list, ini);
       
   103 	}
       
   104 
       
   105 	list = flib_schemelist_create();
       
   106 	if(!list) {
       
   107 		return fromIniHandleError(list, ini);
       
   108 	}
       
   109 
       
   110 	int schemeCount = 0;
       
   111 	if(flib_ini_get_int(ini, &schemeCount, "size")) {
       
   112 		flib_log_e("Missing or malformed scheme count in config file %s.", filename);
       
   113 		return fromIniHandleError(list, ini);
       
   114 	}
       
   115 
       
   116 	for(int i=0; i<schemeCount; i++) {
       
   117 		flib_scheme *scheme = readSchemeFromIni(ini, i);
       
   118 		if(!scheme || flib_schemelist_insert(list, scheme, i)) {
       
   119 			flib_scheme_destroy(scheme);
       
   120 			flib_log_e("Error reading scheme %i from config file %s.", i, filename);
       
   121 			return fromIniHandleError(list, ini);
       
   122 		}
       
   123 	}
       
   124 
       
   125 
       
   126 	flib_ini_destroy(ini);
       
   127 	return list;
       
   128 }
       
   129 
       
   130 static int writeSchemeToIni(const flib_scheme *scheme, flib_ini *ini, int index) {
       
   131 	bool error = false;
       
   132 
       
   133 	char *key = makePrefixedName(index+1, "name");
       
   134 	error |= !key || flib_ini_set_str(ini, key, scheme->name);
       
   135 	free(key);
       
   136 
       
   137 	for(int i=0; i<flib_meta.modCount && !error; i++) {
       
   138 		char *key = makePrefixedName(index+1, flib_meta.mods[i].name);
       
   139 		error |= !key || flib_ini_set_bool(ini, key, scheme->mods[i]);
       
   140 		free(key);
       
   141 	}
       
   142 
       
   143 	for(int i=0; i<flib_meta.settingCount && !error; i++) {
       
   144 		char *key = makePrefixedName(index+1, flib_meta.settings[i].name);
       
   145 		error |= !key || flib_ini_set_int(ini, key, scheme->settings[i]);
       
   146 		free(key);
       
   147 	}
       
   148 	return error;
       
   149 }
       
   150 
       
   151 int flib_schemelist_to_ini(const char *filename, const flib_schemelist *schemes) {
       
   152 	int result = -1;
       
   153 	if(!log_badargs_if2(filename==NULL, schemes==NULL)) {
       
   154 		flib_ini *ini = flib_ini_create(NULL);
       
   155 		if(ini && !flib_ini_create_section(ini, "schemes")) {
       
   156 			bool error = false;
       
   157 			error |= flib_ini_set_int(ini, "size", schemes->schemeCount);
       
   158 			for(int i=0; i<schemes->schemeCount && !error; i++) {
       
   159 				error |= writeSchemeToIni(schemes->schemes[i], ini, i);
       
   160 			}
       
   161 
       
   162 			if(!error) {
       
   163 				result = flib_ini_save(ini, filename);
       
   164 			}
       
   165 		}
       
   166 		flib_ini_destroy(ini);
       
   167 	}
       
   168 	return result;
       
   169 }
       
   170 
       
   171 flib_schemelist *flib_schemelist_create() {
       
   172 	return flib_calloc(1, sizeof(flib_schemelist));
       
   173 }
       
   174 
       
   175 void flib_schemelist_destroy(flib_schemelist *list) {
       
   176 	if(list) {
       
   177 		for(int i=0; i<list->schemeCount; i++) {
       
   178 			flib_scheme_destroy(list->schemes[i]);
       
   179 		}
       
   180 		free(list->schemes);
       
   181 		free(list);
       
   182 	}
       
   183 }
       
   184 
       
   185 flib_scheme *flib_schemelist_find(flib_schemelist *list, const char *name) {
       
   186 	if(!log_badargs_if2(list==NULL, name==NULL)) {
       
   187 		for(int i=0; i<list->schemeCount; i++) {
       
   188 			if(!strcmp(name, list->schemes[i]->name)) {
       
   189 				return list->schemes[i];
       
   190 			}
       
   191 		}
       
   192 	}
       
   193 	return NULL;
       
   194 }
       
   195 
       
   196 GENERATE_STATIC_LIST_INSERT(insertScheme, flib_scheme*)
       
   197 GENERATE_STATIC_LIST_DELETE(deleteScheme, flib_scheme*)
       
   198 
       
   199 int flib_schemelist_insert(flib_schemelist *list, flib_scheme *cfg, int pos) {
       
   200 	if(!log_badargs_if2(list==NULL, cfg==NULL)
       
   201 			&& !insertScheme(&list->schemes, &list->schemeCount, cfg, pos)) {
       
   202 		return 0;
       
   203 	}
       
   204 	return -1;
       
   205 }
       
   206 
       
   207 int flib_schemelist_delete(flib_schemelist *list, int pos) {
       
   208 	if(!log_badargs_if(list==NULL)) {
       
   209 		flib_scheme *elem = list->schemes[pos];
       
   210 		if(!deleteScheme(&list->schemes, &list->schemeCount, pos)) {
       
   211 			flib_scheme_destroy(elem);
       
   212 			return 0;
       
   213 		}
       
   214 	}
       
   215 	return -1;
       
   216 }