#include "utility/ConfigManager.h" #include "tinyxml/tinyxml.h" #include "utility/logging/logging.h" #include "utility/text/TextAccess.h" #include "utility/utilityString.h" std::shared_ptr ConfigManager::createEmpty() { return std::shared_ptr(new ConfigManager()); } std::shared_ptr ConfigManager::createAndLoad(const std::shared_ptr textAccess) { std::shared_ptr configManager = std::shared_ptr(new ConfigManager()); configManager->load(textAccess); return configManager; } bool ConfigManager::getValue(const std::string& key, std::string& value) const { std::multimap::const_iterator it = m_values.find(key); if (it != m_values.end()) { value = it->second; return true; } else { LOG_ERROR("value " + key + " is not present in config."); return false; } } bool ConfigManager::getValue(const std::string& key, int& value) const { std::string valueString; if (getValue(key, valueString)) { value = atoi(valueString.c_str()); return true; } return false; } bool ConfigManager::getValue(const std::string& key, float& value) const { std::string valueString; if (getValue(key, valueString)) { value = static_cast(atof(valueString.c_str())); return true; } return false; } bool ConfigManager::getValue(const std::string& key, bool& value) const { std::string valueString; if (getValue(key, valueString)) { value = (atoi(valueString.c_str()) != 0); return true; } return false; } bool ConfigManager::getValues(const std::string& key, std::vector& values) const { std::pair ::const_iterator, std::multimap::const_iterator> ret; ret = m_values.equal_range(key); if (ret.first != m_values.end()) { std::multimap::const_iterator cit = ret.first; for(;cit!=ret.second;++cit) { values.push_back(cit->second); } return true; } else { LOG_ERROR("value " + key + " is not present in config."); return false; } } bool ConfigManager::getValues(const std::string& key, std::vector& values) const { std::vector valuesStringVector; if (getValues(key, valuesStringVector)) { for (std::string valueString : valuesStringVector) { values.push_back(atoi(valueString.c_str())); } return true; } return false; } bool ConfigManager::getValues(const std::string& key, std::vector& values) const { std::vector valuesStringVector; if (getValues(key, valuesStringVector)) { for (std::string valueString : valuesStringVector) { values.push_back(static_cast(atof(valueString.c_str()))); } return true; } return false; } bool ConfigManager::getValues(const std::string& key, std::vector& values) const { std::vector valuesStringVector; if (getValues(key, valuesStringVector)) { for (std::string valueString : valuesStringVector) { values.push_back(atoi(valueString.c_str()) != 0); } return true; } return false; } void ConfigManager::setValue(const std::string& key, const std::string& value) { std::multimap::iterator it = m_values.find(key); if (it != m_values.end()) { it->second = value; } else { m_values.emplace(key, value); } } void ConfigManager::setValue(const std::string& key, const int value) { setValue(key, std::to_string(value)); } void ConfigManager::setValue(const std::string& key, const float value) { setValue(key, std::to_string(value)); } void ConfigManager::setValue(const std::string& key, const bool value) { setValue(key, std::string(value ? "1" : "0")); } void ConfigManager::setValues(const std::string& key, const std::vector& values) { std::multimap::iterator it = m_values.find(key); if(it != m_values.end()) { m_values.erase(key); } for(std::string s : values) { m_values.emplace(key, s); } } void ConfigManager::setValues(const std::string& key, const std::vector& values) { std::vector stringValues; for(int i : values) { stringValues.push_back(std::to_string(i)); } setValues(key, stringValues); } void ConfigManager::setValues(const std::string& key, const std::vector& values) { std::vector stringValues; for(float f : values) { stringValues.push_back(std::to_string(f)); } setValues(key, stringValues); } void ConfigManager::setValues(const std::string& key, const std::vector& values) { std::vector stringValues; for(bool b : values) { stringValues.push_back(std::string(b ? "1" : "0")); } setValues(key, stringValues); } void ConfigManager::load(const std::shared_ptr textAccess) { std::string text = textAccess->getText(); TiXmlDocument doc; const char* pTest = doc.Parse(text.c_str(), 0, TIXML_ENCODING_UTF8); if (pTest != NULL) { TiXmlHandle docHandle(&doc); TiXmlNode *rootNode = docHandle.FirstChild("config").ToNode(); for (TiXmlNode *childNode = rootNode->FirstChild(); childNode; childNode = childNode->NextSibling()) { parseSubtree(childNode, ""); } } else { LOG_ERROR("Unable to load file."); } } void ConfigManager::save(const std::string filepath) { std::string output(""); createXmlDocument(true, filepath, output); } ConfigManager::ConfigManager() { } bool ConfigManager::createXmlDocument(bool saveAsFile, const std::string filepath, std::string& output) { bool success = true; TiXmlDocument doc; TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "utf-8", "" ); doc.LinkEndChild(decl); TiXmlElement *root = new TiXmlElement("config"); doc.LinkEndChild(root); for(std::multimap::iterator it = m_values.begin(); it != m_values.end(); ++it) { std::vector tokens = utility::splitToVector(it->first, "/"); TiXmlElement* element = doc.RootElement(); TiXmlElement* child; while(tokens.size() > 1) { child = element->FirstChildElement(tokens.front().c_str()); if(!child) { child = new TiXmlElement(tokens.front().c_str()); element->LinkEndChild(child); } tokens.erase(tokens.begin()); element = child; } child = new TiXmlElement(tokens.front().c_str()); element->LinkEndChild(child); TiXmlText* text = new TiXmlText(it->second.c_str()); child->LinkEndChild(text); } if(saveAsFile) { success = doc.SaveFile(filepath.c_str()); } else { TiXmlPrinter printer; doc.Accept(&printer); output = printer.CStr(); } success = doc.SaveFile(filepath.c_str()); doc.Clear(); return success; } void ConfigManager::parseSubtree(TiXmlNode* currentNode, const std::string& currentPath) { if (currentNode->Type() == TiXmlNode::TINYXML_TEXT) { std::string key = currentPath.substr(0, currentPath.size() - 1); m_values.insert(std::pair(key,currentNode->ToText()->Value())); } else { for (TiXmlNode *childNode = currentNode->FirstChild(); childNode; childNode = childNode->NextSibling()) { parseSubtree(childNode, currentPath + std::string(currentNode->Value()) + "/"); } } } std::string ConfigManager::toString() { std::string output; createXmlDocument(false, "", output); return output; }