File indexing completed on 2024-04-21 07:49:16

0001 /***************************************************************************
0002 *   KBlocks, a falling blocks game by KDE                                *
0003 *   SPDX-FileCopyrightText: 2010 Zhongjie Cai <squall.leonhart.cai@gmail.com>       *
0004 *                                                                         *
0005 *   SPDX-License-Identifier: GPL-2.0-or-later
0006 ***************************************************************************/
0007 #include "KBlocksConfigManager.h"
0008 
0009 #include <sys/types.h>
0010 #include <sys/stat.h>
0011 #include <fcntl.h>
0012 #include <stdlib.h>
0013 #include <cctype>
0014 #include <algorithm>
0015 
0016 KBlocksConfigManager::KBlocksConfigManager()
0017 {
0018     stConfigSectionList.clear();
0019     stConfigKeyNameList.clear();
0020     stConfigDataTable.clear();
0021 
0022     isDebug = false;
0023 }
0024 
0025 KBlocksConfigManager::~KBlocksConfigManager()
0026 {
0027     stConfigSectionList.clear();
0028     stConfigKeyNameList.clear();
0029     stConfigDataTable.clear();
0030 }
0031 
0032 int KBlocksConfigManager::SetDebugOutput(bool flag)
0033 {
0034     isDebug = flag;
0035 
0036     return 0;
0037 }
0038 
0039 int KBlocksConfigManager::LoadConfigFile(const string &filename)
0040 {
0041     FILE *fp;
0042     int result;
0043 
0044     fp = fopen(filename.c_str(), "r");
0045 
0046     if (fp == NULL) {
0047         return -1;
0048     }
0049 
0050     result = ParseConfigFile(fp);
0051 
0052     fclose(fp);
0053 
0054     return result;
0055 }
0056 
0057 int KBlocksConfigManager::SaveConfigFile(const string &filename)
0058 {
0059     FILE *fp;
0060     int result;
0061 
0062     fp = fopen(filename.c_str(), "w+");
0063 
0064     if (fp == NULL) {
0065         return -1;
0066     }
0067 
0068     result = ConstructConfigFile(fp);
0069 
0070     fclose(fp);
0071 
0072     return result;
0073 }
0074 
0075 int KBlocksConfigManager::GetSectionCount()
0076 {
0077     return stConfigSectionList.size();
0078 }
0079 
0080 int KBlocksConfigManager::GetKeyCount(const string &SectionName)
0081 {
0082     map< string, map<string, string> >::iterator it;
0083 
0084     it = stConfigDataTable.find(SectionName);
0085 
0086     if (it == stConfigDataTable.end()) {
0087         return -1;
0088     }
0089 
0090     map<string, string> tmpMap = it->second;
0091 
0092     return tmpMap.size();
0093 }
0094 
0095 int KBlocksConfigManager::GetKeyString(const string &SectionName, const string &KeyName, string *KeyString, const string &Default)
0096 {
0097     map< string, map<string, string> >::iterator it;
0098 
0099     it = stConfigDataTable.find(SectionName);
0100 
0101     if (it == stConfigDataTable.end()) {
0102         *KeyString = Default;
0103         return -1;
0104     }
0105 
0106     map<string, string> tmpMap = it->second;
0107 
0108     if (tmpMap.find(KeyName) == tmpMap.end()) {
0109         *KeyString = Default;
0110         return -1;
0111     }
0112 
0113     *KeyString = tmpMap[KeyName];
0114 
0115     return 0;
0116 }
0117 
0118 int KBlocksConfigManager::GetKeyInt(const string &SectionName, const string &KeyName, int *KeyInt, const int Default)
0119 {
0120     map< string, map<string, string> >::iterator it;
0121 
0122     it = stConfigDataTable.find(SectionName);
0123 
0124     if (it == stConfigDataTable.end()) {
0125         *KeyInt = Default;
0126         return -1;
0127     }
0128 
0129     map<string, string> tmpMap = it->second;
0130 
0131     if (tmpMap.find(KeyName) == tmpMap.end()) {
0132         *KeyInt = Default;
0133         return -1;
0134     }
0135 
0136     string tmpString = tmpMap[KeyName];
0137     char *endptr;
0138 
0139     if (tmpString.find("0x") == tmpString.npos) {
0140         *KeyInt = strtol(tmpString.c_str(), &endptr, 10);
0141     } else {
0142         *KeyInt = strtol(tmpString.c_str(), &endptr, 16);
0143     }
0144 
0145     return 0;
0146 }
0147 
0148 int KBlocksConfigManager::GetKeyBool(const string &SectionName, const string &KeyName, bool *KeyBool, const bool Default)
0149 {
0150     string tmpValue;
0151     if (GetKeyString(SectionName, KeyName, &tmpValue, "") == -1) {
0152         *KeyBool = Default;
0153         return -1;
0154     }
0155 
0156     transform(tmpValue.begin(), tmpValue.end(), tmpValue.begin(), (int(*)(int))tolower);
0157     if (tmpValue.find("true") != tmpValue.npos) {
0158         *KeyBool = true;
0159     } else if (tmpValue.find("false") != tmpValue.npos) {
0160         *KeyBool = false;
0161     }
0162 
0163     return 0;
0164 }
0165 
0166 int KBlocksConfigManager::SetKeyString(string SectionName, string KeyName, string KeyString)
0167 {
0168     map<int, string> tmpKeyName;
0169     map< string, map< int, string > >::iterator it_keyname;
0170 
0171     map<string, string> tmpKeyMap;
0172     map< string, map<string, string> >::iterator it_data;
0173 
0174     it_data = stConfigDataTable.find(SectionName);
0175 
0176     if (it_data == stConfigDataTable.end()) {
0177         stConfigDataTable.insert(pair< string, map<string, string> >(SectionName, tmpKeyMap));
0178         stConfigSectionList.insert(pair<int, string>(stConfigSectionList.size() + 1, SectionName));
0179         stConfigKeyNameList.insert(pair< string, map<int, string> >(SectionName, tmpKeyName));
0180     }
0181 
0182     it_data = stConfigDataTable.find(SectionName);
0183 
0184     tmpKeyMap = it_data->second;
0185 
0186     if (tmpKeyMap.find(KeyName) == tmpKeyMap.end()) {
0187         it_keyname = stConfigKeyNameList.find(SectionName);
0188         tmpKeyName = it_keyname->second;
0189         tmpKeyName.insert(pair<int, string>(tmpKeyName.size() + 1, KeyName));
0190         stConfigKeyNameList[SectionName] = tmpKeyName;
0191 
0192         tmpKeyMap.insert(pair<string, string>(KeyName, KeyString));
0193     } else {
0194         tmpKeyMap[KeyName] = KeyString;
0195     }
0196 
0197     stConfigDataTable[SectionName] = tmpKeyMap;
0198 
0199     return 0;
0200 }
0201 
0202 int KBlocksConfigManager::SetKeyInt(string SectionName, string KeyName, int KeyInt)
0203 {
0204     map<int, string> tmpKeyName;
0205     map< string, map< int, string > >::iterator it_keyname;
0206 
0207     map<string, string> tmpKeyMap;
0208     map< string, map<string, string> >::iterator it_data;
0209 
0210     it_data = stConfigDataTable.find(SectionName);
0211 
0212     if (it_data == stConfigDataTable.end()) {
0213         stConfigDataTable.insert(pair< string, map<string, string> >(SectionName, tmpKeyMap));
0214         stConfigSectionList.insert(pair<int, string>(stConfigSectionList.size() + 1, SectionName));
0215         stConfigKeyNameList.insert(pair< string, map<int, string> >(SectionName, tmpKeyName));
0216     }
0217 
0218     it_data = stConfigDataTable.find(SectionName);
0219 
0220     tmpKeyMap = it_data->second;
0221     string tmpString = int16tostring(KeyInt);
0222 
0223     if (tmpKeyMap.find(KeyName) == tmpKeyMap.end()) {
0224         it_keyname = stConfigKeyNameList.find(SectionName);
0225         tmpKeyName = it_keyname->second;
0226         tmpKeyName.insert(pair<int, string>(tmpKeyName.size() + 1, KeyName));
0227         stConfigKeyNameList[SectionName] = tmpKeyName;
0228 
0229         tmpKeyMap.insert(pair<string, string>(KeyName, tmpString));
0230     } else {
0231         tmpKeyMap[KeyName] = tmpString;
0232     }
0233 
0234     stConfigDataTable[SectionName] = tmpKeyMap;
0235 
0236     return 0;
0237 }
0238 
0239 int KBlocksConfigManager::SetKeyBool(const string &SectionName, const string &KeyName, bool KeyBool)
0240 {
0241     if (KeyBool) {
0242         return SetKeyString(SectionName, KeyName, "true");
0243     } else {
0244         return SetKeyString(SectionName, KeyName, "false");
0245     }
0246 }
0247 
0248 int KBlocksConfigManager::ParseConfigFile(FILE *fp)
0249 {
0250     map< string, map< string, string > >::iterator it_section;
0251 
0252     map<int, string> tmpKeyName;
0253     map< string, map< int, string > >::iterator it_keyname;
0254 
0255     map<string, string> tmpKeyMap;
0256     map< string, map< string, string > >::iterator it_data;
0257 
0258     stConfigSectionList.clear();
0259     stConfigKeyNameList.clear();
0260     stConfigDataTable.clear();
0261 
0262     string curSection = "DefaultSection";
0263     string curKey = "DefaultKey";
0264     string curValue = "DefaultValue";
0265 
0266     int lenth;
0267     string tmpString;
0268     char tmpBuff[1024];
0269     while (fgets(tmpBuff, 1024, fp)) {
0270         switch (tmpBuff[0]) {
0271         case '[':
0272             tmpString = string(tmpBuff);
0273             lenth = tmpString.find(']');
0274             curSection = tmpString.substr(1, lenth - 1);
0275 
0276             it_section = stConfigDataTable.find(curSection);
0277 
0278             if (it_section == stConfigDataTable.end()) {
0279                 map<string, string> tmpKeyMap;
0280                 stConfigDataTable.insert(pair< string, map<string, string> >(curSection, tmpKeyMap));
0281 
0282                 map<int, string> tmpKeyName;
0283                 stConfigKeyNameList.insert(pair< string, map<int, string> >(curSection, tmpKeyName));
0284 
0285                 stConfigSectionList.insert(pair<int, string>(stConfigSectionList.size() + 1, curSection));
0286 
0287                 if (isDebug) {
0288                     printf("New section loaded <%s>\n", curSection.c_str());
0289                 }
0290             } else {
0291                 if (isDebug) {
0292                     printf("Existing section updated <%s>\n", curSection.c_str());
0293                 }
0294             }
0295             break;
0296 
0297         case '#':
0298             // skip this line
0299             break;
0300 
0301         case '\n':
0302             // skip this line
0303             break;
0304 
0305         case '\0':
0306             // skip this line
0307             break;
0308 
0309         default:
0310             tmpString = string(tmpBuff);
0311             lenth = tmpString.find('=');
0312             curKey = tmpString.substr(0, lenth);
0313             if (tmpString[tmpString.size() - 1] == '\n') {
0314                 tmpString[tmpString.size() - 1] = '\0';
0315             }
0316             curValue = tmpString.substr(lenth + 1);
0317             transform(curValue.begin(), curValue.end(), curValue.begin(), (int(*)(int))tolower);
0318 
0319             it_data = stConfigDataTable.find(curSection);
0320             if (it_data == stConfigDataTable.end()) {
0321                 stConfigDataTable.insert(pair< string, map<string, string> >(curSection, tmpKeyMap));
0322                 stConfigSectionList.insert(pair<int, string>(stConfigSectionList.size() + 1, curSection));
0323                 stConfigKeyNameList.insert(pair< string, map<int, string> >(curSection, tmpKeyName));
0324 
0325                 if (isDebug) {
0326                     printf("New section added <%s>\n", curSection.c_str());
0327                 }
0328             } else {
0329                 tmpKeyMap = it_data->second;
0330             }
0331 
0332             if (tmpKeyMap.find(curKey) == tmpKeyMap.end()) {
0333                 it_keyname = stConfigKeyNameList.find(curSection);
0334                 tmpKeyName = it_keyname->second;
0335                 tmpKeyName.insert(pair<int, string>(tmpKeyName.size() + 1, curKey));
0336                 stConfigKeyNameList[curSection] = tmpKeyName;
0337 
0338                 if (isDebug) {
0339                     printf("New Key & Value loaded <%s=%s> for section <%s>\n", curKey.c_str(), curValue.c_str(), curSection.c_str());
0340                 }
0341                 tmpKeyMap.insert(pair<string, string>(curKey, curValue));
0342             } else {
0343                 if (isDebug) {
0344                     printf("Existing Key & Value updated <%s=%s> for section <%s>\n", curKey.c_str(), curValue.c_str(), curSection.c_str());
0345                 }
0346                 tmpKeyMap[curKey] = curValue;
0347             }
0348             stConfigDataTable[curSection] = tmpKeyMap;
0349             break;
0350         }
0351     }
0352 
0353     return 0;
0354 }
0355 
0356 int KBlocksConfigManager::ConstructConfigFile(FILE *fp)
0357 {
0358     for (unsigned int i = 1; i < stConfigSectionList.size() + 1; i++) {
0359         string tmpSectionName = stConfigSectionList[i];
0360 
0361         fprintf(fp, "[%s]\n", tmpSectionName.c_str());
0362 
0363         map<int, string> tmpKeyName = stConfigKeyNameList[tmpSectionName];
0364         map<string, string> tmpKeyMap = stConfigDataTable[tmpSectionName];
0365 
0366         for (unsigned int j = 1; j < tmpKeyName.size() + 1; j++) {
0367             string tmpKeyNameStr = tmpKeyName[j];
0368             string tmpKeyValueStr = tmpKeyMap[tmpKeyName[j]];
0369 
0370             fprintf(fp, "%s=%s\n", tmpKeyNameStr.c_str(), tmpKeyValueStr.c_str());
0371         }
0372     }
0373 
0374     return 0;
0375 }
0376 
0377 string KBlocksConfigManager::int16tostring(int input)
0378 {
0379     string tmpString = "";
0380     char tmpChar[2] = {0, 0};
0381 
0382     do {
0383         tmpChar[0] = input & 0x0F;
0384         input >>= 4;
0385         if (tmpChar[0] < 10) {
0386             tmpChar[0] += '0';
0387         } else {
0388             tmpChar[0] += 'a' - 10;
0389         }
0390         tmpString = string(tmpChar) + tmpString;
0391     } while (input != 0);
0392 
0393     tmpString = "0x" + tmpString;
0394 
0395     return tmpString;
0396 }