diff --git a/common/YAML.cpp b/common/YAML.cpp index 52c0a2aec3a47..40ac63fc63002 100644 --- a/common/YAML.cpp +++ b/common/YAML.cpp @@ -3,8 +3,6 @@ #include "YAML.h" -#include "Assertions.h" - #if RYML_VERSION_MAJOR > 0 || RYML_VERSION_MINOR >= 11 #include "c4/yml/error.def.hpp" // for ryml::err_basic_format etc #endif @@ -28,15 +26,16 @@ std::optional ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr callbacks.set_user_data(static_cast(&context)); callbacks.set_error_basic([](ryml::csubstr msg, const ryml::ErrorDataBasic& errdata, void* user_data) { + RapidYAMLContext* context = static_cast(user_data); + std::string description; auto callback = [&description](ryml::csubstr string) { description.append(string.str, string.len); }; ryml::err_basic_format(std::move(callback), msg, errdata); - // We might have already returned, so don't try to recover. - pxFailRel(description.c_str()); - std::abort(); + Error::SetString(context->error, std::move(description)); + std::longjmp(context->env, 1); }); callbacks.set_error_parse([](ryml::csubstr msg, const ryml::ErrorDataParse& errdata, void* user_data) { @@ -53,15 +52,16 @@ std::optional ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr }); callbacks.set_error_visit([](ryml::csubstr msg, const ryml::ErrorDataVisit& errdata, void* user_data) { + RapidYAMLContext* context = static_cast(user_data); + std::string description; auto callback = [&description](ryml::csubstr string) { description.append(string.str, string.len); }; ryml::err_visit_format(std::move(callback), msg, errdata); - // We've probably already returned, so don't try to recover. - pxFailRel(description.c_str()); - std::abort(); + Error::SetString(context->error, std::move(description)); + std::longjmp(context->env, 1); }); #else callbacks.m_user_data = static_cast(&context); diff --git a/pcsx2/GameDatabase.cpp b/pcsx2/GameDatabase.cpp index 6946144a098c2..573c0a8843d2b 100644 --- a/pcsx2/GameDatabase.cpp +++ b/pcsx2/GameDatabase.cpp @@ -32,7 +32,8 @@ namespace GameDatabaseSchema namespace GameDatabase { - static void parseAndInsert(const std::string_view serial, const ryml::NodeRef& node); + static void parseAndInsert(std::string_view serial, const ryml::ConstNodeRef& game_node); + static std::vector parseDynamicPatchEntries(std::string_view serial, const ryml::ConstNodeRef& entries_node); static void initDatabase(); } // namespace GameDatabase @@ -83,120 +84,122 @@ const char* GameDatabaseSchema::GameEntry::compatAsString() const } } -void GameDatabase::parseAndInsert(const std::string_view serial, const ryml::NodeRef& node) +void GameDatabase::parseAndInsert(const std::string_view serial, const ryml::ConstNodeRef& game_node) { GameDatabaseSchema::GameEntry gameEntry; - if (node.has_child("name")) - { - node["name"] >> gameEntry.name; - } - if (node.has_child("name-sort")) - { - node["name-sort"] >> gameEntry.name_sort; - } - if (node.has_child("name-en")) - { - node["name-en"] >> gameEntry.name_en; - } - if (node.has_child("region")) - { - node["region"] >> gameEntry.region; - } - if (node.has_child("compat")) + + if (const ryml::ConstNodeRef node = game_node.find_child("name"); node.readable() && node.has_val()) + ryml::from_chars(node.val(), &gameEntry.name); + + if (const ryml::ConstNodeRef node = game_node.find_child("name-sort"); node.readable() && node.has_val()) + ryml::from_chars(node.val(), &gameEntry.name_sort); + + if (const ryml::ConstNodeRef node = game_node.find_child("name-en"); node.readable() && node.has_val()) + ryml::from_chars(node.val(), &gameEntry.name_en); + + if (const ryml::ConstNodeRef node = game_node.find_child("region"); node.readable() && node.has_val()) + ryml::from_chars(node.val(), &gameEntry.region); + + if (const ryml::ConstNodeRef node = game_node.find_child("compat"); node.readable() && node.has_val() && node.val().is_integer()) { - int val = 0; - node["compat"] >> val; - gameEntry.compat = static_cast(val); + int value = 0; + ryml::from_chars(node.val(), &value); + gameEntry.compat = static_cast(value); } - if (node.has_child("roundModes")) + + if (const ryml::ConstNodeRef round_modes = game_node.find_child("roundModes"); round_modes.readable() && round_modes.is_map()) { - if (node["roundModes"].has_child("eeRoundMode")) + if (const ryml::ConstNodeRef node = round_modes.find_child("eeRoundMode"); node.readable() && node.has_val() && node.val().is_integer()) { - int eeVal = -1; - node["roundModes"]["eeRoundMode"] >> eeVal; - if (eeVal >= 0 && eeVal < static_cast(FPRoundMode::MaxCount)) - gameEntry.eeRoundMode = static_cast(eeVal); + int value = -1; + ryml::from_chars(node.val(), &value); + if (value >= 0 && value < static_cast(FPRoundMode::MaxCount)) + gameEntry.eeRoundMode = static_cast(value); else - Console.Error(fmt::format("GameDB: Invalid EE round mode '{}', specified for serial: '{}'.", eeVal, serial)); + Console.ErrorFmt("GameDB: Invalid EE round mode '{}', specified for serial: '{}'.", value, serial); } - if (node["roundModes"].has_child("eeDivRoundMode")) + if (const ryml::ConstNodeRef node = round_modes.find_child("eeDivRoundMode"); node.readable() && node.has_val() && node.val().is_integer()) { - int eeVal = -1; - node["roundModes"]["eeDivRoundMode"] >> eeVal; - if (eeVal >= 0 && eeVal < static_cast(FPRoundMode::MaxCount)) - gameEntry.eeDivRoundMode = static_cast(eeVal); + int value = -1; + ryml::from_chars(node.val(), &value); + if (value >= 0 && value < static_cast(FPRoundMode::MaxCount)) + gameEntry.eeDivRoundMode = static_cast(value); else - Console.Error(fmt::format("GameDB: Invalid EE division round mode '{}', specified for serial: '{}'.", eeVal, serial)); + Console.ErrorFmt("GameDB: Invalid EE division round mode '{}', specified for serial: '{}'.", value, serial); } - if (node["roundModes"].has_child("vuRoundMode")) + if (const ryml::ConstNodeRef node = round_modes.find_child("vuRoundMode"); node.readable() && node.has_val() && node.val().is_integer()) { - int vuVal = -1; - node["roundModes"]["vuRoundMode"] >> vuVal; - if (vuVal >= 0 && vuVal < static_cast(FPRoundMode::MaxCount)) + int value = -1; + ryml::from_chars(node.val(), &value); + if (value >= 0 && value < static_cast(FPRoundMode::MaxCount)) { - gameEntry.vu0RoundMode = static_cast(vuVal); - gameEntry.vu1RoundMode = static_cast(vuVal); + gameEntry.vu0RoundMode = static_cast(value); + gameEntry.vu1RoundMode = static_cast(value); } else { - Console.Error(fmt::format("GameDB: Invalid VU round mode '{}', specified for serial: '{}'.", vuVal, serial)); + Console.ErrorFmt("GameDB: Invalid VU round mode '{}', specified for serial: '{}'.", value, serial); } } - if (node["roundModes"].has_child("vu0RoundMode")) + if (const ryml::ConstNodeRef node = round_modes.find_child("vu0RoundMode"); node.readable() && node.has_val() && node.val().is_integer()) { - int vuVal = -1; - node["roundModes"]["vu0RoundMode"] >> vuVal; - if (vuVal >= 0 && vuVal < static_cast(FPRoundMode::MaxCount)) - gameEntry.vu0RoundMode = static_cast(vuVal); + int value = -1; + ryml::from_chars(node.val(), &value); + if (value >= 0 && value < static_cast(FPRoundMode::MaxCount)) + gameEntry.vu0RoundMode = static_cast(value); else - Console.Error(fmt::format("GameDB: Invalid VU0 round mode '{}', specified for serial: '{}'.", vuVal, serial)); + Console.ErrorFmt("GameDB: Invalid VU0 round mode '{}', specified for serial: '{}'.", value, serial); } - if (node["roundModes"].has_child("vu1RoundMode")) + if (const ryml::ConstNodeRef node = round_modes.find_child("vu1RoundMode"); node.readable() && node.has_val() && node.val().is_integer()) { - int vuVal = -1; - node["roundModes"]["vu1RoundMode"] >> vuVal; - if (vuVal >= 0 && vuVal < static_cast(FPRoundMode::MaxCount)) - gameEntry.vu1RoundMode = static_cast(vuVal); + int value = -1; + ryml::from_chars(node.val(), &value); + if (value >= 0 && value < static_cast(FPRoundMode::MaxCount)) + gameEntry.vu1RoundMode = static_cast(value); else - Console.Error(fmt::format("GameDB: Invalid VU1 round mode '{}', specified for serial: '{}'.", vuVal, serial)); + Console.ErrorFmt("GameDB: Invalid VU1 round mode '{}', specified for serial: '{}'.", value, serial); } } - if (node.has_child("clampModes")) + + if (const ryml::ConstNodeRef clamp_modes = game_node.find_child("clampModes"); clamp_modes.readable() && clamp_modes.is_map()) { - if (node["clampModes"].has_child("eeClampMode")) + if (const ryml::ConstNodeRef node = clamp_modes.find_child("eeClampMode"); node.readable() && node.has_val() && node.val().is_integer()) { - int eeVal = -1; - node["clampModes"]["eeClampMode"] >> eeVal; - gameEntry.eeClampMode = static_cast(eeVal); + int value = -1; + ryml::from_chars(node.val(), &value); + gameEntry.eeClampMode = static_cast(value); } - if (node["clampModes"].has_child("vuClampMode")) + if (const ryml::ConstNodeRef node = clamp_modes.find_child("vuClampMode"); node.readable() && node.has_val() && node.val().is_integer()) { - int vuVal = -1; - node["clampModes"]["vuClampMode"] >> vuVal; - gameEntry.vu0ClampMode = static_cast(vuVal); - gameEntry.vu1ClampMode = static_cast(vuVal); + int value = -1; + ryml::from_chars(node.val(), &value); + gameEntry.vu0ClampMode = static_cast(value); + gameEntry.vu1ClampMode = static_cast(value); } - if (node["clampModes"].has_child("vu0ClampMode")) + if (const ryml::ConstNodeRef node = clamp_modes.find_child("vu0ClampMode"); node.readable() && node.has_val() && node.val().is_integer()) { - int vuVal = -1; - node["clampModes"]["vu0ClampMode"] >> vuVal; - gameEntry.vu0ClampMode = static_cast(vuVal); + int value = -1; + ryml::from_chars(node.val(), &value); + gameEntry.vu0ClampMode = static_cast(value); } - if (node["clampModes"].has_child("vu1ClampMode")) + if (const ryml::ConstNodeRef node = clamp_modes.find_child("vu1ClampMode"); node.readable() && node.has_val() && node.val().is_integer()) { - int vuVal = -1; - node["clampModes"]["vu1ClampMode"] >> vuVal; - gameEntry.vu1ClampMode = static_cast(vuVal); + int value = -1; + ryml::from_chars(node.val(), &value); + gameEntry.vu1ClampMode = static_cast(value); } } // Validate game fixes, invalid ones will be dropped! - if (node.has_child("gameFixes") && node["gameFixes"].has_children()) + if (const ryml::ConstNodeRef game_fixes = game_node.find_child("gameFixes"); game_fixes.readable() && game_fixes.has_children()) { - for (const auto& n : node["gameFixes"].children()) + for (const ryml::ConstNodeRef& game_fix_node : game_fixes.children()) { - bool fixValidated = false; - auto fix = std::string(n.val().str, n.val().len); + if (!game_fix_node.has_val()) + continue; + + bool fix_validated = false; + std::string fix(game_fix_node.val().str, game_fix_node.val().len); // Enum values don't end with Hack, but gamedb does, so remove it before comparing. if (fix.ends_with("Hack")) @@ -208,25 +211,28 @@ void GameDatabase::parseAndInsert(const std::string_view serial, const ryml::Nod std::find(gameEntry.gameFixes.begin(), gameEntry.gameFixes.end(), id) == gameEntry.gameFixes.end()) { gameEntry.gameFixes.push_back(id); - fixValidated = true; + fix_validated = true; break; } } } - if (!fixValidated) + if (!fix_validated) { - Console.Error(fmt::format("GameDB: Invalid gamefix: '{}', specified for serial: '{}'. Dropping!", fix, serial)); + Console.ErrorFmt("GameDB: Invalid gamefix: '{}', specified for serial: '{}'. Dropping!", fix, serial); } } } - if (node.has_child("speedHacks") && node["speedHacks"].has_children()) + if (const ryml::ConstNodeRef speed_hacks = game_node.find_child("speedHacks"); speed_hacks.readable() && speed_hacks.has_children()) { - for (const auto& n : node["speedHacks"].children()) + for (const ryml::ConstNodeRef& node : speed_hacks.children()) { - const std::string_view id_view = std::string_view(n.key().str, n.key().len); - const std::string_view value_view = std::string_view(n.val().str, n.val().len); + if (!node.has_val()) + continue; + + const std::string_view id_view = std::string_view(node.key().str, node.key().len); + const std::string_view value_view = std::string_view(node.val().str, node.val().len); const std::optional id = Pcsx2Config::SpeedhackOptions::ParseSpeedHackName(id_view); const std::optional value = StringUtil::FromChars(value_view); @@ -238,24 +244,27 @@ void GameDatabase::parseAndInsert(const std::string_view serial, const ryml::Nod } else { - Console.Error(fmt::format("GameDB: Invalid speedhack: '{}={}', specified for serial: '{}'. Dropping!", - id_view, value_view, serial)); + Console.ErrorFmt("GameDB: Invalid speedhack: '{}={}', specified for serial: '{}'. Dropping!", + id_view, value_view, serial); } } } - if (node.has_child("gsHWFixes")) + if (const ryml::ConstNodeRef gs_hw_fixes = game_node.find_child("gsHWFixes"); gs_hw_fixes.readable() && gs_hw_fixes.has_children()) { - for (const auto& n : node["gsHWFixes"].children()) + for (const ryml::ConstNodeRef& node : gs_hw_fixes.children()) { - const std::string_view id_name(n.key().data(), n.key().size()); - std::optional id = GameDatabaseSchema::parseHWFixName(id_name); + if (!node.has_val()) + continue; + + const std::string_view id_name(node.key().data(), node.key().size()); + const std::optional id = GameDatabaseSchema::parseHWFixName(id_name); std::optional value; if (id.has_value() && (id.value() == GameDatabaseSchema::GSHWFixId::GetSkipCount || id.value() == GameDatabaseSchema::GSHWFixId::BeforeDraw || id.value() == GameDatabaseSchema::GSHWFixId::MoveHandler)) { - const std::string_view str_value(n.has_val() ? std::string_view(n.val().data(), n.val().size()) : std::string_view()); + const std::string_view str_value(node.has_val() ? std::string_view(node.val().data(), node.val().size()) : std::string_view()); if (id.value() == GameDatabaseSchema::GSHWFixId::GetSkipCount) value = GSLookupGetSkipCountFunctionId(str_value); else if (id.value() == GameDatabaseSchema::GSHWFixId::BeforeDraw) @@ -265,17 +274,17 @@ void GameDatabase::parseAndInsert(const std::string_view serial, const ryml::Nod if (value.value_or(-1) < 0) { - Console.Error(fmt::format("GameDB: Invalid GS HW Fix Value for '{}' in '{}': '{}'", id_name, serial, str_value)); + Console.ErrorFmt("GameDB: Invalid GS HW Fix Value for '{}' in '{}': '{}'", id_name, serial, str_value); continue; } } else { - value = n.has_val() ? StringUtil::FromChars(std::string_view(n.val().data(), n.val().size())) : 1; + value = node.has_val() ? StringUtil::FromChars(std::string_view(node.val().data(), node.val().size())) : 1; } if (!id.has_value() || !value.has_value()) { - Console.Error(fmt::format("GameDB: Invalid GS HW Fix: '{}' specified for serial '{}'. Dropping!", id_name, serial)); + Console.ErrorFmt("GameDB: Invalid GS HW Fix: '{}' specified for serial '{}'. Dropping!", id_name, serial); continue; } @@ -285,71 +294,86 @@ void GameDatabase::parseAndInsert(const std::string_view serial, const ryml::Nod // Memory Card Filters - Store as a vector to allow flexibility in the future // - currently they are used as a '\n' delimited string in the app - if (node.has_child("memcardFilters") && node["memcardFilters"].has_children()) + if (const ryml::ConstNodeRef memcard_filters = game_node.find_child("memcardFilters"); memcard_filters.readable() && memcard_filters.has_children()) { - for (const auto& n : node["memcardFilters"].children()) + for (const ryml::ConstNodeRef& node : memcard_filters.children()) { - auto memcardFilter = std::string(n.val().str, n.val().len); - gameEntry.memcardFilters.emplace_back(std::move(memcardFilter)); + if (!node.has_val()) + continue; + + std::string memcard_filter(node.val().str, node.val().len); + gameEntry.memcardFilters.emplace_back(std::move(memcard_filter)); } } // Game Patches - if (node.has_child("patches") && node["patches"].has_children()) + if (const ryml::ConstNodeRef patches = game_node.find_child("patches"); patches.readable() && patches.has_children()) { - for (const auto& n : node["patches"].children()) + for (const ryml::ConstNodeRef& patch_node : patches.children()) { // use a crc of 0 for default patches - const std::string_view crc_str(n.key().str, n.key().len); + const std::string_view crc_str(patch_node.key().str, patch_node.key().len); const std::optional crc = (StringUtil::compareNoCase(crc_str, "default")) ? std::optional(0) : StringUtil::FromChars(crc_str, 16); if (!crc.has_value()) { - Console.Error(fmt::format("GameDB: Invalid CRC '{}' found for serial: '{}'. Skipping!", crc_str, serial)); + Console.ErrorFmt("GameDB: Invalid CRC '{}' found for serial '{}'. Skipping!", crc_str, serial); continue; } if (gameEntry.patches.find(crc.value()) != gameEntry.patches.end()) { - Console.Error(fmt::format("GameDB: Duplicate CRC '{}' found for serial: '{}'. Skipping, CRCs are case-insensitive!", crc_str, serial)); + Console.ErrorFmt("GameDB: Duplicate CRC '{}' found for serial '{}'. Skipping, CRCs are case-insensitive!", crc_str, serial); continue; } std::string patch; - if (n.has_child("content")) - n["content"] >> patch; + if (ryml::ConstNodeRef content_node = patch_node.find_child("content"); content_node.readable()) + ryml::from_chars(content_node.val(), &patch); gameEntry.patches.emplace(crc.value(), std::move(patch)); } } - if (node.has_child("dynaPatches") && node["dynaPatches"].has_children()) + if (const ryml::ConstNodeRef dyna_patches = game_node.find_child("dynaPatches"); dyna_patches.readable() && dyna_patches.has_children()) { - for (const auto& n : node["dynaPatches"].children()) + for (const ryml::ConstNodeRef& dyna_patch_node : dyna_patches.children()) { - Patch::DynamicPatch patch; + Patch::DynamicPatch& patch = gameEntry.dynaPatches.emplace_back(); + patch.pattern = parseDynamicPatchEntries(serial, dyna_patch_node.at("pattern")); + patch.replacement = parseDynamicPatchEntries(serial, dyna_patch_node.at("replacement")); + } + } - if (n.has_child("pattern") && n["pattern"].has_children()) - { - for (const auto& db_pattern : n["pattern"].children()) - { - Patch::DynamicPatchEntry entry; - db_pattern["offset"] >> entry.offset; - db_pattern["value"] >> entry.value; + s_game_db.emplace(std::move(serial), std::move(gameEntry)); +} - patch.pattern.push_back(entry); - } - for (const auto& db_replacement : n["replacement"].children()) - { - Patch::DynamicPatchEntry entry; - db_replacement["offset"] >> entry.offset; - db_replacement["value"] >> entry.value; +std::vector GameDatabase::parseDynamicPatchEntries(const std::string_view serial, const ryml::ConstNodeRef& entries_node) +{ + std::vector entries; - patch.replacement.push_back(entry); - } + if (entries_node.readable() && entries_node.has_children()) + { + for (const auto& entry_node : entries_node.children()) + { + ryml::ConstNodeRef offset_node = entry_node.find_child("offset"); + if (!offset_node.readable() || !offset_node.has_val() || !offset_node.val().is_integer()) + { + Console.ErrorFmt("GameDB: Invalid dynamic patch entry found for serial '{}'.", serial); + continue; + } + + ryml::ConstNodeRef value_node = entry_node.find_child("value"); + if (!value_node.readable() || !value_node.has_val() || !value_node.val().is_integer()) + { + Console.ErrorFmt("GameDB: Invalid dynamic patch entry found for serial '{}'.", serial); + continue; } - gameEntry.dynaPatches.push_back(patch); + + Patch::DynamicPatchEntry& entry = entries.emplace_back(); + ryml::from_chars(offset_node.val(), &entry.offset); + ryml::from_chars(value_node.val(), &entry.value); } } - s_game_db.emplace(std::move(serial), std::move(gameEntry)); + return entries; } static const char* s_round_modes[static_cast(FPRoundMode::MaxCount)] = { @@ -978,7 +1002,7 @@ void GameDatabase::initDatabase() const ryml::csubstr yaml = ryml::to_csubstr(*buffer); Error error; - std::optional tree = ParseYAMLFromString(yaml, ryml::to_csubstr(name), &error); + const std::optional tree = ParseYAMLFromString(yaml, ryml::to_csubstr(name), &error); if (!tree.has_value()) { Console.ErrorFmt("GameDB: Failed to parse game database file {}:", path); @@ -986,11 +1010,11 @@ void GameDatabase::initDatabase() return; } - ryml::NodeRef root = tree->rootref(); + ryml::ConstNodeRef root = tree->crootref(); - for (const ryml::NodeRef& n : root.children()) + for (const ryml::ConstNodeRef& game_node : root.children()) { - auto serial = StringUtil::toLower(std::string(n.key().str, n.key().len)); + auto serial = StringUtil::toLower(std::string(game_node.key().str, game_node.key().len)); // Serials and CRCs must be inserted as lower-case, as that is how they are retrieved // this is because the application may pass a lowercase CRC or serial along @@ -1002,10 +1026,10 @@ void GameDatabase::initDatabase() continue; } - if (n.is_map()) - { - parseAndInsert(serial, n); - } + if (!game_node.is_map()) + continue; + + parseAndInsert(serial, game_node); } } @@ -1074,25 +1098,30 @@ static constexpr char HASHDB_YAML_FILE_NAME[] = "RedumpDatabase.yaml"; std::unordered_map s_track_hash_to_entry_map; std::vector s_hash_database; -static bool parseHashDatabaseEntry(const ryml::NodeRef& node) +static bool parseHashDatabaseEntry(const ryml::ConstNodeRef& entry_node) { - if (!node.has_child("name") || !node.has_child("hashes")) + const ryml::ConstNodeRef name_node = entry_node.find_child("name"); + const ryml::ConstNodeRef hashes_node = entry_node.find_child("hashes"); + if (!name_node.readable() || !name_node.has_val() || !hashes_node.readable() || !hashes_node.has_children()) { Console.Warning("[HashDatabase] Incomplete entry found."); return false; } GameDatabase::HashDatabaseEntry entry; - node["name"] >> entry.name; - if (node.has_child("version")) - node["version"] >> entry.version; - if (node.has_child("serial")) - node["serial"] >> entry.serial; + ryml::from_chars(name_node.val(), &entry.name); + + if (const ryml::ConstNodeRef node = entry_node.find_child("version"); node.readable() && node.has_val()) + ryml::from_chars(node.val(), &entry.version); + if (const ryml::ConstNodeRef node = entry_node.find_child("serial"); node.readable() && node.has_val()) + ryml::from_chars(node.val(), &entry.serial); const u32 index = static_cast(s_hash_database.size()); - for (const ryml::ConstNodeRef& n : node["hashes"].children()) + for (const ryml::ConstNodeRef& hash_node : hashes_node.children()) { - if (!n.is_map() || !n.has_child("size") || !n.has_child("md5")) + const ryml::ConstNodeRef size_node = hash_node.find_child("size"); + const ryml::ConstNodeRef md5_node = hash_node.find_child("md5"); + if (!hash_node.is_map() || !size_node.readable() || !size_node.has_val() || !size_node.val().is_integer() || !md5_node.readable()) { Console.ErrorFmt("[HashDatabase] Incomplete hash definition in {}", entry.name); return false; @@ -1100,8 +1129,8 @@ static bool parseHashDatabaseEntry(const ryml::NodeRef& node) GameDatabase::TrackHash th; std::string md5; - n["md5"] >> md5; - n["size"] >> th.size; + ryml::from_chars(md5_node.val(), &md5); + ryml::from_chars(size_node.val(), &th.size); if (!th.parseHash(md5)) { @@ -1140,7 +1169,7 @@ bool GameDatabase::loadHashDatabase() ryml::csubstr yaml = ryml::to_csubstr(*buffer); Error error; - std::optional tree = ParseYAMLFromString(yaml, ryml::to_csubstr(name), &error); + const std::optional tree = ParseYAMLFromString(yaml, ryml::to_csubstr(name), &error); if (!tree.has_value()) { Console.ErrorFmt("[HashDatabase] Failed to parse hash database file {}:", path); @@ -1148,12 +1177,12 @@ bool GameDatabase::loadHashDatabase() return false; } - ryml::NodeRef root = tree->rootref(); + ryml::ConstNodeRef root = tree->crootref(); bool okay = true; - for (const ryml::NodeRef& n : root.children()) + for (const ryml::ConstNodeRef& entry_node : root.children()) { - if (!parseHashDatabaseEntry(n)) + if (!parseHashDatabaseEntry(entry_node)) { okay = false; break; diff --git a/pcsx2/SIO/Memcard/MemoryCardFolder.cpp b/pcsx2/SIO/Memcard/MemoryCardFolder.cpp index 9cc325081a4b8..5d857ebd816df 100644 --- a/pcsx2/SIO/Memcard/MemoryCardFolder.cpp +++ b/pcsx2/SIO/Memcard/MemoryCardFolder.cpp @@ -1788,32 +1788,26 @@ std::vector FolderMemoryCard::GetOrderedF std::string filePath(Path::Combine(dirPath, fd.FileName)); if (!(fd.Attributes & FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY)) { - std::optional yaml = loadYamlFile(Path::Combine(dirPath, "_pcsx2_index").c_str()); + const std::optional yaml = loadYamlFile(Path::Combine(dirPath, "_pcsx2_index").c_str()); EnumeratedFileEntry entry{fd.FileName, fd.CreationTime, fd.ModificationTime, true}; int64_t newOrder = orderForLegacyFiles--; if (yaml.has_value() && !yaml.value().empty()) { - ryml::NodeRef index = yaml.value().rootref(); - for (const auto& n : index.children()) + const ryml::ConstNodeRef index_node = yaml.value().crootref(); + if (const ryml::ConstNodeRef child_node = index_node.find_child(ryml::to_csubstr(fd.FileName)); child_node.readable()) { - auto key = std::string(n.key().str, n.key().len); - } - if (index.has_child(ryml::to_csubstr(fd.FileName))) - { - const auto& node = index[ryml::to_csubstr(fd.FileName)]; - if (node.has_child("timeCreated")) - { - node["timeCreated"] >> entry.m_timeCreated; - } - if (node.has_child("timeModified")) - { - node["timeModified"] >> entry.m_timeModified; - } - if (node.has_child("order")) - { - node["order"] >> newOrder; - } + const ryml::ConstNodeRef time_created = child_node.find_child("timeCreated"); + if (time_created.readable() && time_created.has_val() && time_created.val().is_integer()) + ryml::from_chars(time_created.val(), &entry.m_timeCreated); + + const ryml::ConstNodeRef time_modified = child_node.find_child("timeModified"); + if (time_modified.readable() && time_modified.has_val() && time_modified.val().is_integer()) + ryml::from_chars(time_modified.val(), &entry.m_timeModified); + + const ryml::ConstNodeRef order = child_node.find_child("order"); + if (order.readable() && order.has_val() && order.val().is_integer()) + ryml::from_chars(order.val(), &newOrder); } }