From 842c2a422fc900ebac8a0773962ccc8ee95b3a60 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Thu, 21 Nov 2024 22:37:42 +0100 Subject: [PATCH] ProcessJson: Cache parsed JSON to make accessing significantly faster The cache is invalidated when the string is set --- src/game_interpreter.cpp | 11 ++++++++--- src/game_strings.cpp | 23 +++++++++++++++++++++++ src/game_strings.h | 28 ++++++++++++++++++++++++++-- src/json_helper.cpp | 28 +++++++--------------------- src/json_helper.h | 4 ++-- 5 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index ed54c39cfe..d903697b8f 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -5080,7 +5080,12 @@ bool Game_Interpreter::CommandEasyRpgProcessJson(lcf::rpg::EventCommand const& c int target_var_id = ValueOrVariable(com.parameters[6], com.parameters[7]); std::string json_path = ToString(CommandStringOrVariable(com, 8, 9)); - std::string json_data = ToString(Main_Data::game_strings->Get(source_var_id)); + auto* json_data = Main_Data::game_strings->ParseJson(source_var_id); + + if (!json_data) { + Output::Warning("JSON Parse error for {}", Main_Data::game_strings->Get(source_var_id)); + return true; + } if (target_var_type == 2 && !Player::IsPatchManiac()) { Output::Warning("CommandEasyRpgProcessJson: String operations require Maniac Patch support"); @@ -5090,7 +5095,7 @@ bool Game_Interpreter::CommandEasyRpgProcessJson(lcf::rpg::EventCommand const& c std::optional result; if (operation == 0) { // Get operation: Extract a value from JSON data - result = Json_Helper::GetValue(json_data, json_path); + result = Json_Helper::GetValue(*json_data, json_path); if (result) { switch (target_var_type) { @@ -5127,7 +5132,7 @@ bool Game_Interpreter::CommandEasyRpgProcessJson(lcf::rpg::EventCommand const& c return true; } - result = Json_Helper::SetValue(json_data, json_path, new_value); + result = Json_Helper::SetValue(*json_data, json_path, new_value); if (result) { Main_Data::game_strings->Asg({ source_var_id }, *result); diff --git a/src/game_strings.cpp b/src/game_strings.cpp index c16d988a33..0dfb4319ac 100644 --- a/src/game_strings.cpp +++ b/src/game_strings.cpp @@ -28,11 +28,34 @@ #include "player.h" #include "utils.h" +#ifdef HAVE_NLOHMANN_JSON +#include "json_helper.h" +#endif + void Game_Strings::WarnGet(int id) const { Output::Debug("Invalid read strvar[{}]!", id); --_warnings; } +#ifdef HAVE_NLOHMANN_JSON +nlohmann::json* Game_Strings::ParseJson(int id) { + auto it = _json_cache.find(id); + if (it != _json_cache.end()) { + return &(it->second); + } + + auto str = ToString(Get(id)); + auto res = Json_Helper::Parse(str); + + if (!res) { + return nullptr; + } else { + _json_cache[id] = *res; + return &_json_cache[id]; + } +} +#endif + StringView Game_Strings::Asg(Str_Params params, StringView string) { Set(params, string); return Get(params.string_id); diff --git a/src/game_strings.h b/src/game_strings.h index d630bc8ab5..dbee88cb3c 100644 --- a/src/game_strings.h +++ b/src/game_strings.h @@ -15,7 +15,8 @@ * along with EasyRPG Player. If not, see . */ - // Headers +// Headers +#include "system.h" #include #include #include @@ -27,6 +28,10 @@ #include "player.h" #include "string_view.h" +#ifdef HAVE_NLOHMANN_JSON +#include +#endif + /** * Game_Strings class. */ @@ -59,6 +64,10 @@ class Game_Strings { StringView GetWithMode(StringView str_data, int mode, int arg, const Game_Variables& variables) const; StringView GetWithModeAndPos(StringView str_data, int mode, int arg, int* pos, const Game_Variables& variables); +#ifdef HAVE_NLOHMANN_JSON + nlohmann::json* ParseJson(int id); +#endif + StringView Asg(Str_Params params, StringView string); StringView Cat(Str_Params params, StringView string); int ToNum(Str_Params params, int var_id, Game_Variables& variables); @@ -85,8 +94,11 @@ class Game_Strings { Strings_t _strings; mutable int _warnings = max_warnings; -}; +#ifdef HAVE_NLOHMANN_JSON + std::unordered_map _json_cache; +#endif +}; inline void Game_Strings::Set(Str_Params params, StringView string) { if (params.string_id <= 0) { @@ -108,10 +120,18 @@ inline void Game_Strings::Set(Str_Params params, StringView string) { } else { it->second = ins_string; } + +#ifdef HAVE_NLOHMANN_JSON + _json_cache.erase(params.string_id); +#endif } inline void Game_Strings::SetData(Strings_t s) { _strings = std::move(s); + +#ifdef HAVE_NLOHMANN_JSON + _json_cache.clear(); +#endif } inline void Game_Strings::SetData(const std::vector& s) { @@ -122,6 +142,10 @@ inline void Game_Strings::SetData(const std::vector& s) { } ++i; } + +#ifdef HAVE_NLOHMANN_JSON + _json_cache.clear(); +#endif } inline const Game_Strings::Strings_t& Game_Strings::GetData() const { diff --git a/src/json_helper.cpp b/src/json_helper.cpp index c0f26db2c8..7205f361a1 100644 --- a/src/json_helper.cpp +++ b/src/json_helper.cpp @@ -61,14 +61,7 @@ namespace Json_Helper { return json_obj; } - std::optional GetValue(std::string_view json_data, std::string_view json_path) { - auto json_obj = Parse(json_data); - - if (!json_obj) { - Output::Warning("JSON: Parse error for {}", json_data); - return {}; - } - + std::optional GetValue(nlohmann::json& json_obj, std::string_view json_path) { json::json_pointer ptr((std::string(json_path))); if (ptr.empty()) { @@ -76,21 +69,14 @@ namespace Json_Helper { return {}; } - if (!json_obj->contains(ptr)) { + if (!json_obj.contains(ptr)) { return ""; } - return GetValueAsString((*json_obj)[ptr]); + return GetValueAsString(json_obj[ptr]); } - std::string SetValue(std::string_view json_data, std::string_view json_path, std::string_view value) { - auto json_obj = Parse(json_data); - - if (!json_obj) { - Output::Warning("JSON Parse error for {}", json_data); - return std::string(json_data); - } - + std::string SetValue(nlohmann::json& json_obj, std::string_view json_path, std::string_view value) { json::json_pointer ptr((std::string(json_path))); if (ptr.empty()) { @@ -102,12 +88,12 @@ namespace Json_Helper { if (obj_value.is_discarded()) { // If parsing fails, treat it as a string value - (*json_obj)[ptr] = std::string(value); + json_obj[ptr] = std::string(value); } else { - (*json_obj)[ptr] = obj_value; + json_obj[ptr] = obj_value; } - return (*json_obj).dump(); + return json_obj.dump(); } } diff --git a/src/json_helper.h b/src/json_helper.h index 75a5e775b3..f9cd117e12 100644 --- a/src/json_helper.h +++ b/src/json_helper.h @@ -28,8 +28,8 @@ namespace Json_Helper { std::optional Parse(std::string_view json_data); - std::optional GetValue(std::string_view json_data, std::string_view json_path); - std::string SetValue(std::string_view json_data, std::string_view json_path, std::string_view value); + std::optional GetValue(nlohmann::json& json_obj, std::string_view json_path); + std::string SetValue(nlohmann::json& json_obj, std::string_view json_path, std::string_view value); } #endif // HAVE_NLOHMANN_JSON