aboutsummaryrefslogtreecommitdiff
path: root/lib/settings/configuration.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/settings/configuration.cpp')
-rw-r--r--lib/settings/configuration.cpp233
1 files changed, 100 insertions, 133 deletions
diff --git a/lib/settings/configuration.cpp b/lib/settings/configuration.cpp
index 06ee0bd..af5af65 100644
--- a/lib/settings/configuration.cpp
+++ b/lib/settings/configuration.cpp
@@ -7,22 +7,20 @@
*/
#include "configuration.h"
-#include <libconfig.h++>
+#include <QtCore/QStandardPaths>
#include <sstream>
using namespace libconfig;
-Configuration::Configuration()
+Configuration::Configuration(const std::string &path, const std::string &home)
{
m_userCfg = new Config();
-#ifdef C_LIKE_CONFIG
+ // prettier output
m_userCfg->setOptions(Config::OptionSemicolonSeparators | Config::OptionOpenBraceOnSeparateLine);
-#endif
- // fsync after writing and before closing
m_userCfg->setOption(Config::OptionFsync, true);
- // make sure the cfgPath is empty
- m_userCfgPath = std::string();
+ m_userCfgPath = path;
+ m_homePath = home;
m_defaultCfg = new Config();
}
@@ -33,14 +31,13 @@ Configuration::~Configuration()
delete m_defaultCfg;
}
-bool Configuration::readUserConfiguration(const std::string &path)
+bool Configuration::read()
{
- m_userCfgPath = path;
try {
- m_userCfg->readFile(path.c_str());
- } catch(FileIOException) {
+ m_userCfg->readFile(m_userCfgPath.c_str());
+ } catch(const FileIOException &e) {
return false;
- } catch(ParseException) {
+ } catch(const ParseException &e) {
return false;
}
return true;
@@ -50,30 +47,27 @@ bool Configuration::parse(const std::string &contents)
{
try {
m_userCfg->readString(contents);
- } catch(ParseException) {
+ } catch(const ParseException &e) {
return false;
}
return true;
}
-bool Configuration::writeUserConfiguration(const std::string &path)
+bool Configuration::writeIfNeeded(const std::string &path)
{
- m_userCfgPath = path;
- try {
- m_userCfg->writeFile(m_userCfgPath.c_str());
- } catch(FileIOException) {
- return false;
- }
- return true;
-}
+ if(!path.empty())
+ m_userCfgPath = path;
+
+ if(!changed)
+ return true;
-bool Configuration::writeIfNeeded()
-{
try {
m_userCfg->writeFile(m_userCfgPath.c_str());
- } catch(FileIOException) {
+ } catch(const FileIOException &e) {
return false;
}
+
+ changed = false;
return true;
}
@@ -81,7 +75,7 @@ bool Configuration::parseDefaultConfiguration(const std::string &contents)
{
try {
m_defaultCfg->readString(contents);
- } catch(ParseException) {
+ } catch(const ParseException &e) {
return false;
}
return true;
@@ -94,7 +88,8 @@ std::vector<std::string> Configuration::childrenSettings(const char *name)
for(const Setting &setting : root) {
if(setting.getType() != Setting::TypeGroup) {
- groupNames.push_back(setting.getName());
+ groupNames.emplace_back(setting.getName());
+ //groupNames.push_back(setting.getName());
}
}
@@ -108,7 +103,8 @@ std::vector<std::string> Configuration::childrenGroups(const char *name)
for(const Setting &setting : root) {
if(setting.getType() == Setting::TypeGroup) {
- groupNames.push_back(setting.getName());
+ groupNames.emplace_back(setting.getName());
+ //groupNames.push_back(setting.getName());
}
}
return groupNames;
@@ -116,139 +112,109 @@ std::vector<std::string> Configuration::childrenGroups(const char *name)
void Configuration::resetValue(const char *path)
{
- if(m_userCfg->exists(path)) {
- Setting &v = m_userCfg->lookup(path);
- switch(v.getType()) {
- case Setting::TypeNone:
- break;
- case Setting::TypeInt:
- v = static_cast<int>(m_defaultCfg->lookup(path));
- break;
- case Setting::TypeInt64:
- v = static_cast<long>(m_defaultCfg->lookup(path));
- break;
- case Setting::TypeFloat:
- v = static_cast<double>(m_defaultCfg->lookup(path));
- break;
- case Setting::TypeString:
- v = static_cast<const char *>(m_defaultCfg->lookup(path));
- break;
- case Setting::TypeBoolean:
- v = static_cast<bool>(m_defaultCfg->lookup(path));
- break;
- case Setting::TypeGroup:
- break;
- case Setting::TypeArray:
- break;
- case Setting::TypeList:
- break;
+ if(!m_userCfg->exists(path) && m_defaultCfg->exists(path)) {
+ // entry doesn't exist, create path to it
+ // split path into array of items, sep=.
+ std::string s(path);
+ std::vector<std::string> pathTokens;
+ std::string::size_type prev_pos = 0, pos = 0;
+ while((pos = s.find('.', pos)) != std::string::npos) {
+ std::string substring(s.substr(prev_pos, pos - prev_pos));
+ pathTokens.push_back(substring);
+ prev_pos = ++pos;
}
- }
-}
+ pathTokens.push_back(s.substr(prev_pos, pos - prev_pos)); // Last word
-template <typename T>
-std::optional<T> Configuration::value(const char *path) const
-{
- // if setting doesn't exist, give back a nullopt
- if(!m_userCfg->exists(path)) {
- return std::nullopt;
+ s.clear();
+ // iterate through items, creating the path along the way
+ for(const std::string &t : pathTokens) {
+ Setting &v = m_userCfg->lookup(s);
+ Setting &d = m_defaultCfg->lookup(s).lookup(t);
+
+ if(!v.exists(t)) {
+ v.add(t, d.getType());
+ }
+
+ if(s.empty())
+ s.append(t);
+ else
+ s.append('.' + t);
+ }
}
- // setting was found
- const Setting &setting = m_userCfg->lookup(path);
- std::optional<T> r;
+ // if the path doesn't exist in the defaultCfg, this will crash
- // cast depending on type
- // type checks are done during compile time
- switch(setting.getType()) {
+ // entry exists, reset it
+ Setting &v = m_userCfg->lookup(path);
+ switch(v.getType()) {
case Setting::TypeNone:
- r = std::nullopt;
break;
-
case Setting::TypeInt:
- // int, unsigned int, long, unsigned long
- if constexpr(std::is_same_v<T, std::string>) {
- r = std::optional<std::string>(std::to_string(static_cast<int>(setting)));
- } else if constexpr(std::is_same_v<T, int> || std::is_same_v<T, unsigned int> || std::is_same_v<T, long> || std::is_same_v<T, unsigned long>) {
- r = std::optional<T>(static_cast<T>(setting));
- } else {
- r = std::nullopt;
- }
+ v = static_cast<int>(m_defaultCfg->lookup(path));
break;
-
case Setting::TypeInt64:
- // int, unsigned int; long long, unsigned long long
- if constexpr(std::is_same_v<T, std::string>) {
- r = std::optional<std::string>(std::to_string(static_cast<long long>(setting)));
- } else if constexpr(std::is_same_v<T, int> || std::is_same_v<T, unsigned int> || std::is_same_v<T, long long> || std::is_same_v<T, unsigned long long>) {
- r = std::optional<T>(static_cast<T>(setting));
- } else {
- r = std::nullopt;
- }
+ v = static_cast<long>(m_defaultCfg->lookup(path));
break;
-
case Setting::TypeFloat:
- // float, double
- if constexpr(std::is_same_v<T, std::string>) {
- r = std::optional<std::string>(std::to_string(static_cast<float>(setting)));
- } else if constexpr(std::is_same_v<T, float> || std::is_same_v<T, double>) {
- r = std::optional<T>(static_cast<T>(setting));
- } else {
- r = std::nullopt;
- }
+ v = static_cast<double>(m_defaultCfg->lookup(path));
break;
-
case Setting::TypeString:
- // const char*, std::string
- if constexpr(std::is_same<T, std::string>::value) {
- r = std::optional<std::string>(static_cast<const char *>(setting));
- } else {
- r = std::nullopt;
- }
+ v = static_cast<const char *>(m_defaultCfg->lookup(path));
break;
-
case Setting::TypeBoolean:
- // bool
- if constexpr(std::is_same<T, std::string>::value) {
- r = std::optional<std::string>(static_cast<bool>(setting) ? "true" : "false");
- } else if constexpr(std::is_same<T, bool>::value) {
- r = std::optional<bool>(static_cast<bool>(setting));
- } else {
- r = std::nullopt;
- }
+ v = static_cast<bool>(m_defaultCfg->lookup(path));
break;
-
case Setting::TypeGroup:
- r = std::nullopt;
break;
-
case Setting::TypeArray:
- r = std::nullopt;
break;
-
case Setting::TypeList:
- r = std::nullopt;
break;
}
- return r;
+ // if it's a string, it may contain a path
+ if(v.getType() == Setting::TypeString) {
+ std::string val(static_cast<const char *>(v));
+ v = patchHome(val, m_homePath).c_str();
+ }
+
+ changed = true;
}
-// tell the compiler to export these functions, otherwise you get linking errors
-template std::optional<int> Configuration::value<int>(const char *path) const;
-template std::optional<unsigned int> Configuration::value<unsigned int>(const char *path) const;
-template std::optional<long> Configuration::value<long>(const char *path) const;
-template std::optional<unsigned long> Configuration::value<unsigned long>(const char *path) const;
+std::string Configuration::castToString(const libconfig::Setting &v) const
+{
+ // cast depending on type
+ // type checks are done during compile time
+ switch(v.getType()) {
+ case Setting::TypeNone:
+ return std::string();
+
+ case Setting::TypeInt:
+ // int, unsigned int, long, unsigned long
+ return std::to_string(static_cast<int32_t>(v));
-template std::optional<long long> Configuration::value<long long>(const char *path) const;
-template std::optional<unsigned long long> Configuration::value<unsigned long long>(const char *path) const;
+ case Setting::TypeInt64:
+ // int, unsigned int; long long, unsigned long long
+ return std::to_string(static_cast<int64_t>(v));
-template std::optional<float> Configuration::value<float>(const char *path) const;
-template std::optional<double> Configuration::value<double>(const char *path) const;
+ case Setting::TypeFloat:
+ // float, double
+ return std::to_string(static_cast<double>(v));
+
+ case Setting::TypeString:
+ // const char*, std::string
+ return std::string(static_cast<const char *>(v));
-template std::optional<bool> Configuration::value<bool>(const char *path) const;
+ case Setting::TypeBoolean:
+ // bool
+ return std::string(static_cast<bool>(v) ? "true" : "false");
-template std::optional<std::string> Configuration::value<std::string>(const char *path) const;
+ case Setting::TypeGroup:
+ case Setting::TypeArray:
+ case Setting::TypeList:
+ return std::string();
+ }
+}
template <typename T>
bool Configuration::setValue(std::string path, const T &val)
@@ -319,11 +285,12 @@ template bool Configuration::setValue<bool>(std::string path, const bool &val);
template bool Configuration::setValue<std::string>(std::string path, const std::string &val);
-std::string &patchHome(std::string &path, const std::string &home)
+std::string patchHome(const std::string &path, const std::string &home)
{
+ std::string r = path;
const size_t location = path.find('~');
if(location != std::string::npos) {
- return path.replace(location, 1, home);
+ return r.replace(location, 1, home);
}
- return path;
+ return r;
}