Skip to content

Instantly share code, notes, and snippets.

@bjadamson
Created March 2, 2020 02:32
Show Gist options
  • Save bjadamson/898392bb2ed27107817076a13701a319 to your computer and use it in GitHub Desktop.
Save bjadamson/898392bb2ed27107817076a13701a319 to your computer and use it in GitHub Desktop.
namespace
{
std::optional<std::string_view>
get_stringview(std::string_view const& sv, toml::table const& table)
{
auto const node = table[sv];
if (!node) {
return std::nullopt;
}
assert(node.is_string());
return node.as_string()->get();
}
toml::array const*
get_array(std::string_view const& sv, toml::table const& table)
{
auto const& node = table[sv];
if (!node) {
return nullptr;
}
assert(node.is_array());
return node.as_array();
}
template <typename T>
std::optional<T>
get_floating_point(std::string_view const& sv, toml::table const& table)
{
auto const& node = table[sv];
if (!node) {
return std::nullopt;
}
assert(node.is_floating_point());
auto const fp = node.as_floating_point()->get();
return static_cast<T>(fp);
}
template <typename R, typename FN, typename T, T... ints>
auto constexpr from_sequence(FN const& fn, std::integer_sequence<T, ints...>)
{
size_t i = 0;
R arr;
((arr[i++] = fn(ints)), ...);
// TODO: ? R{{(fn(ints), ...)}};
return arr;
}
template <typename T, size_t N, typename R>
std::optional<R>
get_array_n(std::string_view const& name, toml::table const& table)
{
static_assert(N > 0, "n must be >0");
auto const nview = table[name];
if (!nview) {
return std::nullopt;
}
assert(nview.is_array());
auto const& arr = *nview.as_array();
assert(arr.is_homogeneous());
assert(arr.size() == N);
assert(arr[0].is_number());
using itype = typename toml::array::size_type;
if constexpr (std::is_floating_point_v<T>) {
assert(arr[0].is_floating_point());
auto const as_fp = [&](itype const i) { return static_cast<T>(arr[i].as_floating_point()->get()); };
return from_sequence<R>(as_fp, std::make_integer_sequence<itype, N>{});
}
else if constexpr (std::is_integral_v<T>) {
auto const as_int = [&](itype const i) { return static_cast<T>(arr[i].as_integer()->get()); };
return from_sequence<R>(as_int, std::make_integer_sequence<itype, N>{});
}
else {
static_assert(always_false<T>, "only floating-point and integral types are supported.");
}
}
template <typename T>
auto constexpr get_array3 = get_array_n<T, 3, std::array<T, 3>>;
template <typename T>
auto constexpr get_array4 = get_array_n<T, 4, std::array<T, 4>>;
template <typename T>
auto constexpr get_vec3 = get_array_n<T, 3, glm::vec3>;
template <typename T>
auto constexpr get_vec4 = get_array_n<T, 4, glm::vec4>;
std::optional<bool>
get_bool(std::string_view const& name, toml::table const& table)
{
auto const nview = table[name];
if (!nview) {
return std::nullopt;
}
assert(nview.is_boolean());
return nview.as_boolean()->get();
}
std::optional<int64_t>
get_int64(std::string_view const& name, toml::table const& table)
{
auto const nview = table[name];
if (!nview) {
return std::nullopt;
}
assert(nview.is_integer());
return nview.as_integer()->get();
}
} // namespace
namespace
{
template <auto fn>
auto const&
get_or_abort_ref(std::string_view const& sv, toml::table const& table)
{
auto const opt = fn(sv, table);
assert(opt);
return *opt;
}
template <auto fn>
auto
get_or_abort(std::string_view const& sv, toml::table const& table)
{
auto const opt = fn(sv, table);
assert(opt);
return *opt;
}
auto constexpr get_string_or_abort = get_or_abort<get_stringview>;
auto constexpr get_array_or_abort = get_or_abort_ref<get_array>;
template <typename T>
auto constexpr get_floating_point_or_abort = get_or_abort<get_floating_point<T>>;
template <typename T>
auto constexpr get_array3_or_abort = get_or_abort<get_array3<T>>;
template <typename T>
auto constexpr get_vec3_or_abort = get_or_abort<get_vec3<T>>;
template <typename T>
auto constexpr get_array4_or_abort = get_or_abort<get_array4<T>>;
auto constexpr get_int64_or_abort = get_or_abort<get_int64>;
template <typename T>
auto constexpr get_vec4_or_abort = get_or_abort<get_vec4<T>>;
auto constexpr get_bool_or_abort = get_or_abort<get_bool>;
} // namespace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment