1/***************************************************************************
2* KBlocks, a falling blocks game for KDE *
3* Copyright (C) 2010 Zhongjie Cai <squall.leonhart.cai@gmail.com> *
4* *
5* This program is free software; you can redistribute it and/or modify *
6* it under the terms of the GNU General Public License as published by *
7* the Free Software Foundation; either version 2 of the License, or *
8* (at your option) any later version. *
9***************************************************************************/
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <fcntl.h>
13#include <unistd.h>
14#include <stdlib.h>
15#include <cctype>
16#include <algorithm>
17
18#include "KBlocksConfigManager.h"
19
20KBlocksConfigManager::KBlocksConfigManager()
21{
22 stConfigSectionList.clear();
23 stConfigKeyNameList.clear();
24 stConfigDataTable.clear();
25
26 isDebug = false;
27}
28
29KBlocksConfigManager::~KBlocksConfigManager()
30{
31 stConfigSectionList.clear();
32 stConfigKeyNameList.clear();
33 stConfigDataTable.clear();
34}
35
36int KBlocksConfigManager::SetDebugOutput(bool flag)
37{
38 isDebug = flag;
39
40 return 0;
41}
42
43int KBlocksConfigManager::LoadConfigFile(string filename)
44{
45 FILE* fp;
46 int result;
47
48 fp = fopen(filename.c_str(), "r");
49
50 if (fp == NULL)
51 {
52 return -1;
53 }
54
55 result = ParseConfigFile(fp);
56
57 fclose(fp);
58
59 return result;
60}
61
62int KBlocksConfigManager::SaveConfigFile(string filename)
63{
64 FILE* fp;
65 int result;
66
67 fp = fopen(filename.c_str(), "w+");
68
69 if (fp == NULL)
70 {
71 return -1;
72 }
73
74 result = ConstructConfigFile(fp);
75
76 fclose(fp);
77
78 return result;
79}
80
81int KBlocksConfigManager::GetSectionCount()
82{
83 return stConfigSectionList.size();
84}
85
86int KBlocksConfigManager::GetKeyCount(string SectionName)
87{
88 map< string, map<string,string> >::iterator it;
89
90 it = stConfigDataTable.find(SectionName);
91
92 if (it == stConfigDataTable.end())
93 {
94 return -1;
95 }
96
97 map<string,string> tmpMap = it->second;
98
99 return tmpMap.size();
100}
101
102int KBlocksConfigManager::GetKeyString(string SectionName, string KeyName, string* KeyString, const string Default)
103{
104 map< string, map<string,string> >::iterator it;
105
106 it = stConfigDataTable.find(SectionName);
107
108 if (it == stConfigDataTable.end())
109 {
110 *KeyString = Default;
111 return -1;
112 }
113
114 map<string,string> tmpMap = it->second;
115
116 if (tmpMap.find(KeyName) == tmpMap.end())
117 {
118 *KeyString = Default;
119 return -1;
120 }
121
122 *KeyString = tmpMap[KeyName];
123
124 return 0;
125}
126
127int KBlocksConfigManager::GetKeyInt(string SectionName, string KeyName, int* KeyInt, const int Default)
128{
129 map< string, map<string,string> >::iterator it;
130
131 it = stConfigDataTable.find(SectionName);
132
133 if (it == stConfigDataTable.end())
134 {
135 *KeyInt = Default;
136 return -1;
137 }
138
139 map<string,string> tmpMap = it->second;
140
141 if (tmpMap.find(KeyName) == tmpMap.end())
142 {
143 *KeyInt = Default;
144 return -1;
145 }
146
147 string tmpString = tmpMap[KeyName];
148 char* endptr;
149
150 if (tmpString.find("0x") == tmpString.npos)
151 {
152 *KeyInt = strtol(tmpString.c_str(),&endptr,10);
153 }
154 else
155 {
156 *KeyInt = strtol(tmpString.c_str(),&endptr,16);
157 }
158
159 return 0;
160}
161
162int KBlocksConfigManager::GetKeyBool(string SectionName, string KeyName, bool* KeyBool, const bool Default)
163{
164 string tmpValue;
165 if (GetKeyString(SectionName, KeyName, &tmpValue, "") == -1)
166 {
167 *KeyBool = Default;
168 return -1;
169 }
170
171 transform(tmpValue.begin(), tmpValue.end(), tmpValue.begin(),(int(*)(int))tolower);
172 if (tmpValue.find("true") != tmpValue.npos)
173 {
174 *KeyBool = true;
175 }
176 else if (tmpValue.find("false") != tmpValue.npos)
177 {
178 *KeyBool = false;
179 }
180
181 return 0;
182}
183
184int KBlocksConfigManager::SetKeyString(string SectionName, string KeyName, string KeyString)
185{
186 map<int,string> tmpKeyName;
187 map< string, map< int, string > >::iterator it_keyname;
188
189 map<string,string> tmpKeyMap;
190 map< string, map<string,string> >::iterator it_data;
191
192 it_data = stConfigDataTable.find(SectionName);
193
194 if (it_data == stConfigDataTable.end())
195 {
196 stConfigDataTable.insert(pair< string, map<string,string> >(SectionName, tmpKeyMap));
197 stConfigSectionList.insert(pair<int,string>(stConfigSectionList.size()+1,SectionName));
198 stConfigKeyNameList.insert(pair< string, map<int,string> >(SectionName, tmpKeyName));
199 }
200
201 it_data = stConfigDataTable.find(SectionName);
202
203 tmpKeyMap =it_data->second;
204
205 if (tmpKeyMap.find(KeyName) == tmpKeyMap.end())
206 {
207 it_keyname = stConfigKeyNameList.find(SectionName);
208 tmpKeyName = it_keyname->second;
209 tmpKeyName.insert(pair<int,string>(tmpKeyName.size()+1,KeyName));
210 stConfigKeyNameList[SectionName] = tmpKeyName;
211
212 tmpKeyMap.insert(pair<string,string>(KeyName,KeyString));
213 }
214 else
215 {
216 tmpKeyMap[KeyName] = KeyString;
217 }
218
219 stConfigDataTable[SectionName] = tmpKeyMap;
220
221 return 0;
222}
223
224int KBlocksConfigManager::SetKeyInt(string SectionName, string KeyName, int KeyInt)
225{
226 map<int,string> tmpKeyName;
227 map< string, map< int, string > >::iterator it_keyname;
228
229 map<string,string> tmpKeyMap;
230 map< string, map<string,string> >::iterator it_data;
231
232 it_data = stConfigDataTable.find(SectionName);
233
234 if (it_data == stConfigDataTable.end())
235 {
236 stConfigDataTable.insert(pair< string, map<string,string> >(SectionName, tmpKeyMap));
237 stConfigSectionList.insert(pair<int,string>(stConfigSectionList.size()+1,SectionName));
238 stConfigKeyNameList.insert(pair< string, map<int,string> >(SectionName, tmpKeyName));
239 }
240
241 it_data = stConfigDataTable.find(SectionName);
242
243 tmpKeyMap = it_data->second;
244 string tmpString = int16tostring(KeyInt);
245
246 if (tmpKeyMap.find(KeyName) == tmpKeyMap.end())
247 {
248 it_keyname = stConfigKeyNameList.find(SectionName);
249 tmpKeyName = it_keyname->second;
250 tmpKeyName.insert(pair<int,string>(tmpKeyName.size()+1,KeyName));
251 stConfigKeyNameList[SectionName] = tmpKeyName;
252
253 tmpKeyMap.insert(pair<string,string>(KeyName,tmpString));
254 }
255 else
256 {
257 tmpKeyMap[KeyName] = tmpString;
258 }
259
260 stConfigDataTable[SectionName] = tmpKeyMap;
261
262 return 0;
263}
264
265int KBlocksConfigManager::SetKeyBool(string SectionName, string KeyName, bool KeyBool)
266{
267 if (KeyBool)
268 {
269 return SetKeyString(SectionName, KeyName, "true");
270 }
271 else
272 {
273 return SetKeyString(SectionName, KeyName, "false");
274 }
275}
276
277int KBlocksConfigManager::ParseConfigFile(FILE* fp)
278{
279 map< string, map< string, string > >::iterator it_section;
280
281 map<int,string> tmpKeyName;
282 map< string, map< int, string > >::iterator it_keyname;
283
284 map<string,string> tmpKeyMap;
285 map< string, map< string, string > >::iterator it_data;
286
287 stConfigSectionList.clear();
288 stConfigKeyNameList.clear();
289 stConfigDataTable.clear();
290
291 string curSection = "DefaultSection";
292 string curKey = "DefaultKey";
293 string curValue = "DefaultValue";
294
295 int lenth;
296 string tmpString;
297 char tmpBuff[1024];
298 while(fgets(tmpBuff, 1024, fp))
299 {
300 switch(tmpBuff[0])
301 {
302 case '[':
303 tmpString = string(tmpBuff);
304 lenth = tmpString.find(']');
305 curSection = tmpString.substr(1,lenth-1);
306
307 it_section = stConfigDataTable.find(curSection);
308
309 if (it_section == stConfigDataTable.end())
310 {
311 map<string,string> tmpKeyMap;
312 stConfigDataTable.insert(pair< string, map<string,string> >(curSection, tmpKeyMap));
313
314 map<int,string> tmpKeyName;
315 stConfigKeyNameList.insert(pair< string, map<int,string> >(curSection, tmpKeyName));
316
317 stConfigSectionList.insert(pair<int,string>(stConfigSectionList.size()+1,curSection));
318
319 if (isDebug)
320 {
321 printf("New section loaded <%s>\n",curSection.c_str());
322 }
323 }
324 else
325 {
326 if (isDebug)
327 {
328 printf("Existing section updated <%s>\n",curSection.c_str());
329 }
330 }
331 break;
332
333 case '#':
334 // skip this line
335 break;
336
337 case '\n':
338 // skip this line
339 break;
340
341 case '\0':
342 // skip this line
343 break;
344
345 default:
346 tmpString = string(tmpBuff);
347 lenth = tmpString.find('=');
348 curKey = tmpString.substr(0,lenth);
349 if (tmpString[tmpString.size()-1] == '\n')
350 {
351 tmpString[tmpString.size()-1]='\0';
352 }
353 curValue = tmpString.substr(lenth+1);
354 transform(curValue.begin(),curValue.end(),curValue.begin(),(int(*)(int))tolower);
355
356 it_data = stConfigDataTable.find(curSection);
357 if (it_data == stConfigDataTable.end())
358 {
359 stConfigDataTable.insert(pair< string, map<string,string> >(curSection, tmpKeyMap));
360 stConfigSectionList.insert(pair<int,string>(stConfigSectionList.size()+1,curSection));
361 stConfigKeyNameList.insert(pair< string, map<int,string> >(curSection, tmpKeyName));
362
363 if (isDebug)
364 {
365 printf("New section added <%s>\n",curSection.c_str());
366 }
367 }
368 else
369 {
370 tmpKeyMap = it_data->second;
371 }
372
373 if (tmpKeyMap.find(curKey) == tmpKeyMap.end())
374 {
375 it_keyname = stConfigKeyNameList.find(curSection);
376 tmpKeyName = it_keyname->second;
377 tmpKeyName.insert(pair<int,string>(tmpKeyName.size()+1,curKey));
378 stConfigKeyNameList[curSection] = tmpKeyName;
379
380 if (isDebug)
381 {
382 printf("New Key & Value loaded <%s=%s> for section <%s>\n",curKey.c_str(),curValue.c_str(),curSection.c_str());
383 }
384 tmpKeyMap.insert(pair<string,string>(curKey,curValue));
385 }
386 else
387 {
388 if (isDebug)
389 {
390 printf("Existing Key & Value updated <%s=%s> for section <%s>\n",curKey.c_str(),curValue.c_str(),curSection.c_str());
391 }
392 tmpKeyMap[curKey] = curValue;
393 }
394 stConfigDataTable[curSection] = tmpKeyMap;
395 break;
396 }
397 }
398
399 return 0;
400}
401
402int KBlocksConfigManager::ConstructConfigFile(FILE* fp)
403{
404 for (unsigned int i = 1; i < stConfigSectionList.size()+1; i++)
405 {
406 string tmpSectionName = stConfigSectionList[i];
407
408 fprintf(fp, "[%s]\n", tmpSectionName.c_str());
409
410 map<int,string> tmpKeyName = stConfigKeyNameList[tmpSectionName];
411 map<string,string> tmpKeyMap = stConfigDataTable[tmpSectionName];
412
413 for (unsigned int j = 1; j < tmpKeyName.size()+1; j++)
414 {
415 string tmpKeyNameStr = tmpKeyName[j];
416 string tmpKeyValueStr = tmpKeyMap[tmpKeyName[j]];
417
418 fprintf(fp, "%s=%s\n", tmpKeyNameStr.c_str(), tmpKeyValueStr.c_str());
419 }
420 }
421
422 return 0;
423}
424
425string KBlocksConfigManager::int16tostring(int input)
426{
427 string tmpString = "";
428 char tmpChar[2] = {0,0};
429
430 do
431 {
432 tmpChar[0] = input & 0x0F;
433 input >>= 4;
434 if (tmpChar[0] < 10)
435 {
436 tmpChar[0] += '0';
437 }
438 else
439 {
440 tmpChar[0] += 'a' - 10;
441 }
442 tmpString = string(tmpChar) + tmpString;
443 }
444 while(input != 0);
445
446 tmpString = "0x" + tmpString;
447
448 return tmpString;
449}
450