summaryrefslogtreecommitdiffstats
path: root/src/ConfigBase.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ConfigBase.hpp')
-rw-r--r--src/ConfigBase.hpp283
1 files changed, 283 insertions, 0 deletions
diff --git a/src/ConfigBase.hpp b/src/ConfigBase.hpp
new file mode 100644
index 0000000..5e2a50f
--- /dev/null
+++ b/src/ConfigBase.hpp
@@ -0,0 +1,283 @@
+#ifndef CONFIGBASE
+#define CONFIGBASE
+
+#include <QString>
+#include <QStringList>
+#include <QList>
+#include <QMap>
+
+#include <exception>
+#include <type_traits>
+#include <limits>
+
+using CRSMConfigException = std::logic_error;
+
+namespace CRSMConfigValueType {
+enum Type {
+ None,
+ String,
+ Integer,
+ Boolean,
+ List,
+ Map
+};
+}
+
+class CRSMConfigValueBase {
+public:
+
+ virtual void setValue(const QString&) { }
+ virtual QString value() { return ""; }
+ virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::None; }
+
+
+
+ template<typename Type>
+ static Type getValue(const QString& value);
+
+ template<typename Type>
+ static QString getStringValue(Type val);
+};
+
+template<typename Type, typename = void>
+class CRSMConfigValue : public CRSMConfigValueBase {
+public:
+// CRSMConfigValue(Type&) { }
+
+ virtual void setValue(const QString&) { throw CRSMConfigException("Cannot assign"); }
+ virtual QString value() { throw CRSMConfigException("Cannot get the value"); }
+};
+
+using String = QString;
+using Integer = int;
+using Port = ushort;
+using Boolean = bool;
+#define List(Type) QList<Type>
+#define Map(KeyType, ValueType) QMap<KeyType, ValueType>
+
+
+#define ConfigValue(Value) {#Value, mkConfigValue(Value)}
+#define ConfigValueEx(Value, ...) {#Value, mkConfigValue(Value, __VA_ARGS__)}
+
+template<>
+class CRSMConfigValue<String> : public CRSMConfigValueBase {
+ String& config;
+ bool trimmedQuotes = false;
+
+public:
+ CRSMConfigValue(String& config) : config(config) { }
+
+ virtual void setValue(const QString& value) { config = trimQuotes(QString(value), trimmedQuotes); }
+ virtual QString value()
+ {
+ if(trimmedQuotes)
+ {
+ return "\"" + config + "\"";
+ }
+ else
+ {
+ return config;
+ }
+ }
+ virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::String; }
+
+private:
+ QString& trimQuotes(QString&& string, bool& trimmed)
+ {
+ trimmed = false;
+ if(string.length() >= 2 && string.at(0) == '"' && string.at(string.length() - 1) == '"')
+ {
+ string.remove(0, 1);
+ string.remove(string.length() - 1, 1);
+ trimmed = true;
+ }
+ return string;
+ }
+
+};
+
+template<typename Type>
+class CRSMConfigValue<Type, typename std::enable_if<std::is_integral<Type>::value>::type> : public CRSMConfigValueBase {
+ Type& config;
+
+public:
+ CRSMConfigValue(Type& config) : config(config) { }
+
+ virtual void setValue(const QString& value)
+ {
+ bool ok = true;
+ long long longLongVal = value.toLongLong(&ok, 0);
+ if(!ok) throw CRSMConfigException("\"" + value.toStdString() + "\" could not be parsed as an Integer");
+ if(longLongVal < std::numeric_limits<Type>::min() || longLongVal > std::numeric_limits<Type>::max()) throw CRSMConfigException((QString::number(longLongVal) + " is out of range (" + QString::number(std::numeric_limits<Type>::min()) + " - " + QString::number(std::numeric_limits<Type>::max()) + ")").toStdString());
+ config = static_cast<Type>(longLongVal);
+ }
+ virtual QString value() { return QString::number(config); }
+ virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::Integer; }
+};
+
+template<>
+class CRSMConfigValue<Boolean> : public CRSMConfigValueBase {
+ Boolean& config;
+
+public:
+ CRSMConfigValue(Boolean& config) : config(config) { }
+
+ virtual void setValue(const QString& value)
+ {
+ if(value == "true")
+ {
+ config = true;
+ }
+ else if(value == "false")
+ {
+ config = false;
+ }
+ else
+ {
+ throw CRSMConfigException("\"" + value.toStdString() + "\" could not be parsed as a Boolean");
+ }
+ }
+ virtual QString value() { return config ? "true" : "false"; }
+ virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::Boolean; }
+};
+
+class CRSMConfigValueList : public CRSMConfigValueBase {
+public:
+ virtual void append(const QString& entry) = 0;
+ virtual void remove(const QString& entry) = 0;
+ virtual QStringList getValues() = 0;
+};
+
+class CRSMConfigValueMap : public CRSMConfigValueBase {
+public:
+ virtual void setKeyValue(const QString& key, const QString& value) = 0;
+ virtual void remove(const QString& key) = 0;
+ virtual QMap<QString, QString> getValues() = 0;
+};
+
+template<typename Type>
+class CRSMConfigValue<QList<Type>> : public CRSMConfigValueList {
+ using ListType = QList<Type>;
+
+ ListType& config;
+ const bool deduplicate;
+
+public:
+ CRSMConfigValue(ListType& config, bool deduplicate = true) : config(config), deduplicate(deduplicate) {}
+
+ virtual ListType& list() { return config; }
+ virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::List; }
+
+ virtual void append(const QString &entry)
+ {
+ Type val = CRSMConfigValueBase::getValue<Type>(entry);
+ if(!deduplicate || !config.contains(val))
+ {
+ config.append(val);
+ }
+ }
+
+ virtual void remove(const QString &entry) { config.removeAll(CRSMConfigValueBase::getValue<Type>(entry)); }
+
+ virtual QStringList getValues()
+ {
+ QStringList ret;
+
+ foreach(Type val, config)
+ {
+ ret.append(CRSMConfigValueBase::getStringValue(val));
+ }
+
+ return ret;
+ }
+};
+
+template<typename KeyType, typename ValueType>
+class CRSMConfigValue<QMap<KeyType, ValueType>> : public CRSMConfigValueMap {
+ using MapType = QMap<KeyType, ValueType>;
+
+ MapType& config;
+
+public:
+ CRSMConfigValue(MapType& config) : config(config) {}
+
+ virtual MapType& map() { return config; }
+ virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::Map; }
+
+ virtual void setKeyValue(const QString& key, const QString& value)
+ {
+ config[CRSMConfigValueBase::getValue<KeyType>(key)] = CRSMConfigValueBase::getValue<ValueType>(value);
+ }
+
+ virtual QMap<QString, QString> getValues()
+ {
+ QMap<QString, QString> ret;
+
+ foreach(KeyType key, config.keys())
+ {
+ ret[CRSMConfigValueBase::getStringValue(key)] = CRSMConfigValueBase::getStringValue(config[key]);
+ }
+
+ return ret;
+ }
+
+ virtual void remove(const QString &key)
+ {
+ config.remove(CRSMConfigValueBase::getValue<KeyType>(key));
+ }
+};
+
+template<typename Type>
+class CRSMConfigValue<Type, typename std::enable_if<std::is_enum<Type>::value>::type> : public CRSMConfigValue<typename std::underlying_type<Type>::type> {
+ using UndType = typename std::underlying_type<Type>::type;
+public:
+ CRSMConfigValue(Type& config) : CRSMConfigValue<UndType>::CRSMConfigValue((UndType&)config) {}
+};
+
+template<typename Type, typename... Types>
+CRSMConfigValue<Type>* mkConfigValue(Type& Value, Types... values)
+{
+ return new CRSMConfigValue<Type>(Value, values...);
+}
+
+template<typename Type>
+Type CRSMConfigValueBase::getValue(const QString& value)
+{
+ Type ret;
+ CRSMConfigValue<Type> val(ret);
+ val.setValue(value);
+ return ret;
+}
+
+template<typename Type>
+QString CRSMConfigValueBase::getStringValue(Type value)
+{
+ CRSMConfigValue<Type> val(value);
+ return val.value();
+}
+
+class CRSMConfigBase
+{
+public:
+ explicit CRSMConfigBase(QMap<QString, CRSMConfigValueBase*> configValues) : configValues(configValues) {}
+
+ void setConfigValue(const QString& name, const QString& value);
+ QString getConfigValueLine(const QString& name);
+ void addConfigListEntry(const QString& name, const QString& value);
+ void removeConfigMapListEntry(const QString &name, const QString &value);
+ void setConfigMapValue(const QString& name, const QString& key, const QString& value);
+
+ QString read(const QString& fileName, bool writeDefault = true);
+ bool write(const QString& fileName);
+
+ void setConfigLine(const QString& line);
+
+protected:
+ void addConfigValue(QString name, CRSMConfigValueBase *value);
+ CRSMConfigValueBase& getConfigValue(const QString &name);
+
+ QMap<QString, CRSMConfigValueBase*> configValues;
+};
+
+#endif // CONFIGBASE
+