aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--launcher/CMakeLists.txt1
-rw-r--r--launcher/minecraft/mod/tasks/LocalModParseTask.cpp41
-rw-r--r--libraries/README.md8
-rw-r--r--libraries/qdcss/CMakeLists.txt18
-rw-r--r--libraries/qdcss/include/qdcss.h21
-rw-r--r--libraries/qdcss/src/qdcss.cpp49
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());
+}