From 1e57c2b3f6bd2a4f1756150e669eedffc29cf13d Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Wed, 3 Jan 2018 22:29:17 +0100 Subject: Fixed crash with Settings dialog - User Configuration gets completely written, instead of being just overrides --- lib/settings/configuration.cpp | 171 ++++++++++++++++++++++++++--------------- 1 file changed, 107 insertions(+), 64 deletions(-) (limited to 'lib/settings/configuration.cpp') diff --git a/lib/settings/configuration.cpp b/lib/settings/configuration.cpp index 4603779..1fa1fbf 100644 --- a/lib/settings/configuration.cpp +++ b/lib/settings/configuration.cpp @@ -21,15 +21,14 @@ Configuration::Configuration() // fsync after writing and before closing m_userCfg->setOption(Config::OptionFsync, true); + // make sure the cfgPath is empty + m_userCfgPath = std::string(); + m_defaultCfg = new Config(); } Configuration::~Configuration() { - if(!m_userCfgPath.empty()) { - m_userCfg->writeFile(m_userCfgPath.c_str()); - } - delete m_userCfg; delete m_defaultCfg; } @@ -47,22 +46,42 @@ bool Configuration::readUserConfiguration(const std::string &path) return true; } +bool Configuration::parse(const std::string &contents) +{ + try { + m_userCfg->readString(contents); + } catch (ParseException) { + return false; + } + return true; +} + bool Configuration::writeUserConfiguration(const std::string &path) { m_userCfgPath = path; try { - m_userCfg->writeFile(path.c_str()); + m_userCfg->writeFile(m_userCfgPath.c_str()); } catch (FileIOException) { return false; } return true; } -bool Configuration::readDefaultConfiguration(const std::string &data) +bool Configuration::writeIfNeeded() { try { - m_defaultCfg->readString(data); - } catch(ParseException) { + m_userCfg->writeFile(m_userCfgPath.c_str()); + } catch (FileIOException) { + return false; + } + return true; +} + +bool Configuration::parseDefaultConfiguration(const std::string &contents) +{ + try { + m_defaultCfg->readString(contents); + } catch (ParseException) { return false; } return true; @@ -71,7 +90,7 @@ bool Configuration::readDefaultConfiguration(const std::string &data) std::vector Configuration::childrenSettings(const char* name) { std::vector groupNames; - const Setting &root = m_defaultCfg->lookup(name); + const Setting &root = m_userCfg->lookup(name); for(const Setting &setting : root) { if(setting.getType() != Setting::TypeGroup) { @@ -85,7 +104,7 @@ std::vector Configuration::childrenSettings(const char* name) std::vector Configuration::childrenGroups(const char* name) { std::vector groupNames; - const Setting &root = m_defaultCfg->lookup(name); + const Setting &root = m_userCfg->lookup(name); for(const Setting &setting : root) { if(setting.getType() == Setting::TypeGroup) { @@ -98,20 +117,45 @@ std::vector Configuration::childrenGroups(const char* name) void Configuration::resetValue(const char *path) { if(m_userCfg->exists(path)) { - m_userCfg->getRoot().remove(path); + Setting &v = m_userCfg->lookup(path); + switch (v.getType()) { + case Setting::TypeNone: + break; + case Setting::TypeInt: + v = static_cast(m_defaultCfg->lookup(path)); + break; + case Setting::TypeInt64: + v = static_cast(m_defaultCfg->lookup(path)); + break; + case Setting::TypeFloat: + v = static_cast(m_defaultCfg->lookup(path)); + break; + case Setting::TypeString: + v = static_cast(m_defaultCfg->lookup(path)); + break; + case Setting::TypeBoolean: + v = static_cast(m_defaultCfg->lookup(path)); + break; + case Setting::TypeGroup: + break; + case Setting::TypeArray: + break; + case Setting::TypeList: + break; + } } } template std::optional Configuration::value(const char* path) const { - Config *conf = getConfig(path); - if(conf == nullptr) { + // if setting doesn't exist, give back a nullopt + if(!m_userCfg->exists(path)) { return std::nullopt; } // setting was found - const Setting &setting = conf->lookup(path); + const Setting &setting = m_userCfg->lookup(path); std::optional r; // cast depending on type @@ -207,7 +251,7 @@ template std::optional Configuration::value(const char* path) const; template std::optional Configuration::value(const char* path) const; template -void Configuration::setValue(std::string path, const T &val) +bool Configuration::setValue(std::string path, const T &val) { if(m_userCfg->exists(path)) { Setting &setting = m_userCfg->lookup(path); @@ -215,70 +259,69 @@ void Configuration::setValue(std::string path, const T &val) if constexpr(std::is_unsigned_v && !std::is_same_v) { setting = static_cast>(val); } else if constexpr(std::is_same_v) { - setting = static_cast(val).c_str(); + switch (setting.getType()) { + case Setting::TypeNone: + break; + + case Setting::TypeInt: + case Setting::TypeInt64: + setting = std::stoi(static_cast(val)); + break; + + case Setting::TypeFloat: + setting = std::stod(static_cast(val)); + break; + + case Setting::TypeString: + setting = static_cast(val).c_str(); + break; + + case Setting::TypeBoolean: + if(static_cast(val) == "true") { + setting = true; + } else if (static_cast(val) == "false") { + setting = false; + } + break; + + case Setting::TypeGroup: + break; + case Setting::TypeArray: + break; + case Setting::TypeList: + break; + } + } else { setting = val; } - return; - } - - // the entry doesn't exist, so we need to create it - // libconfig can't create an entry from a path, we need to get its root, and then add it - - // this will error out if entry being added is not in the default config - - std::istringstream p(path); - Setting *userSetting = &m_userCfg->getRoot(); - Setting *defaultSetting = &m_defaultCfg->getRoot(); - - std::string i; - while (std::getline(p, i, '.')) { - defaultSetting = &defaultSetting->lookup(i); - // check if user setting exists, if not, create it - if(!userSetting->exists(i)) { - userSetting = &userSetting->add(i, defaultSetting->getType()); - } - } - if constexpr(std::is_unsigned_v && !std::is_same_v) { - *userSetting = static_cast>(val); - } else if constexpr(std::is_same_v) { - *userSetting = static_cast(val).c_str(); - } else { - *userSetting = val; + changed = true; + return true; } + // the entry doesn't exist + return false; } -template void Configuration::setValue(std::string path, const int &val); -template void Configuration::setValue(std::string path, const unsigned int &val); -template void Configuration::setValue(std::string path, const long &val); -template void Configuration::setValue(std::string path, const unsigned long &val); - -template void Configuration::setValue(std::string path, const long long &val); -template void Configuration::setValue(std::string path, const unsigned long long &val); +template bool Configuration::setValue(std::string path, const int &val); +template bool Configuration::setValue(std::string path, const unsigned int &val); +template bool Configuration::setValue(std::string path, const long &val); +template bool Configuration::setValue(std::string path, const unsigned long &val); -template void Configuration::setValue(std::string path, const float &val); -template void Configuration::setValue(std::string path, const double &val); +template bool Configuration::setValue(std::string path, const long long &val); +template bool Configuration::setValue(std::string path, const unsigned long long &val); -template void Configuration::setValue(std::string path, const bool &val); +template bool Configuration::setValue(std::string path, const float &val); +template bool Configuration::setValue(std::string path, const double &val); -template void Configuration::setValue(std::string path, const std::string &val); +template bool Configuration::setValue(std::string path, const bool &val); -Config *Configuration::getConfig(const char* path) const -{ - if(m_userCfg->exists(path)) { - return m_userCfg; - } else if(m_defaultCfg->exists(path)) { - return m_defaultCfg; - } else { - return nullptr; - } -} +template bool Configuration::setValue(std::string path, const std::string &val); std::string &patchHome(std::string &path, const std::string &home) { - const size_t location = path.find("~"); + const size_t location = path.find('~'); if(location != std::string::npos) { return path.replace(location, 1, home); } -- cgit v1.2.1