From f5400e587723e1bbefffd32298581946ea19b09c Mon Sep 17 00:00:00 2001 From: WasabiRaptor Date: Thu, 7 Mar 2024 18:06:30 -0500 Subject: [PATCH 1/2] improvement to iterating through patch arrays --- source/base/StarAssets.cpp | 62 ++++++++++++++++++++++------------- source/base/StarAssets.hpp | 1 + source/core/StarJsonPatch.cpp | 2 +- source/core/StarJsonPatch.hpp | 2 +- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/source/base/StarAssets.cpp b/source/base/StarAssets.cpp index 2c3d04b..0b8cffe 100644 --- a/source/base/StarAssets.cpp +++ b/source/base/StarAssets.cpp @@ -667,6 +667,38 @@ ByteArray Assets::read(String const& path) const { throw AssetException(strf("No such asset '{}'", path)); } +Json Assets::checkPatchArray(String const& path, AssetSourcePtr const& source, Json const result, JsonArray const patchData, Maybe const external) const { + auto externalRef = external.value(); + auto newResult = result; + for (auto const patch : patchData) { + switch(patch.type()){ + case Json::Type::Array: // if the patch is an array, go down recursively until we get objects + try { + newResult = checkPatchArray(path, source, newResult, patch.toArray(), externalRef); + } catch (JsonPatchTestFail const& e) { + Logger::debug("Patch test failure from file %s in source: '%s' at '%s'. Caused by: %s", path, source->metadata().value("name", ""), m_assetSourcePaths.getLeft(source), e.what()); + } catch (JsonPatchException const& e) { + Logger::error("Could not apply patch from file %s in source: '%s' at '%s'. Caused by: %s", path, source->metadata().value("name", ""), m_assetSourcePaths.getLeft(source), e.what()); + } + break; + case Json::Type::Object: // if its an object, check for operations, or for if an external file is needed for patches to reference + newResult = JsonPatching::applyOperation(newResult, patch, externalRef); + break; + case Json::Type::String: + try { + externalRef = json(patch.toString()); + } catch (...) { + throw JsonPatchTestFail(strf("Unable to load reference asset: %s", patch.toString())); + } + break; + default: + throw JsonPatchException(strf("Patch data is wrong type: %s", Json::typeName(patch.type()))); + break; + } + } + return newResult; +} + Json Assets::readJson(String const& path) const { ByteArray streamData = read(path); try { @@ -677,40 +709,24 @@ Json Assets::readJson(String const& path) const { if (patchJson.isType(Json::Type::Array)) { auto patchData = patchJson.toArray(); try { - if (patchData.size()) { - if (patchData.at(0).type() == Json::Type::Array) { - for (auto const& patch : patchData) { - try { - result = jsonPatch(result, patch.toArray()); - } catch (JsonPatchTestFail const& e) { - Logger::debug("Patch test failure from file {} in source: {}. Caused by: {}", pair.first, m_assetSourcePaths.getLeft(pair.second), e.what()); - } - } - } else if (patchData.at(0).type() == Json::Type::Object) { - try { - result = jsonPatch(result, patchData); - } catch (JsonPatchTestFail const& e) { - Logger::debug("Patch test failure from file {} in source: {}. Caused by: {}", pair.first, m_assetSourcePaths.getLeft(pair.second), e.what()); - } - } else { - throw JsonPatchException(strf("Patch data is wrong type: {}", Json::typeName(patchData.at(0).type()))); - } - } + result = checkPatchArray(pair.first, pair.second, result, patchData, {}); + } catch (JsonPatchTestFail const& e) { + Logger::debug("Patch test failure from file %s in source: '%s' at '%s'. Caused by: %s", pair.first, pair.second->metadata().value("name", ""), m_assetSourcePaths.getLeft(pair.second), e.what()); } catch (JsonPatchException const& e) { - Logger::error("Could not apply patch from file {} in source: {}. Caused by: {}", pair.first, m_assetSourcePaths.getLeft(pair.second), e.what()); + Logger::error("Could not apply patch from file %s in source: '%s' at '%s'. Caused by: %s", pair.first, pair.second->metadata().value("name", ""), m_assetSourcePaths.getLeft(pair.second), e.what()); } - } - else if (patchJson.isType(Json::Type::Object)) { //Kae: Do a good ol' json merge instead if the .patch file is a Json object + } else if (patchJson.isType(Json::Type::Object)) { //Kae: Do a good ol' json merge instead if the .patch file is a Json object auto patchData = patchJson.toObject(); result = jsonMerge(result, patchData); } } return result; } catch (std::exception const& e) { - throw JsonParsingException(strf("Cannot parse json file: {}", path), e); + throw JsonParsingException(strf("Cannot parse json file: %s", path), e); } } + bool Assets::doLoad(AssetId const& id) const { try { // loadAsset automatically manages the queue and freshens the asset diff --git a/source/base/StarAssets.hpp b/source/base/StarAssets.hpp index 0024207..37e9a6c 100644 --- a/source/base/StarAssets.hpp +++ b/source/base/StarAssets.hpp @@ -269,6 +269,7 @@ private: ByteArray read(String const& basePath) const; Json readJson(String const& basePath) const; + Json checkPatchArray(String const& path, AssetSourcePtr const& source, Json const result, JsonArray const patchData, Maybe const external) const; // Load / post process an asset and log any exception. Returns true if the // work was performed (whether successful or not), false if the work is diff --git a/source/core/StarJsonPatch.cpp b/source/core/StarJsonPatch.cpp index 34c6a82..49b6749 100644 --- a/source/core/StarJsonPatch.cpp +++ b/source/core/StarJsonPatch.cpp @@ -27,7 +27,7 @@ namespace JsonPatching { {"copy", std::bind(applyCopyOperation, _1, _2)}, }; - Json applyOperation(Json const& base, Json const& op) { + Json applyOperation(Json const& base, Json const& op, Maybe const& external) { try { auto operation = op.getString("op"); return JsonPatching::functionMap.get(operation)(base, op); diff --git a/source/core/StarJsonPatch.hpp b/source/core/StarJsonPatch.hpp index bd331c4..5610cc6 100644 --- a/source/core/StarJsonPatch.hpp +++ b/source/core/StarJsonPatch.hpp @@ -13,7 +13,7 @@ Json jsonPatch(Json const& base, JsonArray const& patch); namespace JsonPatching { // Applies the given single operation - Json applyOperation(Json const& base, Json const& op); + Json applyOperation(Json const& base, Json const& op, Maybe const& external = {}); // Tests for "value" at "path" // Returns base or throws JsonPatchException From c5e568e47c95ac8210a72effb2e3a24ebd90af1b Mon Sep 17 00:00:00 2001 From: WasabiRaptor Date: Thu, 7 Mar 2024 18:56:13 -0500 Subject: [PATCH 2/2] fine goodbye nice syntax highlighting --- source/base/StarAssets.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/base/StarAssets.cpp b/source/base/StarAssets.cpp index 0b8cffe..b72b446 100644 --- a/source/base/StarAssets.cpp +++ b/source/base/StarAssets.cpp @@ -676,9 +676,9 @@ Json Assets::checkPatchArray(String const& path, AssetSourcePtr const& source, J try { newResult = checkPatchArray(path, source, newResult, patch.toArray(), externalRef); } catch (JsonPatchTestFail const& e) { - Logger::debug("Patch test failure from file %s in source: '%s' at '%s'. Caused by: %s", path, source->metadata().value("name", ""), m_assetSourcePaths.getLeft(source), e.what()); + Logger::debug("Patch test failure from file {} in source: '{}' at '{}'. Caused by: {}", path, source->metadata().value("name", ""), m_assetSourcePaths.getLeft(source), e.what()); } catch (JsonPatchException const& e) { - Logger::error("Could not apply patch from file %s in source: '%s' at '%s'. Caused by: %s", path, source->metadata().value("name", ""), m_assetSourcePaths.getLeft(source), e.what()); + Logger::error("Could not apply patch from file {} in source: '{}' at '{}'. Caused by: {}", path, source->metadata().value("name", ""), m_assetSourcePaths.getLeft(source), e.what()); } break; case Json::Type::Object: // if its an object, check for operations, or for if an external file is needed for patches to reference @@ -688,11 +688,11 @@ Json Assets::checkPatchArray(String const& path, AssetSourcePtr const& source, J try { externalRef = json(patch.toString()); } catch (...) { - throw JsonPatchTestFail(strf("Unable to load reference asset: %s", patch.toString())); + throw JsonPatchTestFail(strf("Unable to load reference asset: {}", patch.toString())); } break; default: - throw JsonPatchException(strf("Patch data is wrong type: %s", Json::typeName(patch.type()))); + throw JsonPatchException(strf("Patch data is wrong type: {}", Json::typeName(patch.type()))); break; } } @@ -711,9 +711,9 @@ Json Assets::readJson(String const& path) const { try { result = checkPatchArray(pair.first, pair.second, result, patchData, {}); } catch (JsonPatchTestFail const& e) { - Logger::debug("Patch test failure from file %s in source: '%s' at '%s'. Caused by: %s", pair.first, pair.second->metadata().value("name", ""), m_assetSourcePaths.getLeft(pair.second), e.what()); + Logger::debug("Patch test failure from file {} in source: '{}' at '{}'. Caused by: {}", pair.first, pair.second->metadata().value("name", ""), m_assetSourcePaths.getLeft(pair.second), e.what()); } catch (JsonPatchException const& e) { - Logger::error("Could not apply patch from file %s in source: '%s' at '%s'. Caused by: %s", pair.first, pair.second->metadata().value("name", ""), m_assetSourcePaths.getLeft(pair.second), e.what()); + Logger::error("Could not apply patch from file {} in source: '{}' at '{}'. Caused by: {}", pair.first, pair.second->metadata().value("name", ""), m_assetSourcePaths.getLeft(pair.second), e.what()); } } else if (patchJson.isType(Json::Type::Object)) { //Kae: Do a good ol' json merge instead if the .patch file is a Json object auto patchData = patchJson.toObject(); @@ -722,7 +722,7 @@ Json Assets::readJson(String const& path) const { } return result; } catch (std::exception const& e) { - throw JsonParsingException(strf("Cannot parse json file: %s", path), e); + throw JsonParsingException(strf("Cannot parse json file: {}", path), e); } }