From 623f87df585024a9901aaaf5662833a623251bd5 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 9 Sep 2024 00:35:31 +1000 Subject: [PATCH] Common: Extract out ryml helpers --- src/common/CMakeLists.txt | 1 + src/common/common.vcxproj | 1 + src/common/common.vcxproj.filters | 1 + src/common/ryml_helpers.h | 124 +++++++++++++++++++++++++++++ src/core/game_database.cpp | 125 ++---------------------------- 5 files changed, 134 insertions(+), 118 deletions(-) create mode 100644 src/common/ryml_helpers.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 2403ab75b..f1531abad 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -44,6 +44,7 @@ add_library(common perf_scope.h progress_callback.cpp progress_callback.h + ryml_helpers.h scoped_guard.h settings_interface.h sha1_digest.cpp diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 54221634c..bbaab73d1 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -31,6 +31,7 @@ + diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index 262410fa2..a671d44e9 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters @@ -48,6 +48,7 @@ + diff --git a/src/common/ryml_helpers.h b/src/common/ryml_helpers.h new file mode 100644 index 000000000..ddde54969 --- /dev/null +++ b/src/common/ryml_helpers.h @@ -0,0 +1,124 @@ +// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin +// SPDX-License-Identifier: CC-BY-NC-ND-4.0 + +#include "types.h" + +#include "ryml.hpp" + +#include +#include + +// RapidYAML utility routines. + +[[maybe_unused]] ALWAYS_INLINE std::string_view to_stringview(const c4::csubstr& s) +{ + return std::string_view(s.data(), s.size()); +} + +[[maybe_unused]] ALWAYS_INLINE std::string_view to_stringview(const c4::substr& s) +{ + return std::string_view(s.data(), s.size()); +} + +[[maybe_unused]] ALWAYS_INLINE c4::csubstr to_csubstr(std::string_view sv) +{ + return c4::csubstr(sv.data(), sv.length()); +} + +[[maybe_unused]] static bool GetStringFromObject(const ryml::ConstNodeRef& object, std::string_view key, + std::string* dest) +{ + dest->clear(); + + const ryml::ConstNodeRef member = object.find_child(to_csubstr(key)); + if (!member.valid()) + return false; + + const c4::csubstr val = member.val(); + if (!val.empty()) + dest->assign(val.data(), val.size()); + + return true; +} + +template +[[maybe_unused]] static bool GetUIntFromObject(const ryml::ConstNodeRef& object, std::string_view key, T* dest) +{ + *dest = 0; + + const ryml::ConstNodeRef member = object.find_child(to_csubstr(key)); + if (!member.valid()) + return false; + + const c4::csubstr val = member.val(); + if (val.empty()) + { + ERROR_LOG("Unexpected empty value in {}", key); + return false; + } + + const std::optional opt_value = StringUtil::FromChars(to_stringview(val)); + if (!opt_value.has_value()) + { + ERROR_LOG("Unexpected non-uint value in {}", key); + return false; + } + + *dest = opt_value.value(); + return true; +} + +template +[[maybe_unused]] static std::optional GetOptionalTFromObject(const ryml::ConstNodeRef& object, std::string_view key) +{ + std::optional ret; + + const ryml::ConstNodeRef member = object.find_child(to_csubstr(key)); + if (member.valid()) + { + const c4::csubstr val = member.val(); + if (!val.empty()) + { + ret = StringUtil::FromChars(to_stringview(val)); + if (!ret.has_value()) + { + if constexpr (std::is_floating_point_v) + ERROR_LOG("Unexpected non-float value in {}", key); + else if constexpr (std::is_integral_v) + ERROR_LOG("Unexpected non-int value in {}", key); + } + } + else + { + ERROR_LOG("Unexpected empty value in {}", key); + } + } + + return ret; +} + +template +[[maybe_unused]] static std::optional +ParseOptionalTFromObject(const ryml::ConstNodeRef& object, std::string_view key, + std::optional (*from_string_function)(const char* str)) +{ + std::optional ret; + + const ryml::ConstNodeRef member = object.find_child(to_csubstr(key)); + if (member.valid()) + { + const c4::csubstr val = member.val(); + if (!val.empty()) + { + ret = from_string_function(TinyString(to_stringview(val))); + if (!ret.has_value()) + ERROR_LOG("Unknown value for {}: {}", key, to_stringview(val)); + } + else + { + ERROR_LOG("Unexpected empty value in {}", key); + } + } + + return ret; +} diff --git a/src/core/game_database.cpp b/src/core/game_database.cpp index 0fe42cccc..d5f44ac24 100644 --- a/src/core/game_database.cpp +++ b/src/core/game_database.cpp @@ -33,6 +33,8 @@ Log_SetChannel(GameDatabase); +#include "common/ryml_helpers.h" + namespace GameDatabase { enum : u32 @@ -143,119 +145,6 @@ static PreferUnorderedStringMap s_code_lookup; static TrackHashesMap s_track_hashes_map; } // namespace GameDatabase -// RapidYAML utility routines. - -ALWAYS_INLINE std::string_view to_stringview(const c4::csubstr& s) -{ - return std::string_view(s.data(), s.size()); -} - -ALWAYS_INLINE std::string_view to_stringview(const c4::substr& s) -{ - return std::string_view(s.data(), s.size()); -} - -ALWAYS_INLINE c4::csubstr to_csubstr(std::string_view sv) -{ - return c4::csubstr(sv.data(), sv.length()); -} - -static bool GetStringFromObject(const ryml::ConstNodeRef& object, std::string_view key, std::string* dest) -{ - dest->clear(); - - const ryml::ConstNodeRef member = object.find_child(to_csubstr(key)); - if (!member.valid()) - return false; - - const c4::csubstr val = member.val(); - if (!val.empty()) - dest->assign(val.data(), val.size()); - - return true; -} - -template -static bool GetUIntFromObject(const ryml::ConstNodeRef& object, std::string_view key, T* dest) -{ - *dest = 0; - - const ryml::ConstNodeRef member = object.find_child(to_csubstr(key)); - if (!member.valid()) - return false; - - const c4::csubstr val = member.val(); - if (val.empty()) - { - ERROR_LOG("Unexpected empty value in {}", key); - return false; - } - - const std::optional opt_value = StringUtil::FromChars(to_stringview(val)); - if (!opt_value.has_value()) - { - ERROR_LOG("Unexpected non-uint value in {}", key); - return false; - } - - *dest = opt_value.value(); - return true; -} - -template -static std::optional GetOptionalTFromObject(const ryml::ConstNodeRef& object, std::string_view key) -{ - std::optional ret; - - const ryml::ConstNodeRef member = object.find_child(to_csubstr(key)); - if (member.valid()) - { - const c4::csubstr val = member.val(); - if (!val.empty()) - { - ret = StringUtil::FromChars(to_stringview(val)); - if (!ret.has_value()) - { - if constexpr (std::is_floating_point_v) - ERROR_LOG("Unexpected non-float value in {}", key); - else if constexpr (std::is_integral_v) - ERROR_LOG("Unexpected non-int value in {}", key); - } - } - else - { - ERROR_LOG("Unexpected empty value in {}", key); - } - } - - return ret; -} - -template -static std::optional ParseOptionalTFromObject(const ryml::ConstNodeRef& object, std::string_view key, - std::optional (*from_string_function)(const char* str)) -{ - std::optional ret; - - const ryml::ConstNodeRef member = object.find_child(to_csubstr(key)); - if (member.valid()) - { - const c4::csubstr val = member.val(); - if (!val.empty()) - { - ret = from_string_function(TinyString(to_stringview(val))); - if (!ret.has_value()) - ERROR_LOG("Unknown value for {}: {}", key, to_stringview(val)); - } - else - { - ERROR_LOG("Unexpected empty value in {}", key); - } - } - - return ret; -} - void GameDatabase::EnsureLoaded() { if (s_loaded) @@ -1110,7 +999,7 @@ bool GameDatabase::LoadGameDBYaml() const ryml::ConstNodeRef root = tree.rootref(); s_entries.reserve(root.num_children()); - for (const ryml::ConstNodeRef& current : root.children()) + for (const ryml::ConstNodeRef& current : root.cchildren()) { // TODO: binary sort const u32 index = static_cast(s_entries.size()); @@ -1177,7 +1066,7 @@ bool GameDatabase::ParseYamlEntry(Entry* entry, const ryml::ConstNodeRef& value) controllers.valid() && controllers.has_children()) { bool first = true; - for (const ryml::ConstNodeRef& controller : controllers.children()) + for (const ryml::ConstNodeRef& controller : controllers.cchildren()) { const std::string_view controller_str = to_stringview(controller.val()); if (controller_str.empty()) @@ -1230,7 +1119,7 @@ bool GameDatabase::ParseYamlEntry(Entry* entry, const ryml::ConstNodeRef& value) if (const ryml::ConstNodeRef traits = value.find_child(to_csubstr("traits")); traits.valid() && traits.has_children()) { - for (const ryml::ConstNodeRef& trait : traits.children()) + for (const ryml::ConstNodeRef& trait : traits.cchildren()) { const std::string_view trait_str = to_stringview(trait.val()); if (trait_str.empty()) @@ -1388,7 +1277,7 @@ bool GameDatabase::LoadTrackHashes() s_track_hashes_map = {}; size_t serials = 0; - for (const ryml::ConstNodeRef& current : root.children()) + for (const ryml::ConstNodeRef& current : root.cchildren()) { const std::string_view serial = to_stringview(current.key()); if (serial.empty() || !current.has_children()) @@ -1405,7 +1294,7 @@ bool GameDatabase::LoadTrackHashes() } u32 revision = 0; - for (const ryml::ConstNodeRef& track_revisions : track_data.children()) + for (const ryml::ConstNodeRef& track_revisions : track_data.cchildren()) { const ryml::ConstNodeRef tracks = track_revisions.find_child(to_csubstr("tracks")); if (!tracks.valid() || !tracks.has_children())