diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | launcher/CMakeLists.txt | 1 | ||||
-rw-r--r-- | launcher/minecraft/mod/tasks/LocalModParseTask.cpp | 41 | ||||
-rw-r--r-- | libraries/README.md | 8 | ||||
-rw-r--r-- | libraries/qdcss/CMakeLists.txt | 18 | ||||
-rw-r--r-- | libraries/qdcss/include/qdcss.h | 21 | ||||
-rw-r--r-- | libraries/qdcss/src/qdcss.cpp | 49 |
7 files changed, 111 insertions, 28 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 37bb49ba..6ce8143c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -448,6 +448,7 @@ if (NOT ghc_filesystem_FOUND) else() message(STATUS "Using system ghc_filesystem") endif() +add_subdirectory(libraries/qdcss) # css parser ############################### Built Artifacts ############################### diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 1bfe9cbc..c6b9e380 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1025,6 +1025,7 @@ target_link_libraries(Launcher_logic nbt++ ${ZLIB_LIBRARIES} tomlplusplus::tomlplusplus + qdcss BuildConfig Katabasis Qt${QT_VERSION_MAJOR}::Widgets diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp index 03b599ea..2263f8ec 100644 --- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp @@ -3,6 +3,7 @@ #include <quazip/quazip.h> #include <quazip/quazipfile.h> #include <toml++/toml.h> +#include <qdcss.h> #include <QJsonArray> #include <QJsonDocument> #include <QJsonObject> @@ -290,37 +291,21 @@ ModDetails ReadNilModInfo(QByteArray contents, QString fname) { ModDetails details; - // this is a css file (why) but we only care about a couple key/value pairs from it - // hence this instead of a css parser lib - // could be made a lot better but it works(tm) - // (does css require properties to be on their own lines? if so, the code can get less horrible looking) - QString contentStr = QString(contents).trimmed(); - int firstidx = contentStr.indexOf("@nilmod"); - firstidx = contentStr.indexOf("{", firstidx); - int lastidx = contentStr.indexOf("}", firstidx); - int nameidx = contentStr.indexOf("name:", firstidx); - int descidx = contentStr.indexOf("description:", firstidx); - int authorsidx = contentStr.indexOf("authors:", firstidx); - int versionidx = contentStr.indexOf("version:", firstidx); - - if (nameidx != -1 && nameidx < lastidx) { - nameidx = contentStr.indexOf('"', nameidx); - details.name = contentStr.mid(nameidx + 1, contentStr.indexOf('"', nameidx + 1) - nameidx - 1); - } - if (descidx != -1 && descidx < lastidx) { - descidx = contentStr.indexOf('"', descidx); - details.description = contentStr.mid(descidx + 1, contentStr.indexOf('"', descidx + 1) - descidx - 1); + QDCSS cssData = QDCSS(contents); + auto name = cssData.get("@nilmod.name"); + auto desc = cssData.get("@nilmod.description"); + auto authors = cssData.get("@nilmod.authors"); + + if (name->has_value()) { + details.name = name->value(); } - if (authorsidx != -1 && authorsidx < lastidx) { - authorsidx = contentStr.indexOf('"', authorsidx); - details.authors.append(contentStr.mid(authorsidx + 1, contentStr.indexOf('"', authorsidx + 1) - authorsidx - 1)); + if (desc->has_value()) { + details.description = desc->value(); } - if (versionidx != -1 && versionidx < lastidx) { - versionidx = contentStr.indexOf('"', versionidx); - details.version = contentStr.mid(versionidx + 1, contentStr.indexOf('"', versionidx + 1) - versionidx - 1); - } else { - details.version = "?"; + if (authors->has_value()) { + details.authors.append(authors->value()); } + details.version = cssData.get("@nilmod.version")->value_or("?"); details.mod_id = fname.remove(".nilmod.css"); diff --git a/libraries/README.md b/libraries/README.md index 95be8740..4da11314 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -140,3 +140,11 @@ A TOML language parser. Used by Forge 1.14+ to store mod metadata. See [github repo](https://github.com/marzer/tomlplusplus). Licenced under the MIT licence. + +## qdcss + +A quick and dirty css parser, used by NilLoader to store mod metadata. + +Translated (and heavily trimmed down) from [the original Java code](https://github.com/unascribed/NilLoader/blob/trunk/src/main/java/nilloader/api/lib/qdcss/QDCSS.java) from NilLoader + +Licensed under LGPL version 3. diff --git a/libraries/qdcss/CMakeLists.txt b/libraries/qdcss/CMakeLists.txt new file mode 100644 index 00000000..0afdef32 --- /dev/null +++ b/libraries/qdcss/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.9.4) +project(qdcss) + +if(QT_VERSION_MAJOR EQUAL 5) + find_package(Qt5 COMPONENTS Core REQUIRED) +elseif(Launcher_QT_VERSION_MAJOR EQUAL 6) + find_package(Qt6 COMPONENTS Core Core5Compat REQUIRED) + list(APPEND qdcss_LIBS Qt${QT_VERSION_MAJOR}::Core5Compat) +endif() + +set(QDCSS_SOURCES + include/qdcss.h + src/qdcss.cpp +) + +add_library(qdcss STATIC ${QDCSS_SOURCES}) +target_include_directories(qdcss PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(qdcss Qt${QT_VERSION_MAJOR}::Core ${qdcss_LIBS}) diff --git a/libraries/qdcss/include/qdcss.h b/libraries/qdcss/include/qdcss.h new file mode 100644 index 00000000..2bcac36f --- /dev/null +++ b/libraries/qdcss/include/qdcss.h @@ -0,0 +1,21 @@ +#ifndef QDCSS_H +#define QDCSS_H + +#include <QMap> +#include <QString> +#include <QStringList> +#include <optional> + +class QDCSS { + // these are all we need to parse a couple string values out of a css string + // lots more in the original code, yet to be ported + // https://github.com/unascribed/NilLoader/blob/trunk/src/main/java/nilloader/api/lib/qdcss/QDCSS.java + public: + QDCSS(QString); + std::optional<QString>* get(QString); + + private: + QMap<QString, QStringList> m_data; +}; + +#endif // QDCSS_H diff --git a/libraries/qdcss/src/qdcss.cpp b/libraries/qdcss/src/qdcss.cpp new file mode 100644 index 00000000..4426dcae --- /dev/null +++ b/libraries/qdcss/src/qdcss.cpp @@ -0,0 +1,49 @@ +#include "qdcss.h" + +#include <QRegularExpression> +#include <QRegularExpressionMatch> +#include <QRegularExpressionMatchIterator> + +QRegularExpression ruleset_re = QRegularExpression(R"([#.]?(@?\w+?)\s*\{(.*?)\})", QRegularExpression::DotMatchesEverythingOption); +QRegularExpression rule_re = QRegularExpression(R"((\S+?)\s*:\s*(?:\"(.*?)(?<!\\)\"|'(.*?)(?<!\\)'|(\S+?))\s*(?:;|$))"); + +QDCSS::QDCSS(QString s) +{ + // not much error handling over here... + // the original java code used indeces returned by the matcher for them, but QRE does not expose those + QRegularExpressionMatchIterator ruleset_i = ruleset_re.globalMatch(s); + while (ruleset_i.hasNext()) { + QRegularExpressionMatch ruleset = ruleset_i.next(); + QString selector = ruleset.captured(1); + QString rules = ruleset.captured(2); + QRegularExpressionMatchIterator rule_i = rule_re.globalMatch(rules); + while (rule_i.hasNext()) { + QRegularExpressionMatch rule = rule_i.next(); + QString property = rule.captured(1); + QString value; + if (!rule.captured(2).isNull()) { + value = rule.captured(2); + } else if (!rule.captured(3).isNull()) { + value = rule.captured(3); + } else { + value = rule.captured(4); + } + QString key = selector + "." + property; + if (!m_data.contains(key)) { + m_data.insert(key, QStringList()); + } + m_data.find(key)->append(value); + } + } +} + +std::optional<QString>* QDCSS::get(QString key) +{ + auto found = m_data.find(key); + + if (found == m_data.end() || found->empty()) { + return new std::optional<QString>; + } + + return new std::optional<QString>(found->back()); +} |