/* Config.cpp * * Loads and stores configuration data in an INI-like format. */ #include #include #include #include "Config.h" namespace PlipSdl { static inline std::string Trim(std::string str) { // Trim front. str.erase(str.cbegin(), std::find_if(str.cbegin(), str.cend(), [](unsigned char c) { return !std::isspace(c); })); // Trim back. str.erase(std::find_if(str.crbegin(), str.crend(), [](unsigned char c) { return !std::isspace(c); }).base(), str.cend()); return str; } static inline std::string ToLower(std::string str) { std::transform(str.cbegin(), str.cend(), str.begin(), [](unsigned char c) { return std::tolower(c); }); return str; } const std::string &Config::GetValue(const std::string &key) { return GetValue(global, key); } const std::string &Config::GetValue(const std::string §ion, const std::string &key) { auto secLower = ToLower(section); auto keyLower = ToLower(key); auto itSection = m_section.find(secLower); if(itSection == m_section.end()) return empty; auto itKey = itSection->second.find(keyLower); if(itKey == itSection->second.end()) return empty; return itKey->second; } bool Config::LoadFile(const std::string &filename) { std::string section = global; std::ifstream file; file.open(filename); if(!file.is_open()) return false; std::string line; int lineNum = 0; while(std::getline(file, line)) { line = Trim(line); ++lineNum; if(line.empty()) continue; // Comment. if(line.front() == '#') continue; if(line.front() == '[' && line.back() == ']') { // Section line.erase(line.begin()); line.erase(line.end() - 1); section = Trim(line); continue; } // Everything else. :) auto equals = line.find('=', 0); if(equals == std::string::npos) { std::cerr << filename << ": no value specified on line " << lineNum << std::endl; continue; } auto key = Trim(line.substr(0, equals)); auto value = Trim(line.substr(equals + 1, std::string::npos)); SetValue(section, key, value); } file.close(); return true; } void Config::SetValue(const std::string &key, const std::string &value) { SetValue(global, key, value); } void Config::SetValue(const std::string §ion, const std::string &key, const std::string &value) { auto secLower = ToLower(section); auto keyLower = ToLower(key); auto itSection = m_section.find(secLower); if(itSection == m_section.end()) { // O.o auto newSection = std::pair> (secLower, std::unordered_map()); newSection.second.insert(std::pair(keyLower, value)); m_section.insert(newSection); return; } auto itKey = itSection->second.find(keyLower); if(itKey == itSection->second.end()) { itSection->second.insert(std::pair(keyLower, value)); return; } itKey->second = value; } }