diff options
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | src/CRSMConfig.hpp | 2 | ||||
| -rw-r--r-- | src/CRSMPackCompatibility.hpp | 2 | ||||
| -rw-r--r-- | src/CRSMStats.hpp | 2 | ||||
| -rw-r--r-- | src/ConfigBase.cpp | 207 | ||||
| -rw-r--r-- | src/ConfigBase.hpp | 330 | ||||
| -rw-r--r-- | src/CrServerManager.pro | 4 | ||||
| l---------[-rw-r--r--] | src/Util.cpp | 192 | ||||
| l---------[-rw-r--r--] | src/Util.hpp | 19 | ||||
| m--------- | src/qt-config | 0 |
10 files changed, 10 insertions, 751 deletions
diff --git a/.gitmodules b/.gitmodules index 34198ce..2adebef 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "src/libcommuni"] path = src/libcommuni url = https://github.com/communi/libcommuni.git +[submodule "src/qt-config"] + path = src/qt-config + url = git@git.t0bd1.at:qt-config diff --git a/src/CRSMConfig.hpp b/src/CRSMConfig.hpp index ceba46b..76bc850 100644 --- a/src/CRSMConfig.hpp +++ b/src/CRSMConfig.hpp @@ -1,6 +1,6 @@ #pragma once -#include "ConfigBase.hpp" +#include "qt-config/ConfigBase.hpp" #include "GreetingSetting.hpp" class CRSMConfig : public ConfigBase { diff --git a/src/CRSMPackCompatibility.hpp b/src/CRSMPackCompatibility.hpp index 08b666e..3b13cda 100644 --- a/src/CRSMPackCompatibility.hpp +++ b/src/CRSMPackCompatibility.hpp @@ -1,5 +1,5 @@ #pragma once -#include "ConfigBase.hpp" +#include "qt-config/ConfigBase.hpp" class CRSMPackCompatibility : public ConfigBase { diff --git a/src/CRSMStats.hpp b/src/CRSMStats.hpp index 595c58b..bed5e26 100644 --- a/src/CRSMStats.hpp +++ b/src/CRSMStats.hpp @@ -1,6 +1,6 @@ #pragma once -#include "ConfigBase.hpp" +#include "qt-config/ConfigBase.hpp" #include "ClientInfo.hpp" #include "CmdFunctionRef.hpp" diff --git a/src/ConfigBase.cpp b/src/ConfigBase.cpp deleted file mode 100644 index ce4bcc0..0000000 --- a/src/ConfigBase.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include "CRSMConfig.hpp" - -#include <QFile> - -void ConfigBase::addConfigValue(QString name, ConfigValueBase* value) -{ - configValues[name] = value; -} - -void ConfigBase::setConfigValue(const QString &name, const QString &value) -{ - ConfigValueBase& configValue = getConfigValue(name); - configValue.setValue(Util::unescape(value)); -} - -QString ConfigBase::getConfigValueLine(const QString &name) -{ - if(configValues.contains(name)) - { - ConfigValueBase& value = *configValues[name]; - switch(value.type()) - { - case ConfigValueType::Map: - { - QString ret; - const QMap<QString, QString>& values = (dynamic_cast<ConfigValueMap*>(&value))->getValues(); - foreach(const QString& mapKey, values.keys()) - { - ret += name + "[" + Util::escape(mapKey, '\\', "]") + "]" + " = " + Util::escape(values.value(mapKey)) + "\n"; - } - return ret; - break; - } - case ConfigValueType::List: - { - QString ret; - foreach(const QString& val, (dynamic_cast<ConfigValueList*>(&value))->getValues()) - { - ret += name + " += " + Util::escape(val) + "\n"; - } - return ret; - break; - } - default: - return name + " = " + Util::escape(value.value()) + "\n"; - } - } - else - { - throw ConfigException("Unknown config value \"" + name.toStdString() + "\""); - } -} - -void ConfigBase::addConfigListEntry(const QString &name, const QString &value) -{ - ConfigValueBase& configValue = getConfigValue(name); - if(configValue.type() != ConfigValueType::List) - { - throw ConfigException("Cannot add a list entry to a non-list-config value \"" + name.toStdString() + "\""); - } - ((ConfigValueList*)&configValue)->append(Util::unescape(value)); -} - -void ConfigBase::removeConfigMapListEntry(const QString &name, const QString &value) -{ - ConfigValueBase& configValue = getConfigValue(name); - if(configValue.type() == ConfigValueType::List) - { - ((ConfigValueList*)&configValue)->remove(Util::unescape(value)); - } - else if(configValue.type() == ConfigValueType::Map) - { - ((ConfigValueMap*)&configValue)->remove(Util::unescape(value)); - } - else - { - throw ConfigException("Cannot remove a list entry from a value which is neither a list nor a map \"" + name.toStdString() + "\""); - } -} - -void ConfigBase::setConfigMapValue(const QString &name, const QString &key, const QString &value) -{ - ConfigValueBase& configValue = getConfigValue(name); - if(configValue.type() != ConfigValueType::Map) - { - throw ConfigException("Cannot set a map value on a non-map-config value \"" + name.toStdString() + "\""); - } - ((ConfigValueMap*)&configValue)->setKeyValue(Util::unescape(key), Util::unescape(value)); -} - -ConfigValueBase& ConfigBase::getConfigValue(const QString& name) -{ - if(!configValues.contains(name)) - { - throw ConfigException("Unknown config value \"" + name.toStdString() + "\""); - } - else - { - return *configValues[name]; - } -} - -QString ConfigBase::read(const QString &fileName, bool writeDefault) -{ - curFileName = fileName; - QString ret = ""; - - QFile config(fileName); - if(!config.exists()) - { - if(writeDefault) - { - if(write(fileName)) - { - return fileName + ": The config-file did not exist, a new one with default values has been created.\n"; - } - else - { - return fileName + ": The config-file did not exist, a new one could not be created.\n"; - } - } - else - { - return ret; - } - } - else if(config.open(QIODevice::ReadOnly | QIODevice::Text)) - { - QString line; - for(size_t lineNr = 1; !config.atEnd(); ++lineNr) - { - try - { - line = config.readLine().trimmed(); - if(!line.isEmpty()) - { - setConfigLine(line); - } - } - catch(ConfigException e) - { - ret += fileName + ":" + QString::number(lineNr) + ": " + e.what() + "\n"; - } - } - } - else - { - return fileName + ": The config-file could not be read.\n"; - } - - return ret; -} - -bool ConfigBase::write(QString fileName) -{ - if(fileName.isEmpty()) - { - fileName = curFileName; - } - if(fileName.isEmpty()) - { - return false; - } - QFile config(fileName); - if(config.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) - { - foreach(const QString& key, configValues.keys()) - { - config.write(getConfigValueLine(key).toUtf8()); - } - - return true; - } - else - { - return false; - } -} - -void ConfigBase::setConfigLine(const QString &line) -{ - static QRegExp valueExp(R"(^([^=]+)=(.*)$)"); - static QRegExp listExp(R"(^([^=]+)\+=(.*)$)"); - static QRegExp listMapRemoveExp(R"(^([^=]+)\-=(.*)$)"); - static QRegExp mapExp(R"(^([^\[]+)\[((?:[^\]\\]|\\\]|\\\\)+)\]\s*=\s*(.*)$)"); - - if(listExp.exactMatch(line)) - { - addConfigListEntry(listExp.cap(1).trimmed(), listExp.cap(2).trimmed()); - } - else if(listMapRemoveExp.exactMatch(line)) - { - removeConfigMapListEntry(listMapRemoveExp.cap(1).trimmed(), listMapRemoveExp.cap(2).trimmed()); - } - else if(mapExp.exactMatch(line)) - { - setConfigMapValue(mapExp.cap(1).trimmed(), mapExp.cap(2).trimmed(), mapExp.cap(3).trimmed()); - } - else if(valueExp.exactMatch(line)) - { - setConfigValue(valueExp.cap(1).trimmed(), valueExp.cap(2).trimmed()); - } - else - { - throw ConfigException("Syntax error: unkown syntax"); - } -} diff --git a/src/ConfigBase.hpp b/src/ConfigBase.hpp deleted file mode 100644 index ade454a..0000000 --- a/src/ConfigBase.hpp +++ /dev/null @@ -1,330 +0,0 @@ -#ifndef CONFIGBASE -#define CONFIGBASE - -#include <QString> -#include <QStringList> -#include <QList> -#include <QMap> -#include <QRegularExpression> - -#include <exception> -#include <type_traits> -#include <limits> - -#include "Util.hpp" - -using ConfigException = std::logic_error; - -namespace ConfigValueType { -enum Type { - None, - String, - Integer, - Boolean, - List, - Map -}; -} - -class ConfigValueBase { -public: - - virtual void setValue(const QString&) { } - virtual QString value() { return ""; } - virtual ConfigValueType::Type type() { return ConfigValueType::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 ConfigValue : public ConfigValueBase { -public: - virtual void setValue(const QString&) { throw ConfigException("Cannot assign"); } - virtual QString value() { throw ConfigException("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 ConfigVal(Value) {#Value, mkConfigValue(Value)} -#define ConfigValEx(Value, ...) {#Value, mkConfigValue(Value, __VA_ARGS__)} - -template<> -class ConfigValue<String> : public ConfigValueBase { - String& config; - bool trimmedQuotes = false; - -public: - ConfigValue(String& config) : config(config) { } - - virtual void setValue(const QString& value) { config = Util::trimQuotes(value, trimmedQuotes); } - virtual QString value() - { - static QRegularExpression quoteExp(R"(^(\s.*|.*\s)$)"); - if(trimmedQuotes || quoteExp.match(config).hasMatch()) - { - return "\"" + config + "\""; - } - else - { - return config; - } - } - virtual ConfigValueType::Type type() { return ConfigValueType::Type::String; } -}; - -template<typename Type> -class ConfigValue<Type, typename std::enable_if<std::is_integral<Type>::value>::type> : public ConfigValueBase { - Type& config; - -public: - ConfigValue(Type& config) : config(config) { } - - virtual void setValue(const QString& value) - { - bool ok = true; - long long longLongVal = value.toLongLong(&ok, 0); - if(!ok) throw ConfigException("\"" + value.toStdString() + "\" could not be parsed as an Integer"); - if(longLongVal < std::numeric_limits<Type>::min() || longLongVal > std::numeric_limits<Type>::max()) throw ConfigException((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 ConfigValueType::Type type() { return ConfigValueType::Type::Integer; } -}; - -template<> -class ConfigValue<Boolean> : public ConfigValueBase { - Boolean& config; - -public: - ConfigValue(Boolean& config) : config(config) { } - - virtual void setValue(const QString& value) - { - if(value == "true") - { - config = true; - } - else if(value == "false") - { - config = false; - } - else - { - throw ConfigException("\"" + value.toStdString() + "\" could not be parsed as a Boolean"); - } - } - virtual QString value() { return config ? "true" : "false"; } - virtual ConfigValueType::Type type() { return ConfigValueType::Type::Boolean; } -}; - -class ConfigValueList : public ConfigValueBase { -public: - virtual void append(const QString& entry) = 0; - virtual void remove(const QString& entry) = 0; - virtual QStringList getValues() = 0; -}; - -class ConfigValueMap : public ConfigValueBase { -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 ConfigValue<QList<Type>> : public ConfigValueList { - using ListType = QList<Type>; - - ListType& config; - const bool deduplicate; - const QChar splitChar; - -public: - ConfigValue(ListType& config, bool deduplicate = true, const QChar splitChar = ';') : config(config), deduplicate(deduplicate), splitChar(splitChar) {} - - virtual ListType& list() { return config; } - virtual ConfigValueType::Type type() { return ConfigValueType::Type::List; } - - virtual void append(const QString &entry) - { - Type val = ConfigValueBase::getValue<Type>(entry); - if(!deduplicate || !config.contains(val)) - { - config.append(val); - } - } - - virtual void remove(const QString &entry) { config.removeAll(ConfigValueBase::getValue<Type>(entry)); } - - virtual QStringList getValues() - { - QStringList ret; - - foreach(Type val, config) - { - ret.append(ConfigValueBase::getStringValue(val)); - } - - return ret; - } - - void setValue(const QString& value) - { - config.clear(); - if(value.isEmpty()) - { - return; - } - QStringList parts = Util::splitEscaped(value, splitChar); - foreach(const QString& part, parts) - { - config.append(ConfigValueBase::getValue<Type>(part)); - } - } - - QString value() - { - QStringList parts; - foreach(const Type& part, config) - { - parts.append(ConfigValueBase::getStringValue(part)); - } - return Util::joinEscape(parts, splitChar); - } -}; - -template<typename KeyType, typename ValueType> -class ConfigValue<QMap<KeyType, ValueType>> : public ConfigValueMap { - using MapType = QMap<KeyType, ValueType>; - - MapType& config; - const QChar assignChar; - const QChar splitChar; - -public: - ConfigValue(MapType& config, const QChar assignChar = ':', const QChar splitChar = ';') : config(config), assignChar(assignChar), splitChar(splitChar) {} - - virtual MapType& map() { return config; } - virtual ConfigValueType::Type type() { return ConfigValueType::Type::Map; } - - virtual void setKeyValue(const QString& key, const QString& value) - { - config[ConfigValueBase::getValue<KeyType>(key)] = ConfigValueBase::getValue<ValueType>(value); - } - - virtual QMap<QString, QString> getValues() - { - QMap<QString, QString> ret; - - foreach(KeyType key, config.keys()) - { - ret[ConfigValueBase::getStringValue(key)] = ConfigValueBase::getStringValue(config[key]); - } - - return ret; - } - - virtual void remove(const QString &key) - { - config.remove(ConfigValueBase::getValue<KeyType>(key)); - } - - QString value() - { - QStringList ret; - foreach(const KeyType& key, config.keys()) - { - ret.append(Util::joinEscape({ConfigValueBase::getStringValue(key), ConfigValueBase::getStringValue(config.value(key))}, assignChar)); - } - return Util::joinEscape(ret, splitChar); - } - - void setValue(const QString& value) - { - config.clear(); - if(value.isEmpty()) - { - return; - } - QStringList parts = Util::splitEscaped(value, splitChar); - foreach(const QString& part, parts) - { - QStringList parts = Util::splitEscaped(part, assignChar); - if(parts.length() != 2) - { - throw ConfigException("Cannot parse corrupt map key-value-pair"); - } - config[ConfigValueBase::getValue<KeyType>(parts.first())] = ConfigValueBase::getValue<ValueType>(parts.at(1)); - } - } -}; - -template<typename Type> -class ConfigValue<Type, typename std::enable_if<std::is_enum<Type>::value>::type> : public ConfigValue<typename std::underlying_type<Type>::type> { - using UndType = typename std::underlying_type<Type>::type; -public: - ConfigValue(Type& config) : ConfigValue<UndType>::ConfigValue((UndType&)config) {} -}; - -template<typename Type, typename... Types> -ConfigValue<Type>* mkConfigValue(Type& Value, Types... values) -{ - return new ConfigValue<Type>(Value, values...); -} - -template<typename Type> -Type ConfigValueBase::getValue(const QString& value) -{ - Type ret; - ConfigValue<Type> val(ret); - val.setValue(value); - return ret; -} - -template<typename Type> -QString ConfigValueBase::getStringValue(Type value) -{ - ConfigValue<Type> val(value); - return val.value(); -} - -class ConfigBase -{ -public: - explicit ConfigBase(QMap<QString, ConfigValueBase*> 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(QString fileName = ""); - - void setConfigLine(const QString& line); - -protected: - void addConfigValue(QString name, ConfigValueBase *value); - ConfigValueBase& getConfigValue(const QString &name); - - QMap<QString, ConfigValueBase*> configValues; - -private: - QString curFileName = ""; -}; - -#endif // CONFIGBASE - diff --git a/src/CrServerManager.pro b/src/CrServerManager.pro index cca74e8..786c8a9 100644 --- a/src/CrServerManager.pro +++ b/src/CrServerManager.pro @@ -20,7 +20,7 @@ TEMPLATE = app SOURCES += main.cpp \ crsm.cpp \ ProcessManager.cpp \ - ConfigBase.cpp \ + qt-config/ConfigBase.cpp \ Util.cpp \ CRSMStats.cpp \ CRSMPackCompatibility.cpp \ @@ -32,7 +32,7 @@ HEADERS += \ crsm.hpp \ ProcessManager.hpp \ CRSMConfig.hpp \ - ConfigBase.hpp \ + qt-config/ConfigBase.hpp \ Util.hpp \ CRSMStats.hpp \ CRSMPackCompatibility.hpp \ diff --git a/src/Util.cpp b/src/Util.cpp index 41500da..bbc718a 100644..120000 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -1,191 +1 @@ -#include "Util.hpp" - -#include <QRegularExpression> - -namespace Util { - QString trimQuotes(QString string, bool& trimmed) - { - if(string.isEmpty()) return string; - - 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; - } - - QString unescape(const QString &string, const QChar escapeChar) - { - if(string.isEmpty()) return string; - QString ret; - bool escaped = false; - QChar c = string.at(0); - for(int i = 0; i < string.length(); ++i) - { - c = string.at(i); - if(!escaped) - { - if(c == escapeChar) - { - escaped = true; - continue; - } - else - { - ret.append(c); - } - } - else - { - if(unescapeChars.contains(c)) - { - ret.append(unescapeChars.value(c)); - } - else - { - ret.append(c); - } - escaped = false; - } - } - if(escaped) - { - ret.append(escapeChar); - } - return ret; - } - - QString escape(const QString &string, const QChar escapeChar, const QString &escapeChars) - { - QString ret; - - for(int i = 0; i < string.length(); ++i) - { - QChar c = string.at(i); - - if(c == escapeChar) - { - ret.append(escapeChar); - ret.append(escapeChar); - } - else if(escapeChars.contains(c)) - { - ret.append(escapeChar); - ret.append(c); - } - else if(unescapeChars.values().contains(c)) - { - ret.append(unescapeChars.key(c)); - } - else - { - ret.append(c); - } - } - - return ret; - } - - QString joinEscape(const QStringList &list, const QChar joinChar, const QChar escapeChar) - { - QString ret; - bool first = true; - foreach(const QString& part, list) - { - if(!first) - { - ret.append(joinChar); - } - else - { - first = false; - } - ret.append(escape(part, escapeChar, joinChar)); - } - return ret; - } - - QStringList splitEscaped(const QString &joined, const QChar splitChar, const QChar escapeChar) - { - QStringList ret; - - int partPos = 0; - bool escaped = false; - for(int i = 0; i < joined.length(); ++i) - { - QChar c = joined.at(i); - if(!escaped) - { - if(c == escapeChar) - { - escaped = true; - } - else if(c == splitChar) - { - ret.append(Util::unescape(joined.mid(partPos, i - partPos), escapeChar)); - partPos = i + 1; - } - } - else - { - escaped = false; - } - } - ret.append(Util::unescape(joined.mid(partPos), escapeChar)); - - return ret; - } - - QString& unescapeClonkString(QString&& string) - { - static QRegularExpression escapeExp(R"(\\[0-7]+)"); - QRegularExpressionMatch match; - while((match = escapeExp.match(string)).hasMatch()) - { - unsigned char c = (unsigned char)match.capturedRef(0).mid(1).toInt(0, 8); - - string.replace(match.capturedStart(), match.capturedLength(), c); - } - return string; - } - - int indexOfEscaped(const QString& string, const QChar subject, int startPos, const QChar escapeChar) - { - if(string.isEmpty()) - { - return -1; - } - if(startPos < 0) - { - startPos += string.length(); - } - bool escaped = false; - for(int pos = startPos; pos < string.length(); ++pos) - { - QChar c = string.at(pos); - if(!escaped) - { - if(c == escapeChar) - { - escaped = true; - continue; - } - else - { - if(c == subject) - { - return pos; - } - } - } - else - { - escaped = false; - } - } - return -1; - } -} +qt-config/Util.cpp
\ No newline at end of file diff --git a/src/Util.hpp b/src/Util.hpp index f90e108..bcc063c 100644..120000 --- a/src/Util.hpp +++ b/src/Util.hpp @@ -1,18 +1 @@ -#pragma once - -#include <QString> -#include <QMap> - -namespace Util { - static const QMap<QChar, QChar> unescapeChars { - {'n', '\n'}, - }; - - QString trimQuotes(QString string, bool& trimmed); - QString unescape(const QString& string, const QChar escapeChar = '\\'); - QString escape(const QString& string, const QChar escapeChar = '\\', const QString& escapeChars = ""); - QString joinEscape(const QStringList& list, const QChar joinChar, const QChar escapeChar = '\\'); - QStringList splitEscaped(const QString& joined, const QChar splitChar, const QChar escapeChar = '\\'); - QString& unescapeClonkString(QString&& string); - int indexOfEscaped(const QString& string, const QChar subject, int startPos = 0, const QChar escapeChar = '\\'); -} +qt-config/Util.hpp
\ No newline at end of file diff --git a/src/qt-config b/src/qt-config new file mode 160000 +Subproject 11a2c0f3e7fe3eff64fdd9ffb40727412e0d221 |
