1 /////////////////////////////////////////
2 //
3 // OpenLieroX
4 //
5 // Auxiliary Software class library
6 //
7 // based on the work of JasonB
8 // enhanced by Dark Charlie and Albert Zeyer
9 //
10 // code under LGPL
11 //
12 /////////////////////////////////////////
13
14
15 // Config file handler
16 // Created 30/9/01
17 // By Jason Boettcher
18
19
20 #include <map>
21 #include <string>
22 #include "LieroX.h"
23 #include "ConfigHandler.h"
24 #include "FindFile.h"
25 #include "StringUtils.h"
26 #include "MathLib.h"
27
28
29
30 typedef std::map<std::string, int, stringcaseless> KeywordMap;
31 static KeywordMap Keywords;
32
33
34 // Internal
35 static bool GetString(const std::string& filename, const std::string& section, const std::string& key, std::string& string, bool abs_fn = false);
36
37
38 ///////////////////
39 // Add a keyword to the list
AddKeyword(const std::string & key,int value)40 bool AddKeyword(const std::string& key, int value)
41 {
42 Keywords[key] = value;
43
44 return true;
45 }
46
47
48
49 ///////////////////
50 // Read a keyword from a file
ReadKeyword(const std::string & filename,const std::string & section,const std::string & key,int * value,int defaultv)51 bool ReadKeyword(const std::string& filename, const std::string& section, const std::string& key, int *value, int defaultv)
52 {
53 std::string string;
54
55 *value = defaultv;
56
57 if(!GetString(filename,section,key,string))
58 return false;
59
60 // Try and find a keyword with matching keys
61 KeywordMap::iterator f = Keywords.find(string);
62 if(f != Keywords.end()) {
63 //notes << filename << ":" << section << "." << key << ": " << f->first << "(" << string << ") = " << f->second << endl;
64 *value = f->second;
65 return true;
66 }
67
68 warnings << filename << ":" << section << "." << key << ": '" << string << "' is an unknown keyword" << endl;
69
70 return false;
71 }
72
73 ///////////////////
74 // Read a keyword from a file (bool version)
ReadKeyword(const std::string & filename,const std::string & section,const std::string & key,bool * value,bool defaultv)75 bool ReadKeyword(const std::string& filename, const std::string& section, const std::string& key, bool *value, bool defaultv)
76 {
77 int v = defaultv ? 1 : 0;
78 bool ret = ReadKeyword(filename, section, key, &v, defaultv ? 1 : 0);
79 *value = v != 0;
80 return ret;
81 }
82
83 ///////////////////
84 // Read bit flags specified by keywords from a file
ReadKeywordList(const std::string & filename,const std::string & section,const std::string & key,int * value,int defaultv)85 bool ReadKeywordList(const std::string& filename, const std::string& section, const std::string& key, int *value, int defaultv)
86 {
87 std::string string;
88
89 *value = defaultv;
90
91 if(!GetString(filename,section,key,string))
92 return false;
93
94 std::vector<std::string> split = explode(string, ",");
95 for (std::vector<std::string>::iterator it = split.begin(); it != split.end(); it++) {
96 TrimSpaces(*it);
97 KeywordMap::iterator key = Keywords.find(*it);
98 if (key != Keywords.end())
99 *value |= key->second;
100 }
101
102 return true;
103 }
104
105
106 ///////////////////
107 // Read an interger from a file
ReadInteger(const std::string & filename,const std::string & section,const std::string & key,int * value,int defaultv)108 bool ReadInteger(const std::string& filename, const std::string& section, const std::string& key, int *value, int defaultv)
109 {
110 std::string string;
111
112 *value = defaultv;
113
114 if(!GetString(filename,section,key,string))
115 return false;
116
117 *value = from_string<int>(string);
118
119 return true;
120 }
121
122
123 ///////////////////
124 // Read a string from a file
ReadString(const std::string & filename,const std::string & section,const std::string & key,std::string & value,std::string defaultv,bool abs_fn)125 bool ReadString(const std::string& filename, const std::string& section, const std::string& key, std::string& value, std::string defaultv, bool abs_fn)
126 {
127 value = defaultv;
128
129 return GetString(filename,section,key,value, abs_fn);
130
131 /*int result = GetString(filename,section,key,value);
132
133 if (strlen(value) <= 0)
134 strcpy(value,defaultv);
135
136 return result;*/
137 }
138
139
140
141 ///////////////////
142 // Read a float from a file
ReadFloat(const std::string & filename,const std::string & section,const std::string & key,float * value,float defaultv)143 bool ReadFloat(const std::string& filename, const std::string& section, const std::string& key, float *value, float defaultv)
144 {
145 std::string string;
146
147 *value = defaultv;
148
149 if(!GetString(filename,section,key,string))
150 return false;
151
152 *value = (float)atof(string);
153
154 return true;
155 }
156
157
158
ReadColour(const std::string & filename,const std::string & section,const std::string & key,Color & value,const Color & defaultv)159 bool ReadColour(const std::string& filename, const std::string& section, const std::string& key, Color& value, const Color& defaultv) {
160 std::string string;
161
162 value = defaultv;
163
164 if(!GetString(filename,section,key,string))
165 return false;
166
167 value = StrToCol(string);
168
169 return true;
170 }
171
172 //////////////////
173 // Reads an array of integers
ReadIntArray(const std::string & filename,const std::string & section,const std::string & key,int * array,int num_items)174 bool ReadIntArray(const std::string& filename, const std::string& section, const std::string& key, int *array, int num_items)
175 {
176 std::string string;
177
178 if (!GetString(filename,section,key,string))
179 return false;
180
181 std::vector<std::string> arr = explode(string,",");
182 for (int i=0; i<MIN(num_items,(int)arr.size()); i++)
183 array[i] = from_string<int>(arr[i]);
184
185 return num_items == (int)arr.size();
186 }
187
188
189
190 ///////////////////
191 // Read a string
GetString(const std::string & filename,const std::string & section,const std::string & key,std::string & string,bool abs_fn)192 static bool GetString(const std::string& filename, const std::string& section, const std::string& key, std::string& string, bool abs_fn)
193 {
194 FILE *config = NULL;
195 std::string Line;
196 std::string tmpLine;
197 std::string curSection;
198 std::string temp;
199 std::string curKey;
200 size_t chardest = 0;
201 int Position;
202 bool found = false;
203
204 if(filename == "")
205 return false;
206
207 if(abs_fn) {
208 config = fopen(Utf8ToSystemNative(filename).c_str(), "rt");
209 } else
210 config = OpenGameFile(filename,"rt");
211 if(!config)
212 return false;
213
214 //string="";
215 curSection="";
216 temp="";
217 curKey="";
218
219 // Check for UTF-8 encoded file and skip the UTF-8 mark if it is
220 uchar utf8mark[3];
221 if(fread(utf8mark, sizeof(utf8mark)/sizeof(uchar), 1, config) == 0) {
222 fclose(config);
223 return false;
224 }
225 if (utf8mark[0] != 0xEF || utf8mark[1] != 0xBB || utf8mark[2] != 0xBF)
226 fseek(config, 0, SEEK_SET); // Not a UTF-8 file, jump back to the beginning
227
228
229 while(!feof(config) && !ferror(config))
230 {
231 // Parse the lines
232 Line = ReadUntil(config, '\n');
233 TrimSpaces(Line);
234
235 ///////////////////
236 // Comment, Ignore
237 if(Line.size() == 0 || Line[0] == '#')
238 continue;
239
240 ////////////
241 // Sections
242 if(Line[0] == '[' && Line[Line.size()-1] == ']')
243 {
244 curSection = Line.substr(1);
245 curSection.erase(curSection.size()-1);
246 continue;
247 }
248
249 ////////
250 // Keys
251 chardest = Line.find('=');
252 if(chardest != std::string::npos)
253 {
254 // Key
255 Position = (int)chardest;
256 tmpLine = Line;
257 tmpLine.erase(Position);
258 TrimSpaces(tmpLine);
259 curKey = tmpLine;
260
261 // Check if this is the key were looking for under the section were looking for
262 if(stringcasecmp(curKey,key) == 0 && stringcasecmp(curSection,section) == 0)
263 {
264 // Get the value
265 tmpLine = Line.substr(Position+1);
266 TrimSpaces(tmpLine);
267 string = tmpLine;
268 found = true;
269 break;
270 }
271 continue;
272 }
273 }
274
275 fclose(config);
276
277 return found;
278 }
279
280
281