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