Replaced tomlc99 with tomlplusplus
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
parent
c6bcb6228b
commit
600c49f7f0
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -6,3 +6,7 @@
|
|||||||
[submodule "libraries/quazip"]
|
[submodule "libraries/quazip"]
|
||||||
path = libraries/quazip
|
path = libraries/quazip
|
||||||
url = https://github.com/stachenov/quazip.git
|
url = https://github.com/stachenov/quazip.git
|
||||||
|
[submodule "libraries/tomlplusplus"]
|
||||||
|
path = libraries/tomlplusplus
|
||||||
|
url = https://github.com/marzer/tomlplusplus.git
|
||||||
|
shallow = true
|
||||||
|
@ -312,7 +312,7 @@ endif()
|
|||||||
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
||||||
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
||||||
add_subdirectory(libraries/classparser) # class parser library
|
add_subdirectory(libraries/classparser) # class parser library
|
||||||
add_subdirectory(libraries/tomlc99) # toml parser
|
add_subdirectory(libraries/tomlplusplus) # toml parser
|
||||||
add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much
|
add_subdirectory(libraries/katabasis) # An OAuth2 library that tried to do too much
|
||||||
add_subdirectory(libraries/gamemode)
|
add_subdirectory(libraries/gamemode)
|
||||||
add_subdirectory(libraries/murmur2) # Hash for usage with the CurseForge API
|
add_subdirectory(libraries/murmur2) # Hash for usage with the CurseForge API
|
||||||
|
30
COPYING.md
30
COPYING.md
@ -315,30 +315,24 @@
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
## tomlc99
|
## tomlplusplus
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 CK Tan
|
Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
|
||||||
https://github.com/cktan/tomlc99
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
||||||
in the Software without restriction, including without limitation the rights
|
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
||||||
copies or substantial portions of the Software.
|
Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
## O2 (Katabasis fork)
|
## O2 (Katabasis fork)
|
||||||
|
|
||||||
|
@ -965,7 +965,7 @@ target_link_libraries(Launcher_logic
|
|||||||
Launcher_murmur2
|
Launcher_murmur2
|
||||||
nbt++
|
nbt++
|
||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
tomlc99
|
tomlplusplus::tomlplusplus
|
||||||
BuildConfig
|
BuildConfig
|
||||||
Katabasis
|
Katabasis
|
||||||
Qt${QT_VERSION_MAJOR}::Widgets
|
Qt${QT_VERSION_MAJOR}::Widgets
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
#include "LocalModParseTask.h"
|
#include "LocalModParseTask.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonValue>
|
|
||||||
#include <QString>
|
|
||||||
#include <quazip/quazip.h>
|
#include <quazip/quazip.h>
|
||||||
#include <quazip/quazipfile.h>
|
#include <quazip/quazipfile.h>
|
||||||
#include <toml.h>
|
#include <toml++/toml.h>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "FileSystem.h"
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include "settings/INIFile.h"
|
#include "settings/INIFile.h"
|
||||||
#include "FileSystem.h"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -22,8 +22,7 @@ namespace {
|
|||||||
// https://github.com/MinecraftForge/FML/wiki/FML-mod-information-file/5bf6a2d05145ec79387acc0d45c958642fb049fc
|
// https://github.com/MinecraftForge/FML/wiki/FML-mod-information-file/5bf6a2d05145ec79387acc0d45c958642fb049fc
|
||||||
ModDetails ReadMCModInfo(QByteArray contents)
|
ModDetails ReadMCModInfo(QByteArray contents)
|
||||||
{
|
{
|
||||||
auto getInfoFromArray = [&](QJsonArray arr) -> ModDetails
|
auto getInfoFromArray = [&](QJsonArray arr) -> ModDetails {
|
||||||
{
|
|
||||||
if (!arr.at(0).isObject()) {
|
if (!arr.at(0).isObject()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -32,16 +31,14 @@ ModDetails ReadMCModInfo(QByteArray contents)
|
|||||||
details.mod_id = firstObj.value("modid").toString();
|
details.mod_id = firstObj.value("modid").toString();
|
||||||
auto name = firstObj.value("name").toString();
|
auto name = firstObj.value("name").toString();
|
||||||
// NOTE: ignore stupid example mods copies where the author didn't even bother to change the name
|
// NOTE: ignore stupid example mods copies where the author didn't even bother to change the name
|
||||||
if(name != "Example Mod") {
|
if (name != "Example Mod") {
|
||||||
details.name = name;
|
details.name = name;
|
||||||
}
|
}
|
||||||
details.version = firstObj.value("version").toString();
|
details.version = firstObj.value("version").toString();
|
||||||
auto homeurl = firstObj.value("url").toString().trimmed();
|
auto homeurl = firstObj.value("url").toString().trimmed();
|
||||||
if(!homeurl.isEmpty())
|
if (!homeurl.isEmpty()) {
|
||||||
{
|
|
||||||
// fix up url.
|
// fix up url.
|
||||||
if (!homeurl.startsWith("http://") && !homeurl.startsWith("https://") && !homeurl.startsWith("ftp://"))
|
if (!homeurl.startsWith("http://") && !homeurl.startsWith("https://") && !homeurl.startsWith("ftp://")) {
|
||||||
{
|
|
||||||
homeurl.prepend("http://");
|
homeurl.prepend("http://");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,8 +50,7 @@ ModDetails ReadMCModInfo(QByteArray contents)
|
|||||||
authors = firstObj.value("authors").toArray();
|
authors = firstObj.value("authors").toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto author: authors)
|
for (auto author : authors) {
|
||||||
{
|
|
||||||
details.authors.append(author.toString());
|
details.authors.append(author.toString());
|
||||||
}
|
}
|
||||||
return details;
|
return details;
|
||||||
@ -62,14 +58,11 @@ ModDetails ReadMCModInfo(QByteArray contents)
|
|||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
|
||||||
// this is the very old format that had just the array
|
// this is the very old format that had just the array
|
||||||
if (jsonDoc.isArray())
|
if (jsonDoc.isArray()) {
|
||||||
{
|
|
||||||
return getInfoFromArray(jsonDoc.array());
|
return getInfoFromArray(jsonDoc.array());
|
||||||
}
|
} else if (jsonDoc.isObject()) {
|
||||||
else if (jsonDoc.isObject())
|
|
||||||
{
|
|
||||||
auto val = jsonDoc.object().value("modinfoversion");
|
auto val = jsonDoc.object().value("modinfoversion");
|
||||||
if(val.isUndefined()) {
|
if (val.isUndefined()) {
|
||||||
val = jsonDoc.object().value("modListVersion");
|
val = jsonDoc.object().value("modListVersion");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,18 +72,16 @@ ModDetails ReadMCModInfo(QByteArray contents)
|
|||||||
if (version < 0)
|
if (version < 0)
|
||||||
version = Json::ensureString(val, "").toInt();
|
version = Json::ensureString(val, "").toInt();
|
||||||
|
|
||||||
if (version != 2)
|
if (version != 2) {
|
||||||
{
|
|
||||||
qCritical() << "BAD stuff happened to mod json:";
|
qCritical() << "BAD stuff happened to mod json:";
|
||||||
qCritical() << contents;
|
qCritical() << contents;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
auto arrVal = jsonDoc.object().value("modlist");
|
auto arrVal = jsonDoc.object().value("modlist");
|
||||||
if(arrVal.isUndefined()) {
|
if (arrVal.isUndefined()) {
|
||||||
arrVal = jsonDoc.object().value("modList");
|
arrVal = jsonDoc.object().value("modList");
|
||||||
}
|
}
|
||||||
if (arrVal.isArray())
|
if (arrVal.isArray()) {
|
||||||
{
|
|
||||||
return getInfoFromArray(arrVal.toArray());
|
return getInfoFromArray(arrVal.toArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,109 +93,77 @@ ModDetails ReadMCModTOML(QByteArray contents)
|
|||||||
{
|
{
|
||||||
ModDetails details;
|
ModDetails details;
|
||||||
|
|
||||||
char errbuf[200];
|
// auto tomlData = toml::parse(contents.toStdString());
|
||||||
// top-level table
|
toml::table tomlData;
|
||||||
toml_table_t* tomlData = toml_parse(contents.data(), errbuf, sizeof(errbuf));
|
#if TOML_EXCEPTIONS
|
||||||
|
try {
|
||||||
if(!tomlData)
|
tomlData = toml::parse(contents.toStdString());
|
||||||
{
|
} catch (const toml::parse_error& err) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
tomlData = toml::parse(contents.toStdString());
|
||||||
|
if (!tomlData) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// array defined by [[mods]]
|
// array defined by [[mods]]
|
||||||
toml_array_t* tomlModsArr = toml_array_in(tomlData, "mods");
|
auto tomlModsArr = tomlData["mods"].as_array();
|
||||||
if(!tomlModsArr)
|
if (!tomlModsArr) {
|
||||||
{
|
|
||||||
qWarning() << "Corrupted mods.toml? Couldn't find [[mods]] array!";
|
qWarning() << "Corrupted mods.toml? Couldn't find [[mods]] array!";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only really care about the first element, since multiple mods in one file is not supported by us at the moment
|
// we only really care about the first element, since multiple mods in one file is not supported by us at the moment
|
||||||
toml_table_t* tomlModsTable0 = toml_table_at(tomlModsArr, 0);
|
auto tomlModsTable0 = tomlModsArr->get(0);
|
||||||
if(!tomlModsTable0)
|
if (!tomlModsTable0) {
|
||||||
{
|
|
||||||
qWarning() << "Corrupted mods.toml? [[mods]] didn't have an element at index 0!";
|
qWarning() << "Corrupted mods.toml? [[mods]] didn't have an element at index 0!";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
auto modsTable = tomlModsTable0->as_table();
|
||||||
|
if (!tomlModsTable0) {
|
||||||
|
qWarning() << "Corrupted mods.toml? [[mods]] was not a table!";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
// mandatory properties - always in [[mods]]
|
// mandatory properties - always in [[mods]]
|
||||||
toml_datum_t modIdDatum = toml_string_in(tomlModsTable0, "modId");
|
if (auto modIdDatum = (*modsTable)["modId"].as_string()) {
|
||||||
if(modIdDatum.ok)
|
details.mod_id = QString::fromStdString(modIdDatum->get());
|
||||||
{
|
|
||||||
details.mod_id = modIdDatum.u.s;
|
|
||||||
// library says this is required for strings
|
|
||||||
free(modIdDatum.u.s);
|
|
||||||
}
|
}
|
||||||
toml_datum_t versionDatum = toml_string_in(tomlModsTable0, "version");
|
if (auto versionDatum = (*modsTable)["version"].as_string()) {
|
||||||
if(versionDatum.ok)
|
details.version = QString::fromStdString(versionDatum->get());
|
||||||
{
|
|
||||||
details.version = versionDatum.u.s;
|
|
||||||
free(versionDatum.u.s);
|
|
||||||
}
|
}
|
||||||
toml_datum_t displayNameDatum = toml_string_in(tomlModsTable0, "displayName");
|
if (auto displayNameDatum = (*modsTable)["displayName"].as_string()) {
|
||||||
if(displayNameDatum.ok)
|
details.name = QString::fromStdString(displayNameDatum->get());
|
||||||
{
|
|
||||||
details.name = displayNameDatum.u.s;
|
|
||||||
free(displayNameDatum.u.s);
|
|
||||||
}
|
}
|
||||||
toml_datum_t descriptionDatum = toml_string_in(tomlModsTable0, "description");
|
if (auto descriptionDatum = (*modsTable)["description"].as_string()) {
|
||||||
if(descriptionDatum.ok)
|
details.description = QString::fromStdString(descriptionDatum->get());
|
||||||
{
|
|
||||||
details.description = descriptionDatum.u.s;
|
|
||||||
free(descriptionDatum.u.s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional properties - can be in the root table or [[mods]]
|
// optional properties - can be in the root table or [[mods]]
|
||||||
toml_datum_t authorsDatum = toml_string_in(tomlData, "authors");
|
|
||||||
QString authors = "";
|
QString authors = "";
|
||||||
if(authorsDatum.ok)
|
if (auto authorsDatum = tomlData["authors"].as_string()) {
|
||||||
{
|
authors = QString::fromStdString(authorsDatum->get());
|
||||||
authors = authorsDatum.u.s;
|
} else if (auto authorsDatum = (*modsTable)["authors"].as_string()) {
|
||||||
free(authorsDatum.u.s);
|
authors = QString::fromStdString(authorsDatum->get());
|
||||||
}
|
}
|
||||||
else
|
if (!authors.isEmpty()) {
|
||||||
{
|
|
||||||
authorsDatum = toml_string_in(tomlModsTable0, "authors");
|
|
||||||
if(authorsDatum.ok)
|
|
||||||
{
|
|
||||||
authors = authorsDatum.u.s;
|
|
||||||
free(authorsDatum.u.s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!authors.isEmpty())
|
|
||||||
{
|
|
||||||
details.authors.append(authors);
|
details.authors.append(authors);
|
||||||
}
|
}
|
||||||
|
|
||||||
toml_datum_t homeurlDatum = toml_string_in(tomlData, "displayURL");
|
|
||||||
QString homeurl = "";
|
QString homeurl = "";
|
||||||
if(homeurlDatum.ok)
|
if (auto homeurlDatum = tomlData["displayURL"].as_string()) {
|
||||||
{
|
homeurl = QString::fromStdString(homeurlDatum->get());
|
||||||
homeurl = homeurlDatum.u.s;
|
} else if (auto homeurlDatum = (*modsTable)["displayURL"].as_string()) {
|
||||||
free(homeurlDatum.u.s);
|
homeurl = QString::fromStdString(homeurlDatum->get());
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
homeurlDatum = toml_string_in(tomlModsTable0, "displayURL");
|
|
||||||
if(homeurlDatum.ok)
|
|
||||||
{
|
|
||||||
homeurl = homeurlDatum.u.s;
|
|
||||||
free(homeurlDatum.u.s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!homeurl.isEmpty())
|
|
||||||
{
|
|
||||||
// fix up url.
|
// fix up url.
|
||||||
if (!homeurl.startsWith("http://") && !homeurl.startsWith("https://") && !homeurl.startsWith("ftp://"))
|
if (!homeurl.isEmpty() && !homeurl.startsWith("http://") && !homeurl.startsWith("https://") && !homeurl.startsWith("ftp://")) {
|
||||||
{
|
|
||||||
homeurl.prepend("http://");
|
homeurl.prepend("http://");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
details.homeurl = homeurl;
|
details.homeurl = homeurl;
|
||||||
|
|
||||||
// this seems to be recursive, so it should free everything
|
|
||||||
toml_free(tomlData);
|
|
||||||
|
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,25 +183,20 @@ ModDetails ReadFabricModInfo(QByteArray contents)
|
|||||||
details.name = object.contains("name") ? object.value("name").toString() : details.mod_id;
|
details.name = object.contains("name") ? object.value("name").toString() : details.mod_id;
|
||||||
details.description = object.value("description").toString();
|
details.description = object.value("description").toString();
|
||||||
|
|
||||||
if (schemaVersion >= 1)
|
if (schemaVersion >= 1) {
|
||||||
{
|
|
||||||
QJsonArray authors = object.value("authors").toArray();
|
QJsonArray authors = object.value("authors").toArray();
|
||||||
for (auto author: authors)
|
for (auto author : authors) {
|
||||||
{
|
if (author.isObject()) {
|
||||||
if(author.isObject()) {
|
|
||||||
details.authors.append(author.toObject().value("name").toString());
|
details.authors.append(author.toObject().value("name").toString());
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
details.authors.append(author.toString());
|
details.authors.append(author.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object.contains("contact"))
|
if (object.contains("contact")) {
|
||||||
{
|
|
||||||
QJsonObject contact = object.value("contact").toObject();
|
QJsonObject contact = object.value("contact").toObject();
|
||||||
|
|
||||||
if (contact.contains("homepage"))
|
if (contact.contains("homepage")) {
|
||||||
{
|
|
||||||
details.homeurl = contact.value("homepage").toString();
|
details.homeurl = contact.value("homepage").toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,8 +215,7 @@ ModDetails ReadQuiltModInfo(QByteArray contents)
|
|||||||
ModDetails details;
|
ModDetails details;
|
||||||
|
|
||||||
// https://github.com/QuiltMC/rfcs/blob/be6ba280d785395fefa90a43db48e5bfc1d15eb4/specification/0002-quilt.mod.json.md
|
// https://github.com/QuiltMC/rfcs/blob/be6ba280d785395fefa90a43db48e5bfc1d15eb4/specification/0002-quilt.mod.json.md
|
||||||
if (schemaVersion == 1)
|
if (schemaVersion == 1) {
|
||||||
{
|
|
||||||
auto modInfo = Json::requireObject(object.value("quilt_loader"), "Quilt mod info");
|
auto modInfo = Json::requireObject(object.value("quilt_loader"), "Quilt mod info");
|
||||||
|
|
||||||
details.mod_id = Json::requireString(modInfo.value("id"), "Mod ID");
|
details.mod_id = Json::requireString(modInfo.value("id"), "Mod ID");
|
||||||
@ -280,8 +233,7 @@ ModDetails ReadQuiltModInfo(QByteArray contents)
|
|||||||
|
|
||||||
auto modContact = Json::ensureObject(modMetadata.value("contact"));
|
auto modContact = Json::ensureObject(modMetadata.value("contact"));
|
||||||
|
|
||||||
if (modContact.contains("homepage"))
|
if (modContact.contains("homepage")) {
|
||||||
{
|
|
||||||
details.homeurl = Json::requireString(modContact.value("homepage"));
|
details.homeurl = Json::requireString(modContact.value("homepage"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,21 +266,17 @@ ModDetails ReadLiteModInfo(QByteArray contents)
|
|||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
|
||||||
auto object = jsonDoc.object();
|
auto object = jsonDoc.object();
|
||||||
if (object.contains("name"))
|
if (object.contains("name")) {
|
||||||
{
|
|
||||||
details.mod_id = details.name = object.value("name").toString();
|
details.mod_id = details.name = object.value("name").toString();
|
||||||
}
|
}
|
||||||
if (object.contains("version"))
|
if (object.contains("version")) {
|
||||||
{
|
|
||||||
details.version = object.value("version").toString("");
|
details.version = object.value("version").toString("");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
details.version = object.value("revision").toString("");
|
details.version = object.value("revision").toString("");
|
||||||
}
|
}
|
||||||
details.mcversion = object.value("mcversion").toString();
|
details.mcversion = object.value("mcversion").toString();
|
||||||
auto author = object.value("author").toString();
|
auto author = object.value("author").toString();
|
||||||
if(!author.isEmpty()) {
|
if (!author.isEmpty()) {
|
||||||
details.authors.append(author);
|
details.authors.append(author);
|
||||||
}
|
}
|
||||||
details.description = object.value("description").toString();
|
details.description = object.value("description").toString();
|
||||||
@ -336,14 +284,10 @@ ModDetails ReadLiteModInfo(QByteArray contents)
|
|||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
LocalModParseTask::LocalModParseTask(int token, ResourceType type, const QFileInfo& modFile):
|
LocalModParseTask::LocalModParseTask(int token, ResourceType type, const QFileInfo& modFile)
|
||||||
Task(nullptr, false),
|
: Task(nullptr, false), m_token(token), m_type(type), m_modFile(modFile), m_result(new Result())
|
||||||
m_token(token),
|
|
||||||
m_type(type),
|
|
||||||
m_modFile(modFile),
|
|
||||||
m_result(new Result())
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void LocalModParseTask::processAsZip()
|
void LocalModParseTask::processAsZip()
|
||||||
@ -354,10 +298,8 @@ void LocalModParseTask::processAsZip()
|
|||||||
|
|
||||||
QuaZipFile file(&zip);
|
QuaZipFile file(&zip);
|
||||||
|
|
||||||
if (zip.setCurrentFile("META-INF/mods.toml"))
|
if (zip.setCurrentFile("META-INF/mods.toml")) {
|
||||||
{
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -366,12 +308,9 @@ void LocalModParseTask::processAsZip()
|
|||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// to replace ${file.jarVersion} with the actual version, as needed
|
// to replace ${file.jarVersion} with the actual version, as needed
|
||||||
if (m_result->details.version == "${file.jarVersion}")
|
if (m_result->details.version == "${file.jarVersion}") {
|
||||||
{
|
if (zip.setCurrentFile("META-INF/MANIFEST.MF")) {
|
||||||
if (zip.setCurrentFile("META-INF/MANIFEST.MF"))
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
{
|
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -379,10 +318,8 @@ void LocalModParseTask::processAsZip()
|
|||||||
// quick and dirty line-by-line parser
|
// quick and dirty line-by-line parser
|
||||||
auto manifestLines = file.readAll().split('\n');
|
auto manifestLines = file.readAll().split('\n');
|
||||||
QString manifestVersion = "";
|
QString manifestVersion = "";
|
||||||
for (auto &line : manifestLines)
|
for (auto& line : manifestLines) {
|
||||||
{
|
if (QString(line).startsWith("Implementation-Version: ")) {
|
||||||
if (QString(line).startsWith("Implementation-Version: "))
|
|
||||||
{
|
|
||||||
manifestVersion = QString(line).remove("Implementation-Version: ");
|
manifestVersion = QString(line).remove("Implementation-Version: ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -390,8 +327,7 @@ void LocalModParseTask::processAsZip()
|
|||||||
|
|
||||||
// some mods use ${projectversion} in their build.gradle, causing this mess to show up in MANIFEST.MF
|
// some mods use ${projectversion} in their build.gradle, causing this mess to show up in MANIFEST.MF
|
||||||
// also keep with forge's behavior of setting the version to "NONE" if none is found
|
// also keep with forge's behavior of setting the version to "NONE" if none is found
|
||||||
if (manifestVersion.contains("task ':jar' property 'archiveVersion'") || manifestVersion == "")
|
if (manifestVersion.contains("task ':jar' property 'archiveVersion'") || manifestVersion == "") {
|
||||||
{
|
|
||||||
manifestVersion = "NONE";
|
manifestVersion = "NONE";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,11 +339,8 @@ void LocalModParseTask::processAsZip()
|
|||||||
|
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
} else if (zip.setCurrentFile("mcmod.info")) {
|
||||||
else if (zip.setCurrentFile("mcmod.info"))
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
{
|
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -416,11 +349,8 @@ void LocalModParseTask::processAsZip()
|
|||||||
file.close();
|
file.close();
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
} else if (zip.setCurrentFile("quilt.mod.json")) {
|
||||||
else if (zip.setCurrentFile("quilt.mod.json"))
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
{
|
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -429,11 +359,8 @@ void LocalModParseTask::processAsZip()
|
|||||||
file.close();
|
file.close();
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
} else if (zip.setCurrentFile("fabric.mod.json")) {
|
||||||
else if (zip.setCurrentFile("fabric.mod.json"))
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
{
|
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -442,11 +369,8 @@ void LocalModParseTask::processAsZip()
|
|||||||
file.close();
|
file.close();
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
} else if (zip.setCurrentFile("forgeversion.properties")) {
|
||||||
else if (zip.setCurrentFile("forgeversion.properties"))
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
{
|
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -463,8 +387,7 @@ void LocalModParseTask::processAsZip()
|
|||||||
void LocalModParseTask::processAsFolder()
|
void LocalModParseTask::processAsFolder()
|
||||||
{
|
{
|
||||||
QFileInfo mcmod_info(FS::PathCombine(m_modFile.filePath(), "mcmod.info"));
|
QFileInfo mcmod_info(FS::PathCombine(m_modFile.filePath(), "mcmod.info"));
|
||||||
if (mcmod_info.isFile())
|
if (mcmod_info.isFile()) {
|
||||||
{
|
|
||||||
QFile mcmod(mcmod_info.filePath());
|
QFile mcmod(mcmod_info.filePath());
|
||||||
if (!mcmod.open(QIODevice::ReadOnly))
|
if (!mcmod.open(QIODevice::ReadOnly))
|
||||||
return;
|
return;
|
||||||
@ -483,10 +406,8 @@ void LocalModParseTask::processAsLitemod()
|
|||||||
|
|
||||||
QuaZipFile file(&zip);
|
QuaZipFile file(&zip);
|
||||||
|
|
||||||
if (zip.setCurrentFile("litemod.json"))
|
if (zip.setCurrentFile("litemod.json")) {
|
||||||
{
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -505,8 +426,7 @@ bool LocalModParseTask::abort()
|
|||||||
|
|
||||||
void LocalModParseTask::executeTask()
|
void LocalModParseTask::executeTask()
|
||||||
{
|
{
|
||||||
switch(m_type)
|
switch (m_type) {
|
||||||
{
|
|
||||||
case ResourceType::ZIPFILE:
|
case ResourceType::ZIPFILE:
|
||||||
processAsZip();
|
processAsZip();
|
||||||
break;
|
break;
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* PolyMC - Minecraft Launcher
|
* PolyMC - Minecraft Launcher
|
||||||
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, version 3.
|
* the Free Software Foundation, version 3.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Packwiz.h"
|
#include "Packwiz.h"
|
||||||
|
|
||||||
@ -22,9 +22,7 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "toml.h"
|
#include <toml++/toml.h>
|
||||||
#include "FileSystem.h"
|
|
||||||
|
|
||||||
#include "minecraft/mod/Mod.h"
|
#include "minecraft/mod/Mod.h"
|
||||||
#include "modplatform/ModIndex.h"
|
#include "modplatform/ModIndex.h"
|
||||||
|
|
||||||
@ -44,7 +42,7 @@ auto getRealIndexName(QDir& index_dir, QString normalized_fname, bool should_fin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(should_find_match && !QString::compare(normalized_fname, real_fname, Qt::CaseSensitive)){
|
if (should_find_match && !QString::compare(normalized_fname, real_fname, Qt::CaseSensitive)) {
|
||||||
qCritical() << "Could not find a match for a valid metadata file!";
|
qCritical() << "Could not find a match for a valid metadata file!";
|
||||||
qCritical() << "File: " << normalized_fname;
|
qCritical() << "File: " << normalized_fname;
|
||||||
return {};
|
return {};
|
||||||
@ -57,7 +55,7 @@ auto getRealIndexName(QDir& index_dir, QString normalized_fname, bool should_fin
|
|||||||
// Helpers
|
// Helpers
|
||||||
static inline auto indexFileName(QString const& mod_slug) -> QString
|
static inline auto indexFileName(QString const& mod_slug) -> QString
|
||||||
{
|
{
|
||||||
if(mod_slug.endsWith(".pw.toml"))
|
if (mod_slug.endsWith(".pw.toml"))
|
||||||
return mod_slug;
|
return mod_slug;
|
||||||
return QString("%1.pw.toml").arg(mod_slug);
|
return QString("%1.pw.toml").arg(mod_slug);
|
||||||
}
|
}
|
||||||
@ -65,32 +63,28 @@ static inline auto indexFileName(QString const& mod_slug) -> QString
|
|||||||
static ModPlatform::ProviderCapabilities ProviderCaps;
|
static ModPlatform::ProviderCapabilities ProviderCaps;
|
||||||
|
|
||||||
// Helper functions for extracting data from the TOML file
|
// Helper functions for extracting data from the TOML file
|
||||||
auto stringEntry(toml_table_t* parent, const char* entry_name) -> QString
|
auto stringEntry(toml::table table, const std::string entry_name) -> QString
|
||||||
{
|
{
|
||||||
toml_datum_t var = toml_string_in(parent, entry_name);
|
auto node = table[entry_name];
|
||||||
if (!var.ok) {
|
if (!node) {
|
||||||
qCritical() << QString("Failed to read str property '%1' in mod metadata.").arg(entry_name);
|
qCritical() << QString::fromStdString("Failed to read str property '" + entry_name + "' in mod metadata.");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString tmp = var.u.s;
|
return QString::fromStdString(node.value_or(""));
|
||||||
free(var.u.s);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto intEntry(toml_table_t* parent, const char* entry_name) -> int
|
auto intEntry(toml::table table, const std::string entry_name) -> int
|
||||||
{
|
{
|
||||||
toml_datum_t var = toml_int_in(parent, entry_name);
|
auto node = table[entry_name];
|
||||||
if (!var.ok) {
|
if (!node) {
|
||||||
qCritical() << QString("Failed to read int property '%1' in mod metadata.").arg(entry_name);
|
qCritical() << QString::fromStdString("Failed to read int property '" + entry_name + "' in mod metadata.");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return var.u.i;
|
return node.value_or(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod
|
auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, ModPlatform::IndexedVersion& mod_version) -> Mod
|
||||||
{
|
{
|
||||||
Mod mod;
|
Mod mod;
|
||||||
@ -99,10 +93,9 @@ auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, Mo
|
|||||||
mod.name = mod_pack.name;
|
mod.name = mod_pack.name;
|
||||||
mod.filename = mod_version.fileName;
|
mod.filename = mod_version.fileName;
|
||||||
|
|
||||||
if(mod_pack.provider == ModPlatform::Provider::FLAME){
|
if (mod_pack.provider == ModPlatform::Provider::FLAME) {
|
||||||
mod.mode = "metadata:curseforge";
|
mod.mode = "metadata:curseforge";
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
mod.mode = "url";
|
mod.mode = "url";
|
||||||
mod.url = mod_version.downloadUrl;
|
mod.url = mod_version.downloadUrl;
|
||||||
}
|
}
|
||||||
@ -120,8 +113,8 @@ auto V1::createModFormat(QDir& index_dir, ModPlatform::IndexedPack& mod_pack, Mo
|
|||||||
auto V1::createModFormat(QDir& index_dir, ::Mod& internal_mod, QString slug) -> Mod
|
auto V1::createModFormat(QDir& index_dir, ::Mod& internal_mod, QString slug) -> Mod
|
||||||
{
|
{
|
||||||
// Try getting metadata if it exists
|
// Try getting metadata if it exists
|
||||||
Mod mod { getIndexForMod(index_dir, slug) };
|
Mod mod{ getIndexForMod(index_dir, slug) };
|
||||||
if(mod.isValid())
|
if (mod.isValid())
|
||||||
return mod;
|
return mod;
|
||||||
|
|
||||||
qWarning() << QString("Tried to create mod metadata with a Mod without metadata!");
|
qWarning() << QString("Tried to create mod metadata with a Mod without metadata!");
|
||||||
@ -131,7 +124,7 @@ auto V1::createModFormat(QDir& index_dir, ::Mod& internal_mod, QString slug) ->
|
|||||||
|
|
||||||
void V1::updateModIndex(QDir& index_dir, Mod& mod)
|
void V1::updateModIndex(QDir& index_dir, Mod& mod)
|
||||||
{
|
{
|
||||||
if(!mod.isValid()){
|
if (!mod.isValid()) {
|
||||||
qCritical() << QString("Tried to update metadata of an invalid mod!");
|
qCritical() << QString("Tried to update metadata of an invalid mod!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -150,7 +143,9 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod)
|
|||||||
// TODO: We should do more stuff here, as the user is likely trying to
|
// TODO: We should do more stuff here, as the user is likely trying to
|
||||||
// override a file. In this case, check versions and ask the user what
|
// override a file. In this case, check versions and ask the user what
|
||||||
// they want to do!
|
// they want to do!
|
||||||
if (index_file.exists()) { index_file.remove(); }
|
if (index_file.exists()) {
|
||||||
|
index_file.remove();
|
||||||
|
}
|
||||||
|
|
||||||
if (!index_file.open(QIODevice::ReadWrite)) {
|
if (!index_file.open(QIODevice::ReadWrite)) {
|
||||||
qCritical() << QString("Could not open file %1!").arg(indexFileName(mod.name));
|
qCritical() << QString("Could not open file %1!").arg(indexFileName(mod.name));
|
||||||
@ -174,12 +169,12 @@ void V1::updateModIndex(QDir& index_dir, Mod& mod)
|
|||||||
|
|
||||||
in_stream << QString("\n[update]\n");
|
in_stream << QString("\n[update]\n");
|
||||||
in_stream << QString("[update.%1]\n").arg(ProviderCaps.name(mod.provider));
|
in_stream << QString("[update.%1]\n").arg(ProviderCaps.name(mod.provider));
|
||||||
switch(mod.provider){
|
switch (mod.provider) {
|
||||||
case(ModPlatform::Provider::FLAME):
|
case (ModPlatform::Provider::FLAME):
|
||||||
in_stream << QString("file-id = %1\n").arg(mod.file_id.toString());
|
in_stream << QString("file-id = %1\n").arg(mod.file_id.toString());
|
||||||
in_stream << QString("project-id = %1\n").arg(mod.project_id.toString());
|
in_stream << QString("project-id = %1\n").arg(mod.project_id.toString());
|
||||||
break;
|
break;
|
||||||
case(ModPlatform::Provider::MODRINTH):
|
case (ModPlatform::Provider::MODRINTH):
|
||||||
addToStream("mod-id", mod.mod_id().toString());
|
addToStream("mod-id", mod.mod_id().toString());
|
||||||
addToStream("version", mod.version().toString());
|
addToStream("version", mod.version().toString());
|
||||||
break;
|
break;
|
||||||
@ -230,27 +225,25 @@ auto V1::getIndexForMod(QDir& index_dir, QString slug) -> Mod
|
|||||||
if (real_fname.isEmpty())
|
if (real_fname.isEmpty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
QFile index_file(index_dir.absoluteFilePath(real_fname));
|
toml::table table;
|
||||||
|
#if TOML_EXCEPTIONS
|
||||||
if (!index_file.open(QIODevice::ReadOnly)) {
|
try {
|
||||||
qWarning() << QString("Failed to open mod metadata for %1").arg(slug);
|
table = toml::parse_file(index_dir.absoluteFilePath(real_fname).toStdString());
|
||||||
|
} catch (const toml::parse_error& err) {
|
||||||
|
qWarning() << QString("Could not open file %1!").arg(normalized_fname);
|
||||||
|
qWarning() << "Reason: " << QString(err.what());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
toml_table_t* table = nullptr;
|
table = toml::parse_file(index_dir.absoluteFilePath(real_fname).toStdString());
|
||||||
|
|
||||||
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
||||||
char errbuf[200];
|
|
||||||
auto file_bytearray = index_file.readAll();
|
|
||||||
table = toml_parse(file_bytearray.data(), errbuf, sizeof(errbuf));
|
|
||||||
|
|
||||||
index_file.close();
|
|
||||||
|
|
||||||
if (!table) {
|
if (!table) {
|
||||||
qWarning() << QString("Could not open file %1!").arg(normalized_fname);
|
qWarning() << QString("Could not open file %1!").arg(normalized_fname);
|
||||||
qWarning() << "Reason: " << QString(errbuf);
|
qWarning() << "Reason: " << QString(table.error().what());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// index_file.close();
|
||||||
|
|
||||||
mod.slug = slug;
|
mod.slug = slug;
|
||||||
|
|
||||||
@ -261,45 +254,42 @@ auto V1::getIndexForMod(QDir& index_dir, QString slug) -> Mod
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // [download] info
|
{ // [download] info
|
||||||
toml_table_t* download_table = toml_table_in(table, "download");
|
auto download_table = table["download"].as_table();
|
||||||
if (!download_table) {
|
if (!download_table) {
|
||||||
qCritical() << QString("No [download] section found on mod metadata!");
|
qCritical() << QString("No [download] section found on mod metadata!");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.mode = stringEntry(download_table, "mode");
|
mod.mode = stringEntry(*download_table, "mode");
|
||||||
mod.url = stringEntry(download_table, "url");
|
mod.url = stringEntry(*download_table, "url");
|
||||||
mod.hash_format = stringEntry(download_table, "hash-format");
|
mod.hash_format = stringEntry(*download_table, "hash-format");
|
||||||
mod.hash = stringEntry(download_table, "hash");
|
mod.hash = stringEntry(*download_table, "hash");
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // [update] info
|
{ // [update] info
|
||||||
using Provider = ModPlatform::Provider;
|
using Provider = ModPlatform::Provider;
|
||||||
|
|
||||||
toml_table_t* update_table = toml_table_in(table, "update");
|
auto update_table = table["update"];
|
||||||
if (!update_table) {
|
if (!update_table || !update_table.is_table()) {
|
||||||
qCritical() << QString("No [update] section found on mod metadata!");
|
qCritical() << QString("No [update] section found on mod metadata!");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
toml_table_t* mod_provider_table = nullptr;
|
toml::table* mod_provider_table = nullptr;
|
||||||
if ((mod_provider_table = toml_table_in(update_table, ProviderCaps.name(Provider::FLAME)))) {
|
if ((mod_provider_table = update_table[ProviderCaps.name(Provider::FLAME)].as_table())) {
|
||||||
mod.provider = Provider::FLAME;
|
mod.provider = Provider::FLAME;
|
||||||
mod.file_id = intEntry(mod_provider_table, "file-id");
|
mod.file_id = intEntry(*mod_provider_table, "file-id");
|
||||||
mod.project_id = intEntry(mod_provider_table, "project-id");
|
mod.project_id = intEntry(*mod_provider_table, "project-id");
|
||||||
} else if ((mod_provider_table = toml_table_in(update_table, ProviderCaps.name(Provider::MODRINTH)))) {
|
} else if ((mod_provider_table = update_table[ProviderCaps.name(Provider::MODRINTH)].as_table())) {
|
||||||
mod.provider = Provider::MODRINTH;
|
mod.provider = Provider::MODRINTH;
|
||||||
mod.mod_id() = stringEntry(mod_provider_table, "mod-id");
|
mod.mod_id() = stringEntry(*mod_provider_table, "mod-id");
|
||||||
mod.version() = stringEntry(mod_provider_table, "version");
|
mod.version() = stringEntry(*mod_provider_table, "version");
|
||||||
} else {
|
} else {
|
||||||
qCritical() << QString("No mod provider on mod metadata!");
|
qCritical() << QString("No mod provider on mod metadata!");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toml_free(table);
|
|
||||||
|
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,17 +44,17 @@ Java launcher part for Minecraft.
|
|||||||
|
|
||||||
It:
|
It:
|
||||||
|
|
||||||
* Starts a process
|
- Starts a process
|
||||||
* Waits for a launch script on stdin
|
- Waits for a launch script on stdin
|
||||||
* Consumes the launch script you feed it
|
- Consumes the launch script you feed it
|
||||||
* Proceeds with launch when it gets the `launcher` command
|
- Proceeds with launch when it gets the `launcher` command
|
||||||
|
|
||||||
This means the process is essentially idle until the final command is sent. You can, for example, attach a profiler before you send it.
|
This means the process is essentially idle until the final command is sent. You can, for example, attach a profiler before you send it.
|
||||||
|
|
||||||
A `legacy` and `onesix` launchers are available.
|
A `legacy` and `onesix` launchers are available.
|
||||||
|
|
||||||
* `legacy` is intended for use with Minecraft versions < 1.6 and is deprecated.
|
- `legacy` is intended for use with Minecraft versions < 1.6 and is deprecated.
|
||||||
* `onesix` can handle launching any Minecraft version, at the cost of some extra features `legacy` enables (custom window icon and title).
|
- `onesix` can handle launching any Minecraft version, at the cost of some extra features `legacy` enables (custom window icon and title).
|
||||||
|
|
||||||
Example (some parts have been censored):
|
Example (some parts have been censored):
|
||||||
|
|
||||||
@ -177,11 +177,11 @@ A PolyMC-specific library for probing system information.
|
|||||||
|
|
||||||
Apache 2.0
|
Apache 2.0
|
||||||
|
|
||||||
## tomlc99
|
## tomlplusplus
|
||||||
|
|
||||||
A TOML language parser. Used by Forge 1.14+ to store mod metadata.
|
A TOML language parser. Used by Forge 1.14+ to store mod metadata.
|
||||||
|
|
||||||
See [github repo](https://github.com/cktan/tomlc99).
|
See [github repo](https://github.com/marzer/tomlplusplus).
|
||||||
|
|
||||||
Licenced under the MIT licence.
|
Licenced under the MIT licence.
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
project(tomlc99)
|
|
||||||
|
|
||||||
set(tomlc99_SOURCES
|
|
||||||
include/toml.h
|
|
||||||
src/toml.c
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(tomlc99 STATIC ${tomlc99_SOURCES})
|
|
||||||
|
|
||||||
target_include_directories(tomlc99 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
@ -1,22 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2017 CK Tan
|
|
||||||
https://github.com/cktan/tomlc99
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
@ -1,197 +0,0 @@
|
|||||||
# tomlc99
|
|
||||||
|
|
||||||
TOML in c99; v1.0 compliant.
|
|
||||||
|
|
||||||
If you are looking for a C++ library, you might try this wrapper: [https://github.com/cktan/tomlcpp](https://github.com/cktan/tomlcpp).
|
|
||||||
|
|
||||||
* Compatible with [TOML v1.0.0](https://toml.io/en/v1.0.0).
|
|
||||||
* Tested with multiple test suites, including
|
|
||||||
[BurntSushi/toml-test](https://github.com/BurntSushi/toml-test) and
|
|
||||||
[iarna/toml-spec-tests](https://github.com/iarna/toml-spec-tests).
|
|
||||||
* Provides very simple and intuitive interface.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Please see the `toml.h` file for details. What follows is a simple example that
|
|
||||||
parses this config file:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[server]
|
|
||||||
host = "www.example.com"
|
|
||||||
port = [ 8080, 8181, 8282 ]
|
|
||||||
```
|
|
||||||
|
|
||||||
The steps for getting values from our file is usually :
|
|
||||||
|
|
||||||
1. Parse the TOML file.
|
|
||||||
2. Traverse and locate a table in TOML.
|
|
||||||
3. Extract values from the table.
|
|
||||||
4. Free up allocated memory.
|
|
||||||
|
|
||||||
Below is an example of parsing the values from the example table.
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "toml.h"
|
|
||||||
|
|
||||||
static void error(const char* msg, const char* msg1)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "ERROR: %s%s\n", msg, msg1?msg1:"");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
FILE* fp;
|
|
||||||
char errbuf[200];
|
|
||||||
|
|
||||||
// 1. Read and parse toml file
|
|
||||||
fp = fopen("sample.toml", "r");
|
|
||||||
if (!fp) {
|
|
||||||
error("cannot open sample.toml - ", strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
toml_table_t* conf = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
if (!conf) {
|
|
||||||
error("cannot parse - ", errbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Traverse to a table.
|
|
||||||
toml_table_t* server = toml_table_in(conf, "server");
|
|
||||||
if (!server) {
|
|
||||||
error("missing [server]", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Extract values
|
|
||||||
toml_datum_t host = toml_string_in(server, "host");
|
|
||||||
if (!host.ok) {
|
|
||||||
error("cannot read server.host", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
toml_array_t* portarray = toml_array_in(server, "port");
|
|
||||||
if (!portarray) {
|
|
||||||
error("cannot read server.port", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("host: %s\n", host.u.s);
|
|
||||||
printf("port: ");
|
|
||||||
for (int i = 0; ; i++) {
|
|
||||||
toml_datum_t port = toml_int_at(portarray, i);
|
|
||||||
if (!port.ok) break;
|
|
||||||
printf("%d ", (int)port.u.i);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
// 4. Free memory
|
|
||||||
free(host.u.s);
|
|
||||||
toml_free(conf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Accessing Table Content
|
|
||||||
|
|
||||||
TOML tables are dictionaries where lookups are done using string keys. In
|
|
||||||
general, all access functions on tables are named `toml_*_in(...)`.
|
|
||||||
|
|
||||||
In the normal case, you know the key and its content type, and retrievals can be done
|
|
||||||
using one of these functions:
|
|
||||||
|
|
||||||
```c
|
|
||||||
toml_string_in(tab, key);
|
|
||||||
toml_bool_in(tab, key);
|
|
||||||
toml_int_in(tab, key);
|
|
||||||
toml_double_in(tab, key);
|
|
||||||
toml_timestamp_in(tab, key);
|
|
||||||
toml_table_in(tab, key);
|
|
||||||
toml_array_in(tab, key);
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also interrogate the keys in a table using an integer index:
|
|
||||||
|
|
||||||
```c
|
|
||||||
toml_table_t* tab = toml_parse_file(...);
|
|
||||||
for (int i = 0; ; i++) {
|
|
||||||
const char* key = toml_key_in(tab, i);
|
|
||||||
if (!key) break;
|
|
||||||
printf("key %d: %s\n", i, key);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Accessing Array Content
|
|
||||||
|
|
||||||
TOML arrays can be deref-ed using integer indices. In general, all access methods on arrays are named `toml_*_at()`.
|
|
||||||
|
|
||||||
To obtain the size of an array:
|
|
||||||
|
|
||||||
```c
|
|
||||||
int size = toml_array_nelem(arr);
|
|
||||||
```
|
|
||||||
|
|
||||||
To obtain the content of an array, use a valid index and call one of these functions:
|
|
||||||
|
|
||||||
```c
|
|
||||||
toml_string_at(arr, idx);
|
|
||||||
toml_bool_at(arr, idx);
|
|
||||||
toml_int_at(arr, idx);
|
|
||||||
toml_double_at(arr, idx);
|
|
||||||
toml_timestamp_at(arr, idx);
|
|
||||||
toml_table_at(arr, idx);
|
|
||||||
toml_array_at(arr, idx);
|
|
||||||
```
|
|
||||||
|
|
||||||
### toml_datum_t
|
|
||||||
|
|
||||||
Some `toml_*_at` and `toml_*_in` functions return a toml_datum_t
|
|
||||||
structure. The `ok` flag in the structure indicates if the function
|
|
||||||
call was successful. If so, you may proceed to read the value
|
|
||||||
corresponding to the type of the content.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```c
|
|
||||||
toml_datum_t host = toml_string_in(tab, "host");
|
|
||||||
if (host.ok) {
|
|
||||||
printf("host: %s\n", host.u.s);
|
|
||||||
free(host.u.s); /* FREE applies to string and timestamp types only */
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**IMPORTANT: if the accessed value is a string or a timestamp, you must call `free(datum.u.s)` or `free(datum.u.ts)` respectively after usage.**
|
|
||||||
|
|
||||||
## Building and installing
|
|
||||||
|
|
||||||
A normal *make* suffices. You can also simply include the
|
|
||||||
`toml.c` and `toml.h` files in your project.
|
|
||||||
|
|
||||||
Invoking `make install` will install the header and library files into
|
|
||||||
/usr/local/{include,lib}.
|
|
||||||
|
|
||||||
Alternatively, specify `make install prefix=/a/file/path` to install into
|
|
||||||
/a/file/path/{include,lib}.
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
To test against the standard test set provided by BurntSushi/toml-test:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
% make
|
|
||||||
% cd test1
|
|
||||||
% bash build.sh # do this once
|
|
||||||
% bash run.sh # this will run the test suite
|
|
||||||
```
|
|
||||||
|
|
||||||
To test against the standard test set provided by iarna/toml:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
% make
|
|
||||||
% cd test2
|
|
||||||
% bash build.sh # do this once
|
|
||||||
% bash run.sh # this will run the test suite
|
|
||||||
```
|
|
@ -1,175 +0,0 @@
|
|||||||
/*
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2017 - 2019 CK Tan
|
|
||||||
https://github.com/cktan/tomlc99
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*/
|
|
||||||
#ifndef TOML_H
|
|
||||||
#define TOML_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define TOML_EXTERN extern "C"
|
|
||||||
#else
|
|
||||||
#define TOML_EXTERN extern
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct toml_timestamp_t toml_timestamp_t;
|
|
||||||
typedef struct toml_table_t toml_table_t;
|
|
||||||
typedef struct toml_array_t toml_array_t;
|
|
||||||
typedef struct toml_datum_t toml_datum_t;
|
|
||||||
|
|
||||||
/* Parse a file. Return a table on success, or 0 otherwise.
|
|
||||||
* Caller must toml_free(the-return-value) after use.
|
|
||||||
*/
|
|
||||||
TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp,
|
|
||||||
char* errbuf,
|
|
||||||
int errbufsz);
|
|
||||||
|
|
||||||
/* Parse a string containing the full config.
|
|
||||||
* Return a table on success, or 0 otherwise.
|
|
||||||
* Caller must toml_free(the-return-value) after use.
|
|
||||||
*/
|
|
||||||
TOML_EXTERN toml_table_t* toml_parse(char* conf, /* NUL terminated, please. */
|
|
||||||
char* errbuf,
|
|
||||||
int errbufsz);
|
|
||||||
|
|
||||||
/* Free the table returned by toml_parse() or toml_parse_file(). Once
|
|
||||||
* this function is called, any handles accessed through this tab
|
|
||||||
* directly or indirectly are no longer valid.
|
|
||||||
*/
|
|
||||||
TOML_EXTERN void toml_free(toml_table_t* tab);
|
|
||||||
|
|
||||||
|
|
||||||
/* Timestamp types. The year, month, day, hour, minute, second, z
|
|
||||||
* fields may be NULL if they are not relevant. e.g. In a DATE
|
|
||||||
* type, the hour, minute, second and z fields will be NULLs.
|
|
||||||
*/
|
|
||||||
struct toml_timestamp_t {
|
|
||||||
struct { /* internal. do not use. */
|
|
||||||
int year, month, day;
|
|
||||||
int hour, minute, second, millisec;
|
|
||||||
char z[10];
|
|
||||||
} __buffer;
|
|
||||||
int *year, *month, *day;
|
|
||||||
int *hour, *minute, *second, *millisec;
|
|
||||||
char* z;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
* Enhanced access methods
|
|
||||||
*/
|
|
||||||
struct toml_datum_t {
|
|
||||||
int ok;
|
|
||||||
union {
|
|
||||||
toml_timestamp_t* ts; /* ts must be freed after use */
|
|
||||||
char* s; /* string value. s must be freed after use */
|
|
||||||
int b; /* bool value */
|
|
||||||
int64_t i; /* int value */
|
|
||||||
double d; /* double value */
|
|
||||||
} u;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* on arrays: */
|
|
||||||
/* ... retrieve size of array. */
|
|
||||||
TOML_EXTERN int toml_array_nelem(const toml_array_t* arr);
|
|
||||||
/* ... retrieve values using index. */
|
|
||||||
TOML_EXTERN toml_datum_t toml_string_at(const toml_array_t* arr, int idx);
|
|
||||||
TOML_EXTERN toml_datum_t toml_bool_at(const toml_array_t* arr, int idx);
|
|
||||||
TOML_EXTERN toml_datum_t toml_int_at(const toml_array_t* arr, int idx);
|
|
||||||
TOML_EXTERN toml_datum_t toml_double_at(const toml_array_t* arr, int idx);
|
|
||||||
TOML_EXTERN toml_datum_t toml_timestamp_at(const toml_array_t* arr, int idx);
|
|
||||||
/* ... retrieve array or table using index. */
|
|
||||||
TOML_EXTERN toml_array_t* toml_array_at(const toml_array_t* arr, int idx);
|
|
||||||
TOML_EXTERN toml_table_t* toml_table_at(const toml_array_t* arr, int idx);
|
|
||||||
|
|
||||||
/* on tables: */
|
|
||||||
/* ... retrieve the key in table at keyidx. Return 0 if out of range. */
|
|
||||||
TOML_EXTERN const char* toml_key_in(const toml_table_t* tab, int keyidx);
|
|
||||||
/* ... retrieve values using key. */
|
|
||||||
TOML_EXTERN toml_datum_t toml_string_in(const toml_table_t* arr, const char* key);
|
|
||||||
TOML_EXTERN toml_datum_t toml_bool_in(const toml_table_t* arr, const char* key);
|
|
||||||
TOML_EXTERN toml_datum_t toml_int_in(const toml_table_t* arr, const char* key);
|
|
||||||
TOML_EXTERN toml_datum_t toml_double_in(const toml_table_t* arr, const char* key);
|
|
||||||
TOML_EXTERN toml_datum_t toml_timestamp_in(const toml_table_t* arr, const char* key);
|
|
||||||
/* .. retrieve array or table using key. */
|
|
||||||
TOML_EXTERN toml_array_t* toml_array_in(const toml_table_t* tab,
|
|
||||||
const char* key);
|
|
||||||
TOML_EXTERN toml_table_t* toml_table_in(const toml_table_t* tab,
|
|
||||||
const char* key);
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
|
||||||
* lesser used
|
|
||||||
*/
|
|
||||||
/* Return the array kind: 't'able, 'a'rray, 'v'alue, 'm'ixed */
|
|
||||||
TOML_EXTERN char toml_array_kind(const toml_array_t* arr);
|
|
||||||
|
|
||||||
/* For array kind 'v'alue, return the type of values
|
|
||||||
i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp, 'm'ixed
|
|
||||||
0 if unknown
|
|
||||||
*/
|
|
||||||
TOML_EXTERN char toml_array_type(const toml_array_t* arr);
|
|
||||||
|
|
||||||
/* Return the key of an array */
|
|
||||||
TOML_EXTERN const char* toml_array_key(const toml_array_t* arr);
|
|
||||||
|
|
||||||
/* Return the number of key-values in a table */
|
|
||||||
TOML_EXTERN int toml_table_nkval(const toml_table_t* tab);
|
|
||||||
|
|
||||||
/* Return the number of arrays in a table */
|
|
||||||
TOML_EXTERN int toml_table_narr(const toml_table_t* tab);
|
|
||||||
|
|
||||||
/* Return the number of sub-tables in a table */
|
|
||||||
TOML_EXTERN int toml_table_ntab(const toml_table_t* tab);
|
|
||||||
|
|
||||||
/* Return the key of a table*/
|
|
||||||
TOML_EXTERN const char* toml_table_key(const toml_table_t* tab);
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
* misc
|
|
||||||
*/
|
|
||||||
TOML_EXTERN int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret);
|
|
||||||
TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]);
|
|
||||||
TOML_EXTERN void toml_set_memutil(void* (*xxmalloc)(size_t),
|
|
||||||
void (*xxfree)(void*));
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
|
||||||
* deprecated
|
|
||||||
*/
|
|
||||||
/* A raw value, must be processed by toml_rto* before using. */
|
|
||||||
typedef const char* toml_raw_t;
|
|
||||||
TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t* tab, const char* key);
|
|
||||||
TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t* arr, int idx);
|
|
||||||
TOML_EXTERN int toml_rtos(toml_raw_t s, char** ret);
|
|
||||||
TOML_EXTERN int toml_rtob(toml_raw_t s, int* ret);
|
|
||||||
TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t* ret);
|
|
||||||
TOML_EXTERN int toml_rtod(toml_raw_t s, double* ret);
|
|
||||||
TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double* ret, char* buf, int buflen);
|
|
||||||
TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t* ret);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* TOML_H */
|
|
File diff suppressed because it is too large
Load Diff
1
libraries/tomlplusplus
Submodule
1
libraries/tomlplusplus
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit fb8ce80350bcde1d109e9b4d7a571bbc2f29a8bd
|
Loading…
Reference in New Issue
Block a user