diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index af48ba7e13..dd71f8b967 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -87,6 +87,7 @@ add_library(common JitRegister.cpp JitRegister.h JsonUtil.h + JsonUtil.cpp Lazy.h LinearDiskCache.h Logging/ConsoleListener.h diff --git a/Source/Core/Common/JsonUtil.cpp b/Source/Core/Common/JsonUtil.cpp index 3e842c5c18..fa9b8a73c9 100644 --- a/Source/Core/Common/JsonUtil.cpp +++ b/Source/Core/Common/JsonUtil.cpp @@ -3,6 +3,10 @@ #include "Common/JsonUtil.h" +#include + +#include "Common/FileUtil.h" + picojson::object ToJsonObject(const Common::Vec3& vec) { picojson::object obj; @@ -38,3 +42,27 @@ std::optional ReadBoolFromJson(const picojson::object& obj, const std::str return std::nullopt; return it->second.get(); } + +bool JsonToFile(const std::string& filename, const picojson::value& root, bool prettify) +{ + std::ofstream json_stream; + File::OpenFStream(json_stream, filename, std::ios_base::out); + if (!json_stream.is_open()) + { + return false; + } + json_stream << root.serialize(prettify); + return true; +} + +bool JsonFromFile(const std::string& filename, picojson::value* root, std::string* error) +{ + std::string json_data; + if (!File::ReadFileToString(filename, json_data)) + { + return false; + } + + *error = picojson::parse(*root, json_data); + return error->empty(); +} diff --git a/Source/Core/Common/JsonUtil.h b/Source/Core/Common/JsonUtil.h index eec836d507..c830d777a4 100644 --- a/Source/Core/Common/JsonUtil.h +++ b/Source/Core/Common/JsonUtil.h @@ -9,7 +9,6 @@ #include -#include "Common/MathUtil.h" #include "Common/Matrix.h" // Ideally this would use a concept like, 'template ' to constrain it, @@ -47,7 +46,7 @@ std::optional ReadNumericFromJson(const picojson::object& obj, const std:: return std::nullopt; if (!it->second.is()) return std::nullopt; - return MathUtil::SaturatingCast(it->second.get()); + return static_cast(it->second.get()); } std::optional ReadStringFromJson(const picojson::object& obj, const std::string& key); @@ -56,3 +55,6 @@ std::optional ReadBoolFromJson(const picojson::object& obj, const std::str picojson::object ToJsonObject(const Common::Vec3& vec); void FromJson(const picojson::object& obj, Common::Vec3& vec); + +bool JsonToFile(const std::string& filename, const picojson::value& root, bool prettify = false); +bool JsonFromFile(const std::string& filename, picojson::value* root, std::string* error); diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index beec3e9a2d..e18d83375b 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -813,6 +813,7 @@ + diff --git a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp index 89aa00c8d3..870dbf9bba 100644 --- a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp +++ b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp @@ -12,6 +12,7 @@ #include "Common/CommonPaths.h" #include "Common/FileUtil.h" #include "Common/IniFile.h" +#include "Common/JsonUtil.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" #include "Core/ConfigManager.h" @@ -23,18 +24,9 @@ namespace InputCommon::DynamicInputTextures { Configuration::Configuration(const std::string& json_path) { - std::string json_data; - if (!File::ReadFileToString(json_path, json_data)) - { - ERROR_LOG_FMT(VIDEO, "Failed to load dynamic input json file '{}'", json_path); - m_valid = false; - return; - } - picojson::value root; - const auto error = picojson::parse(root, json_data); - - if (!error.empty()) + std::string error; + if (!JsonFromFile(json_path, &root, &error)) { ERROR_LOG_FMT(VIDEO, "Failed to load dynamic input json file '{}' due to parse error: {}", json_path, error); diff --git a/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.cpp b/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.cpp index be5159b448..90d77d8ec9 100644 --- a/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.cpp +++ b/Source/Core/VideoCommon/Assets/DirectFilesystemAssetLibrary.cpp @@ -10,6 +10,7 @@ #include "Common/FileUtil.h" #include "Common/IOFile.h" +#include "Common/JsonUtil.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" #include "VideoCommon/Assets/MaterialAsset.h" @@ -133,24 +134,16 @@ CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadPixelShader(const return {}; } - std::string json_data; - if (!File::ReadFileToString(PathToString(metadata->second), json_data)) - { - ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the json file '{}',", asset_id, - PathToString(metadata->second)); - return {}; - } - picojson::value root; - const auto error = picojson::parse(root, json_data); - - if (!error.empty()) + std::string error; + if (!JsonFromFile(PathToString(metadata->second), &root, &error)) { ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the json file '{}', due to parse error: {}", asset_id, PathToString(metadata->second), error); return {}; } + if (!root.is()) { ERROR_LOG_FMT( @@ -181,18 +174,21 @@ CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadMaterial(const As } const auto& asset_path = asset_map.begin()->second; - std::string json_data; - if (!File::ReadFileToString(PathToString(asset_path), json_data)) + std::size_t metadata_size; { - ERROR_LOG_FMT(VIDEO, "Asset '{}' error - material failed to load the json file '{}',", - asset_id, PathToString(asset_path)); - return {}; + std::error_code ec; + metadata_size = std::filesystem::file_size(asset_path, ec); + if (ec) + { + ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to get material file size with error '{}'!", + asset_id, ec); + return {}; + } } picojson::value root; - const auto error = picojson::parse(root, json_data); - - if (!error.empty()) + std::string error; + if (!JsonFromFile(PathToString(asset_path), &root, &error)) { ERROR_LOG_FMT( VIDEO, @@ -220,7 +216,7 @@ CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadMaterial(const As return {}; } - return LoadInfo{json_data.size(), GetLastAssetWriteTime(asset_id)}; + return LoadInfo{metadata_size, GetLastAssetWriteTime(asset_id)}; } CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadMesh(const AssetID& asset_id, @@ -292,18 +288,9 @@ CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadMesh(const AssetI return {}; } - std::string json_data; - if (!File::ReadFileToString(PathToString(metadata->second), json_data)) - { - ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the json file '{}'!", asset_id, - PathToString(metadata->second)); - return {}; - } - picojson::value root; - const auto error = picojson::parse(root, json_data); - - if (!error.empty()) + std::string error; + if (!JsonFromFile(PathToString(metadata->second), &root, &error)) { ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the json file '{}', due to parse error: {}", @@ -362,18 +349,9 @@ CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadTexture(const Ass return {}; } - std::string json_data; - if (!File::ReadFileToString(PathToString(metadata->second), json_data)) - { - ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the json file '{}',", asset_id, - PathToString(metadata->second)); - return {}; - } - picojson::value root; - const auto error = picojson::parse(root, json_data); - - if (!error.empty()) + std::string error; + if (!JsonFromFile(PathToString(metadata->second), &root, &error)) { ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the json file '{}', due to parse error: {}", diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp index 62586202b5..76d1ad6af6 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp +++ b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsMod.cpp @@ -7,6 +7,7 @@ #include "Common/CommonPaths.h" #include "Common/FileUtil.h" +#include "Common/JsonUtil.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" @@ -15,17 +16,9 @@ std::optional GraphicsModConfig::Create(const std::string& file_path, Source source) { - std::string json_data; - if (!File::ReadFileToString(file_path, json_data)) - { - ERROR_LOG_FMT(VIDEO, "Failed to load graphics mod json file '{}'", file_path); - return std::nullopt; - } - picojson::value root; - const auto error = picojson::parse(root, json_data); - - if (!error.empty()) + std::string error; + if (!JsonFromFile(file_path, &root, &error)) { ERROR_LOG_FMT(VIDEO, "Failed to load graphics mod json file '{}' due to parse error: {}", file_path, error); diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.cpp index 0873c09e91..5fa2c011b6 100644 --- a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.cpp +++ b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.cpp @@ -12,6 +12,7 @@ #include "Common/CommonPaths.h" #include "Common/FileSearch.h" #include "Common/FileUtil.h" +#include "Common/JsonUtil.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" #include "Core/ConfigManager.h" @@ -42,17 +43,9 @@ void GraphicsModGroupConfig::Load() std::set known_paths; if (File::Exists(file_path)) { - std::string json_data; - if (!File::ReadFileToString(file_path, json_data)) - { - ERROR_LOG_FMT(VIDEO, "Failed to load graphics mod group json file '{}'", file_path); - return; - } - picojson::value root; - const auto error = picojson::parse(root, json_data); - - if (!error.empty()) + std::string error; + if (!JsonFromFile(file_path, &root, &error)) { ERROR_LOG_FMT(VIDEO, "Failed to load graphics mod group json file '{}' due to parse error: {}",