#pragma once #include "toml_table.h" #include "toml_array.h" #include "toml_value.h" namespace toml::impl { template struct node_view_traits; template <> struct node_view_traits { using haystack_type = const table*; using key_type = string_view; [[nodiscard]] static const node* get(const table* tbl, key_type key) noexcept { return tbl->get(key); } template [[nodiscard]] static const node_of* as(const table* tbl, key_type key) noexcept { return tbl->get_as(key); } }; template <> struct node_view_traits { using haystack_type = table*; using key_type = string_view; [[nodiscard]] static node* get(table* tbl, key_type key) noexcept { return tbl->get(key); } [[nodiscard]] static const node* get(const table* tbl, key_type key) noexcept { return tbl->get(key); } template [[nodiscard]] static node_of* as(table* tbl, key_type key) noexcept { return tbl->get_as(key); } template [[nodiscard]] static const node_of* as(const table* tbl, key_type key) noexcept { return tbl->get_as(key); } }; template struct sub_view final { }; template struct node_view_traits> { using haystack_type = T; using key_type = string_view; [[nodiscard]] static auto get(haystack_type& view, string_view key) noexcept { auto parent = view.as_table(); return parent ? parent->get(key) : nullptr; } [[nodiscard]] static const node* get(const haystack_type& view, string_view key) noexcept { auto parent = view.as_table(); return parent ? parent->get(key) : nullptr; } template [[nodiscard]] static auto as(haystack_type& view, string_view key) noexcept { auto parent = view.as_table(); return parent ? parent->template get_as(key) : nullptr; } template [[nodiscard]] static const node_of* as(const haystack_type& view, string_view key) noexcept { auto parent = view.as_table(); return parent ? parent->template get_as(key) : nullptr; } }; template struct node_view_traits> { using haystack_type = T; using key_type = size_t; [[nodiscard]] static auto get(haystack_type& view, size_t index) noexcept { auto parent = view.as_array(); return parent ? parent->get(index) : nullptr; } [[nodiscard]] static const node* get(const haystack_type& view, size_t index) noexcept { auto parent = view.as_array(); return parent ? parent->get(index) : nullptr; } template [[nodiscard]] static auto as(haystack_type& view, size_t index) noexcept { auto parent = view.as_array(); return parent ? parent->template get_as(index) : nullptr; } template [[nodiscard]] static const node_of* as(const haystack_type& view, size_t index) noexcept { auto parent = view.as_array(); return parent ? parent->template get_as(index) : nullptr; } }; } namespace toml { template class node_view final { public: using traits = impl::node_view_traits; using key_type = typename traits::key_type; private: using haystack_type = typename traits::haystack_type; haystack_type haystack_; key_type key_; public: TOML_NODISCARD_CTOR node_view(haystack_type obj, key_type key) noexcept : haystack_{ obj }, key_{ key } {} [[nodiscard]] auto get() noexcept { return traits::get(haystack_, key_); } [[nodiscard]] const node* get() const noexcept { return traits::get(haystack_, key_); } [[nodiscard]] explicit operator bool() const noexcept { return !!get(); } template [[nodiscard]] auto as() noexcept { static_assert( impl::is_value_or_node, "Template type parameter must be one of the basic value types, a toml::table, or a toml::array" ); return traits::template as(haystack_, key_); } template [[nodiscard]] const node_of* as() const noexcept { static_assert( impl::is_value_or_node, "Template type parameter must be one of the basic value types, a toml::table, or a toml::array" ); return traits::template as(haystack_, key_); } [[nodiscard]] auto as_string() noexcept { return as(); } [[nodiscard]] auto as_integer() noexcept { return as(); } [[nodiscard]] auto as_floating_point() noexcept { return as(); } [[nodiscard]] auto as_boolean() noexcept { return as(); } [[nodiscard]] auto as_date() noexcept { return as(); } [[nodiscard]] auto as_time() noexcept { return as
(); } [[nodiscard]] const value* as_string() const noexcept { return as(); } [[nodiscard]] const value* as_integer() const noexcept { return as(); } [[nodiscard]] const value* as_floating_point() const noexcept { return as(); } [[nodiscard]] const value* as_boolean() const noexcept { return as(); } [[nodiscard]] const value* as_date() const noexcept { return as(); } [[nodiscard]] const value
(); } private: template [[nodiscard]] static bool value_equality(const node_view& lhs, const U& rhs) noexcept { const auto val = lhs.as>(); return val && val->get() == rhs; } template [[nodiscard]] static bool container_equality(const node_view& lhs, const U& rhs) noexcept { using elem_t = std::remove_const_t; static_assert( impl::is_value_or_promotable, "Container element type must be (or be promotable to) one of the basic value types" ); const array* arr = lhs.as(); if (!arr || arr->size() != rhs.size()) return false; if (rhs.size() == 0_sz) return true; size_t i{}; for (auto& list_elem : rhs) { const auto elem = arr->get_as>(i++); if (!elem || elem->get() != list_elem) return false; } return true; } public: [[nodiscard]] bool operator == (string_view rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (int64_t rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (int32_t rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (int16_t rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (int8_t rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (uint32_t rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (uint16_t rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (uint8_t rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (double rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (float rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (bool rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (const date& rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (const time& rhs) const noexcept { return value_equality(*this, rhs); } [[nodiscard]] bool operator == (const date_time& rhs) const noexcept { return value_equality(*this, rhs); } template [[nodiscard]] bool operator == (const std::initializer_list& rhs) const noexcept { return container_equality(*this, rhs); } template [[nodiscard]] bool operator == (const std::vector& rhs) const noexcept { return container_equality(*this, rhs); } template [[nodiscard]] friend bool operator == (const U& lhs, const node_view& rhs) noexcept { return rhs == lhs; } [[nodiscard]] node_view, string_view>> operator[] (string_view key) noexcept { return { *this, key }; } [[nodiscard]] node_view, size_t>> operator[] (size_t index) noexcept { return { *this, index }; } }; inline node_view
table::operator[] (string_view key) noexcept { return { this, key }; } inline node_view table::operator[] (string_view key) const noexcept { return { this, key }; } }