//# This file is a part of toml++ and is subject to the the terms of the MIT license. //# Copyright (c) Mark Gillard //# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. // SPDX-License-Identifier: MIT #pragma once #include "std_utility.h" #include "forward_declarations.h" #include "source_region.h" #include "header_start.h" TOML_NAMESPACE_START { /// \brief A TOML node. /// /// \detail A parsed TOML document forms a tree made up of tables, arrays and values. /// This type is the base of each of those, providing a lot of the polymorphic plumbing. class TOML_ABSTRACT_BASE TOML_EXPORTED_CLASS node { private: /// \cond friend class TOML_PARSER_TYPENAME; source_region source_{}; template TOML_NODISCARD decltype(auto) get_value_exact() const noexcept(impl::value_retrieval_is_nothrow); template using ref_type_ = std::conditional_t< // std::is_reference_v, // impl::copy_ref, std::remove_reference_t>, T>, // impl::copy_cvref, N> // >; template using ref_type = std::conditional_t< // std::is_reference_v, // ref_type_, // ref_type_> // >; template TOML_PURE_GETTER static ref_type TOML_CALLCONV do_ref(N&& n) noexcept { using unwrapped_type = impl::unwrap_node; static_assert(toml::is_value || toml::is_container, "The template type argument of node::ref() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); TOML_ASSERT_ASSUME( n.template is() && "template type argument provided to toml::node::ref() didn't match the node's actual type"); using node_ref = std::remove_volatile_t>&; using val_type = std::remove_volatile_t; using out_ref = ref_type; static_assert(std::is_reference_v); if constexpr (toml::is_value) return static_cast(const_cast(n).template ref_cast().get()); else return static_cast(const_cast(n).template ref_cast()); } protected: TOML_EXPORTED_MEMBER_FUNCTION node() noexcept; TOML_EXPORTED_MEMBER_FUNCTION node(const node&) noexcept; TOML_EXPORTED_MEMBER_FUNCTION node(node&&) noexcept; TOML_EXPORTED_MEMBER_FUNCTION node& operator=(const node&) noexcept; TOML_EXPORTED_MEMBER_FUNCTION node& operator=(node&&) noexcept; template using ref_cast_type_ = std::conditional_t< // std::is_reference_v, // impl::copy_ref, std::remove_reference_t>, T>, // impl::copy_cvref, N> // >; template using ref_cast_type = std::conditional_t< // std::is_reference_v, // ref_cast_type_, // ref_cast_type_> // >; template TOML_PURE_INLINE_GETTER ref_cast_type ref_cast() & noexcept { using out_ref = ref_cast_type; using out_type = std::remove_reference_t; return static_cast(*reinterpret_cast(this)); } template TOML_PURE_INLINE_GETTER ref_cast_type ref_cast() && noexcept { using out_ref = ref_cast_type; using out_type = std::remove_reference_t; return static_cast(*reinterpret_cast(this)); } template TOML_PURE_INLINE_GETTER ref_cast_type ref_cast() const& noexcept { using out_ref = ref_cast_type; using out_type = std::remove_reference_t; return static_cast(*reinterpret_cast(this)); } template TOML_PURE_INLINE_GETTER ref_cast_type ref_cast() const&& noexcept { using out_ref = ref_cast_type; using out_type = std::remove_reference_t; return static_cast(*reinterpret_cast(this)); } /// \endcond public: TOML_EXPORTED_MEMBER_FUNCTION virtual ~node() noexcept; /// \name Type checks /// @{ /// \brief Checks if a node contains values/elements of only one type. /// /// \detail \cpp /// auto cfg = toml::parse("arr = [ 1, 2, 3, 4.0 ]"); /// toml::array& arr = *cfg["arr"].as_array(); /// /// toml::node* nonmatch{}; /// if (arr.is_homogeneous(toml::node_type::integer, nonmatch)) /// std::cout << "array was homogeneous"sv << "\n"; /// else /// std::cout << "array was not homogeneous!\n" /// << "first non-match was a "sv << nonmatch->type() << " at " << nonmatch->source() << "\n"; /// \ecpp /// /// \out /// array was not homogeneous! /// first non-match was a floating-point at line 1, column 18 /// \eout /// /// \param ntype A TOML node type.
/// \conditional_return{toml::node_type::none} /// "is every element the same type?" /// \conditional_return{Anything else} /// "is every element one of these?" /// /// \param first_nonmatch Reference to a pointer in which the address of the first non-matching element /// will be stored if the return value is false. /// /// \returns True if the node was homogeneous. /// /// \remarks Always returns `false` for empty tables and arrays. TOML_PURE_GETTER virtual bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept = 0; /// \brief Checks if a node contains values/elements of only one type (const overload). TOML_PURE_GETTER virtual bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept = 0; /// \brief Checks if the node contains values/elements of only one type. /// /// \detail \cpp /// auto arr = toml::array{ 1, 2, 3 }; /// std::cout << "homogenous: "sv << arr.is_homogeneous(toml::node_type::none) << "\n"; /// std::cout << "all floats: "sv << arr.is_homogeneous(toml::node_type::floating_point) << "\n"; /// std::cout << "all arrays: "sv << arr.is_homogeneous(toml::node_type::array) << "\n"; /// std::cout << "all ints: "sv << arr.is_homogeneous(toml::node_type::integer) << "\n"; /// \ecpp /// /// \out /// homogeneous: true /// all floats: false /// all arrays: false /// all ints: true /// \eout /// /// \param ntype A TOML node type.
/// \conditional_return{toml::node_type::none} /// "is every element the same type?" /// \conditional_return{Anything else} /// "is every element one of these?" /// /// \returns True if the node was homogeneous. /// /// \remarks Always returns `false` for empty tables and arrays. TOML_PURE_GETTER virtual bool is_homogeneous(node_type ntype) const noexcept = 0; /// \brief Checks if the node contains values/elements of only one type. /// /// \detail \cpp /// auto arr = toml::array{ 1, 2, 3 }; /// std::cout << "homogenous: "sv << arr.is_homogeneous() << "\n"; /// std::cout << "all doubles: "sv << arr.is_homogeneous() << "\n"; /// std::cout << "all arrays: "sv << arr.is_homogeneous() << "\n"; /// std::cout << "all integers: "sv << arr.is_homogeneous() << "\n"; /// \ecpp /// /// \out /// homogeneous: true /// all floats: false /// all arrays: false /// all ints: true /// \eout /// /// \tparam ElemType A TOML node or value type.
/// \conditional_return{Left as `void`} /// "is every element the same type?"
/// \conditional_return{Explicitly specified} /// "is every element a T?" /// /// \returns True if the node was homogeneous. /// /// \remarks Always returns `false` for empty tables and arrays. template TOML_PURE_GETTER bool is_homogeneous() const noexcept { using type = impl::remove_cvref>; static_assert(std::is_void_v || toml::is_value || toml::is_container, "The template type argument of node::is_homogeneous() must be void or one " "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); return is_homogeneous(impl::node_type_of); } /// \brief Returns the node's type identifier. TOML_PURE_GETTER virtual node_type type() const noexcept = 0; /// \brief Returns true if this node is a table. TOML_PURE_GETTER virtual bool is_table() const noexcept = 0; /// \brief Returns true if this node is an array. TOML_PURE_GETTER virtual bool is_array() const noexcept = 0; /// \brief Returns true if this node is an array containing only tables. TOML_PURE_GETTER virtual bool is_array_of_tables() const noexcept = 0; /// \brief Returns true if this node is a value. TOML_PURE_GETTER virtual bool is_value() const noexcept = 0; /// \brief Returns true if this node is a string value. TOML_PURE_GETTER virtual bool is_string() const noexcept = 0; /// \brief Returns true if this node is an integer value. TOML_PURE_GETTER virtual bool is_integer() const noexcept = 0; /// \brief Returns true if this node is an floating-point value. TOML_PURE_GETTER virtual bool is_floating_point() const noexcept = 0; /// \brief Returns true if this node is an integer or floating-point value. TOML_PURE_GETTER virtual bool is_number() const noexcept = 0; /// \brief Returns true if this node is a boolean value. TOML_PURE_GETTER virtual bool is_boolean() const noexcept = 0; /// \brief Returns true if this node is a local date value. TOML_PURE_GETTER virtual bool is_date() const noexcept = 0; /// \brief Returns true if this node is a local time value. TOML_PURE_GETTER virtual bool is_time() const noexcept = 0; /// \brief Returns true if this node is a date-time value. TOML_PURE_GETTER virtual bool is_date_time() const noexcept = 0; /// \brief Checks if a node is a specific type. /// /// \tparam T A TOML node or value type. /// /// \returns Returns true if this node is an instance of the specified type. template TOML_PURE_INLINE_GETTER bool is() const noexcept { using type = impl::remove_cvref>; static_assert(toml::is_value || toml::is_container, "The template type argument of node::is() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); if constexpr (std::is_same_v) return is_table(); else if constexpr (std::is_same_v) return is_array(); else if constexpr (std::is_same_v) return is_string(); else if constexpr (std::is_same_v) return is_integer(); else if constexpr (std::is_same_v) return is_floating_point(); else if constexpr (std::is_same_v) return is_boolean(); else if constexpr (std::is_same_v) return is_date(); else if constexpr (std::is_same_v) return is_time(); else if constexpr (std::is_same_v) return is_date_time(); } /// @} /// \name Type casts /// @{ /// \brief Returns a pointer to the node as a toml::table, if it is one. TOML_PURE_GETTER virtual table* as_table() noexcept = 0; /// \brief Returns a pointer to the node as a toml::array, if it is one. TOML_PURE_GETTER virtual array* as_array() noexcept = 0; /// \brief Returns a pointer to the node as a toml::value, if it is one. TOML_PURE_GETTER virtual toml::value* as_string() noexcept = 0; /// \brief Returns a pointer to the node as a toml::value, if it is one. TOML_PURE_GETTER virtual toml::value* as_integer() noexcept = 0; /// \brief Returns a pointer to the node as a toml::value, if it is one. TOML_PURE_GETTER virtual toml::value* as_floating_point() noexcept = 0; /// \brief Returns a pointer to the node as a toml::value, if it is one. TOML_PURE_GETTER virtual toml::value* as_boolean() noexcept = 0; /// \brief Returns a pointer to the node as a toml::value, if it is one. TOML_PURE_GETTER virtual toml::value* as_date() noexcept = 0; /// \brief Returns a pointer to the node as a toml::value, if it is one. TOML_PURE_GETTER virtual toml::value