Skip to content

Commit

Permalink
Common: Extract out ryml helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Sep 8, 2024
1 parent b10f043 commit 3078339
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 118 deletions.
1 change: 1 addition & 0 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/common/common.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<ClInclude Include="path.h" />
<ClInclude Include="perf_scope.h" />
<ClInclude Include="progress_callback.h" />
<ClInclude Include="ryml_helpers.h" />
<ClInclude Include="scoped_guard.h" />
<ClInclude Include="settings_interface.h" />
<ClInclude Include="sha1_digest.h" />
Expand Down
1 change: 1 addition & 0 deletions src/common/common.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<ClInclude Include="gsvector.h" />
<ClInclude Include="gsvector_formatter.h" />
<ClInclude Include="gsvector_nosimd.h" />
<ClInclude Include="ryml_helpers.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="small_string.cpp" />
Expand Down
124 changes: 124 additions & 0 deletions src/common/ryml_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: CC-BY-NC-ND-4.0

#include "types.h"

#include "ryml.hpp"

#include <string>
#include <string_view>

// 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<typename T>
[[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<T> opt_value = StringUtil::FromChars<T>(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<typename T>
[[maybe_unused]] static std::optional<T> GetOptionalTFromObject(const ryml::ConstNodeRef& object, std::string_view key)
{
std::optional<T> 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<T>(to_stringview(val));
if (!ret.has_value())
{
if constexpr (std::is_floating_point_v<T>)
ERROR_LOG("Unexpected non-float value in {}", key);
else if constexpr (std::is_integral_v<T>)
ERROR_LOG("Unexpected non-int value in {}", key);
}
}
else
{
ERROR_LOG("Unexpected empty value in {}", key);
}
}

return ret;
}

template<typename T>
[[maybe_unused]] static std::optional<T>
ParseOptionalTFromObject(const ryml::ConstNodeRef& object, std::string_view key,
std::optional<T> (*from_string_function)(const char* str))
{
std::optional<T> 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;
}
125 changes: 7 additions & 118 deletions src/core/game_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

Log_SetChannel(GameDatabase);

#include "common/ryml_helpers.h"

namespace GameDatabase {

enum : u32
Expand Down Expand Up @@ -143,119 +145,6 @@ static PreferUnorderedStringMap<u32> 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<typename T>
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<T> opt_value = StringUtil::FromChars<T>(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<typename T>
static std::optional<T> GetOptionalTFromObject(const ryml::ConstNodeRef& object, std::string_view key)
{
std::optional<T> 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<T>(to_stringview(val));
if (!ret.has_value())
{
if constexpr (std::is_floating_point_v<T>)
ERROR_LOG("Unexpected non-float value in {}", key);
else if constexpr (std::is_integral_v<T>)
ERROR_LOG("Unexpected non-int value in {}", key);
}
}
else
{
ERROR_LOG("Unexpected empty value in {}", key);
}
}

return ret;
}

template<typename T>
static std::optional<T> ParseOptionalTFromObject(const ryml::ConstNodeRef& object, std::string_view key,
std::optional<T> (*from_string_function)(const char* str))
{
std::optional<T> 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)
Expand Down Expand Up @@ -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<u32>(s_entries.size());
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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())
Expand All @@ -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())
Expand Down

0 comments on commit 3078339

Please sign in to comment.