|
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 "scheme.h" |
|
21 |
|
22 #include "../util/inihelper.h" |
|
23 #include "../util/logging.h" |
|
24 #include "../util/util.h" |
|
25 #include "../util/refcounter.h" |
|
26 |
|
27 #include <stdio.h> |
|
28 #include <stdlib.h> |
|
29 #include <limits.h> |
|
30 #include <string.h> |
|
31 |
|
32 static void flib_metascheme_destroy(flib_metascheme *meta) { |
|
33 if(meta) { |
|
34 if(meta->settings) { |
|
35 for(int i=0; i<meta->settingCount; i++) { |
|
36 free(meta->settings[i].name); |
|
37 free(meta->settings[i].engineCommand); |
|
38 } |
|
39 free(meta->settings); |
|
40 } |
|
41 if(meta->mods) { |
|
42 for(int i=0; i<meta->modCount; i++) { |
|
43 free(meta->mods[i].name); |
|
44 } |
|
45 free(meta->mods); |
|
46 } |
|
47 free(meta); |
|
48 } |
|
49 } |
|
50 |
|
51 static void flib_scheme_destroy(flib_scheme* scheme) { |
|
52 if(scheme) { |
|
53 flib_metascheme_release(scheme->meta); |
|
54 free(scheme->mods); |
|
55 free(scheme->settings); |
|
56 free(scheme->name); |
|
57 free(scheme); |
|
58 } |
|
59 } |
|
60 |
|
61 static flib_metascheme *flib_metascheme_from_ini_handleError(flib_metascheme *result, flib_ini *ini) { |
|
62 flib_metascheme_destroy(result); |
|
63 flib_ini_destroy(ini); |
|
64 return NULL; |
|
65 } |
|
66 |
|
67 static int readMetaSettingSections(flib_ini *ini, flib_metascheme *result, int limit) { |
|
68 while(result->settingCount<limit) { |
|
69 char sectionName[32]; |
|
70 if(snprintf(sectionName, sizeof(sectionName), "setting%i", result->settingCount) <= 0) { |
|
71 return -1; |
|
72 } |
|
73 if(!flib_ini_enter_section(ini, sectionName)) { |
|
74 flib_metascheme_setting *metasetting = &result->settings[result->settingCount]; |
|
75 result->settingCount++; |
|
76 |
|
77 bool error = false; |
|
78 error |= flib_ini_get_str(ini, &metasetting->name, "name"); |
|
79 error |= flib_ini_get_str_opt(ini, &metasetting->engineCommand, "command", NULL); |
|
80 error |= flib_ini_get_bool(ini, &metasetting->times1000, "times1000"); |
|
81 error |= flib_ini_get_bool(ini, &metasetting->maxMeansInfinity, "maxmeansinfinity"); |
|
82 error |= flib_ini_get_int(ini, &metasetting->min, "min"); |
|
83 error |= flib_ini_get_int(ini, &metasetting->max, "max"); |
|
84 error |= flib_ini_get_int(ini, &metasetting->def, "default"); |
|
85 if(error) { |
|
86 flib_log_e("Missing or malformed ini parameter in metaconfig, section %s", sectionName); |
|
87 return -1; |
|
88 } |
|
89 } else { |
|
90 return 0; |
|
91 } |
|
92 } |
|
93 return 0; |
|
94 } |
|
95 |
|
96 static int readMetaModSections(flib_ini *ini, flib_metascheme *result, int limit) { |
|
97 while(result->modCount<limit) { |
|
98 char sectionName[32]; |
|
99 if(snprintf(sectionName, sizeof(sectionName), "mod%i", result->modCount) <= 0) { |
|
100 return -1; |
|
101 } |
|
102 if(!flib_ini_enter_section(ini, sectionName)) { |
|
103 flib_metascheme_mod *metamod = &result->mods[result->modCount]; |
|
104 result->modCount++; |
|
105 |
|
106 bool error = false; |
|
107 error |= flib_ini_get_str(ini, &metamod->name, "name"); |
|
108 error |= flib_ini_get_int(ini, &metamod->bitmaskIndex, "bitmaskIndex"); |
|
109 if(error) { |
|
110 flib_log_e("Missing or malformed ini parameter in metaconfig, section %s", sectionName); |
|
111 return -1; |
|
112 } |
|
113 } else { |
|
114 return 0; |
|
115 } |
|
116 } |
|
117 return 0; |
|
118 } |
|
119 |
|
120 flib_metascheme *flib_metascheme_from_ini(const char *filename) { |
|
121 if(log_badargs_if(filename==NULL)) { |
|
122 return NULL; |
|
123 } |
|
124 flib_metascheme *result = flib_metascheme_retain(flib_calloc(1, sizeof(flib_metascheme))); |
|
125 flib_ini *ini = flib_ini_load(filename); |
|
126 |
|
127 if(!result || !ini) { |
|
128 return flib_metascheme_from_ini_handleError(result, ini); |
|
129 } |
|
130 |
|
131 // We're overallocating here for simplicity |
|
132 int sectionCount = flib_ini_get_sectioncount(ini); |
|
133 result->settingCount = 0; |
|
134 result->modCount = 0; |
|
135 result->settings = flib_calloc(sectionCount, sizeof(flib_metascheme_setting)); |
|
136 result->mods = flib_calloc(sectionCount, sizeof(flib_metascheme_mod)); |
|
137 |
|
138 if(!result->settings || !result->mods) { |
|
139 return flib_metascheme_from_ini_handleError(result, ini); |
|
140 } |
|
141 |
|
142 if(readMetaSettingSections(ini, result, sectionCount) || readMetaModSections(ini, result, sectionCount)) { |
|
143 return flib_metascheme_from_ini_handleError(result, ini); |
|
144 } |
|
145 |
|
146 if(result->settingCount+result->modCount != sectionCount) { |
|
147 flib_log_e("Unknown or non-contiguous sections headers in metaconfig."); |
|
148 return flib_metascheme_from_ini_handleError(result, ini); |
|
149 } |
|
150 |
|
151 flib_ini_destroy(ini); |
|
152 return result; |
|
153 } |
|
154 |
|
155 flib_metascheme *flib_metascheme_retain(flib_metascheme *metainfo) { |
|
156 if(metainfo) { |
|
157 flib_retain(&metainfo->_referenceCount, "flib_metascheme"); |
|
158 } |
|
159 return metainfo; |
|
160 } |
|
161 |
|
162 void flib_metascheme_release(flib_metascheme *meta) { |
|
163 if(meta && flib_release(&meta->_referenceCount, "flib_metascheme")) { |
|
164 flib_metascheme_destroy(meta); |
|
165 } |
|
166 } |
|
167 |
|
168 flib_scheme *flib_scheme_create(flib_metascheme *meta, const char *schemeName) { |
|
169 flib_scheme *result = flib_scheme_retain(flib_calloc(1, sizeof(flib_scheme))); |
|
170 if(log_badargs_if2(meta==NULL, schemeName==NULL) || result==NULL) { |
|
171 return NULL; |
|
172 } |
|
173 |
|
174 result->meta = flib_metascheme_retain(meta); |
|
175 result->name = flib_strdupnull(schemeName); |
|
176 result->mods = flib_calloc(meta->modCount, sizeof(*result->mods)); |
|
177 result->settings = flib_calloc(meta->settingCount, sizeof(*result->settings)); |
|
178 |
|
179 if(!result->mods || !result->settings || !result->name) { |
|
180 flib_scheme_destroy(result); |
|
181 return NULL; |
|
182 } |
|
183 |
|
184 for(int i=0; i<meta->settingCount; i++) { |
|
185 result->settings[i] = meta->settings[i].def; |
|
186 } |
|
187 return result; |
|
188 } |
|
189 |
|
190 flib_scheme *flib_scheme_copy(const flib_scheme *scheme) { |
|
191 flib_scheme *result = NULL; |
|
192 if(scheme) { |
|
193 result = flib_scheme_create(scheme->meta, scheme->name); |
|
194 if(result) { |
|
195 memcpy(result->mods, scheme->mods, scheme->meta->modCount * sizeof(*scheme->mods)); |
|
196 memcpy(result->settings, scheme->settings, scheme->meta->settingCount * sizeof(*scheme->settings)); |
|
197 } |
|
198 } |
|
199 return result; |
|
200 } |
|
201 |
|
202 flib_scheme *flib_scheme_retain(flib_scheme *scheme) { |
|
203 if(scheme) { |
|
204 flib_retain(&scheme->_referenceCount, "flib_scheme"); |
|
205 } |
|
206 return scheme; |
|
207 } |
|
208 |
|
209 void flib_scheme_release(flib_scheme *scheme) { |
|
210 if(scheme && flib_release(&scheme->_referenceCount, "flib_scheme")) { |
|
211 flib_scheme_destroy(scheme); |
|
212 } |
|
213 } |
|
214 |
|
215 bool flib_scheme_get_mod(flib_scheme *scheme, const char *name) { |
|
216 if(!log_badargs_if2(scheme==NULL, name==NULL)) { |
|
217 for(int i=0; i<scheme->meta->modCount; i++) { |
|
218 if(!strcmp(scheme->meta->mods[i].name, name)) { |
|
219 return scheme->mods[i]; |
|
220 } |
|
221 } |
|
222 flib_log_e("Unable to find game mod %s", name); |
|
223 } |
|
224 return false; |
|
225 } |
|
226 |
|
227 int flib_scheme_get_setting(flib_scheme *scheme, const char *name, int def) { |
|
228 if(!log_badargs_if2(scheme==NULL, name==NULL)) { |
|
229 for(int i=0; i<scheme->meta->settingCount; i++) { |
|
230 if(!strcmp(scheme->meta->settings[i].name, name)) { |
|
231 return scheme->settings[i]; |
|
232 } |
|
233 } |
|
234 flib_log_e("Unable to find game setting %s", name); |
|
235 } |
|
236 return def; |
|
237 } |