//# 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 "forward_declarations.h" #include "std_map.h" #include "std_initializer_list.h" #include "array.h" #include "make_node.h" #include "node_view.h" #include "key.h" #include "header_start.h" /// \cond TOML_IMPL_NAMESPACE_START { template struct table_proxy_pair { using value_type = std::conditional_t; const toml::key& first; value_type& second; }; template class table_iterator { private: template friend class table_iterator; using proxy_type = table_proxy_pair; using mutable_map_iterator = std::map>::iterator; using const_map_iterator = std::map>::const_iterator; using map_iterator = std::conditional_t; mutable map_iterator iter_; alignas(proxy_type) mutable unsigned char proxy_[sizeof(proxy_type)]; mutable bool proxy_instantiated_ = false; TOML_NODISCARD proxy_type* get_proxy() const noexcept { if (!proxy_instantiated_) { auto p = ::new (static_cast(proxy_)) proxy_type{ iter_->first, *iter_->second.get() }; proxy_instantiated_ = true; return p; } else return TOML_LAUNDER(reinterpret_cast(proxy_)); } public: TOML_NODISCARD_CTOR table_iterator() noexcept = default; TOML_NODISCARD_CTOR explicit table_iterator(mutable_map_iterator iter) noexcept // : iter_{ iter } {} TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) TOML_NODISCARD_CTOR explicit table_iterator(const_map_iterator iter) noexcept // : iter_{ iter } {} TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) TOML_NODISCARD_CTOR table_iterator(const table_iterator& other) noexcept // : iter_{ other.iter_ } {} TOML_NODISCARD_CTOR table_iterator(const table_iterator& other) noexcept // : iter_{ other.iter_ } {} table_iterator& operator=(const table_iterator& rhs) noexcept { iter_ = rhs.iter_; proxy_instantiated_ = false; return *this; } using value_type = table_proxy_pair; using reference = value_type&; using pointer = value_type*; using difference_type = typename std::iterator_traits::difference_type; using iterator_category = typename std::iterator_traits::iterator_category; table_iterator& operator++() noexcept // ++pre { ++iter_; proxy_instantiated_ = false; return *this; } table_iterator operator++(int) noexcept // post++ { table_iterator out{ iter_ }; ++iter_; proxy_instantiated_ = false; return out; } table_iterator& operator--() noexcept // --pre { --iter_; proxy_instantiated_ = false; return *this; } table_iterator operator--(int) noexcept // post-- { table_iterator out{ iter_ }; --iter_; proxy_instantiated_ = false; return out; } TOML_PURE_INLINE_GETTER reference operator*() const noexcept { return *get_proxy(); } TOML_PURE_INLINE_GETTER pointer operator->() const noexcept { return get_proxy(); } TOML_PURE_INLINE_GETTER explicit operator const map_iterator&() const noexcept { return iter_; } TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst) TOML_PURE_INLINE_GETTER explicit operator const const_map_iterator() const noexcept { return iter_; } TOML_PURE_INLINE_GETTER friend bool operator==(const table_iterator& lhs, const table_iterator& rhs) noexcept { return lhs.iter_ == rhs.iter_; } TOML_PURE_INLINE_GETTER friend bool operator!=(const table_iterator& lhs, const table_iterator& rhs) noexcept { return lhs.iter_ != rhs.iter_; } }; struct table_init_pair { mutable toml::key key; mutable node_ptr value; template TOML_NODISCARD_CTOR table_init_pair(K&& k, V&& v, value_flags flags = preserve_source_value_flags) // : key{ static_cast(k) }, value{ make_node(static_cast(v), flags) } {} }; } TOML_IMPL_NAMESPACE_END; /// \endcond TOML_NAMESPACE_START { /// \brief A BidirectionalIterator for iterating over key-value pairs in a toml::table. using table_iterator = POXY_IMPLEMENTATION_DETAIL(impl::table_iterator); /// \brief A BidirectionalIterator for iterating over const key-value pairs in a toml::table. using const_table_iterator = POXY_IMPLEMENTATION_DETAIL(impl::table_iterator); /// \brief A TOML table. /// /// \detail The interface of this type is modeled after std::map, with some /// additional considerations made for the heterogeneous nature of a /// TOML table. /// /// \cpp /// toml::table tbl = toml::parse(R"( /// /// [animals] /// cats = [ "tiger", "lion", "puma" ] /// birds = [ "macaw", "pigeon", "canary" ] /// fish = [ "salmon", "trout", "carp" ] /// /// )"sv); /// /// // operator[] retrieves node-views /// std::cout << "cats: " << tbl["animals"]["cats"] << "\n"; /// std::cout << "fish[1]: " << tbl["animals"]["fish"][1] << "\n"; /// /// // at_path() does fully-qualified "toml path" lookups /// std::cout << "cats: " << tbl.at_path("animals.cats") << "\n"; /// std::cout << "fish[1]: " << tbl.at_path("animals.fish[1]") << "\n"; /// \ecpp /// /// \out /// cats: ['tiger', 'lion', 'puma'] /// fish[1] : 'trout' /// cats : ['tiger', 'lion', 'puma'] /// fish[1] : 'trout' /// \eout class TOML_EXPORTED_CLASS table : public node { private: /// \cond using map_type = std::map>; using map_pair = std::pair; using map_iterator = typename map_type::iterator; using const_map_iterator = typename map_type::const_iterator; map_type map_; bool inline_ = false; TOML_NODISCARD_CTOR TOML_EXPORTED_MEMBER_FUNCTION table(const impl::table_init_pair*, const impl::table_init_pair*); /// \endcond public: /// \brief Default constructor. TOML_NODISCARD_CTOR TOML_EXPORTED_MEMBER_FUNCTION table() noexcept; TOML_EXPORTED_MEMBER_FUNCTION ~table() noexcept; /// \brief Copy constructor. TOML_NODISCARD_CTOR TOML_EXPORTED_MEMBER_FUNCTION table(const table&); /// \brief Move constructor. TOML_NODISCARD_CTOR TOML_EXPORTED_MEMBER_FUNCTION table(table&& other) noexcept; /// \brief Constructs a table with one or more initial key-value pairs. /// /// \detail \cpp /// auto tbl = toml::table{ /// { "foo", 1 }, /// { "bar", 2.0 }, /// { "kek", "three" } /// }; /// std::cout << tbl << "\n"; /// \ecpp /// /// \out /// { foo = 1, bar = 2.0, kek = "three" } /// \eout /// /// \param kvps A list of key-value pairs used to initialize the table. TOML_NODISCARD_CTOR TOML_EXPORTED_MEMBER_FUNCTION explicit table(std::initializer_list kvps) // : table(kvps.begin(), kvps.end()) {} /// \brief Copy-assignment operator. TOML_EXPORTED_MEMBER_FUNCTION table& operator=(const table&); /// \brief Move-assignment operator. TOML_EXPORTED_MEMBER_FUNCTION table& operator=(table&& rhs) noexcept; /// \name Type checks /// @{ /// \brief Returns #toml::node_type::table. TOML_CONST_INLINE_GETTER node_type type() const noexcept final { return node_type::table; } TOML_PURE_GETTER TOML_EXPORTED_MEMBER_FUNCTION bool is_homogeneous(node_type ntype) const noexcept final; TOML_PURE_GETTER TOML_EXPORTED_MEMBER_FUNCTION bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final; TOML_PURE_GETTER TOML_EXPORTED_MEMBER_FUNCTION bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final; /// \cond 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 table::is_homogeneous() must be void or one " "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); return is_homogeneous(impl::node_type_of); } /// \endcond /// \brief Returns `true`. TOML_CONST_INLINE_GETTER bool is_table() const noexcept final { return true; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_array() const noexcept final { return false; } /// \brief Returns `false`. TOML_PURE_GETTER bool is_array_of_tables() const noexcept final { return false; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_value() const noexcept final { return false; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_string() const noexcept final { return false; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_integer() const noexcept final { return false; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_floating_point() const noexcept final { return false; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_number() const noexcept final { return false; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_boolean() const noexcept final { return false; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_date() const noexcept final { return false; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_time() const noexcept final { return false; } /// \brief Returns `false`. TOML_CONST_INLINE_GETTER bool is_date_time() const noexcept final { return false; } /// @} /// \name Type casts /// @{ /// \brief Returns a pointer to the table. TOML_CONST_INLINE_GETTER table* as_table() noexcept final { return this; } /// \brief Returns `nullptr`. TOML_CONST_INLINE_GETTER array* as_array() noexcept final { return nullptr; } /// \brief Returns `nullptr`. TOML_CONST_INLINE_GETTER toml::value* as_string() noexcept final { return nullptr; } /// \brief Returns `nullptr`. TOML_CONST_INLINE_GETTER toml::value* as_integer() noexcept final { return nullptr; } /// \brief Returns `nullptr`. TOML_CONST_INLINE_GETTER toml::value* as_floating_point() noexcept final { return nullptr; } /// \brief Returns `nullptr`. TOML_CONST_INLINE_GETTER toml::value* as_boolean() noexcept final { return nullptr; } /// \brief Returns `nullptr`. TOML_CONST_INLINE_GETTER toml::value* as_date() noexcept final { return nullptr; } /// \brief Returns `nullptr`. TOML_CONST_INLINE_GETTER toml::value