diff options
Diffstat (limited to 'vendor/toml++')
37 files changed, 10545 insertions, 11995 deletions
diff --git a/vendor/toml++/impl/array.hpp b/vendor/toml++/impl/array.hpp index ad79379..c276637 100644 --- a/vendor/toml++/impl/array.hpp +++ b/vendor/toml++/impl/array.hpp @@ -1,15 +1,15 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once +#include "header_start.hpp" +#include "make_node.hpp" +#include "std_initializer_list.hpp" #include "std_utility.hpp" #include "std_vector.hpp" -#include "std_initializer_list.hpp" #include "value.hpp" -#include "make_node.hpp" -#include "header_start.hpp" #ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN #if TOML_GCC && TOML_GCC <= 7 @@ -19,1771 +19,1530 @@ #endif #endif -#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN && !defined(TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED) -#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE \ - "If you're seeing this error it's because you're using one of toml++'s for_each() functions on a compiler with " \ - "known bugs in that area (e.g. GCC 7). On these compilers returning a bool (or bool-convertible) value from the " \ - "for_each() callable causes spurious compilation failures, while returning nothing (void) works fine. " \ - "If you believe this message is incorrect for your compiler, you can try your luck by #defining " \ - "TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN as 0 and recompiling - if it works, great! Let me know at " \ - "https://github.com/marzer/tomlplusplus/issues. Alternatively, if you don't have any need for early-exiting from " \ - "for_each(), you can suppress this error by #defining TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED " \ - "and moving on with your life." +#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN && \ + !defined(TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED) +#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE \ + "If you're seeing this error it's because you're using one of toml++'s for_each() functions on " \ + "a compiler with " \ + "known bugs in that area (e.g. GCC 7). On these compilers returning a bool (or " \ + "bool-convertible) value from the " \ + "for_each() callable causes spurious compilation failures, while returning nothing (void) " \ + "works fine. " \ + "If you believe this message is incorrect for your compiler, you can try your luck by " \ + "#defining " \ + "TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN as 0 and recompiling - if it works, great! Let me know " \ + "at " \ + "https://github.com/marzer/tomlplusplus/issues. Alternatively, if you don't have any need for " \ + "early-exiting from " \ + "for_each(), you can suppress this error by #defining " \ + "TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED " \ + "and moving on with your life." #endif /// \cond -TOML_IMPL_NAMESPACE_START -{ - template <bool IsConst> - class TOML_TRIVIAL_ABI array_iterator - { - private: - template <bool> - friend class array_iterator; - - using mutable_vector_iterator = std::vector<node_ptr>::iterator; - using const_vector_iterator = std::vector<node_ptr>::const_iterator; - using vector_iterator = std::conditional_t<IsConst, const_vector_iterator, mutable_vector_iterator>; - - mutable vector_iterator iter_; - - public: - using value_type = std::conditional_t<IsConst, const node, node>; - using reference = value_type&; - using pointer = value_type*; - using difference_type = ptrdiff_t; - using iterator_category = typename std::iterator_traits<vector_iterator>::iterator_category; - - TOML_NODISCARD_CTOR - array_iterator() noexcept = default; - - TOML_NODISCARD_CTOR - explicit array_iterator(mutable_vector_iterator iter) noexcept // - : iter_{ iter } - {} - - TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) - TOML_NODISCARD_CTOR - explicit array_iterator(const_vector_iterator iter) noexcept // - : iter_{ iter } - {} - - TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) - TOML_NODISCARD_CTOR - array_iterator(const array_iterator<false>& other) noexcept // - : iter_{ other.iter_ } - {} - - TOML_NODISCARD_CTOR - array_iterator(const array_iterator&) noexcept = default; - - array_iterator& operator=(const array_iterator&) noexcept = default; - - array_iterator& operator++() noexcept // ++pre - { - ++iter_; - return *this; - } - - array_iterator operator++(int) noexcept // post++ - { - array_iterator out{ iter_ }; - ++iter_; - return out; - } - - array_iterator& operator--() noexcept // --pre - { - --iter_; - return *this; - } - - array_iterator operator--(int) noexcept // post-- - { - array_iterator out{ iter_ }; - --iter_; - return out; - } - - TOML_PURE_INLINE_GETTER - reference operator*() const noexcept - { - return *iter_->get(); - } - - TOML_PURE_INLINE_GETTER - pointer operator->() const noexcept - { - return iter_->get(); - } - - TOML_PURE_INLINE_GETTER - explicit operator const vector_iterator&() const noexcept - { - return iter_; - } - - TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst) - TOML_PURE_INLINE_GETTER - explicit operator const const_vector_iterator() const noexcept - { - return iter_; - } - - array_iterator& operator+=(ptrdiff_t rhs) noexcept - { - iter_ += rhs; - return *this; - } - - array_iterator& operator-=(ptrdiff_t rhs) noexcept - { - iter_ -= rhs; - return *this; - } - - TOML_NODISCARD - friend array_iterator operator+(const array_iterator& lhs, ptrdiff_t rhs) noexcept - { - return array_iterator{ lhs.iter_ + rhs }; - } - - TOML_NODISCARD - friend array_iterator operator+(ptrdiff_t lhs, const array_iterator& rhs) noexcept - { - return array_iterator{ rhs.iter_ + lhs }; - } - - TOML_NODISCARD - friend array_iterator operator-(const array_iterator& lhs, ptrdiff_t rhs) noexcept - { - return array_iterator{ lhs.iter_ - rhs }; - } - - TOML_PURE_INLINE_GETTER - friend ptrdiff_t operator-(const array_iterator& lhs, const array_iterator& rhs) noexcept - { - return lhs.iter_ - rhs.iter_; - } - - TOML_PURE_INLINE_GETTER - friend bool operator==(const array_iterator& lhs, const array_iterator& rhs) noexcept - { - return lhs.iter_ == rhs.iter_; - } - - TOML_PURE_INLINE_GETTER - friend bool operator!=(const array_iterator& lhs, const array_iterator& rhs) noexcept - { - return lhs.iter_ != rhs.iter_; - } - - TOML_PURE_INLINE_GETTER - friend bool operator<(const array_iterator& lhs, const array_iterator& rhs) noexcept - { - return lhs.iter_ < rhs.iter_; - } - - TOML_PURE_INLINE_GETTER - friend bool operator<=(const array_iterator& lhs, const array_iterator& rhs) noexcept - { - return lhs.iter_ <= rhs.iter_; - } - - TOML_PURE_INLINE_GETTER - friend bool operator>(const array_iterator& lhs, const array_iterator& rhs) noexcept - { - return lhs.iter_ > rhs.iter_; - } - - TOML_PURE_INLINE_GETTER - friend bool operator>=(const array_iterator& lhs, const array_iterator& rhs) noexcept - { - return lhs.iter_ >= rhs.iter_; - } - - TOML_PURE_INLINE_GETTER - reference operator[](ptrdiff_t idx) const noexcept - { - return *(iter_ + idx)->get(); - } - }; - - struct array_init_elem - { - mutable node_ptr value; - - template <typename T> - TOML_NODISCARD_CTOR - array_init_elem(T&& val, value_flags flags = preserve_source_value_flags) // - : value{ make_node(static_cast<T&&>(val), flags) } - {} - }; +TOML_IMPL_NAMESPACE_START { + template <bool IsConst> + class TOML_TRIVIAL_ABI array_iterator { + private: + template <bool> + friend class array_iterator; + + using mutable_vector_iterator = std::vector<node_ptr>::iterator; + using const_vector_iterator = std::vector<node_ptr>::const_iterator; + using vector_iterator = + std::conditional_t<IsConst, const_vector_iterator, mutable_vector_iterator>; + + mutable vector_iterator iter_; + + public: + using value_type = std::conditional_t<IsConst, const node, node>; + using reference = value_type&; + using pointer = value_type*; + using difference_type = ptrdiff_t; + using iterator_category = typename std::iterator_traits<vector_iterator>::iterator_category; + + TOML_NODISCARD_CTOR + array_iterator() noexcept = default; + + TOML_NODISCARD_CTOR + explicit array_iterator(mutable_vector_iterator iter) noexcept // + : iter_{iter} {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + explicit array_iterator(const_vector_iterator iter) noexcept // + : iter_{iter} {} + + TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst) + TOML_NODISCARD_CTOR + array_iterator(const array_iterator<false>& other) noexcept // + : iter_{other.iter_} {} + + TOML_NODISCARD_CTOR + array_iterator(const array_iterator&) noexcept = default; + + array_iterator& operator=(const array_iterator&) noexcept = default; + + array_iterator& operator++() noexcept // ++pre + { + ++iter_; + return *this; + } + + array_iterator operator++(int) noexcept // post++ + { + array_iterator out{iter_}; + ++iter_; + return out; + } + + array_iterator& operator--() noexcept // --pre + { + --iter_; + return *this; + } + + array_iterator operator--(int) noexcept // post-- + { + array_iterator out{iter_}; + --iter_; + return out; + } + + TOML_PURE_INLINE_GETTER + reference operator*() const noexcept { return *iter_->get(); } + + TOML_PURE_INLINE_GETTER + pointer operator->() const noexcept { return iter_->get(); } + + TOML_PURE_INLINE_GETTER + explicit operator const vector_iterator&() const noexcept { return iter_; } + + TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst) + TOML_PURE_INLINE_GETTER + explicit operator const const_vector_iterator() const noexcept { return iter_; } + + array_iterator& operator+=(ptrdiff_t rhs) noexcept { + iter_ += rhs; + return *this; + } + + array_iterator& operator-=(ptrdiff_t rhs) noexcept { + iter_ -= rhs; + return *this; + } + + TOML_NODISCARD + friend array_iterator operator+(const array_iterator& lhs, ptrdiff_t rhs) noexcept { + return array_iterator{lhs.iter_ + rhs}; + } + + TOML_NODISCARD + friend array_iterator operator+(ptrdiff_t lhs, const array_iterator& rhs) noexcept { + return array_iterator{rhs.iter_ + lhs}; + } + + TOML_NODISCARD + friend array_iterator operator-(const array_iterator& lhs, ptrdiff_t rhs) noexcept { + return array_iterator{lhs.iter_ - rhs}; + } + + TOML_PURE_INLINE_GETTER + friend ptrdiff_t operator-(const array_iterator& lhs, const array_iterator& rhs) noexcept { + return lhs.iter_ - rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator==(const array_iterator& lhs, const array_iterator& rhs) noexcept { + return lhs.iter_ == rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator!=(const array_iterator& lhs, const array_iterator& rhs) noexcept { + return lhs.iter_ != rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator<(const array_iterator& lhs, const array_iterator& rhs) noexcept { + return lhs.iter_ < rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator<=(const array_iterator& lhs, const array_iterator& rhs) noexcept { + return lhs.iter_ <= rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator>(const array_iterator& lhs, const array_iterator& rhs) noexcept { + return lhs.iter_ > rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + friend bool operator>=(const array_iterator& lhs, const array_iterator& rhs) noexcept { + return lhs.iter_ >= rhs.iter_; + } + + TOML_PURE_INLINE_GETTER + reference operator[](ptrdiff_t idx) const noexcept { return *(iter_ + idx)->get(); } + }; + + struct array_init_elem { + mutable node_ptr value; + + template <typename T> + TOML_NODISCARD_CTOR array_init_elem(T&& val, + value_flags flags = preserve_source_value_flags) // + : value{make_node(static_cast<T&&>(val), flags)} {} + }; } TOML_IMPL_NAMESPACE_END; /// \endcond -TOML_NAMESPACE_START -{ - /// \brief A RandomAccessIterator for iterating over elements in a toml::array. - using array_iterator = POXY_IMPLEMENTATION_DETAIL(impl::array_iterator<false>); - - /// \brief A RandomAccessIterator for iterating over const elements in a toml::array. - using const_array_iterator = POXY_IMPLEMENTATION_DETAIL(impl::array_iterator<true>); - - /// \brief A TOML array. - /// - /// \detail The interface of this type is modeled after std::vector, with some - /// additional considerations made for the heterogeneous nature of a - /// TOML array. - /// - /// \godbolt{sjK4da} - /// - /// \cpp - /// - /// toml::table tbl = toml::parse(R"( - /// arr = [1, 2, 3, 4, 'five'] - /// )"sv); - /// - /// // get the element as an array - /// toml::array& arr = *tbl.get_as<toml::array>("arr"); - /// std::cout << arr << "\n"; - /// - /// // increment each element with visit() - /// for (auto&& elem : arr) - /// { - /// elem.visit([](auto&& el) noexcept - /// { - /// if constexpr (toml::is_number<decltype(el)>) - /// (*el)++; - /// else if constexpr (toml::is_string<decltype(el)>) - /// el = "six"sv; - /// }); - /// } - /// std::cout << arr << "\n"; - /// - /// // add and remove elements - /// arr.push_back(7); - /// arr.push_back(8.0f); - /// arr.push_back("nine"sv); - /// arr.erase(arr.cbegin()); - /// std::cout << arr << "\n"; - /// - /// // emplace elements - /// arr.emplace_back("ten"); - /// arr.emplace_back<toml::array>(11, 12.0); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2, 3, 4, 'five' ] - /// [ 2, 3, 4, 5, 'six' ] - /// [ 3, 4, 5, 'six', 7, 8.0, 'nine' ] - /// [ 3, 4, 5, 'six', 7, 8.0, 'nine', 'ten', [ 11, 12.0 ] ] - /// \eout - class TOML_EXPORTED_CLASS array : public node - { - private: - /// \cond - - using vector_type = std::vector<impl::node_ptr>; - using vector_iterator = typename vector_type::iterator; - using const_vector_iterator = typename vector_type::const_iterator; - vector_type elems_; - - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - array(const impl::array_init_elem*, const impl::array_init_elem*); - - TOML_NODISCARD_CTOR - array(std::false_type, std::initializer_list<impl::array_init_elem> elems) // - : array{ elems.begin(), elems.end() } - {} - - TOML_EXPORTED_MEMBER_FUNCTION - void preinsertion_resize(size_t idx, size_t count); - - TOML_EXPORTED_MEMBER_FUNCTION - void insert_at_back(impl::node_ptr&&); - - TOML_EXPORTED_MEMBER_FUNCTION - vector_iterator insert_at(const_vector_iterator, impl::node_ptr&&); - - template <typename T> - void emplace_back_if_not_empty_view(T&& val, value_flags flags) - { - if constexpr (is_node_view<T>) - { - if (!val) - return; - } - insert_at_back(impl::make_node(static_cast<T&&>(val), flags)); - } - - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - size_t total_leaf_count() const noexcept; - - TOML_EXPORTED_MEMBER_FUNCTION - void flatten_child(array&& child, size_t& dest_index) noexcept; - - /// \endcond - - public: - using value_type = node; - using size_type = size_t; - using difference_type = ptrdiff_t; - using reference = node&; - using const_reference = const node&; - - /// \brief Default constructor. - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - array() noexcept; - - TOML_EXPORTED_MEMBER_FUNCTION - ~array() noexcept; - - /// \brief Copy constructor. - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - array(const array&); - - /// \brief Move constructor. - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - array(array&& other) noexcept; - - /// \brief Constructs an array with one or more initial elements. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, 2.0, "three"sv, toml::array{ 4, 5 } }; - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2.0, 'three', [ 4, 5 ] ] - /// \eout - /// - /// \remark \parblock If you need to construct an array with one child array element, the array's move constructor - /// will take precedence and perform a move-construction instead. You can use toml::inserter to - /// suppress this behaviour: \cpp - /// // desired result: [ [ 42 ] ] - /// auto bad = toml::array{ toml::array{ 42 } } - /// auto good = toml::array{ toml::inserter{ toml::array{ 42 } } } - /// std::cout << "bad: " << bad << "\n"; - /// std::cout << "good:" << good << "\n"; - /// \ecpp - /// - /// \out - /// bad: [ 42 ] - /// good: [ [ 42 ] ] - /// \eout - /// - /// \endparblock - /// - /// \tparam ElemType One of the TOML node or value types (or a type promotable to one). - /// \tparam ElemTypes One of the TOML node or value types (or a type promotable to one). - /// \param val The node or value used to initialize element 0. - /// \param vals The nodes or values used to initialize elements 1...N. - TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0 || !std::is_same_v<impl::remove_cvref<ElemType>, array>), - typename ElemType, - typename... ElemTypes) - TOML_NODISCARD_CTOR - explicit array(ElemType&& val, ElemTypes&&... vals) - : array{ std::false_type{}, - std::initializer_list<impl::array_init_elem>{ static_cast<ElemType&&>(val), - static_cast<ElemTypes&&>(vals)... } } - {} - - /// \brief Copy-assignment operator. - TOML_EXPORTED_MEMBER_FUNCTION - array& operator=(const array&); - - /// \brief Move-assignment operator. - TOML_EXPORTED_MEMBER_FUNCTION - array& operator=(array&& rhs) noexcept; - - /// \name Type checks - /// @{ - - /// \brief Returns #toml::node_type::array. - TOML_CONST_INLINE_GETTER - node_type type() const noexcept final - { - return node_type::array; - } - - 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 <typename ElemType = void> - TOML_PURE_GETTER - bool is_homogeneous() const noexcept - { - using type = impl::remove_cvref<impl::unwrap_node<ElemType>>; - static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>, - "The template type argument of array::is_homogeneous() must be void or one " - "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - return is_homogeneous(impl::node_type_of<type>); - } - /// \endcond - - /// \brief Returns `false`. - TOML_CONST_INLINE_GETTER - bool is_table() const noexcept final - { - return false; - } - - /// \brief Returns `true`. - TOML_CONST_INLINE_GETTER - bool is_array() const noexcept final - { - return true; - } - - /// \brief Returns `true` if the array contains only tables. - TOML_PURE_GETTER - bool is_array_of_tables() const noexcept final - { - return is_homogeneous(node_type::table); - } - - /// \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 `nullptr`. - TOML_CONST_INLINE_GETTER - table* as_table() noexcept final - { - return nullptr; - } - - /// \brief Returns a pointer to the array. - TOML_CONST_INLINE_GETTER - array* as_array() noexcept final - { - return this; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<std::string>* as_string() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<int64_t>* as_integer() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<double>* as_floating_point() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<bool>* as_boolean() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<date>* as_date() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<time>* as_time() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<date_time>* as_date_time() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const table* as_table() const noexcept final - { - return nullptr; - } - - /// \brief Returns a const-qualified pointer to the array. - TOML_CONST_INLINE_GETTER - const array* as_array() const noexcept final - { - return this; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<std::string>* as_string() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<int64_t>* as_integer() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<double>* as_floating_point() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<bool>* as_boolean() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<date>* as_date() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<time>* as_time() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<date_time>* as_date_time() const noexcept final - { - return nullptr; - } - - /// @} - - /// \name Value retrieval - /// @{ - - /// \brief Gets a pointer to the element at a specific index. - /// - /// \detail \cpp - /// auto arr = toml::array{ 99, "bottles of beer on the wall" }; - /// std::cout << "element [0] exists: "sv << !!arr.get(0) << "\n"; - /// std::cout << "element [1] exists: "sv << !!arr.get(1) << "\n"; - /// std::cout << "element [2] exists: "sv << !!arr.get(2) << "\n"; - /// if (toml::node* val = arr.get(0)) - /// std::cout << "element [0] is an "sv << val->type() << "\n"; - /// \ecpp - /// - /// \out - /// element [0] exists: true - /// element [1] exists: true - /// element [2] exists: false - /// element [0] is an integer - /// \eout - /// - /// \param index The element's index. - /// - /// \returns A pointer to the element at the specified index if one existed, or nullptr. - TOML_PURE_INLINE_GETTER - node* get(size_t index) noexcept - { - return index < elems_.size() ? elems_[index].get() : nullptr; - } - - /// \brief Gets a pointer to the element at a specific index (const overload). - /// - /// \param index The element's index. - /// - /// \returns A pointer to the element at the specified index if one existed, or nullptr. - TOML_PURE_INLINE_GETTER - const node* get(size_t index) const noexcept - { - return const_cast<array&>(*this).get(index); - } - - /// \brief Gets a pointer to the element at a specific index if it is a particular type. - /// - /// \detail \cpp - /// auto arr = toml::array{ 42, "is the meaning of life, apparently."sv }; - /// if (toml::value<int64_t>* val = arr.get_as<int64_t>(0)) - /// std::cout << "element [0] is an integer with value "sv << *val << "\n"; - /// \ecpp - /// - /// \out - /// element [0] is an integer with value 42 - /// \eout - /// - /// \tparam ElemType toml::table, toml::array, or a native TOML value type - /// \param index The element's index. - /// - /// \returns A pointer to the selected element if it existed and was of the specified type, or nullptr. - template <typename ElemType> - TOML_NODISCARD - impl::wrap_node<ElemType>* get_as(size_t index) noexcept - { - if (auto val = get(index)) - return val->template as<ElemType>(); - return nullptr; - } - - /// \brief Gets a pointer to the element at a specific index if it is a particular type (const overload). - /// - /// \tparam ElemType toml::table, toml::array, or a native TOML value type - /// \param index The element's index. - /// - /// \returns A pointer to the selected element if it existed and was of the specified type, or nullptr. - template <typename ElemType> - TOML_NODISCARD - const impl::wrap_node<ElemType>* get_as(size_t index) const noexcept - { - return const_cast<array&>(*this).template get_as<ElemType>(index); - } - - /// \cond - using node::operator[]; // inherit operator[toml::path] - /// \endcond - - /// \brief Gets a reference to the element at a specific index. - TOML_NODISCARD - node& operator[](size_t index) noexcept - { - return *elems_[index]; - } - - /// \brief Gets a reference to the element at a specific index. - TOML_NODISCARD - const node& operator[](size_t index) const noexcept - { - return *elems_[index]; - } - - /// \brief Gets a reference to the element at a specific index, throwing `std::out_of_range` if none existed. - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node& at(size_t index); - - /// \brief Gets a reference to the element at a specific index, throwing `std::out_of_range` if none existed. - TOML_NODISCARD - const node& at(size_t index) const - { - return const_cast<array&>(*this).at(index); - } - - /// \brief Returns a reference to the first element in the array. - TOML_NODISCARD - node& front() noexcept - { - return *elems_.front(); - } - - /// \brief Returns a reference to the first element in the array. - TOML_NODISCARD - const node& front() const noexcept - { - return *elems_.front(); - } - - /// \brief Returns a reference to the last element in the array. - TOML_NODISCARD - node& back() noexcept - { - return *elems_.back(); - } - - /// \brief Returns a reference to the last element in the array. - TOML_NODISCARD - const node& back() const noexcept - { - return *elems_.back(); - } - - /// @} - - /// \name Iteration - /// @{ - - /// \brief A RandomAccessIterator for iterating over elements in a toml::array. - using iterator = array_iterator; - - /// \brief A RandomAccessIterator for iterating over const elements in a toml::array. - using const_iterator = const_array_iterator; - - /// \brief Returns an iterator to the first element. - TOML_NODISCARD - iterator begin() noexcept - { - return iterator{ elems_.begin() }; - } - - /// \brief Returns an iterator to the first element. - TOML_NODISCARD - const_iterator begin() const noexcept - { - return const_iterator{ elems_.cbegin() }; - } - - /// \brief Returns an iterator to the first element. - TOML_NODISCARD - const_iterator cbegin() const noexcept - { - return const_iterator{ elems_.cbegin() }; - } - - /// \brief Returns an iterator to one-past-the-last element. - TOML_NODISCARD - iterator end() noexcept - { - return iterator{ elems_.end() }; - } - - /// \brief Returns an iterator to one-past-the-last element. - TOML_NODISCARD - const_iterator end() const noexcept - { - return const_iterator{ elems_.cend() }; - } - - /// \brief Returns an iterator to one-past-the-last element. - TOML_NODISCARD - const_iterator cend() const noexcept - { - return const_iterator{ elems_.cend() }; - } - - private: - /// \cond - - template <typename T, typename Array> - using for_each_elem_ref = impl::copy_cvref<impl::wrap_node<impl::remove_cvref<impl::unwrap_node<T>>>, Array>; - - template <typename Func, typename Array, typename T> - using can_for_each = std::disjunction<std::is_invocable<Func, for_each_elem_ref<T, Array>, size_t>, - std::is_invocable<Func, size_t, for_each_elem_ref<T, Array>>, - std::is_invocable<Func, for_each_elem_ref<T, Array>>>; - - template <typename Func, typename Array, typename T> - using can_for_each_nothrow = std::conditional_t< - // first form - std::is_invocable_v<Func, for_each_elem_ref<T, Array>, size_t>, - std::is_nothrow_invocable<Func, for_each_elem_ref<T, Array>, size_t>, - std::conditional_t< - // second form - std::is_invocable_v<Func, size_t, for_each_elem_ref<T, Array>>, - std::is_nothrow_invocable<Func, size_t, for_each_elem_ref<T, Array>>, - std::conditional_t< - // third form - std::is_invocable_v<Func, for_each_elem_ref<T, Array>>, - std::is_nothrow_invocable<Func, for_each_elem_ref<T, Array>>, - std::false_type>>>; - - template <typename Func, typename Array> - using can_for_each_any = std::disjunction<can_for_each<Func, Array, table>, - can_for_each<Func, Array, array>, - can_for_each<Func, Array, std::string>, - can_for_each<Func, Array, int64_t>, - can_for_each<Func, Array, double>, - can_for_each<Func, Array, bool>, - can_for_each<Func, Array, date>, - can_for_each<Func, Array, time>, - can_for_each<Func, Array, date_time>>; - - template <typename Func, typename Array, typename T> - using for_each_is_nothrow_one = std::disjunction<std::negation<can_for_each<Func, Array, T>>, // - can_for_each_nothrow<Func, Array, T>>; - - template <typename Func, typename Array> - using for_each_is_nothrow = std::conjunction<for_each_is_nothrow_one<Func, Array, table>, - for_each_is_nothrow_one<Func, Array, array>, - for_each_is_nothrow_one<Func, Array, std::string>, - for_each_is_nothrow_one<Func, Array, int64_t>, - for_each_is_nothrow_one<Func, Array, double>, - for_each_is_nothrow_one<Func, Array, bool>, - for_each_is_nothrow_one<Func, Array, date>, - for_each_is_nothrow_one<Func, Array, time>, - for_each_is_nothrow_one<Func, Array, date_time>>; - - template <typename Func, typename Array> - static void do_for_each(Func&& visitor, Array&& arr) // - noexcept(for_each_is_nothrow<Func&&, Array&&>::value) - { - static_assert(can_for_each_any<Func&&, Array&&>::value, - "TOML array for_each visitors must be invocable for at least one of the toml::node " - "specializations:" TOML_SA_NODE_TYPE_LIST); - - for (size_t i = 0; i < arr.size(); i++) - { - using node_ref = impl::copy_cvref<toml::node, Array&&>; - static_assert(std::is_reference_v<node_ref>); +TOML_NAMESPACE_START { + /// \brief A RandomAccessIterator for iterating over elements in a toml::array. + using array_iterator = POXY_IMPLEMENTATION_DETAIL(impl::array_iterator<false>); + + /// \brief A RandomAccessIterator for iterating over const elements in a toml::array. + using const_array_iterator = POXY_IMPLEMENTATION_DETAIL(impl::array_iterator<true>); + + /// \brief A TOML array. + /// + /// \detail The interface of this type is modeled after std::vector, with some + /// additional considerations made for the heterogeneous nature of a + /// TOML array. + /// + /// \godbolt{sjK4da} + /// + /// \cpp + /// + /// toml::table tbl = toml::parse(R"( + /// arr = [1, 2, 3, 4, 'five'] + /// )"sv); + /// + /// // get the element as an array + /// toml::array& arr = *tbl.get_as<toml::array>("arr"); + /// std::cout << arr << "\n"; + /// + /// // increment each element with visit() + /// for (auto&& elem : arr) + /// { + /// elem.visit([](auto&& el) noexcept + /// { + /// if constexpr (toml::is_number<decltype(el)>) + /// (*el)++; + /// else if constexpr (toml::is_string<decltype(el)>) + /// el = "six"sv; + /// }); + /// } + /// std::cout << arr << "\n"; + /// + /// // add and remove elements + /// arr.push_back(7); + /// arr.push_back(8.0f); + /// arr.push_back("nine"sv); + /// arr.erase(arr.cbegin()); + /// std::cout << arr << "\n"; + /// + /// // emplace elements + /// arr.emplace_back("ten"); + /// arr.emplace_back<toml::array>(11, 12.0); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, 3, 4, 'five' ] + /// [ 2, 3, 4, 5, 'six' ] + /// [ 3, 4, 5, 'six', 7, 8.0, 'nine' ] + /// [ 3, 4, 5, 'six', 7, 8.0, 'nine', 'ten', [ 11, 12.0 ] ] + /// \eout + class TOML_EXPORTED_CLASS array : public node { + private: + /// \cond + + using vector_type = std::vector<impl::node_ptr>; + using vector_iterator = typename vector_type::iterator; + using const_vector_iterator = typename vector_type::const_iterator; + vector_type elems_; + + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + array(const impl::array_init_elem*, const impl::array_init_elem*); + + TOML_NODISCARD_CTOR + array(std::false_type, std::initializer_list<impl::array_init_elem> elems) // + : array{elems.begin(), elems.end()} {} + + TOML_EXPORTED_MEMBER_FUNCTION + void preinsertion_resize(size_t idx, size_t count); + + TOML_EXPORTED_MEMBER_FUNCTION + void insert_at_back(impl::node_ptr&&); + + TOML_EXPORTED_MEMBER_FUNCTION + vector_iterator insert_at(const_vector_iterator, impl::node_ptr&&); + + template <typename T> + void emplace_back_if_not_empty_view(T&& val, value_flags flags) { + if constexpr (is_node_view<T>) { + if (!val) return; + } + insert_at_back(impl::make_node(static_cast<T&&>(val), flags)); + } + + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + size_t total_leaf_count() const noexcept; + + TOML_EXPORTED_MEMBER_FUNCTION + void flatten_child(array&& child, size_t& dest_index) noexcept; + + /// \endcond + + public: + using value_type = node; + using size_type = size_t; + using difference_type = ptrdiff_t; + using reference = node&; + using const_reference = const node&; + + /// \brief Default constructor. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + array() noexcept; + + TOML_EXPORTED_MEMBER_FUNCTION + ~array() noexcept; + + /// \brief Copy constructor. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + array(const array&); + + /// \brief Move constructor. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + array(array&& other) noexcept; + + /// \brief Constructs an array with one or more initial elements. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 2.0, "three"sv, toml::array{ 4, 5 } }; + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2.0, 'three', [ 4, 5 ] ] + /// \eout + /// + /// \remark \parblock If you need to construct an array with one child array element, the + /// array's move constructor will take precedence and perform a move-construction instead. You + /// can use toml::inserter to suppress this behaviour: \cpp + /// // desired result: [ [ 42 ] ] + /// auto bad = toml::array{ toml::array{ 42 } } + /// auto good = toml::array{ toml::inserter{ toml::array{ 42 } } } + /// std::cout << "bad: " << bad << "\n"; + /// std::cout << "good:" << good << "\n"; + /// \ecpp + /// + /// \out + /// bad: [ 42 ] + /// good: [ [ 42 ] ] + /// \eout + /// + /// \endparblock + /// + /// \tparam ElemType One of the TOML node or value types (or a type promotable to one). + /// \tparam ElemTypes One of the TOML node or value types (or a type promotable to one). + /// \param val The node or value used to initialize element 0. + /// \param vals The nodes or values used to initialize elements 1...N. + TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0 || + !std::is_same_v<impl::remove_cvref<ElemType>, array>), + typename ElemType, typename... ElemTypes) + TOML_NODISCARD_CTOR + explicit array(ElemType&& val, ElemTypes&&... vals) + : array{std::false_type{}, + std::initializer_list<impl::array_init_elem>{static_cast<ElemType&&>(val), + static_cast<ElemTypes&&>(vals)...}} {} + + /// \brief Copy-assignment operator. + TOML_EXPORTED_MEMBER_FUNCTION + array& operator=(const array&); + + /// \brief Move-assignment operator. + TOML_EXPORTED_MEMBER_FUNCTION + array& operator=(array&& rhs) noexcept; + + /// \name Type checks + /// @{ + + /// \brief Returns #toml::node_type::array. + TOML_CONST_INLINE_GETTER + node_type type() const noexcept final { return node_type::array; } + + 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 <typename ElemType = void> + TOML_PURE_GETTER bool is_homogeneous() const noexcept { + using type = impl::remove_cvref<impl::unwrap_node<ElemType>>; + static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>, + "The template type argument of array::is_homogeneous() must be void or one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + return is_homogeneous(impl::node_type_of<type>); + } + /// \endcond + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_table() const noexcept final { return false; } + + /// \brief Returns `true`. + TOML_CONST_INLINE_GETTER + bool is_array() const noexcept final { return true; } + + /// \brief Returns `true` if the array contains only tables. + TOML_PURE_GETTER + bool is_array_of_tables() const noexcept final { return is_homogeneous(node_type::table); } + + /// \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 `nullptr`. + TOML_CONST_INLINE_GETTER + table* as_table() noexcept final { return nullptr; } + + /// \brief Returns a pointer to the array. + TOML_CONST_INLINE_GETTER + array* as_array() noexcept final { return this; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<std::string>* as_string() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<int64_t>* as_integer() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<double>* as_floating_point() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<bool>* as_boolean() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<date>* as_date() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<time>* as_time() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<date_time>* as_date_time() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const table* as_table() const noexcept final { return nullptr; } + + /// \brief Returns a const-qualified pointer to the array. + TOML_CONST_INLINE_GETTER + const array* as_array() const noexcept final { return this; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<std::string>* as_string() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<int64_t>* as_integer() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<double>* as_floating_point() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<bool>* as_boolean() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<date>* as_date() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<time>* as_time() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<date_time>* as_date_time() const noexcept final { return nullptr; } + + /// @} + + /// \name Value retrieval + /// @{ + + /// \brief Gets a pointer to the element at a specific index. + /// + /// \detail \cpp + /// auto arr = toml::array{ 99, "bottles of beer on the wall" }; + /// std::cout << "element [0] exists: "sv << !!arr.get(0) << "\n"; + /// std::cout << "element [1] exists: "sv << !!arr.get(1) << "\n"; + /// std::cout << "element [2] exists: "sv << !!arr.get(2) << "\n"; + /// if (toml::node* val = arr.get(0)) + /// std::cout << "element [0] is an "sv << val->type() << "\n"; + /// \ecpp + /// + /// \out + /// element [0] exists: true + /// element [1] exists: true + /// element [2] exists: false + /// element [0] is an integer + /// \eout + /// + /// \param index The element's index. + /// + /// \returns A pointer to the element at the specified index if one existed, or nullptr. + TOML_PURE_INLINE_GETTER + node* get(size_t index) noexcept { + return index < elems_.size() ? elems_[index].get() : nullptr; + } + + /// \brief Gets a pointer to the element at a specific index (const overload). + /// + /// \param index The element's index. + /// + /// \returns A pointer to the element at the specified index if one existed, or nullptr. + TOML_PURE_INLINE_GETTER + const node* get(size_t index) const noexcept { return const_cast<array&>(*this).get(index); } + + /// \brief Gets a pointer to the element at a specific index if it is a particular type. + /// + /// \detail \cpp + /// auto arr = toml::array{ 42, "is the meaning of life, apparently."sv }; + /// if (toml::value<int64_t>* val = arr.get_as<int64_t>(0)) + /// std::cout << "element [0] is an integer with value "sv << *val << "\n"; + /// \ecpp + /// + /// \out + /// element [0] is an integer with value 42 + /// \eout + /// + /// \tparam ElemType toml::table, toml::array, or a native TOML value type + /// \param index The element's index. + /// + /// \returns A pointer to the selected element if it existed and was of the specified type, or + /// nullptr. + template <typename ElemType> + TOML_NODISCARD impl::wrap_node<ElemType>* get_as(size_t index) noexcept { + if (auto val = get(index)) return val->template as<ElemType>(); + return nullptr; + } + + /// \brief Gets a pointer to the element at a specific index if it is a particular type (const + /// overload). + /// + /// \tparam ElemType toml::table, toml::array, or a native TOML value type + /// \param index The element's index. + /// + /// \returns A pointer to the selected element if it existed and was of the specified type, or + /// nullptr. + template <typename ElemType> + TOML_NODISCARD const impl::wrap_node<ElemType>* get_as(size_t index) const noexcept { + return const_cast<array&>(*this).template get_as<ElemType>(index); + } + + /// \cond + using node::operator[]; // inherit operator[toml::path] + /// \endcond + + /// \brief Gets a reference to the element at a specific index. + TOML_NODISCARD + node& operator[](size_t index) noexcept { return *elems_[index]; } + + /// \brief Gets a reference to the element at a specific index. + TOML_NODISCARD + const node& operator[](size_t index) const noexcept { return *elems_[index]; } + + /// \brief Gets a reference to the element at a specific index, throwing `std::out_of_range` if + /// none existed. + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node& at(size_t index); + + /// \brief Gets a reference to the element at a specific index, throwing `std::out_of_range` if + /// none existed. + TOML_NODISCARD + const node& at(size_t index) const { return const_cast<array&>(*this).at(index); } + + /// \brief Returns a reference to the first element in the array. + TOML_NODISCARD + node& front() noexcept { return *elems_.front(); } + + /// \brief Returns a reference to the first element in the array. + TOML_NODISCARD + const node& front() const noexcept { return *elems_.front(); } + + /// \brief Returns a reference to the last element in the array. + TOML_NODISCARD + node& back() noexcept { return *elems_.back(); } + + /// \brief Returns a reference to the last element in the array. + TOML_NODISCARD + const node& back() const noexcept { return *elems_.back(); } + + /// @} + + /// \name Iteration + /// @{ + + /// \brief A RandomAccessIterator for iterating over elements in a toml::array. + using iterator = array_iterator; + + /// \brief A RandomAccessIterator for iterating over const elements in a toml::array. + using const_iterator = const_array_iterator; + + /// \brief Returns an iterator to the first element. + TOML_NODISCARD + iterator begin() noexcept { return iterator{elems_.begin()}; } + + /// \brief Returns an iterator to the first element. + TOML_NODISCARD + const_iterator begin() const noexcept { return const_iterator{elems_.cbegin()}; } + + /// \brief Returns an iterator to the first element. + TOML_NODISCARD + const_iterator cbegin() const noexcept { return const_iterator{elems_.cbegin()}; } + + /// \brief Returns an iterator to one-past-the-last element. + TOML_NODISCARD + iterator end() noexcept { return iterator{elems_.end()}; } + + /// \brief Returns an iterator to one-past-the-last element. + TOML_NODISCARD + const_iterator end() const noexcept { return const_iterator{elems_.cend()}; } + + /// \brief Returns an iterator to one-past-the-last element. + TOML_NODISCARD + const_iterator cend() const noexcept { return const_iterator{elems_.cend()}; } + + private: + /// \cond + + template <typename T, typename Array> + using for_each_elem_ref = + impl::copy_cvref<impl::wrap_node<impl::remove_cvref<impl::unwrap_node<T>>>, Array>; + + template <typename Func, typename Array, typename T> + using can_for_each = + std::disjunction<std::is_invocable<Func, for_each_elem_ref<T, Array>, size_t>, + std::is_invocable<Func, size_t, for_each_elem_ref<T, Array>>, + std::is_invocable<Func, for_each_elem_ref<T, Array>>>; + + template <typename Func, typename Array, typename T> + using can_for_each_nothrow = std::conditional_t< + // first form + std::is_invocable_v<Func, for_each_elem_ref<T, Array>, size_t>, + std::is_nothrow_invocable<Func, for_each_elem_ref<T, Array>, size_t>, + std::conditional_t< + // second form + std::is_invocable_v<Func, size_t, for_each_elem_ref<T, Array>>, + std::is_nothrow_invocable<Func, size_t, for_each_elem_ref<T, Array>>, + std::conditional_t< + // third form + std::is_invocable_v<Func, for_each_elem_ref<T, Array>>, + std::is_nothrow_invocable<Func, for_each_elem_ref<T, Array>>, std::false_type>>>; + + template <typename Func, typename Array> + using can_for_each_any = + std::disjunction<can_for_each<Func, Array, table>, can_for_each<Func, Array, array>, + can_for_each<Func, Array, std::string>, can_for_each<Func, Array, int64_t>, + can_for_each<Func, Array, double>, can_for_each<Func, Array, bool>, + can_for_each<Func, Array, date>, can_for_each<Func, Array, time>, + can_for_each<Func, Array, date_time>>; + + template <typename Func, typename Array, typename T> + using for_each_is_nothrow_one = + std::disjunction<std::negation<can_for_each<Func, Array, T>>, // + can_for_each_nothrow<Func, Array, T>>; + + template <typename Func, typename Array> + using for_each_is_nothrow = std::conjunction< + for_each_is_nothrow_one<Func, Array, table>, for_each_is_nothrow_one<Func, Array, array>, + for_each_is_nothrow_one<Func, Array, std::string>, + for_each_is_nothrow_one<Func, Array, int64_t>, for_each_is_nothrow_one<Func, Array, double>, + for_each_is_nothrow_one<Func, Array, bool>, for_each_is_nothrow_one<Func, Array, date>, + for_each_is_nothrow_one<Func, Array, time>, + for_each_is_nothrow_one<Func, Array, date_time>>; + + template <typename Func, typename Array> + static void do_for_each(Func&& visitor, Array&& arr) // + noexcept(for_each_is_nothrow<Func&&, Array&&>::value) { + static_assert( + can_for_each_any<Func&&, Array&&>::value, + "TOML array for_each visitors must be invocable for at least one of the toml::node " + "specializations:" TOML_SA_NODE_TYPE_LIST); + + for (size_t i = 0; i < arr.size(); i++) { + using node_ref = impl::copy_cvref<toml::node, Array&&>; + static_assert(std::is_reference_v<node_ref>); #if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN #ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED - static_assert(impl::always_false<Func, Array, node_ref>, // - TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE); + static_assert(impl::always_false<Func, Array, node_ref>, // + TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE); #endif - static_cast<node_ref>(static_cast<Array&&>(arr)[i]) - .visit( - [&]([[maybe_unused]] auto&& elem) // - noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>::value) - { - using elem_ref = for_each_elem_ref<decltype(elem), Array&&>; - static_assert(std::is_reference_v<elem_ref>); - - // func(elem, i) - if constexpr (std::is_invocable_v<Func&&, elem_ref, size_t>) - { - static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i); - } - - // func(i, elem) - else if constexpr (std::is_invocable_v<Func&&, size_t, elem_ref>) - { - static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem)); - } - - // func(elem) - else if constexpr (std::is_invocable_v<Func&&, elem_ref>) - { - static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem)); - } - }); + static_cast<node_ref>(static_cast<Array&&>(arr)[i]) + .visit([&]([[maybe_unused]] auto&& elem) // + noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>::value) { + using elem_ref = for_each_elem_ref<decltype(elem), Array&&>; + static_assert(std::is_reference_v<elem_ref>); + + // func(elem, i) + if constexpr (std::is_invocable_v<Func&&, elem_ref, size_t>) { + static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i); + } + + // func(i, elem) + else if constexpr (std::is_invocable_v<Func&&, size_t, elem_ref>) { + static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem)); + } + + // func(elem) + else if constexpr (std::is_invocable_v<Func&&, elem_ref>) { + static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem)); + } + }); #else - const auto keep_going = - static_cast<node_ref>(static_cast<Array&&>(arr)[i]) - .visit( - [&]([[maybe_unused]] auto&& elem) // - noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>::value) - { - using elem_ref = for_each_elem_ref<decltype(elem), Array&&>; - static_assert(std::is_reference_v<elem_ref>); - - // func(elem, i) - if constexpr (std::is_invocable_v<Func&&, elem_ref, size_t>) - { - using return_type = - decltype(static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i)); - - if constexpr (impl::is_constructible_or_convertible<bool, return_type>) - { - return static_cast<bool>( - static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i)); - } - else - { - static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i); - return true; - } - } - - // func(i, elem) - else if constexpr (std::is_invocable_v<Func&&, size_t, elem_ref>) - { - using return_type = - decltype(static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem))); - - if constexpr (impl::is_constructible_or_convertible<bool, return_type>) - { - return static_cast<bool>( - static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem))); - } - else - { - static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem)); - return true; - } - } - - // func(elem) - else if constexpr (std::is_invocable_v<Func&&, elem_ref>) - { - using return_type = - decltype(static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem))); - - if constexpr (impl::is_constructible_or_convertible<bool, return_type>) - { - return static_cast<bool>( - static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem))); - } - else - { - static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem)); - return true; - } - } - - // visitor not compatible with this particular type - else - return true; - }); - - if (!keep_going) - return; + const auto keep_going = + static_cast<node_ref>(static_cast<Array&&>(arr)[i]) + .visit( + [&]([[maybe_unused]] auto&& elem) // + noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>::value) { + using elem_ref = for_each_elem_ref<decltype(elem), Array&&>; + static_assert(std::is_reference_v<elem_ref>); + + // func(elem, i) + if constexpr (std::is_invocable_v<Func&&, elem_ref, size_t>) { + using return_type = + decltype(static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i)); + + if constexpr (impl::is_constructible_or_convertible<bool, return_type>) { + return static_cast<bool>( + static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i)); + } else { + static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i); + return true; + } + } + + // func(i, elem) + else if constexpr (std::is_invocable_v<Func&&, size_t, elem_ref>) { + using return_type = + decltype(static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem))); + + if constexpr (impl::is_constructible_or_convertible<bool, return_type>) { + return static_cast<bool>( + static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem))); + } else { + static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem)); + return true; + } + } + + // func(elem) + else if constexpr (std::is_invocable_v<Func&&, elem_ref>) { + using return_type = + decltype(static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem))); + + if constexpr (impl::is_constructible_or_convertible<bool, return_type>) { + return static_cast<bool>( + static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem))); + } else { + static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem)); + return true; + } + } + + // visitor not compatible with this particular type + else + return true; + }); + + if (!keep_going) return; #endif - } - } - - /// \endcond - - public: - /// \brief Invokes a visitor on each element in the array. - /// - /// \tparam Func A callable type invocable with one of the following signatures: - /// <ul> - /// <li> `func(elem, index)` - /// <li> `func(elem)` - /// <li> `func(index, elem)` - /// </ul> - /// Where: - /// <ul> - /// <li> `elem` will recieve the element as it's concrete type with cvref-qualifications matching the array - /// <li> `index` will recieve a `size_t` indicating the element's index - /// </ul> - /// Visitors returning `bool` (or something convertible to `bool`) will cause iteration to - /// stop if they return `false`. - /// - /// \param visitor The visitor object. - /// - /// \returns A reference to the array. - /// - /// \details \cpp - /// toml::array arr{ 0, 1, 2, 3.0, "four", "five", 6 }; - /// - /// // select only the integers using a strongly-typed visitor - /// arr.for_each([](toml::value<int64_t>& elem) - /// { - /// std::cout << elem << ", "; - /// }); - /// std::cout << "\n"; - /// - /// // select all the numeric values using a generic visitor + is_number<> metafunction - /// arr.for_each([](auto&& elem) - /// { - /// if constexpr (toml::is_number<decltype(elem)>) - /// std::cout << elem << ", "; - /// }); - /// std::cout << "\n"; - /// - /// // select all the numeric values until we encounter something non-numeric - /// arr.for_each([](auto&& elem) - /// { - /// if constexpr (toml::is_number<decltype(elem)>) - /// { - /// std::cout << elem << ", "; - /// return true; // "keep going" - /// } - /// else - /// return false; // "stop!" - /// - /// }); - /// std::cout << "\n"; - /// - /// \ecpp - /// \out - /// 0, 1, 2, 6, - /// 0, 1, 2, 3.0, 6, - /// 0, 1, 2, 3.0, - /// \eout - /// - /// \see node::visit() - template <typename Func> - array& for_each(Func&& visitor) & // - noexcept(for_each_is_nothrow<Func&&, array&>::value) - { - do_for_each(static_cast<Func&&>(visitor), *this); - return *this; - } - - /// \brief Invokes a visitor on each element in the array (rvalue overload). - template <typename Func> - array&& for_each(Func&& visitor) && // - noexcept(for_each_is_nothrow<Func&&, array&&>::value) - { - do_for_each(static_cast<Func&&>(visitor), static_cast<array&&>(*this)); - return static_cast<array&&>(*this); - } - - /// \brief Invokes a visitor on each element in the array (const lvalue overload). - template <typename Func> - const array& for_each(Func&& visitor) const& // - noexcept(for_each_is_nothrow<Func&&, const array&>::value) - { - do_for_each(static_cast<Func&&>(visitor), *this); - return *this; - } - - /// \brief Invokes a visitor on each element in the array (const rvalue overload). - template <typename Func> - const array&& for_each(Func&& visitor) const&& // - noexcept(for_each_is_nothrow<Func&&, const array&&>::value) - { - do_for_each(static_cast<Func&&>(visitor), static_cast<const array&&>(*this)); - return static_cast<const array&&>(*this); - } - - /// @} - - /// \name Size and Capacity - /// @{ - - /// \brief Returns true if the array is empty. - TOML_NODISCARD - bool empty() const noexcept - { - return elems_.empty(); - } - - /// \brief Returns the number of elements in the array. - TOML_NODISCARD - size_t size() const noexcept - { - return elems_.size(); - } - - /// \brief Returns the maximum number of elements that can be stored in an array on the current platform. - TOML_NODISCARD - size_t max_size() const noexcept - { - return elems_.max_size(); - } - - /// \brief Returns the current max number of elements that may be held in the array's internal storage. - TOML_NODISCARD - size_t capacity() const noexcept - { - return elems_.capacity(); - } - - /// \brief Reserves internal storage capacity up to a pre-determined number of elements. - TOML_EXPORTED_MEMBER_FUNCTION - void reserve(size_t new_capacity); - - /// \brief Requests the removal of any unused internal storage capacity. - TOML_EXPORTED_MEMBER_FUNCTION - void shrink_to_fit(); - - /// \brief Shrinks the array to the given size. - /// - /// \detail \godbolt{rxEzK5} - /// - /// \cpp - /// auto arr = toml::array{ 1, 2, 3 }; - /// std::cout << arr << "\n"; - /// - /// arr.truncate(5); // no-op - /// std::cout << arr << "\n"; - /// - /// arr.truncate(1); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2, 3 ] - /// [ 1, 2, 3 ] - /// [ 1] - /// \eout - /// - /// \remarks Does nothing if the requested size is larger than or equal to the current size. - TOML_EXPORTED_MEMBER_FUNCTION - void truncate(size_t new_size); - - /// \brief Resizes the array. - /// - /// \detail \godbolt{W5zqx3} - /// - /// \cpp - /// auto arr = toml::array{ 1, 2, 3 }; - /// std::cout << arr << "\n"; - /// - /// arr.resize(6, 42); - /// std::cout << arr << "\n"; - /// - /// arr.resize(2, 0); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2, 3 ] - /// [ 1, 2, 3, 42, 42, 42 ] - /// [ 1, 2 ] - /// \eout - /// - /// \tparam ElemType toml::node, toml::table, toml::array, or a native TOML value type - /// (or a type promotable to one). - /// - /// \param new_size The number of elements the array will have after resizing. - /// \param default_init_val The node or value used to initialize new elements if the array needs to grow. - /// \param default_init_flags Value flags to apply to new values created if new elements are created by growing. - template <typename ElemType> - void resize(size_t new_size, - ElemType&& default_init_val, - value_flags default_init_flags = preserve_source_value_flags) - { - static_assert(!is_node_view<ElemType>, - "The default element type argument to toml::array::resize may not be toml::node_view."); - - if (!new_size) - clear(); - else if (new_size > elems_.size()) - insert(cend(), new_size - elems_.size(), static_cast<ElemType&&>(default_init_val), default_init_flags); - else - truncate(new_size); - } - - /// @} - - /// \name Erasure - /// @{ - - /// \brief Removes the specified element from the array. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, 2, 3 }; - /// std::cout << arr << "\n"; - /// - /// arr.erase(arr.cbegin() + 1); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2, 3 ] - /// [ 1, 3 ] - /// \eout - /// - /// \param pos Iterator to the element being erased. - /// - /// \returns Iterator to the first element immediately following the removed element. - TOML_EXPORTED_MEMBER_FUNCTION - iterator erase(const_iterator pos) noexcept; - - /// \brief Removes the elements in the range [first, last) from the array. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, "bad", "karma" 2 }; - /// std::cout << arr << "\n"; - /// - /// arr.erase(arr.cbegin() + 1, arr.cbegin() + 3); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 'bad', 'karma', 3 ] - /// [ 1, 3 ] - /// \eout - /// - /// \param first Iterator to the first element being erased. - /// \param last Iterator to the one-past-the-last element being erased. - /// - /// \returns Iterator to the first element immediately following the last removed element. - TOML_EXPORTED_MEMBER_FUNCTION - iterator erase(const_iterator first, const_iterator last) noexcept; - - /// \brief Flattens this array, recursively hoisting the contents of child arrays up into itself. - /// - /// \detail \cpp - /// - /// auto arr = toml::array{ 1, 2, toml::array{ 3, 4, toml::array{ 5 } }, 6, toml::array{} }; - /// std::cout << arr << "\n"; - /// - /// arr.flatten(); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2, [ 3, 4, [ 5 ] ], 6, [] ] - /// [ 1, 2, 3, 4, 5, 6 ] - /// \eout - /// - /// \remarks Arrays inside child tables are not flattened. - /// - /// \returns A reference to the array. - TOML_EXPORTED_MEMBER_FUNCTION - array& flatten() &; - - /// \brief Flattens this array, recursively hoisting the contents of child arrays up into itself (rvalue overload). - array&& flatten() && - { - return static_cast<toml::array&&>(this->flatten()); - } - - /// \brief Removes empty child arrays and tables. - /// - /// \detail \cpp - /// - /// auto arr = toml::array{ 1, 2, toml::array{ }, toml::array{ 3, toml::array{ } }, 4 }; - /// std::cout << arr << "\n"; - /// - /// arr.prune(true); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2, [], [ 3, [] ], 4 ] - /// [ 1, 2, [ 3 ], 4 ] - /// \eout - /// - /// \param recursive Should child arrays and tables themselves be pruned? - /// - /// \returns A reference to the array. - TOML_EXPORTED_MEMBER_FUNCTION - array& prune(bool recursive = true) & noexcept; - - /// \brief Removes empty child arrays and tables (rvalue overload). - /// - /// \param recursive Should child arrays and tables themselves be pruned? - /// - /// \returns An rvalue reference to the array. - array&& prune(bool recursive = true) && noexcept - { - return static_cast<toml::array&&>(this->prune(recursive)); - } - - /// \brief Removes the last element from the array. - TOML_EXPORTED_MEMBER_FUNCTION - void pop_back() noexcept; - - /// \brief Removes all elements from the array. - TOML_EXPORTED_MEMBER_FUNCTION - void clear() noexcept; - - /// @} - - /// \name Insertion and Emplacement - /// @{ - - /// \brief Inserts a new element at a specific position in the array. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, 3 }; - /// arr.insert(arr.cbegin() + 1, "two"); - /// arr.insert(arr.cend(), toml::array{ 4, 5 }); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 'two', 3, [ 4, 5 ] ] - /// \eout - /// - /// \tparam ElemType toml::node, toml::node_view, toml::table, toml::array, or a native TOML value type - /// (or a type promotable to one). - /// \param pos The insertion position. - /// \param val The node or value being inserted. - /// \param flags Value flags to apply to new values. - /// - /// \returns \conditional_return{Valid input} - /// An iterator to the newly-inserted element. - /// \conditional_return{Input is a null toml::node_view} - /// end() - /// - /// \attention The return value will always be `end()` if the input value was a null toml::node_view, - /// because no insertion can take place. This is the only circumstance in which this can occur. - template <typename ElemType> - iterator insert(const_iterator pos, ElemType&& val, value_flags flags = preserve_source_value_flags) - { - if constexpr (is_node_view<ElemType>) - { - if (!val) - return end(); - } - return iterator{ insert_at(const_vector_iterator{ pos }, - impl::make_node(static_cast<ElemType&&>(val), flags)) }; - } - - /// \brief Repeatedly inserts a new element starting at a specific position in the array. - /// - /// \detail \cpp - /// auto arr = toml::array{ - /// "with an evil twinkle in its eye the goose said", - /// "and immediately we knew peace was never an option." - /// }; - /// arr.insert(arr.cbegin() + 1, 3, "honk"); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ - /// 'with an evil twinkle in its eye the goose said', - /// 'honk', - /// 'honk', - /// 'honk', - /// 'and immediately we knew peace was never an option.' - /// ] - /// \eout - /// - /// \tparam ElemType toml::node, toml::node_view, toml::table, toml::array, or a native TOML value type - /// (or a type promotable to one). - /// \param pos The insertion position. - /// \param count The number of times the node or value should be inserted. - /// \param val The node or value being inserted. - /// \param flags Value flags to apply to new values. - /// - /// \returns \conditional_return{Valid input} - /// An iterator to the newly-inserted element. - /// \conditional_return{count == 0} - /// A copy of pos - /// \conditional_return{Input is a null toml::node_view} - /// end() - /// - /// \attention The return value will always be `end()` if the input value was a null toml::node_view, - /// because no insertion can take place. This is the only circumstance in which this can occur. - template <typename ElemType> - iterator insert(const_iterator pos, - size_t count, - ElemType&& val, - value_flags flags = preserve_source_value_flags) - { - if constexpr (is_node_view<ElemType>) - { - if (!val) - return end(); - } - switch (count) - { - case 0: return iterator{ elems_.begin() + (const_vector_iterator{ pos } - elems_.cbegin()) }; - case 1: return insert(pos, static_cast<ElemType&&>(val), flags); - default: - { - const auto start_idx = static_cast<size_t>(const_vector_iterator{ pos } - elems_.cbegin()); - preinsertion_resize(start_idx, count); - size_t i = start_idx; - for (size_t e = start_idx + count - 1u; i < e; i++) - elems_[i] = impl::make_node(val, flags); - - //# potentially move the initial value into the last element - elems_[i] = impl::make_node(static_cast<ElemType&&>(val), flags); - return iterator{ elems_.begin() + static_cast<ptrdiff_t>(start_idx) }; - } - } - } - - /// \brief Inserts a range of elements into the array at a specific position. - /// - /// \tparam Iter An iterator type. Must satisfy ForwardIterator. - /// \param pos The insertion position. - /// \param first Iterator to the first node or value being inserted. - /// \param last Iterator to the one-past-the-last node or value being inserted. - /// \param flags Value flags to apply to new values. - /// - /// \returns \conditional_return{Valid input} - /// An iterator to the first newly-inserted element. - /// \conditional_return{first >= last} - /// A copy of pos - /// \conditional_return{All objects in the range were null toml::node_views} - /// A copy of pos - template <typename Iter> - iterator insert(const_iterator pos, Iter first, Iter last, value_flags flags = preserve_source_value_flags) - { - const auto distance = std::distance(first, last); - if (distance <= 0) - return iterator{ elems_.begin() + (const_vector_iterator{ pos } - elems_.cbegin()) }; - else - { - auto count = distance; - using deref_type = decltype(*first); - if constexpr (is_node_view<deref_type>) - { - for (auto it = first; it != last; it++) - if (!(*it)) - count--; - if (!count) - return iterator{ elems_.begin() + (const_vector_iterator{ pos } - elems_.cbegin()) }; - } - const auto start_idx = static_cast<size_t>(const_vector_iterator{ pos } - elems_.cbegin()); - preinsertion_resize(start_idx, static_cast<size_t>(count)); - size_t i = start_idx; - for (auto it = first; it != last; it++) - { - if constexpr (is_node_view<deref_type>) - { - if (!(*it)) - continue; - } - if constexpr (std::is_rvalue_reference_v<deref_type>) - elems_[i++] = impl::make_node(std::move(*it), flags); - else - elems_[i++] = impl::make_node(*it, flags); - } - return iterator{ elems_.begin() + static_cast<ptrdiff_t>(start_idx) }; - } - } - - /// \brief Inserts a range of elements into the array at a specific position. - /// - /// \tparam ElemType toml::node_view, toml::table, toml::array, or a native TOML value type - /// (or a type promotable to one). - /// \param pos The insertion position. - /// \param ilist An initializer list containing the values to be inserted. - /// \param flags Value flags to apply to new values. - /// - /// \returns \conditional_return{Valid input} - /// An iterator to the first newly-inserted element. - /// \conditional_return{Input list is empty} - /// A copy of pos - /// \conditional_return{All objects in the list were null toml::node_views} - /// A copy of pos - template <typename ElemType> - iterator insert(const_iterator pos, - std::initializer_list<ElemType> ilist, - value_flags flags = preserve_source_value_flags) - { - return insert(pos, ilist.begin(), ilist.end(), flags); - } - - /// \brief Emplaces a new element at a specific position in the array. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, 2 }; - /// - /// //add a string using std::string's substring constructor - /// arr.emplace<std::string>(arr.cbegin() + 1, "this is not a drill"sv, 14, 5); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 'drill', 2 ] - /// \eout - /// - /// \tparam ElemType toml::table, toml::array, or any native TOML value type. - /// \tparam Args Value constructor argument types. - /// \param pos The insertion position. - /// \param args Arguments to forward to the value's constructor. - /// - /// \returns An iterator to the inserted element. - /// - /// \remarks There is no difference between insert() and emplace() - /// for trivial value types (floats, ints, bools). - template <typename ElemType = void, typename... Args> - iterator emplace(const_iterator pos, Args&&... args) - { - using raw_elem_type = impl::remove_cvref<ElemType>; - using elem_type = std::conditional_t<std::is_void_v<raw_elem_type>, // - impl::emplaced_type_of<Args&&...>, - raw_elem_type>; - - using type = impl::remove_cvref<impl::unwrap_node<elem_type>>; - static_assert(impl::is_native<type> || impl::is_one_of<type, table, array>, - "Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - return iterator{ insert_at(const_vector_iterator{ pos }, - impl::node_ptr{ new impl::wrap_node<type>{ static_cast<Args&&>(args)... } }) }; - } - - /// \brief Replaces the element at a specific position in the array with a different value. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, 2, 3 }; - /// std::cout << arr << "\n"; - /// arr.replace(arr.cbegin() + 1, "two"); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2, 3 ] - /// [ 1, 'two', 3 ] - /// \eout - /// - /// \tparam ElemType toml::node, toml::node_view, toml::table, toml::array, or a native TOML value type - /// (or a type promotable to one). - /// \param pos The insertion position. - /// \param val The node or value being inserted. - /// \param flags Value flags to apply to new values. - /// - /// \returns \conditional_return{Valid input} - /// An iterator to the replaced element. - /// \conditional_return{Input is a null toml::node_view} - /// end() - /// - /// \attention The return value will always be `end()` if the input value was a null toml::node_view, - /// because no replacement can take place. This is the only circumstance in which this can occur. - template <typename ElemType> - iterator replace(const_iterator pos, ElemType&& val, value_flags flags = preserve_source_value_flags) - { - TOML_ASSERT(pos >= cbegin() && pos < cend()); - - if constexpr (is_node_view<ElemType>) - { - if (!val) - return end(); - } - - const auto it = elems_.begin() + (const_vector_iterator{ pos } - elems_.cbegin()); - *it = impl::make_node(static_cast<ElemType&&>(val), flags); - return iterator{ it }; - } - - /// \brief Appends a new element to the end of the array. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, 2 }; - /// arr.push_back(3); - /// arr.push_back(4.0); - /// arr.push_back(toml::array{ 5, "six"sv }); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2, 3, 4.0, [ 5, 'six' ] ] - /// \eout - /// - /// \tparam ElemType toml::node, toml::node_view, toml::table, toml::array, or a native TOML value type - /// \param val The node or value being added. - /// \param flags Value flags to apply to new values. - /// - /// \attention No insertion takes place if the input value is a null toml::node_view. - /// This is the only circumstance in which this can occur. - template <typename ElemType> - void push_back(ElemType&& val, value_flags flags = preserve_source_value_flags) - { - emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), flags); - } - - /// \brief Emplaces a new element at the end of the array. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, 2 }; - /// arr.emplace_back<toml::array>(3, "four"sv); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// [ 1, 2, [ 3, 'four' ] ] - /// \eout - /// - /// \tparam ElemType toml::table, toml::array, or a native TOML value type - /// \tparam Args Element constructor argument types. - /// \param args Arguments to forward to the elements's constructor. - /// - /// \returns A reference to the newly-constructed element. - /// - /// \remarks There is no difference between push_back() and emplace_back() - /// For trivial value types (floats, ints, bools). - template <typename ElemType = void, typename... Args> - decltype(auto) emplace_back(Args&&... args) - { - using raw_elem_type = impl::remove_cvref<ElemType>; - using elem_type = std::conditional_t<std::is_void_v<raw_elem_type>, // - impl::emplaced_type_of<Args&&...>, - raw_elem_type>; - - static constexpr auto moving_node_ptr = std::is_same_v<elem_type, impl::node_ptr> // - && sizeof...(Args) == 1u // - && impl::first_is_same<impl::node_ptr&&, Args&&...>; - - using unwrapped_type = impl::remove_cvref<impl::unwrap_node<elem_type>>; - - static_assert( - moving_node_ptr // - || impl::is_native<unwrapped_type> // - || impl::is_one_of<unwrapped_type, table, array>, // - "ElemType argument of array::emplace_back() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - if constexpr (moving_node_ptr) - { - insert_at_back(static_cast<Args&&>(args)...); - return *elems_.back(); - } - else - { - auto ptr = new impl::wrap_node<unwrapped_type>{ static_cast<Args&&>(args)... }; - insert_at_back(impl::node_ptr{ ptr }); - return *ptr; - } - } - - /// @} - - private: - /// \cond - - TOML_NODISCARD - TOML_EXPORTED_STATIC_FUNCTION - static bool TOML_CALLCONV equal(const array&, const array&) noexcept; - - template <typename T> - TOML_NODISCARD - static bool equal_to_container(const array& lhs, const T& rhs) noexcept - { - using element_type = std::remove_const_t<typename T::value_type>; - static_assert(impl::is_losslessly_convertible_to_native<element_type>, - "Container element type must be losslessly convertible one of the native TOML value types"); - - if (lhs.size() != rhs.size()) - return false; - if (rhs.size() == 0u) - return true; - - size_t i{}; - for (auto& list_elem : rhs) - { - const auto elem = lhs.get_as<impl::native_type_of<element_type>>(i++); - if (!elem || *elem != list_elem) - return false; - } - - return true; - } - - /// \endcond - - public: - /// \name Equality - /// @{ - - /// \brief Equality operator. - /// - /// \param lhs The LHS array. - /// \param rhs The RHS array. - /// - /// \returns True if the arrays contained the same elements. - TOML_NODISCARD - friend bool operator==(const array& lhs, const array& rhs) noexcept - { - return equal(lhs, rhs); - } - - /// \brief Inequality operator. - /// - /// \param lhs The LHS array. - /// \param rhs The RHS array. - /// - /// \returns True if the arrays did not contain the same elements. - TOML_NODISCARD - friend bool operator!=(const array& lhs, const array& rhs) noexcept - { - return !equal(lhs, rhs); - } - - /// \brief Initializer list equality operator. - template <typename T> - TOML_NODISCARD - friend bool operator==(const array& lhs, const std::initializer_list<T>& rhs) noexcept - { - return equal_to_container(lhs, rhs); - } - TOML_ASYMMETRICAL_EQUALITY_OPS(const array&, const std::initializer_list<T>&, template <typename T>); - - /// \brief Vector equality operator. - template <typename T> - TOML_NODISCARD - friend bool operator==(const array& lhs, const std::vector<T>& rhs) noexcept - { - return equal_to_container(lhs, rhs); - } - TOML_ASYMMETRICAL_EQUALITY_OPS(const array&, const std::vector<T>&, template <typename T>); - - /// @} + } + } + + /// \endcond + + public: + /// \brief Invokes a visitor on each element in the array. + /// + /// \tparam Func A callable type invocable with one of the following signatures: + /// <ul> + /// <li> `func(elem, index)` + /// <li> `func(elem)` + /// <li> `func(index, elem)` + /// </ul> + /// Where: + /// <ul> + /// <li> `elem` will recieve the element as it's concrete type with cvref-qualifications + ///matching the array <li> `index` will recieve a `size_t` indicating the element's index + /// </ul> + /// Visitors returning `bool` (or something convertible to `bool`) will cause iteration + ///to stop if they return `false`. + /// + /// \param visitor The visitor object. + /// + /// \returns A reference to the array. + /// + /// \details \cpp + /// toml::array arr{ 0, 1, 2, 3.0, "four", "five", 6 }; + /// + /// // select only the integers using a strongly-typed visitor + /// arr.for_each([](toml::value<int64_t>& elem) + /// { + /// std::cout << elem << ", "; + /// }); + /// std::cout << "\n"; + /// + /// // select all the numeric values using a generic visitor + is_number<> metafunction + /// arr.for_each([](auto&& elem) + /// { + /// if constexpr (toml::is_number<decltype(elem)>) + /// std::cout << elem << ", "; + /// }); + /// std::cout << "\n"; + /// + /// // select all the numeric values until we encounter something non-numeric + /// arr.for_each([](auto&& elem) + /// { + /// if constexpr (toml::is_number<decltype(elem)>) + /// { + /// std::cout << elem << ", "; + /// return true; // "keep going" + /// } + /// else + /// return false; // "stop!" + /// + /// }); + /// std::cout << "\n"; + /// + /// \ecpp + /// \out + /// 0, 1, 2, 6, + /// 0, 1, 2, 3.0, 6, + /// 0, 1, 2, 3.0, + /// \eout + /// + /// \see node::visit() + template <typename Func> + array& for_each(Func&& visitor) & // + noexcept(for_each_is_nothrow<Func&&, array&>::value) { + do_for_each(static_cast<Func&&>(visitor), *this); + return *this; + } + + /// \brief Invokes a visitor on each element in the array (rvalue overload). + template <typename Func> + array&& for_each(Func&& visitor) && // + noexcept(for_each_is_nothrow<Func&&, array&&>::value) { + do_for_each(static_cast<Func&&>(visitor), static_cast<array&&>(*this)); + return static_cast<array&&>(*this); + } + + /// \brief Invokes a visitor on each element in the array (const lvalue overload). + template <typename Func> + const array& for_each(Func&& visitor) const& // + noexcept(for_each_is_nothrow<Func&&, const array&>::value) { + do_for_each(static_cast<Func&&>(visitor), *this); + return *this; + } + + /// \brief Invokes a visitor on each element in the array (const rvalue overload). + template <typename Func> + const array&& for_each(Func&& visitor) const&& // + noexcept(for_each_is_nothrow<Func&&, const array&&>::value) { + do_for_each(static_cast<Func&&>(visitor), static_cast<const array&&>(*this)); + return static_cast<const array&&>(*this); + } + + /// @} + + /// \name Size and Capacity + /// @{ + + /// \brief Returns true if the array is empty. + TOML_NODISCARD + bool empty() const noexcept { return elems_.empty(); } + + /// \brief Returns the number of elements in the array. + TOML_NODISCARD + size_t size() const noexcept { return elems_.size(); } + + /// \brief Returns the maximum number of elements that can be stored in an array on the current + /// platform. + TOML_NODISCARD + size_t max_size() const noexcept { return elems_.max_size(); } + + /// \brief Returns the current max number of elements that may be held in the array's internal + /// storage. + TOML_NODISCARD + size_t capacity() const noexcept { return elems_.capacity(); } + + /// \brief Reserves internal storage capacity up to a pre-determined number of elements. + TOML_EXPORTED_MEMBER_FUNCTION + void reserve(size_t new_capacity); + + /// \brief Requests the removal of any unused internal storage capacity. + TOML_EXPORTED_MEMBER_FUNCTION + void shrink_to_fit(); + + /// \brief Shrinks the array to the given size. + /// + /// \detail \godbolt{rxEzK5} + /// + /// \cpp + /// auto arr = toml::array{ 1, 2, 3 }; + /// std::cout << arr << "\n"; + /// + /// arr.truncate(5); // no-op + /// std::cout << arr << "\n"; + /// + /// arr.truncate(1); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, 3 ] + /// [ 1, 2, 3 ] + /// [ 1] + /// \eout + /// + /// \remarks Does nothing if the requested size is larger than or equal to the current size. + TOML_EXPORTED_MEMBER_FUNCTION + void truncate(size_t new_size); + + /// \brief Resizes the array. + /// + /// \detail \godbolt{W5zqx3} + /// + /// \cpp + /// auto arr = toml::array{ 1, 2, 3 }; + /// std::cout << arr << "\n"; + /// + /// arr.resize(6, 42); + /// std::cout << arr << "\n"; + /// + /// arr.resize(2, 0); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, 3 ] + /// [ 1, 2, 3, 42, 42, 42 ] + /// [ 1, 2 ] + /// \eout + /// + /// \tparam ElemType toml::node, toml::table, toml::array, or a native TOML value type + /// (or a type promotable to one). + /// + /// \param new_size The number of elements the array will have after resizing. + /// \param default_init_val The node or value used to initialize new elements if the array + /// needs to grow. + /// \param default_init_flags Value flags to apply to new values created if new elements are + /// created by growing. + template <typename ElemType> + void resize(size_t new_size, ElemType&& default_init_val, + value_flags default_init_flags = preserve_source_value_flags) { + static_assert( + !is_node_view<ElemType>, + "The default element type argument to toml::array::resize may not be toml::node_view."); + + if (!new_size) + clear(); + else if (new_size > elems_.size()) + insert(cend(), new_size - elems_.size(), static_cast<ElemType&&>(default_init_val), + default_init_flags); + else + truncate(new_size); + } + + /// @} + + /// \name Erasure + /// @{ + + /// \brief Removes the specified element from the array. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 2, 3 }; + /// std::cout << arr << "\n"; + /// + /// arr.erase(arr.cbegin() + 1); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, 3 ] + /// [ 1, 3 ] + /// \eout + /// + /// \param pos Iterator to the element being erased. + /// + /// \returns Iterator to the first element immediately following the removed element. + TOML_EXPORTED_MEMBER_FUNCTION + iterator erase(const_iterator pos) noexcept; + + /// \brief Removes the elements in the range [first, last) from the array. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, "bad", "karma" 2 }; + /// std::cout << arr << "\n"; + /// + /// arr.erase(arr.cbegin() + 1, arr.cbegin() + 3); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 'bad', 'karma', 3 ] + /// [ 1, 3 ] + /// \eout + /// + /// \param first Iterator to the first element being erased. + /// \param last Iterator to the one-past-the-last element being erased. + /// + /// \returns Iterator to the first element immediately following the last removed element. + TOML_EXPORTED_MEMBER_FUNCTION + iterator erase(const_iterator first, const_iterator last) noexcept; + + /// \brief Flattens this array, recursively hoisting the contents of child arrays up into + /// itself. + /// + /// \detail \cpp + /// + /// auto arr = toml::array{ 1, 2, toml::array{ 3, 4, toml::array{ 5 } }, 6, toml::array{} }; + /// std::cout << arr << "\n"; + /// + /// arr.flatten(); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, [ 3, 4, [ 5 ] ], 6, [] ] + /// [ 1, 2, 3, 4, 5, 6 ] + /// \eout + /// + /// \remarks Arrays inside child tables are not flattened. + /// + /// \returns A reference to the array. + TOML_EXPORTED_MEMBER_FUNCTION + array& flatten() &; + + /// \brief Flattens this array, recursively hoisting the contents of child arrays up into + /// itself (rvalue overload). + array&& flatten() && { return static_cast<toml::array&&>(this->flatten()); } + + /// \brief Removes empty child arrays and tables. + /// + /// \detail \cpp + /// + /// auto arr = toml::array{ 1, 2, toml::array{ }, toml::array{ 3, toml::array{ } }, 4 }; + /// std::cout << arr << "\n"; + /// + /// arr.prune(true); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, [], [ 3, [] ], 4 ] + /// [ 1, 2, [ 3 ], 4 ] + /// \eout + /// + /// \param recursive Should child arrays and tables themselves be pruned? + /// + /// \returns A reference to the array. + TOML_EXPORTED_MEMBER_FUNCTION + array& prune(bool recursive = true) & noexcept; + + /// \brief Removes empty child arrays and tables (rvalue overload). + /// + /// \param recursive Should child arrays and tables themselves be pruned? + /// + /// \returns An rvalue reference to the array. + array&& prune(bool recursive = true) && noexcept { + return static_cast<toml::array&&>(this->prune(recursive)); + } + + /// \brief Removes the last element from the array. + TOML_EXPORTED_MEMBER_FUNCTION + void pop_back() noexcept; + + /// \brief Removes all elements from the array. + TOML_EXPORTED_MEMBER_FUNCTION + void clear() noexcept; + + /// @} + + /// \name Insertion and Emplacement + /// @{ + + /// \brief Inserts a new element at a specific position in the array. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 3 }; + /// arr.insert(arr.cbegin() + 1, "two"); + /// arr.insert(arr.cend(), toml::array{ 4, 5 }); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 'two', 3, [ 4, 5 ] ] + /// \eout + /// + /// \tparam ElemType toml::node, toml::node_view, toml::table, toml::array, or a native TOML + /// value type (or a type promotable to one). + /// \param pos The insertion position. + /// \param val The node or value being inserted. + /// \param flags Value flags to apply to new values. + /// + /// \returns \conditional_return{Valid input} + /// An iterator to the newly-inserted element. + /// \conditional_return{Input is a null toml::node_view} + /// end() + /// + /// \attention The return value will always be `end()` if the input value was a null + /// toml::node_view, because no insertion can take place. This is the only circumstance in which + /// this can occur. + template <typename ElemType> + iterator insert(const_iterator pos, ElemType&& val, + value_flags flags = preserve_source_value_flags) { + if constexpr (is_node_view<ElemType>) { + if (!val) return end(); + } + return iterator{insert_at(const_vector_iterator{pos}, + impl::make_node(static_cast<ElemType&&>(val), flags))}; + } + + /// \brief Repeatedly inserts a new element starting at a specific position in the array. + /// + /// \detail \cpp + /// auto arr = toml::array{ + /// "with an evil twinkle in its eye the goose said", + /// "and immediately we knew peace was never an option." + /// }; + /// arr.insert(arr.cbegin() + 1, 3, "honk"); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ + /// 'with an evil twinkle in its eye the goose said', + /// 'honk', + /// 'honk', + /// 'honk', + /// 'and immediately we knew peace was never an option.' + /// ] + /// \eout + /// + /// \tparam ElemType toml::node, toml::node_view, toml::table, toml::array, or a native TOML + /// value type (or a type promotable to one). + /// \param pos The insertion position. + /// \param count The number of times the node or value should be inserted. + /// \param val The node or value being inserted. + /// \param flags Value flags to apply to new values. + /// + /// \returns \conditional_return{Valid input} + /// An iterator to the newly-inserted element. + /// \conditional_return{count == 0} + /// A copy of pos + /// \conditional_return{Input is a null toml::node_view} + /// end() + /// + /// \attention The return value will always be `end()` if the input value was a null + /// toml::node_view, because no insertion can take place. This is the only circumstance in which + /// this can occur. + template <typename ElemType> + iterator insert(const_iterator pos, size_t count, ElemType&& val, + value_flags flags = preserve_source_value_flags) { + if constexpr (is_node_view<ElemType>) { + if (!val) return end(); + } + switch (count) { + case 0: + return iterator{elems_.begin() + (const_vector_iterator{pos} - elems_.cbegin())}; + case 1: + return insert(pos, static_cast<ElemType&&>(val), flags); + default: { + const auto start_idx = static_cast<size_t>(const_vector_iterator{pos} - elems_.cbegin()); + preinsertion_resize(start_idx, count); + size_t i = start_idx; + for (size_t e = start_idx + count - 1u; i < e; i++) + elems_[i] = impl::make_node(val, flags); + + // # potentially move the initial value into the last element + elems_[i] = impl::make_node(static_cast<ElemType&&>(val), flags); + return iterator{elems_.begin() + static_cast<ptrdiff_t>(start_idx)}; + } + } + } + + /// \brief Inserts a range of elements into the array at a specific position. + /// + /// \tparam Iter An iterator type. Must satisfy ForwardIterator. + /// \param pos The insertion position. + /// \param first Iterator to the first node or value being inserted. + /// \param last Iterator to the one-past-the-last node or value being inserted. + /// \param flags Value flags to apply to new values. + /// + /// \returns \conditional_return{Valid input} + /// An iterator to the first newly-inserted element. + /// \conditional_return{first >= last} + /// A copy of pos + /// \conditional_return{All objects in the range were null toml::node_views} + /// A copy of pos + template <typename Iter> + iterator insert(const_iterator pos, Iter first, Iter last, + value_flags flags = preserve_source_value_flags) { + const auto distance = std::distance(first, last); + if (distance <= 0) + return iterator{elems_.begin() + (const_vector_iterator{pos} - elems_.cbegin())}; + else { + auto count = distance; + using deref_type = decltype(*first); + if constexpr (is_node_view<deref_type>) { + for (auto it = first; it != last; it++) + if (!(*it)) count--; + if (!count) + return iterator{elems_.begin() + (const_vector_iterator{pos} - elems_.cbegin())}; + } + const auto start_idx = static_cast<size_t>(const_vector_iterator{pos} - elems_.cbegin()); + preinsertion_resize(start_idx, static_cast<size_t>(count)); + size_t i = start_idx; + for (auto it = first; it != last; it++) { + if constexpr (is_node_view<deref_type>) { + if (!(*it)) continue; + } + if constexpr (std::is_rvalue_reference_v<deref_type>) + elems_[i++] = impl::make_node(std::move(*it), flags); + else + elems_[i++] = impl::make_node(*it, flags); + } + return iterator{elems_.begin() + static_cast<ptrdiff_t>(start_idx)}; + } + } + + /// \brief Inserts a range of elements into the array at a specific position. + /// + /// \tparam ElemType toml::node_view, toml::table, toml::array, or a native TOML value type + /// (or a type promotable to one). + /// \param pos The insertion position. + /// \param ilist An initializer list containing the values to be inserted. + /// \param flags Value flags to apply to new values. + /// + /// \returns \conditional_return{Valid input} + /// An iterator to the first newly-inserted element. + /// \conditional_return{Input list is empty} + /// A copy of pos + /// \conditional_return{All objects in the list were null toml::node_views} + /// A copy of pos + template <typename ElemType> + iterator insert(const_iterator pos, std::initializer_list<ElemType> ilist, + value_flags flags = preserve_source_value_flags) { + return insert(pos, ilist.begin(), ilist.end(), flags); + } + + /// \brief Emplaces a new element at a specific position in the array. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 2 }; + /// + /// //add a string using std::string's substring constructor + /// arr.emplace<std::string>(arr.cbegin() + 1, "this is not a drill"sv, 14, 5); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 'drill', 2 ] + /// \eout + /// + /// \tparam ElemType toml::table, toml::array, or any native TOML value type. + /// \tparam Args Value constructor argument types. + /// \param pos The insertion position. + /// \param args Arguments to forward to the value's constructor. + /// + /// \returns An iterator to the inserted element. + /// + /// \remarks There is no difference between insert() and emplace() + /// for trivial value types (floats, ints, bools). + template <typename ElemType = void, typename... Args> + iterator emplace(const_iterator pos, Args&&... args) { + using raw_elem_type = impl::remove_cvref<ElemType>; + using elem_type = std::conditional_t<std::is_void_v<raw_elem_type>, // + impl::emplaced_type_of<Args&&...>, raw_elem_type>; + + using type = impl::remove_cvref<impl::unwrap_node<elem_type>>; + static_assert(impl::is_native<type> || impl::is_one_of<type, table, array>, + "Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + return iterator{ + insert_at(const_vector_iterator{pos}, + impl::node_ptr{new impl::wrap_node<type>{static_cast<Args&&>(args)...}})}; + } + + /// \brief Replaces the element at a specific position in the array with a different value. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 2, 3 }; + /// std::cout << arr << "\n"; + /// arr.replace(arr.cbegin() + 1, "two"); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, 3 ] + /// [ 1, 'two', 3 ] + /// \eout + /// + /// \tparam ElemType toml::node, toml::node_view, toml::table, toml::array, or a native TOML + /// value type (or a type promotable to one). + /// \param pos The insertion position. + /// \param val The node or value being inserted. + /// \param flags Value flags to apply to new values. + /// + /// \returns \conditional_return{Valid input} + /// An iterator to the replaced element. + /// \conditional_return{Input is a null toml::node_view} + /// end() + /// + /// \attention The return value will always be `end()` if the input value was a null + /// toml::node_view, because no replacement can take place. This is the only circumstance in + /// which this can occur. + template <typename ElemType> + iterator replace(const_iterator pos, ElemType&& val, + value_flags flags = preserve_source_value_flags) { + TOML_ASSERT(pos >= cbegin() && pos < cend()); + + if constexpr (is_node_view<ElemType>) { + if (!val) return end(); + } + + const auto it = elems_.begin() + (const_vector_iterator{pos} - elems_.cbegin()); + *it = impl::make_node(static_cast<ElemType&&>(val), flags); + return iterator{it}; + } + + /// \brief Appends a new element to the end of the array. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 2 }; + /// arr.push_back(3); + /// arr.push_back(4.0); + /// arr.push_back(toml::array{ 5, "six"sv }); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, 3, 4.0, [ 5, 'six' ] ] + /// \eout + /// + /// \tparam ElemType toml::node, toml::node_view, toml::table, toml::array, or a native TOML + /// value type + /// \param val The node or value being added. + /// \param flags Value flags to apply to new values. + /// + /// \attention No insertion takes place if the input value is a null toml::node_view. + /// This is the only circumstance in which this can occur. + template <typename ElemType> + void push_back(ElemType&& val, value_flags flags = preserve_source_value_flags) { + emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), flags); + } + + /// \brief Emplaces a new element at the end of the array. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 2 }; + /// arr.emplace_back<toml::array>(3, "four"sv); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// [ 1, 2, [ 3, 'four' ] ] + /// \eout + /// + /// \tparam ElemType toml::table, toml::array, or a native TOML value type + /// \tparam Args Element constructor argument types. + /// \param args Arguments to forward to the elements's constructor. + /// + /// \returns A reference to the newly-constructed element. + /// + /// \remarks There is no difference between push_back() and emplace_back() + /// For trivial value types (floats, ints, bools). + template <typename ElemType = void, typename... Args> + decltype(auto) emplace_back(Args&&... args) { + using raw_elem_type = impl::remove_cvref<ElemType>; + using elem_type = std::conditional_t<std::is_void_v<raw_elem_type>, // + impl::emplaced_type_of<Args&&...>, raw_elem_type>; + + static constexpr auto moving_node_ptr = std::is_same_v<elem_type, impl::node_ptr> // + && sizeof...(Args) == 1u // + && impl::first_is_same<impl::node_ptr&&, Args&&...>; + + using unwrapped_type = impl::remove_cvref<impl::unwrap_node<elem_type>>; + + static_assert(moving_node_ptr // + || impl::is_native<unwrapped_type> // + || impl::is_one_of<unwrapped_type, table, array>, // + "ElemType argument of array::emplace_back() must be one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + if constexpr (moving_node_ptr) { + insert_at_back(static_cast<Args&&>(args)...); + return *elems_.back(); + } else { + auto ptr = new impl::wrap_node<unwrapped_type>{static_cast<Args&&>(args)...}; + insert_at_back(impl::node_ptr{ptr}); + return *ptr; + } + } + + /// @} + + private: + /// \cond + + TOML_NODISCARD + TOML_EXPORTED_STATIC_FUNCTION + static bool TOML_CALLCONV equal(const array&, const array&) noexcept; + + template <typename T> + TOML_NODISCARD static bool equal_to_container(const array& lhs, const T& rhs) noexcept { + using element_type = std::remove_const_t<typename T::value_type>; + static_assert(impl::is_losslessly_convertible_to_native<element_type>, + "Container element type must be losslessly convertible one of the native TOML " + "value types"); + + if (lhs.size() != rhs.size()) return false; + if (rhs.size() == 0u) return true; + + size_t i{}; + for (auto& list_elem : rhs) { + const auto elem = lhs.get_as<impl::native_type_of<element_type>>(i++); + if (!elem || *elem != list_elem) return false; + } + + return true; + } + + /// \endcond + + public: + /// \name Equality + /// @{ + + /// \brief Equality operator. + /// + /// \param lhs The LHS array. + /// \param rhs The RHS array. + /// + /// \returns True if the arrays contained the same elements. + TOML_NODISCARD + friend bool operator==(const array& lhs, const array& rhs) noexcept { return equal(lhs, rhs); } + + /// \brief Inequality operator. + /// + /// \param lhs The LHS array. + /// \param rhs The RHS array. + /// + /// \returns True if the arrays did not contain the same elements. + TOML_NODISCARD + friend bool operator!=(const array& lhs, const array& rhs) noexcept { return !equal(lhs, rhs); } + + /// \brief Initializer list equality operator. + template <typename T> + TOML_NODISCARD friend bool operator==(const array& lhs, + const std::initializer_list<T>& rhs) noexcept { + return equal_to_container(lhs, rhs); + } + TOML_ASYMMETRICAL_EQUALITY_OPS(const array&, const std::initializer_list<T>&, + template <typename T>); + + /// \brief Vector equality operator. + template <typename T> + TOML_NODISCARD friend bool operator==(const array& lhs, const std::vector<T>& rhs) noexcept { + return equal_to_container(lhs, rhs); + } + TOML_ASYMMETRICAL_EQUALITY_OPS(const array&, const std::vector<T>&, template <typename T>); + + /// @} #if TOML_ENABLE_FORMATTERS - /// \brief Prints the array out to a stream as formatted TOML. - /// - /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. - friend std::ostream& operator<<(std::ostream& lhs, const array& rhs) - { - impl::print_to_stream(lhs, rhs); - return lhs; - } + /// \brief Prints the array out to a stream as formatted TOML. + /// + /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. + friend std::ostream& operator<<(std::ostream& lhs, const array& rhs) { + impl::print_to_stream(lhs, rhs); + return lhs; + } #endif - }; + }; } TOML_NAMESPACE_END; diff --git a/vendor/toml++/impl/at_path.hpp b/vendor/toml++/impl/at_path.hpp index e351e6b..8ea273e 100644 --- a/vendor/toml++/impl/at_path.hpp +++ b/vendor/toml++/impl/at_path.hpp @@ -1,96 +1,92 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "forward_declarations.hpp" /// \cond -TOML_IMPL_NAMESPACE_START -{ - template <typename T> - using parse_path_callback = bool(TOML_CALLCONV*)(void*, T); +TOML_IMPL_NAMESPACE_START { + template <typename T> + using parse_path_callback = bool(TOML_CALLCONV*)(void*, T); - TOML_NODISCARD - bool TOML_CALLCONV parse_path(std::string_view, - void*, - parse_path_callback<std::string_view>, - parse_path_callback<size_t>); + TOML_NODISCARD + bool TOML_CALLCONV parse_path(std::string_view, void*, parse_path_callback<std::string_view>, + parse_path_callback<size_t>); } TOML_IMPL_NAMESPACE_END; /// \endcond -TOML_NAMESPACE_START -{ - /// \brief Returns a view of the node matching a fully-qualified "TOML path". - /// - /// \detail \cpp - /// auto config = toml::parse(R"( - /// - /// [foo] - /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] - /// - /// )"sv); - /// - /// std::cout << toml::at_path(config, "foo.bar[2]") << "\n"; - /// std::cout << toml::at_path(config, "foo.bar[3][0]") << "\n"; - /// std::cout << toml::at_path(config, "foo.bar[4].kek") << "\n"; - /// \ecpp - /// - /// \out - /// 2 - /// 3 - /// 4 - /// \eout - /// - /// - /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: - /// \cpp - /// toml::at_path(config, "foo.bar") // same as config["foo"]["bar"] - /// toml::at_path(config, "foo. bar") // same as config["foo"][" bar"] - /// toml::at_path(config, "foo..bar") // same as config["foo"][""]["bar"] - /// toml::at_path(config, ".foo.bar") // same as config[""]["foo"]["bar"] - /// \ecpp - /// <br> - /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted strings. - /// This function makes no allowance for this, instead treating all period characters as sub-table delimiters. - /// If you have periods in your table keys, first consider: - /// 1. Not doing that - /// 2. Using node_view::operator[] instead. - /// - /// \param root The root node from which the path will be traversed. - /// \param path The "TOML path" to traverse. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - node_view<node> TOML_CALLCONV at_path(node & root, std::string_view path) noexcept; +TOML_NAMESPACE_START { + /// \brief Returns a view of the node matching a fully-qualified "TOML path". + /// + /// \detail \cpp + /// auto config = toml::parse(R"( + /// + /// [foo] + /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] + /// + /// )"sv); + /// + /// std::cout << toml::at_path(config, "foo.bar[2]") << "\n"; + /// std::cout << toml::at_path(config, "foo.bar[3][0]") << "\n"; + /// std::cout << toml::at_path(config, "foo.bar[4].kek") << "\n"; + /// \ecpp + /// + /// \out + /// 2 + /// 3 + /// 4 + /// \eout + /// + /// + /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: + /// \cpp + /// toml::at_path(config, "foo.bar") // same as config["foo"]["bar"] + /// toml::at_path(config, "foo. bar") // same as config["foo"][" bar"] + /// toml::at_path(config, "foo..bar") // same as config["foo"][""]["bar"] + /// toml::at_path(config, ".foo.bar") // same as config[""]["foo"]["bar"] + /// \ecpp + /// <br> + /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted + /// strings. This function makes no allowance for this, instead treating all period characters as + /// sub-table delimiters. If you have periods in your table keys, first consider: + /// 1. Not doing that + /// 2. Using node_view::operator[] instead. + /// + /// \param root The root node from which the path will be traversed. + /// \param path The "TOML path" to traverse. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + node_view<node> TOML_CALLCONV at_path(node & root, std::string_view path) noexcept; - /// \brief Returns a const view of the node matching a fully-qualified "TOML path". - /// - /// \see #toml::at_path(node&, std::string_view) - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - node_view<const node> TOML_CALLCONV at_path(const node& root, std::string_view path) noexcept; + /// \brief Returns a const view of the node matching a fully-qualified "TOML path". + /// + /// \see #toml::at_path(node&, std::string_view) + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + node_view<const node> TOML_CALLCONV at_path(const node& root, std::string_view path) noexcept; #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Returns a view of the node matching a fully-qualified "TOML path". - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \see #toml::at_path(node&, std::string_view) - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - node_view<node> TOML_CALLCONV at_path(node & root, std::wstring_view path); + /// \brief Returns a view of the node matching a fully-qualified "TOML path". + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \see #toml::at_path(node&, std::string_view) + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + node_view<node> TOML_CALLCONV at_path(node & root, std::wstring_view path); - /// \brief Returns a const view of the node matching a fully-qualified "TOML path". - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \see #toml::at_path(node&, std::string_view) - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - node_view<const node> TOML_CALLCONV at_path(const node& root, std::wstring_view path); + /// \brief Returns a const view of the node matching a fully-qualified "TOML path". + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \see #toml::at_path(node&, std::string_view) + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + node_view<const node> TOML_CALLCONV at_path(const node& root, std::wstring_view path); #endif } diff --git a/vendor/toml++/impl/date_time.hpp b/vendor/toml++/impl/date_time.hpp index 8957ad3..92acfbf 100644 --- a/vendor/toml++/impl/date_time.hpp +++ b/vendor/toml++/impl/date_time.hpp @@ -1,467 +1,417 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "forward_declarations.hpp" -#include "print_to_stream.hpp" #include "header_start.hpp" +#include "print_to_stream.hpp" -TOML_NAMESPACE_START -{ - /// \brief A local date. - struct TOML_TRIVIAL_ABI date - { - /// \brief The year component. - uint16_t year; - - /// \brief The month component, from 1 - 12. - uint8_t month; - - /// \brief The day component, from 1 - 31. - uint8_t day; - - /// \brief Default constructor. Does not initialize the members. - TOML_NODISCARD_CTOR - date() noexcept = default; - - /// \brief Constructs a date from individual date component values. - TOML_CONSTRAINED_TEMPLATE((impl::all_integral<Y, M, D>), typename Y, typename M, typename D) - TOML_NODISCARD_CTOR - constexpr date(Y y, M m, D d) noexcept // - : year{ static_cast<uint16_t>(y) }, - month{ static_cast<uint8_t>(m) }, - day{ static_cast<uint8_t>(d) } - {} - - /// \brief Equality operator. - TOML_PURE_GETTER - friend constexpr bool operator==(const date& lhs, const date& rhs) noexcept - { - return lhs.year == rhs.year // - && lhs.month == rhs.month // - && lhs.day == rhs.day; - } - - /// \brief Inequality operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator!=(const date& lhs, const date& rhs) noexcept - { - return !(lhs == rhs); - } - - private: - /// \cond - - TOML_PURE_GETTER - static constexpr uint32_t pack(const date& d) noexcept - { - return (static_cast<uint32_t>(d.year) << 16) | (static_cast<uint32_t>(d.month) << 8) - | static_cast<uint32_t>(d.day); - } - - /// \endcond - - public: - /// \brief Less-than operator. - TOML_PURE_GETTER - friend constexpr bool operator<(const date& lhs, const date& rhs) noexcept - { - return pack(lhs) < pack(rhs); - } - - /// \brief Less-than-or-equal-to operator. - TOML_PURE_GETTER - friend constexpr bool operator<=(const date& lhs, const date& rhs) noexcept - { - return pack(lhs) <= pack(rhs); - } - - /// \brief Greater-than operator. - TOML_PURE_GETTER - friend constexpr bool operator>(const date& lhs, const date& rhs) noexcept - { - return pack(lhs) > pack(rhs); - } - - /// \brief Greater-than-or-equal-to operator. - TOML_PURE_GETTER - friend constexpr bool operator>=(const date& lhs, const date& rhs) noexcept - { - return pack(lhs) >= pack(rhs); - } - - /// \brief Prints a date out to a stream as `YYYY-MM-DD` (per RFC 3339). - /// - /// \detail \cpp - /// std::cout << toml::date{ 1987, 3, 16 } << "\n"; - /// \ecpp - /// - /// \out - /// 1987-03-16 - /// \eout - friend std::ostream& operator<<(std::ostream& lhs, const date& rhs) - { - impl::print_to_stream(lhs, rhs); - return lhs; - } - }; - - /// \brief A local time-of-day. - struct TOML_TRIVIAL_ABI time - { - /// \brief The hour component, from 0 - 23. - uint8_t hour; - - /// \brief The minute component, from 0 - 59. - uint8_t minute; - - /// \brief The second component, from 0 - 59. - uint8_t second; - - /// \brief The fractional nanoseconds component, from 0 - 999999999. - uint32_t nanosecond; - - /// \brief Default constructor. Does not initialize the members. - TOML_NODISCARD_CTOR - time() noexcept = default; - - /// \brief Constructs a time from individual time component values. - TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M, S, NS>), - typename H, - typename M, - typename S = uint8_t, - typename NS = uint32_t) - TOML_NODISCARD_CTOR - constexpr time(H h, M m, S s = S{}, NS ns = NS{}) noexcept // - : hour{ static_cast<uint8_t>(h) }, - minute{ static_cast<uint8_t>(m) }, - second{ static_cast<uint8_t>(s) }, - nanosecond{ static_cast<uint32_t>(ns) } - {} - - /// \brief Equality operator. - TOML_PURE_GETTER - friend constexpr bool operator==(const time& lhs, const time& rhs) noexcept - { - return lhs.hour == rhs.hour // - && lhs.minute == rhs.minute // - && lhs.second == rhs.second // - && lhs.nanosecond == rhs.nanosecond; - } - - /// \brief Inequality operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator!=(const time& lhs, const time& rhs) noexcept - { - return !(lhs == rhs); - } - - private: - /// \cond - - TOML_PURE_GETTER - static constexpr uint64_t pack(const time& t) noexcept - { - return static_cast<uint64_t>(t.hour) << 48 | static_cast<uint64_t>(t.minute) << 40 - | static_cast<uint64_t>(t.second) << 32 | static_cast<uint64_t>(t.nanosecond); - } - - /// \endcond - - public: - /// \brief Less-than operator. - TOML_PURE_GETTER - friend constexpr bool operator<(const time& lhs, const time& rhs) noexcept - { - return pack(lhs) < pack(rhs); - } - - /// \brief Less-than-or-equal-to operator. - TOML_PURE_GETTER - friend constexpr bool operator<=(const time& lhs, const time& rhs) noexcept - { - return pack(lhs) <= pack(rhs); - } - - /// \brief Greater-than operator. - TOML_PURE_GETTER - friend constexpr bool operator>(const time& lhs, const time& rhs) noexcept - { - return pack(lhs) > pack(rhs); - } - - /// \brief Greater-than-or-equal-to operator. - TOML_PURE_GETTER - friend constexpr bool operator>=(const time& lhs, const time& rhs) noexcept - { - return pack(lhs) >= pack(rhs); - } - - /// \brief Prints a time out to a stream as `HH:MM:SS.FFFFFF` (per RFC 3339). - /// \detail \cpp - /// std::cout << toml::time{ 10, 20, 34 } << "\n"; - /// std::cout << toml::time{ 10, 20, 34, 500000000 } << "\n"; - /// \ecpp - /// - /// \out - /// 10:20:34 - /// 10:20:34.5 - /// \eout - friend std::ostream& operator<<(std::ostream& lhs, const time& rhs) - { - impl::print_to_stream(lhs, rhs); - return lhs; - } - }; - - /// \brief A timezone offset. - struct TOML_TRIVIAL_ABI time_offset - { - /// \brief Offset from UTC+0, in minutes. - int16_t minutes; - - /// \brief Default constructor. Does not initialize the members. - TOML_NODISCARD_CTOR - time_offset() noexcept = default; - - /// \brief Constructs a timezone offset from individual hour and minute totals. - /// - /// \detail \cpp - /// std::cout << toml::time_offset{ 2, 30 } << "\n"; - /// std::cout << toml::time_offset{ -2, 30 } << "\n"; - /// std::cout << toml::time_offset{ -2, -30 } << "\n"; - /// std::cout << toml::time_offset{ 0, 0 } << "\n"; - /// \ecpp - /// - /// \out - /// +02:30 - /// -01:30 - /// -02:30 - /// Z - /// \eout - /// - /// \tparam H An integral type. - /// \tparam M An integral type. - /// - /// \param h The total hours. - /// \param m The total minutes. - TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M>), typename H, typename M) - TOML_NODISCARD_CTOR - constexpr time_offset(H h, M m) noexcept // - : minutes{ static_cast<int16_t>(static_cast<impl::common_signed_type<H, M>>(h) - * impl::common_signed_type<H, M>{ 60 } - + static_cast<impl::common_signed_type<H, M>>(m)) } - {} - - /// \brief Equality operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator==(time_offset lhs, time_offset rhs) noexcept - { - return lhs.minutes == rhs.minutes; - } - - /// \brief Inequality operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator!=(time_offset lhs, time_offset rhs) noexcept - { - return lhs.minutes != rhs.minutes; - } - - /// \brief Less-than operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator<(time_offset lhs, time_offset rhs) noexcept - { - return lhs.minutes < rhs.minutes; - } - - /// \brief Less-than-or-equal-to operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator<=(time_offset lhs, time_offset rhs) noexcept - { - return lhs.minutes <= rhs.minutes; - } - - /// \brief Greater-than operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator>(time_offset lhs, time_offset rhs) noexcept - { - return lhs.minutes > rhs.minutes; - } - - /// \brief Greater-than-or-equal-to operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator>=(time_offset lhs, time_offset rhs) noexcept - { - return lhs.minutes >= rhs.minutes; - } - - /// \brief Prints a time_offset out to a stream as `+-HH:MM or Z` (per RFC 3339). - /// \detail \cpp - /// std::cout << toml::time_offset{ 2, 30 } << "\n"; - /// std::cout << toml::time_offset{ 2, -30 } << "\n"; - /// std::cout << toml::time_offset{} << "\n"; - /// std::cout << toml::time_offset{ -2, 30 } << "\n"; - /// std::cout << toml::time_offset{ -2, -30 } << "\n"; - /// \ecpp - /// - /// \out - /// +02:30 - /// +01:30 - /// Z - /// -01:30 - /// -02:30 - /// \eout - friend std::ostream& operator<<(std::ostream& lhs, const time_offset& rhs) - { - impl::print_to_stream(lhs, rhs); - return lhs; - } - }; - - TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt); - - /// \brief A date-time. - struct date_time - { - /// \brief The date component. - toml::date date; - - /// \brief The time component. - toml::time time; - - /// \brief The timezone offset component. - /// - /// \remarks The date_time is said to be 'local' if the offset is empty. - optional<toml::time_offset> offset; - - /// \brief Default constructor. Does not initialize the members. - TOML_NODISCARD_CTOR - date_time() noexcept = default; - - /// \brief Constructs a local date-time. - /// - /// \param d The date component. - /// \param t The time component. - TOML_NODISCARD_CTOR - constexpr date_time(const toml::date& d, const toml::time& t) noexcept // - : date{ d }, - time{ t }, - offset{} // TINAE - icc bugfix - {} - - /// \brief Constructs a local date-time. - /// - /// \param d The date component. - TOML_NODISCARD_CTOR - explicit constexpr date_time(const toml::date& d) noexcept // - : date{ d }, - time{}, - offset{} // TINAE - icc bugfix - {} - - /// \brief Constructs a local date-time. - /// - /// \param t The time component. - TOML_NODISCARD_CTOR - explicit constexpr date_time(const toml::time& t) noexcept // - : date{}, - time{ t }, - offset{} // TINAE - icc bugfix - {} - - /// \brief Constructs an offset date-time. - /// - /// \param d The date component. - /// \param t The time component. - /// \param off The timezone offset. - TOML_NODISCARD_CTOR - constexpr date_time(const toml::date& d, const toml::time& t, const toml::time_offset& off) noexcept - : date{ d }, - time{ t }, - offset{ off } - {} - - /// \brief Returns true if this date_time does not contain timezone offset information. - TOML_PURE_INLINE_GETTER - constexpr bool is_local() const noexcept - { - return !offset.has_value(); - } - - /// \brief Equality operator. - TOML_PURE_GETTER - friend constexpr bool operator==(const date_time& lhs, const date_time& rhs) noexcept - { - return lhs.date == rhs.date // - && lhs.time == rhs.time // - && lhs.offset == rhs.offset; - } - - /// \brief Inequality operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator!=(const date_time& lhs, const date_time& rhs) noexcept - { - return !(lhs == rhs); - } - - /// \brief Less-than operator. - TOML_PURE_GETTER - friend constexpr bool operator<(const date_time& lhs, const date_time& rhs) noexcept - { - if (lhs.date != rhs.date) - return lhs.date < rhs.date; - if (lhs.time != rhs.time) - return lhs.time < rhs.time; - return lhs.offset < rhs.offset; - } - - /// \brief Less-than-or-equal-to operator. - TOML_PURE_GETTER - friend constexpr bool operator<=(const date_time& lhs, const date_time& rhs) noexcept - { - if (lhs.date != rhs.date) - return lhs.date < rhs.date; - if (lhs.time != rhs.time) - return lhs.time < rhs.time; - return lhs.offset <= rhs.offset; - } - - /// \brief Greater-than operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator>(const date_time& lhs, const date_time& rhs) noexcept - { - return !(lhs <= rhs); - } - - /// \brief Greater-than-or-equal-to operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator>=(const date_time& lhs, const date_time& rhs) noexcept - { - return !(lhs < rhs); - } - - /// \brief Prints a date_time out to a stream in RFC 3339 format. - /// \detail \cpp - /// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 } } << "\n"; - /// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, { -2, -30 } } << "\n"; - /// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, {} } << "\n"; - /// \ecpp - /// - /// \out - /// 1987-03-16T10:20:34 - /// 1987-03-16T10:20:34-02:30 - /// 1987-03-16T10:20:34Z - /// \eout - friend std::ostream& operator<<(std::ostream& lhs, const date_time& rhs) - { - impl::print_to_stream(lhs, rhs); - return lhs; - } - }; - - TOML_ABI_NAMESPACE_END; // TOML_HAS_CUSTOM_OPTIONAL_TYPE +TOML_NAMESPACE_START { + /// \brief A local date. + struct TOML_TRIVIAL_ABI date { + /// \brief The year component. + uint16_t year; + + /// \brief The month component, from 1 - 12. + uint8_t month; + + /// \brief The day component, from 1 - 31. + uint8_t day; + + /// \brief Default constructor. Does not initialize the members. + TOML_NODISCARD_CTOR + date() noexcept = default; + + /// \brief Constructs a date from individual date component values. + TOML_CONSTRAINED_TEMPLATE((impl::all_integral<Y, M, D>), typename Y, typename M, typename D) + TOML_NODISCARD_CTOR + constexpr date(Y y, M m, D d) noexcept // + : year{static_cast<uint16_t>(y)}, + month{static_cast<uint8_t>(m)}, + day{static_cast<uint8_t>(d)} {} + + /// \brief Equality operator. + TOML_PURE_GETTER + friend constexpr bool operator==(const date& lhs, const date& rhs) noexcept { + return lhs.year == rhs.year // + && lhs.month == rhs.month // + && lhs.day == rhs.day; + } + + /// \brief Inequality operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator!=(const date& lhs, const date& rhs) noexcept { + return !(lhs == rhs); + } + + private: + /// \cond + + TOML_PURE_GETTER + static constexpr uint32_t pack(const date& d) noexcept { + return (static_cast<uint32_t>(d.year) << 16) | (static_cast<uint32_t>(d.month) << 8) | + static_cast<uint32_t>(d.day); + } + + /// \endcond + + public: + /// \brief Less-than operator. + TOML_PURE_GETTER + friend constexpr bool operator<(const date& lhs, const date& rhs) noexcept { + return pack(lhs) < pack(rhs); + } + + /// \brief Less-than-or-equal-to operator. + TOML_PURE_GETTER + friend constexpr bool operator<=(const date& lhs, const date& rhs) noexcept { + return pack(lhs) <= pack(rhs); + } + + /// \brief Greater-than operator. + TOML_PURE_GETTER + friend constexpr bool operator>(const date& lhs, const date& rhs) noexcept { + return pack(lhs) > pack(rhs); + } + + /// \brief Greater-than-or-equal-to operator. + TOML_PURE_GETTER + friend constexpr bool operator>=(const date& lhs, const date& rhs) noexcept { + return pack(lhs) >= pack(rhs); + } + + /// \brief Prints a date out to a stream as `YYYY-MM-DD` (per RFC 3339). + /// + /// \detail \cpp + /// std::cout << toml::date{ 1987, 3, 16 } << "\n"; + /// \ecpp + /// + /// \out + /// 1987-03-16 + /// \eout + friend std::ostream& operator<<(std::ostream& lhs, const date& rhs) { + impl::print_to_stream(lhs, rhs); + return lhs; + } + }; + + /// \brief A local time-of-day. + struct TOML_TRIVIAL_ABI time { + /// \brief The hour component, from 0 - 23. + uint8_t hour; + + /// \brief The minute component, from 0 - 59. + uint8_t minute; + + /// \brief The second component, from 0 - 59. + uint8_t second; + + /// \brief The fractional nanoseconds component, from 0 - 999999999. + uint32_t nanosecond; + + /// \brief Default constructor. Does not initialize the members. + TOML_NODISCARD_CTOR + time() noexcept = default; + + /// \brief Constructs a time from individual time component values. + TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M, S, NS>), typename H, typename M, + typename S = uint8_t, typename NS = uint32_t) + TOML_NODISCARD_CTOR + constexpr time(H h, M m, S s = S{}, NS ns = NS{}) noexcept // + : hour{static_cast<uint8_t>(h)}, + minute{static_cast<uint8_t>(m)}, + second{static_cast<uint8_t>(s)}, + nanosecond{static_cast<uint32_t>(ns)} {} + + /// \brief Equality operator. + TOML_PURE_GETTER + friend constexpr bool operator==(const time& lhs, const time& rhs) noexcept { + return lhs.hour == rhs.hour // + && lhs.minute == rhs.minute // + && lhs.second == rhs.second // + && lhs.nanosecond == rhs.nanosecond; + } + + /// \brief Inequality operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator!=(const time& lhs, const time& rhs) noexcept { + return !(lhs == rhs); + } + + private: + /// \cond + + TOML_PURE_GETTER + static constexpr uint64_t pack(const time& t) noexcept { + return static_cast<uint64_t>(t.hour) << 48 | static_cast<uint64_t>(t.minute) << 40 | + static_cast<uint64_t>(t.second) << 32 | static_cast<uint64_t>(t.nanosecond); + } + + /// \endcond + + public: + /// \brief Less-than operator. + TOML_PURE_GETTER + friend constexpr bool operator<(const time& lhs, const time& rhs) noexcept { + return pack(lhs) < pack(rhs); + } + + /// \brief Less-than-or-equal-to operator. + TOML_PURE_GETTER + friend constexpr bool operator<=(const time& lhs, const time& rhs) noexcept { + return pack(lhs) <= pack(rhs); + } + + /// \brief Greater-than operator. + TOML_PURE_GETTER + friend constexpr bool operator>(const time& lhs, const time& rhs) noexcept { + return pack(lhs) > pack(rhs); + } + + /// \brief Greater-than-or-equal-to operator. + TOML_PURE_GETTER + friend constexpr bool operator>=(const time& lhs, const time& rhs) noexcept { + return pack(lhs) >= pack(rhs); + } + + /// \brief Prints a time out to a stream as `HH:MM:SS.FFFFFF` (per RFC 3339). + /// \detail \cpp + /// std::cout << toml::time{ 10, 20, 34 } << "\n"; + /// std::cout << toml::time{ 10, 20, 34, 500000000 } << "\n"; + /// \ecpp + /// + /// \out + /// 10:20:34 + /// 10:20:34.5 + /// \eout + friend std::ostream& operator<<(std::ostream& lhs, const time& rhs) { + impl::print_to_stream(lhs, rhs); + return lhs; + } + }; + + /// \brief A timezone offset. + struct TOML_TRIVIAL_ABI time_offset { + /// \brief Offset from UTC+0, in minutes. + int16_t minutes; + + /// \brief Default constructor. Does not initialize the members. + TOML_NODISCARD_CTOR + time_offset() noexcept = default; + + /// \brief Constructs a timezone offset from individual hour and minute totals. + /// + /// \detail \cpp + /// std::cout << toml::time_offset{ 2, 30 } << "\n"; + /// std::cout << toml::time_offset{ -2, 30 } << "\n"; + /// std::cout << toml::time_offset{ -2, -30 } << "\n"; + /// std::cout << toml::time_offset{ 0, 0 } << "\n"; + /// \ecpp + /// + /// \out + /// +02:30 + /// -01:30 + /// -02:30 + /// Z + /// \eout + /// + /// \tparam H An integral type. + /// \tparam M An integral type. + /// + /// \param h The total hours. + /// \param m The total minutes. + TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M>), typename H, typename M) + TOML_NODISCARD_CTOR + constexpr time_offset(H h, M m) noexcept // + : minutes{static_cast<int16_t>(static_cast<impl::common_signed_type<H, M>>(h) * + impl::common_signed_type<H, M>{60} + + static_cast<impl::common_signed_type<H, M>>(m))} {} + + /// \brief Equality operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator==(time_offset lhs, time_offset rhs) noexcept { + return lhs.minutes == rhs.minutes; + } + + /// \brief Inequality operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator!=(time_offset lhs, time_offset rhs) noexcept { + return lhs.minutes != rhs.minutes; + } + + /// \brief Less-than operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator<(time_offset lhs, time_offset rhs) noexcept { + return lhs.minutes < rhs.minutes; + } + + /// \brief Less-than-or-equal-to operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator<=(time_offset lhs, time_offset rhs) noexcept { + return lhs.minutes <= rhs.minutes; + } + + /// \brief Greater-than operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator>(time_offset lhs, time_offset rhs) noexcept { + return lhs.minutes > rhs.minutes; + } + + /// \brief Greater-than-or-equal-to operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator>=(time_offset lhs, time_offset rhs) noexcept { + return lhs.minutes >= rhs.minutes; + } + + /// \brief Prints a time_offset out to a stream as `+-HH:MM or Z` (per RFC 3339). + /// \detail \cpp + /// std::cout << toml::time_offset{ 2, 30 } << "\n"; + /// std::cout << toml::time_offset{ 2, -30 } << "\n"; + /// std::cout << toml::time_offset{} << "\n"; + /// std::cout << toml::time_offset{ -2, 30 } << "\n"; + /// std::cout << toml::time_offset{ -2, -30 } << "\n"; + /// \ecpp + /// + /// \out + /// +02:30 + /// +01:30 + /// Z + /// -01:30 + /// -02:30 + /// \eout + friend std::ostream& operator<<(std::ostream& lhs, const time_offset& rhs) { + impl::print_to_stream(lhs, rhs); + return lhs; + } + }; + + TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt); + + /// \brief A date-time. + struct date_time { + /// \brief The date component. + toml::date date; + + /// \brief The time component. + toml::time time; + + /// \brief The timezone offset component. + /// + /// \remarks The date_time is said to be 'local' if the offset is empty. + optional<toml::time_offset> offset; + + /// \brief Default constructor. Does not initialize the members. + TOML_NODISCARD_CTOR + date_time() noexcept = default; + + /// \brief Constructs a local date-time. + /// + /// \param d The date component. + /// \param t The time component. + TOML_NODISCARD_CTOR + constexpr date_time(const toml::date& d, const toml::time& t) noexcept // + : date{d}, + time{t}, + offset{} // TINAE - icc bugfix + {} + + /// \brief Constructs a local date-time. + /// + /// \param d The date component. + TOML_NODISCARD_CTOR + explicit constexpr date_time(const toml::date& d) noexcept // + : date{d}, + time{}, + offset{} // TINAE - icc bugfix + {} + + /// \brief Constructs a local date-time. + /// + /// \param t The time component. + TOML_NODISCARD_CTOR + explicit constexpr date_time(const toml::time& t) noexcept // + : date{}, + time{t}, + offset{} // TINAE - icc bugfix + {} + + /// \brief Constructs an offset date-time. + /// + /// \param d The date component. + /// \param t The time component. + /// \param off The timezone offset. + TOML_NODISCARD_CTOR + constexpr date_time(const toml::date& d, const toml::time& t, + const toml::time_offset& off) noexcept + : date{d}, time{t}, offset{off} {} + + /// \brief Returns true if this date_time does not contain timezone offset information. + TOML_PURE_INLINE_GETTER + constexpr bool is_local() const noexcept { return !offset.has_value(); } + + /// \brief Equality operator. + TOML_PURE_GETTER + friend constexpr bool operator==(const date_time& lhs, const date_time& rhs) noexcept { + return lhs.date == rhs.date // + && lhs.time == rhs.time // + && lhs.offset == rhs.offset; + } + + /// \brief Inequality operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator!=(const date_time& lhs, const date_time& rhs) noexcept { + return !(lhs == rhs); + } + + /// \brief Less-than operator. + TOML_PURE_GETTER + friend constexpr bool operator<(const date_time& lhs, const date_time& rhs) noexcept { + if (lhs.date != rhs.date) return lhs.date < rhs.date; + if (lhs.time != rhs.time) return lhs.time < rhs.time; + return lhs.offset < rhs.offset; + } + + /// \brief Less-than-or-equal-to operator. + TOML_PURE_GETTER + friend constexpr bool operator<=(const date_time& lhs, const date_time& rhs) noexcept { + if (lhs.date != rhs.date) return lhs.date < rhs.date; + if (lhs.time != rhs.time) return lhs.time < rhs.time; + return lhs.offset <= rhs.offset; + } + + /// \brief Greater-than operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator>(const date_time& lhs, const date_time& rhs) noexcept { + return !(lhs <= rhs); + } + + /// \brief Greater-than-or-equal-to operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator>=(const date_time& lhs, const date_time& rhs) noexcept { + return !(lhs < rhs); + } + + /// \brief Prints a date_time out to a stream in RFC 3339 format. + /// \detail \cpp + /// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 } } << "\n"; + /// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, { -2, -30 } } << "\n"; + /// std::cout << toml::date_time{ { 1987, 3, 16 }, { 10, 20, 34 }, {} } << "\n"; + /// \ecpp + /// + /// \out + /// 1987-03-16T10:20:34 + /// 1987-03-16T10:20:34-02:30 + /// 1987-03-16T10:20:34Z + /// \eout + friend std::ostream& operator<<(std::ostream& lhs, const date_time& rhs) { + impl::print_to_stream(lhs, rhs); + return lhs; + } + }; + + TOML_ABI_NAMESPACE_END; // TOML_HAS_CUSTOM_OPTIONAL_TYPE } TOML_NAMESPACE_END; diff --git a/vendor/toml++/impl/formatter.hpp b/vendor/toml++/impl/formatter.hpp index 0c97833..ba3a349 100644 --- a/vendor/toml++/impl/formatter.hpp +++ b/vendor/toml++/impl/formatter.hpp @@ -1,194 +1,161 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" #if TOML_ENABLE_FORMATTERS #include "forward_declarations.hpp" -#include "print_to_stream.hpp" #include "header_start.hpp" +#include "print_to_stream.hpp" /// \cond -TOML_IMPL_NAMESPACE_START -{ - struct formatter_constants - { - format_flags mandatory_flags; - format_flags ignored_flags; - - std::string_view float_pos_inf; - std::string_view float_neg_inf; - std::string_view float_nan; - - std::string_view bool_true; - std::string_view bool_false; - }; - - struct formatter_config - { - format_flags flags; - std::string_view indent; - }; - - class TOML_EXPORTED_CLASS formatter - { - private: - const node* source_; +TOML_IMPL_NAMESPACE_START { + struct formatter_constants { + format_flags mandatory_flags; + format_flags ignored_flags; + + std::string_view float_pos_inf; + std::string_view float_neg_inf; + std::string_view float_nan; + + std::string_view bool_true; + std::string_view bool_false; + }; + + struct formatter_config { + format_flags flags; + std::string_view indent; + }; + + class TOML_EXPORTED_CLASS formatter { + private: + const node* source_; #if TOML_ENABLE_PARSER && !TOML_EXCEPTIONS - const parse_result* result_; + const parse_result* result_; #endif - const formatter_constants* constants_; - formatter_config config_; - size_t indent_columns_; - format_flags int_format_mask_; - std::ostream* stream_; // - int indent_; // these are set in attach() - bool naked_newline_; // - - protected: - TOML_PURE_INLINE_GETTER - const node& source() const noexcept - { - return *source_; - } - - TOML_PURE_INLINE_GETTER - std::ostream& stream() const noexcept - { - return *stream_; - } - - TOML_PURE_INLINE_GETTER - int indent() const noexcept - { - return indent_; - } - - void indent(int level) noexcept - { - indent_ = level; - } - - void increase_indent() noexcept - { - indent_++; - } - - void decrease_indent() noexcept - { - indent_--; - } - - TOML_PURE_INLINE_GETTER - size_t indent_columns() const noexcept - { - return indent_columns_; - } - - TOML_PURE_INLINE_GETTER - bool indent_array_elements() const noexcept - { - return !!(config_.flags & format_flags::indent_array_elements); - } - - TOML_PURE_INLINE_GETTER - bool indent_sub_tables() const noexcept - { - return !!(config_.flags & format_flags::indent_sub_tables); - } - - TOML_PURE_INLINE_GETTER - bool literal_strings_allowed() const noexcept - { - return !!(config_.flags & format_flags::allow_literal_strings); - } - - TOML_PURE_INLINE_GETTER - bool multi_line_strings_allowed() const noexcept - { - return !!(config_.flags & format_flags::allow_multi_line_strings); - } - - TOML_PURE_INLINE_GETTER - bool real_tabs_in_strings_allowed() const noexcept - { - return !!(config_.flags & format_flags::allow_real_tabs_in_strings); - } - - TOML_PURE_INLINE_GETTER - bool unicode_strings_allowed() const noexcept - { - return !!(config_.flags & format_flags::allow_unicode_strings); - } - - TOML_PURE_INLINE_GETTER - bool terse_kvps() const noexcept - { - return !!(config_.flags & format_flags::terse_key_value_pairs); - } - - TOML_EXPORTED_MEMBER_FUNCTION - void attach(std::ostream& stream) noexcept; - - TOML_EXPORTED_MEMBER_FUNCTION - void detach() noexcept; - - TOML_EXPORTED_MEMBER_FUNCTION - void print_newline(bool force = false); - - TOML_EXPORTED_MEMBER_FUNCTION - void print_indent(); - - TOML_EXPORTED_MEMBER_FUNCTION - void print_unformatted(char); - - TOML_EXPORTED_MEMBER_FUNCTION - void print_unformatted(std::string_view); - - TOML_EXPORTED_MEMBER_FUNCTION - void print_string(std::string_view str, - bool allow_multi_line = true, - bool allow_bare = false, - bool allow_literal_whitespace = true); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const value<std::string>&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const value<int64_t>&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const value<double>&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const value<bool>&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const value<date>&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const value<time>&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const value<date_time>&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print_value(const node&, node_type); - - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - bool dump_failed_parse_result(); - - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - formatter(const node*, const parse_result*, const formatter_constants&, const formatter_config&) noexcept; - }; + const formatter_constants* constants_; + formatter_config config_; + size_t indent_columns_; + format_flags int_format_mask_; + std::ostream* stream_; // + int indent_; // these are set in attach() + bool naked_newline_; // + + protected: + TOML_PURE_INLINE_GETTER + const node& source() const noexcept { return *source_; } + + TOML_PURE_INLINE_GETTER + std::ostream& stream() const noexcept { return *stream_; } + + TOML_PURE_INLINE_GETTER + int indent() const noexcept { return indent_; } + + void indent(int level) noexcept { indent_ = level; } + + void increase_indent() noexcept { indent_++; } + + void decrease_indent() noexcept { indent_--; } + + TOML_PURE_INLINE_GETTER + size_t indent_columns() const noexcept { return indent_columns_; } + + TOML_PURE_INLINE_GETTER + bool indent_array_elements() const noexcept { + return !!(config_.flags & format_flags::indent_array_elements); + } + + TOML_PURE_INLINE_GETTER + bool indent_sub_tables() const noexcept { + return !!(config_.flags & format_flags::indent_sub_tables); + } + + TOML_PURE_INLINE_GETTER + bool literal_strings_allowed() const noexcept { + return !!(config_.flags & format_flags::allow_literal_strings); + } + + TOML_PURE_INLINE_GETTER + bool multi_line_strings_allowed() const noexcept { + return !!(config_.flags & format_flags::allow_multi_line_strings); + } + + TOML_PURE_INLINE_GETTER + bool real_tabs_in_strings_allowed() const noexcept { + return !!(config_.flags & format_flags::allow_real_tabs_in_strings); + } + + TOML_PURE_INLINE_GETTER + bool unicode_strings_allowed() const noexcept { + return !!(config_.flags & format_flags::allow_unicode_strings); + } + + TOML_PURE_INLINE_GETTER + bool terse_kvps() const noexcept { + return !!(config_.flags & format_flags::terse_key_value_pairs); + } + + TOML_EXPORTED_MEMBER_FUNCTION + void attach(std::ostream& stream) noexcept; + + TOML_EXPORTED_MEMBER_FUNCTION + void detach() noexcept; + + TOML_EXPORTED_MEMBER_FUNCTION + void print_newline(bool force = false); + + TOML_EXPORTED_MEMBER_FUNCTION + void print_indent(); + + TOML_EXPORTED_MEMBER_FUNCTION + void print_unformatted(char); + + TOML_EXPORTED_MEMBER_FUNCTION + void print_unformatted(std::string_view); + + TOML_EXPORTED_MEMBER_FUNCTION + void print_string(std::string_view str, bool allow_multi_line = true, bool allow_bare = false, + bool allow_literal_whitespace = true); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const value<std::string>&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const value<int64_t>&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const value<double>&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const value<bool>&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const value<date>&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const value<time>&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const value<date_time>&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print_value(const node&, node_type); + + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + bool dump_failed_parse_result(); + + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + formatter(const node*, const parse_result*, const formatter_constants&, + const formatter_config&) noexcept; + }; } TOML_IMPL_NAMESPACE_END; /// \endcond #include "header_end.hpp" -#endif // TOML_ENABLE_FORMATTERS +#endif // TOML_ENABLE_FORMATTERS diff --git a/vendor/toml++/impl/forward_declarations.hpp b/vendor/toml++/impl/forward_declarations.hpp index 386a9e0..b755855 100644 --- a/vendor/toml++/impl/forward_declarations.hpp +++ b/vendor/toml++/impl/forward_declarations.hpp @@ -1,38 +1,43 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once -#include "std_string.hpp" #include "std_new.hpp" +#include "std_string.hpp" TOML_DISABLE_WARNINGS; -#include <cstdint> -#include <cstddef> -#include <cstring> #include <cfloat> #include <climits> #include <cmath> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <iosfwd> #include <limits> #include <memory> -#include <iosfwd> #include <type_traits> TOML_ENABLE_WARNINGS; #include "header_start.hpp" -//#--------------------------------------------------------------------------------------------------------------------- -//# ENVIRONMENT GROUND-TRUTHS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # ENVIRONMENT GROUND-TRUTHS +// #--------------------------------------------------------------------------------------------------------------------- /// \cond #ifndef TOML_DISABLE_ENVIRONMENT_CHECKS -#define TOML_ENV_MESSAGE \ - "If you're seeing this error it's because you're building toml++ for an environment that doesn't conform to " \ - "one of the 'ground truths' assumed by the library. Essentially this just means that I don't have the " \ - "resources to test on more platforms, but I wish I did! You can try disabling the checks by defining " \ - "TOML_DISABLE_ENVIRONMENT_CHECKS, but your mileage may vary. Please consider filing an issue at " \ - "https://github.com/marzer/tomlplusplus/issues to help me improve support for your target environment. " \ - "Thanks!" +#define TOML_ENV_MESSAGE \ + "If you're seeing this error it's because you're building toml++ for an environment that " \ + "doesn't conform to " \ + "one of the 'ground truths' assumed by the library. Essentially this just means that I don't " \ + "have the " \ + "resources to test on more platforms, but I wish I did! You can try disabling the checks by " \ + "defining " \ + "TOML_DISABLE_ENVIRONMENT_CHECKS, but your mileage may vary. Please consider filing an issue " \ + "at " \ + "https://github.com/marzer/tomlplusplus/issues to help me improve support for your target " \ + "environment. " \ + "Thanks!" static_assert(CHAR_BIT == 8, TOML_ENV_MESSAGE); #ifdef FLT_RADIX @@ -46,83 +51,81 @@ static_assert(std::numeric_limits<double>::digits10 == 15, TOML_ENV_MESSAGE); static_assert(std::numeric_limits<double>::radix == 2, TOML_ENV_MESSAGE); #undef TOML_ENV_MESSAGE -#endif // !TOML_DISABLE_ENVIRONMENT_CHECKS +#endif // !TOML_DISABLE_ENVIRONMENT_CHECKS /// \endcond -//#--------------------------------------------------------------------------------------------------------------------- -//# UNDOCUMENTED TYPEDEFS AND FORWARD DECLARATIONS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # UNDOCUMENTED TYPEDEFS AND FORWARD DECLARATIONS +// #--------------------------------------------------------------------------------------------------------------------- /// \cond // undocumented forward declarations are hidden from doxygen because they fuck it up =/ -namespace toml // non-abi namespace; this is not an error -{ - using ::std::size_t; - using ::std::intptr_t; - using ::std::uintptr_t; - using ::std::ptrdiff_t; - using ::std::nullptr_t; - using ::std::int8_t; - using ::std::int16_t; - using ::std::int32_t; - using ::std::int64_t; - using ::std::uint8_t; - using ::std::uint16_t; - using ::std::uint32_t; - using ::std::uint64_t; - using ::std::uint_least32_t; - using ::std::uint_least64_t; -} - -TOML_NAMESPACE_START +namespace toml // non-abi namespace; this is not an error { - struct date; - struct time; - struct time_offset; - - TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt); - struct date_time; - TOML_ABI_NAMESPACE_END; - - struct source_position; - struct source_region; - - class node; - template <typename> - class node_view; - - class key; - class array; - class table; - template <typename> - class value; - - class path; - - class toml_formatter; - class json_formatter; - class yaml_formatter; - - TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex); +using ::std::int16_t; +using ::std::int32_t; +using ::std::int64_t; +using ::std::int8_t; +using ::std::intptr_t; +using ::std::nullptr_t; +using ::std::ptrdiff_t; +using ::std::size_t; +using ::std::uint16_t; +using ::std::uint32_t; +using ::std::uint64_t; +using ::std::uint8_t; +using ::std::uint_least32_t; +using ::std::uint_least64_t; +using ::std::uintptr_t; +} // namespace toml + +TOML_NAMESPACE_START { + struct date; + struct time; + struct time_offset; + + TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt); + struct date_time; + TOML_ABI_NAMESPACE_END; + + struct source_position; + struct source_region; + + class node; + template <typename> + class node_view; + + class key; + class array; + class table; + template <typename> + class value; + + class path; + + class toml_formatter; + class json_formatter; + class yaml_formatter; + + TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex); #if TOML_EXCEPTIONS - using parse_result = table; + using parse_result = table; #else - class parse_result; + class parse_result; #endif - TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS + TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS } TOML_NAMESPACE_END; -TOML_IMPL_NAMESPACE_START -{ - using node_ptr = std::unique_ptr<node>; +TOML_IMPL_NAMESPACE_START { + using node_ptr = std::unique_ptr<node>; - TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, impl_ex, impl_noex); - class parser; - TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS + TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, impl_ex, impl_noex); + class parser; + TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS - // clang-format off + // clang-format off inline constexpr std::string_view control_char_escapes[] = { @@ -174,7 +177,7 @@ TOML_IMPL_NAMESPACE_START "date-time"sv }; - // clang-format on + // clang-format on } TOML_IMPL_NAMESPACE_END; @@ -190,906 +193,819 @@ TOML_IMPL_NAMESPACE_END; /// \endcond -//#--------------------------------------------------------------------------------------------------------------------- -//# DOCUMENTED TYPEDEFS AND FORWARD DECLARATIONS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # DOCUMENTED TYPEDEFS AND FORWARD DECLARATIONS +// #--------------------------------------------------------------------------------------------------------------------- /// \brief The root namespace for all toml++ functions and types. -namespace toml -{ -} +namespace toml {} -TOML_NAMESPACE_START // abi namespace +TOML_NAMESPACE_START // abi namespace { - /// \brief Convenience literal operators for working with toml++. - /// - /// \detail This namespace exists so you can safely hoist the toml++ literal operators into another scope - /// without dragging in everything from the toml namespace: \cpp - /// - /// #include <toml++/toml.hpp> - /// using namespace toml::literals; - /// - /// int main() - /// { - /// toml::table tbl = "vals = [1, 2, 3]"_toml; - /// - /// // ... do stuff with the table generated by the "_toml" literal ... - /// - /// return 0; - /// } - /// \ecpp - /// - inline namespace literals - { - } - - /// \brief TOML node type identifiers. - enum class TOML_CLOSED_ENUM node_type : uint8_t - { - none, ///< Not-a-node. - table, ///< The node is a toml::table. - array, ///< The node is a toml::array. - string, ///< The node is a toml::value<std::string>. - integer, ///< The node is a toml::value<int64_t>. - floating_point, ///< The node is a toml::value<double>. - boolean, ///< The node is a toml::value<bool>. - date, ///< The node is a toml::value<date>. - time, ///< The node is a toml::value<time>. - date_time ///< The node is a toml::value<date_time>. - }; - - /// \brief Pretty-prints the value of a node_type to a stream. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, 2.0, "3", false }; - /// for (size_t i = 0; i < arr.size() i++) - /// std::cout << "Element ["sv << i << "] is: "sv << arr[i].type() << "\n"; - /// \ecpp - /// - /// \out - /// Element [0] is: integer - /// Element [1] is: floating-point - /// Element [2] is: string - /// Element [3] is: boolean - /// \eout - template <typename Char> - inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, node_type rhs) - { - const auto str = impl::node_type_friendly_names[static_cast<std::underlying_type_t<node_type>>(rhs)]; - using str_char_t = decltype(str)::value_type; - if constexpr (std::is_same_v<Char, str_char_t>) - return lhs << str; - else - { - if constexpr (sizeof(Char) == sizeof(str_char_t)) - return lhs << std::basic_string_view<Char>{ reinterpret_cast<const Char*>(str.data()), str.length() }; - else - return lhs << str.data(); - } - } - - /// \brief Metadata associated with TOML values. - enum class TOML_OPEN_FLAGS_ENUM value_flags : uint16_t // being an "OPEN" flags enum is not an error - { - /// \brief None. - none, - - /// \brief Format integer values as binary. - format_as_binary = 1, - - /// \brief Format integer values as octal. - format_as_octal = 2, - - /// \brief Format integer values as hexadecimal. - format_as_hexadecimal = 3, - }; - TOML_MAKE_FLAGS(value_flags); - - /// \brief Special #toml::value_flags constant used for array + table insert functions to specify that any value - /// nodes being copied should not have their flags property overridden by the inserting function's `flags` argument. - inline constexpr value_flags preserve_source_value_flags = - POXY_IMPLEMENTATION_DETAIL(value_flags{ static_cast<std::underlying_type_t<value_flags>>(-1) }); - - /// \brief Format flags for modifying how TOML data is printed to streams. - /// - /// \note Formatters may disregard/override any of these flags according to the requirements of their - /// output target (e.g. #toml::json_formatter will always apply quotes to dates and times). - enum class TOML_CLOSED_FLAGS_ENUM format_flags : uint64_t - { - /// \brief None. - none, - - /// \brief Dates and times will be emitted as quoted strings. - quote_dates_and_times = (1ull << 0), - - /// \brief Infinities and NaNs will be emitted as quoted strings. - quote_infinities_and_nans = (1ull << 1), - - /// \brief Strings will be emitted as single-quoted literal strings where possible. - allow_literal_strings = (1ull << 2), - - /// \brief Strings containing newlines will be emitted as triple-quoted 'multi-line' strings where possible. - allow_multi_line_strings = (1ull << 3), - - /// \brief Allow real tab characters in string literals (as opposed to the escaped form `\t`). - allow_real_tabs_in_strings = (1ull << 4), - - /// \brief Allow non-ASCII characters in strings (as opposed to their escaped form, e.g. `\u00DA`). - allow_unicode_strings = (1ull << 5), - - /// \brief Allow integers with #value_flags::format_as_binary to be emitted as binary. - allow_binary_integers = (1ull << 6), - - /// \brief Allow integers with #value_flags::format_as_octal to be emitted as octal. - allow_octal_integers = (1ull << 7), - - /// \brief Allow integers with #value_flags::format_as_hexadecimal to be emitted as hexadecimal. - allow_hexadecimal_integers = (1ull << 8), - - /// \brief Apply indentation to tables nested within other tables/arrays. - indent_sub_tables = (1ull << 9), - - /// \brief Apply indentation to array elements when the array is forced to wrap over multiple lines. - indent_array_elements = (1ull << 10), - - /// \brief Combination mask of all indentation-enabling flags. - indentation = indent_sub_tables | indent_array_elements, - - /// \brief Emit floating-point values with relaxed (human-friendly) precision. - /// \warning Setting this flag may cause serialized documents to no longer round-trip correctly - /// since floats might have a less precise value upon being written out than they did when being - /// read in. Use this flag at your own risk. - relaxed_float_precision = (1ull << 11), - - /// \brief Avoids the use of whitespace around key-value pairs. - terse_key_value_pairs = (1ull << 12), - }; - TOML_MAKE_FLAGS(format_flags); - - /// \brief Helper class for suppressing move-construction in single-argument array constructors. - /// - /// \detail \cpp - /// // desired result: [ [ 42 ] ] - /// auto bad = toml::array{ toml::array{ 42 } }; - /// auto good = toml::array{ toml::inserter{ toml::array{ 42 } } }; - /// std::cout << "bad: " << bad << "\n"; - /// std::cout << "good:" << good << "\n"; - /// \ecpp - /// \out - /// bad: [ 42 ] - /// good: [ [ 42 ] ] - /// \eout - /// - /// \see toml::array - template <typename T> - struct TOML_TRIVIAL_ABI inserter - { - static_assert(std::is_reference_v<T>); - - T value; - }; - template <typename T> - inserter(T&&) -> inserter<T&&>; - template <typename T> - inserter(T&) -> inserter<T&>; - - /// \brief The 'default' formatter used by TOML objects when they are printed to a stream. - /// \detail This is an alias for #toml::toml_formatter. - using default_formatter = toml_formatter; + /// \brief Convenience literal operators for working with toml++. + /// + /// \detail This namespace exists so you can safely hoist the toml++ literal operators into + /// another scope without dragging in everything from the toml namespace: \cpp + /// + /// #include <toml++/toml.hpp> + /// using namespace toml::literals; + /// + /// int main() + /// { + /// toml::table tbl = "vals = [1, 2, 3]"_toml; + /// + /// // ... do stuff with the table generated by the "_toml" literal ... + /// + /// return 0; + /// } + /// \ecpp + /// + inline namespace literals {} + + /// \brief TOML node type identifiers. + enum class TOML_CLOSED_ENUM node_type : uint8_t { + none, ///< Not-a-node. + table, ///< The node is a toml::table. + array, ///< The node is a toml::array. + string, ///< The node is a toml::value<std::string>. + integer, ///< The node is a toml::value<int64_t>. + floating_point, ///< The node is a toml::value<double>. + boolean, ///< The node is a toml::value<bool>. + date, ///< The node is a toml::value<date>. + time, ///< The node is a toml::value<time>. + date_time ///< The node is a toml::value<date_time>. + }; + + /// \brief Pretty-prints the value of a node_type to a stream. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 2.0, "3", false }; + /// for (size_t i = 0; i < arr.size() i++) + /// std::cout << "Element ["sv << i << "] is: "sv << arr[i].type() << "\n"; + /// \ecpp + /// + /// \out + /// Element [0] is: integer + /// Element [1] is: floating-point + /// Element [2] is: string + /// Element [3] is: boolean + /// \eout + template <typename Char> + inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, node_type rhs) { + const auto str = + impl::node_type_friendly_names[static_cast<std::underlying_type_t<node_type>>(rhs)]; + using str_char_t = decltype(str)::value_type; + if constexpr (std::is_same_v<Char, str_char_t>) + return lhs << str; + else { + if constexpr (sizeof(Char) == sizeof(str_char_t)) + return lhs << std::basic_string_view<Char>{reinterpret_cast<const Char*>(str.data()), + str.length()}; + else + return lhs << str.data(); + } + } + + /// \brief Metadata associated with TOML values. + enum class TOML_OPEN_FLAGS_ENUM + value_flags : uint16_t // being an "OPEN" flags enum is not an error + { + /// \brief None. + none, + + /// \brief Format integer values as binary. + format_as_binary = 1, + + /// \brief Format integer values as octal. + format_as_octal = 2, + + /// \brief Format integer values as hexadecimal. + format_as_hexadecimal = 3, + }; + TOML_MAKE_FLAGS(value_flags); + + /// \brief Special #toml::value_flags constant used for array + table insert functions to specify + /// that any value nodes being copied should not have their flags property overridden by the + /// inserting function's `flags` argument. + inline constexpr value_flags preserve_source_value_flags = + POXY_IMPLEMENTATION_DETAIL(value_flags{static_cast<std::underlying_type_t<value_flags>>(-1)}); + + /// \brief Format flags for modifying how TOML data is printed to streams. + /// + /// \note Formatters may disregard/override any of these flags according to the requirements of + /// their + /// output target (e.g. #toml::json_formatter will always apply quotes to dates and times). + enum class TOML_CLOSED_FLAGS_ENUM format_flags : uint64_t { + /// \brief None. + none, + + /// \brief Dates and times will be emitted as quoted strings. + quote_dates_and_times = (1ull << 0), + + /// \brief Infinities and NaNs will be emitted as quoted strings. + quote_infinities_and_nans = (1ull << 1), + + /// \brief Strings will be emitted as single-quoted literal strings where possible. + allow_literal_strings = (1ull << 2), + + /// \brief Strings containing newlines will be emitted as triple-quoted 'multi-line' strings + /// where possible. + allow_multi_line_strings = (1ull << 3), + + /// \brief Allow real tab characters in string literals (as opposed to the escaped form `\t`). + allow_real_tabs_in_strings = (1ull << 4), + + /// \brief Allow non-ASCII characters in strings (as opposed to their escaped form, e.g. + /// `\u00DA`). + allow_unicode_strings = (1ull << 5), + + /// \brief Allow integers with #value_flags::format_as_binary to be emitted as binary. + allow_binary_integers = (1ull << 6), + + /// \brief Allow integers with #value_flags::format_as_octal to be emitted as octal. + allow_octal_integers = (1ull << 7), + + /// \brief Allow integers with #value_flags::format_as_hexadecimal to be emitted as hexadecimal. + allow_hexadecimal_integers = (1ull << 8), + + /// \brief Apply indentation to tables nested within other tables/arrays. + indent_sub_tables = (1ull << 9), + + /// \brief Apply indentation to array elements when the array is forced to wrap over multiple + /// lines. + indent_array_elements = (1ull << 10), + + /// \brief Combination mask of all indentation-enabling flags. + indentation = indent_sub_tables | indent_array_elements, + + /// \brief Emit floating-point values with relaxed (human-friendly) precision. + /// \warning Setting this flag may cause serialized documents to no longer round-trip correctly + /// since floats might have a less precise value upon being written out than they did when + ///being read in. Use this flag at your own risk. + relaxed_float_precision = (1ull << 11), + + /// \brief Avoids the use of whitespace around key-value pairs. + terse_key_value_pairs = (1ull << 12), + }; + TOML_MAKE_FLAGS(format_flags); + + /// \brief Helper class for suppressing move-construction in single-argument array constructors. + /// + /// \detail \cpp + /// // desired result: [ [ 42 ] ] + /// auto bad = toml::array{ toml::array{ 42 } }; + /// auto good = toml::array{ toml::inserter{ toml::array{ 42 } } }; + /// std::cout << "bad: " << bad << "\n"; + /// std::cout << "good:" << good << "\n"; + /// \ecpp + /// \out + /// bad: [ 42 ] + /// good: [ [ 42 ] ] + /// \eout + /// + /// \see toml::array + template <typename T> + struct TOML_TRIVIAL_ABI inserter { + static_assert(std::is_reference_v<T>); + + T value; + }; + template <typename T> + inserter(T&&) -> inserter<T&&>; + template <typename T> + inserter(T&) -> inserter<T&>; + + /// \brief The 'default' formatter used by TOML objects when they are printed to a stream. + /// \detail This is an alias for #toml::toml_formatter. + using default_formatter = toml_formatter; } TOML_NAMESPACE_END; -//#--------------------------------------------------------------------------------------------------------------------- -//# METAFUNCTIONS & TYPE TRAITS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # METAFUNCTIONS & TYPE TRAITS +// #--------------------------------------------------------------------------------------------------------------------- /// \cond -TOML_IMPL_NAMESPACE_START -{ - template <typename T> - using remove_cvref = std::remove_cv_t<std::remove_reference_t<T>>; +TOML_IMPL_NAMESPACE_START { + template <typename T> + using remove_cvref = std::remove_cv_t<std::remove_reference_t<T>>; - template <typename... T> - using common_signed_type = std::common_type_t<std::make_signed_t<T>...>; + template <typename... T> + using common_signed_type = std::common_type_t<std::make_signed_t<T>...>; - template <typename T, typename... U> - inline constexpr bool is_one_of = (false || ... || std::is_same_v<T, U>); + template <typename T, typename... U> + inline constexpr bool is_one_of = (false || ... || std::is_same_v<T, U>); - template <typename... T> - inline constexpr bool all_integral = (std::is_integral_v<T> && ...); + template <typename... T> + inline constexpr bool all_integral = (std::is_integral_v<T> && ...); - template <typename T> - inline constexpr bool is_cvref = std::is_reference_v<T> || std::is_const_v<T> || std::is_volatile_v<T>; + template <typename T> + inline constexpr bool is_cvref = + std::is_reference_v<T> || std::is_const_v<T> || std::is_volatile_v<T>; - template <typename T> - inline constexpr bool is_wide_string = - is_one_of<std::decay_t<T>, const wchar_t*, wchar_t*, std::wstring_view, std::wstring>; + template <typename T> + inline constexpr bool is_wide_string = + is_one_of<std::decay_t<T>, const wchar_t*, wchar_t*, std::wstring_view, std::wstring>; - template <typename T> - inline constexpr bool value_retrieval_is_nothrow = !std::is_same_v<remove_cvref<T>, std::string> + template <typename T> + inline constexpr bool value_retrieval_is_nothrow = + !std::is_same_v<remove_cvref<T>, std::string> #if TOML_HAS_CHAR8 - && !std::is_same_v<remove_cvref<T>, std::u8string> + && !std::is_same_v<remove_cvref<T>, std::u8string> #endif - && !is_wide_string<T>; - - template <typename, typename> - struct copy_ref_; - template <typename Dest, typename Src> - using copy_ref = typename copy_ref_<Dest, Src>::type; - - template <typename Dest, typename Src> - struct copy_ref_ - { - using type = Dest; - }; - - template <typename Dest, typename Src> - struct copy_ref_<Dest, Src&> - { - using type = std::add_lvalue_reference_t<Dest>; - }; - - template <typename Dest, typename Src> - struct copy_ref_<Dest, Src&&> - { - using type = std::add_rvalue_reference_t<Dest>; - }; - - template <typename, typename> - struct copy_cv_; - template <typename Dest, typename Src> - using copy_cv = typename copy_cv_<Dest, Src>::type; - - template <typename Dest, typename Src> - struct copy_cv_ - { - using type = Dest; - }; - - template <typename Dest, typename Src> - struct copy_cv_<Dest, const Src> - { - using type = std::add_const_t<Dest>; - }; - - template <typename Dest, typename Src> - struct copy_cv_<Dest, volatile Src> - { - using type = std::add_volatile_t<Dest>; - }; - - template <typename Dest, typename Src> - struct copy_cv_<Dest, const volatile Src> - { - using type = std::add_cv_t<Dest>; - }; - - template <typename Dest, typename Src> - using copy_cvref = - copy_ref<copy_ref<copy_cv<std::remove_reference_t<Dest>, std::remove_reference_t<Src>>, Dest>, Src>; - - template <typename...> - inline constexpr bool always_false = false; - - template <typename T, typename... U> - inline constexpr bool first_is_same = false; - template <typename T, typename... U> - inline constexpr bool first_is_same<T, T, U...> = true; - - template <typename T, bool = std::is_enum_v<T>> - struct underlying_type_ - { - using type = std::underlying_type_t<T>; - }; - template <typename T> - struct underlying_type_<T, false> - { - using type = T; - }; - template <typename T> - using underlying_type = typename underlying_type_<T>::type; - - // general value traits - // (as they relate to their equivalent native TOML type) - struct default_value_traits - { - using native_type = void; - static constexpr bool is_native = false; - static constexpr bool is_losslessly_convertible_to_native = false; - static constexpr bool can_represent_native = false; - static constexpr bool can_partially_represent_native = false; - static constexpr auto type = node_type::none; - }; - - template <typename T> - struct value_traits; - - template <typename T, bool = std::is_enum_v<T>> - struct value_traits_base_selector - { - static_assert(!is_cvref<T>); - - using type = default_value_traits; - }; - template <typename T> - struct value_traits_base_selector<T, true> - { - static_assert(!is_cvref<T>); - - using type = value_traits<underlying_type<T>>; - }; - - template <typename T> - struct value_traits : value_traits_base_selector<T>::type - {}; - template <typename T> - struct value_traits<const T> : value_traits<T> - {}; - template <typename T> - struct value_traits<volatile T> : value_traits<T> - {}; - template <typename T> - struct value_traits<const volatile T> : value_traits<T> - {}; - template <typename T> - struct value_traits<T&> : value_traits<T> - {}; - template <typename T> - struct value_traits<T&&> : value_traits<T> - {}; - - // integer value_traits specializations - standard types - template <typename T> - struct integer_limits - { - static constexpr T min = T{ (std::numeric_limits<underlying_type<T>>::min)() }; - static constexpr T max = T{ (std::numeric_limits<underlying_type<T>>::max)() }; - }; - template <typename T> - struct integer_traits_base : integer_limits<T> - { - using native_type = int64_t; - static constexpr bool is_native = std::is_same_v<underlying_type<T>, native_type>; - static constexpr bool is_signed = static_cast<underlying_type<T>>(-1) < underlying_type<T>{}; - static constexpr auto type = node_type::integer; - static constexpr bool can_partially_represent_native = true; - }; - template <typename T> - struct unsigned_integer_traits : integer_traits_base<T> - { - static constexpr bool is_losslessly_convertible_to_native = - integer_limits<underlying_type<T>>::max <= 9223372036854775807ULL; - static constexpr bool can_represent_native = false; - }; - template <typename T> - struct signed_integer_traits : integer_traits_base<T> - { - using native_type = int64_t; - static constexpr bool is_losslessly_convertible_to_native = - integer_limits<underlying_type<T>>::min >= (-9223372036854775807LL - 1LL) - && integer_limits<underlying_type<T>>::max <= 9223372036854775807LL; - static constexpr bool can_represent_native = - integer_limits<underlying_type<T>>::min <= (-9223372036854775807LL - 1LL) - && integer_limits<underlying_type<T>>::max >= 9223372036854775807LL; - }; - template <typename T, bool S = integer_traits_base<T>::is_signed> - struct integer_traits : signed_integer_traits<T> - {}; - template <typename T> - struct integer_traits<T, false> : unsigned_integer_traits<T> - {}; - template <> - struct value_traits<signed char> : integer_traits<signed char> - {}; - template <> - struct value_traits<unsigned char> : integer_traits<unsigned char> - {}; - template <> - struct value_traits<signed short> : integer_traits<signed short> - {}; - template <> - struct value_traits<unsigned short> : integer_traits<unsigned short> - {}; - template <> - struct value_traits<signed int> : integer_traits<signed int> - {}; - template <> - struct value_traits<unsigned int> : integer_traits<unsigned int> - {}; - template <> - struct value_traits<signed long> : integer_traits<signed long> - {}; - template <> - struct value_traits<unsigned long> : integer_traits<unsigned long> - {}; - template <> - struct value_traits<signed long long> : integer_traits<signed long long> - {}; - template <> - struct value_traits<unsigned long long> : integer_traits<unsigned long long> - {}; - static_assert(value_traits<int64_t>::is_native); - static_assert(value_traits<int64_t>::is_signed); - static_assert(value_traits<int64_t>::is_losslessly_convertible_to_native); - static_assert(value_traits<int64_t>::can_represent_native); - static_assert(value_traits<int64_t>::can_partially_represent_native); - - // integer value_traits specializations - non-standard types + && !is_wide_string<T>; + + template <typename, typename> + struct copy_ref_; + template <typename Dest, typename Src> + using copy_ref = typename copy_ref_<Dest, Src>::type; + + template <typename Dest, typename Src> + struct copy_ref_ { + using type = Dest; + }; + + template <typename Dest, typename Src> + struct copy_ref_<Dest, Src&> { + using type = std::add_lvalue_reference_t<Dest>; + }; + + template <typename Dest, typename Src> + struct copy_ref_<Dest, Src&&> { + using type = std::add_rvalue_reference_t<Dest>; + }; + + template <typename, typename> + struct copy_cv_; + template <typename Dest, typename Src> + using copy_cv = typename copy_cv_<Dest, Src>::type; + + template <typename Dest, typename Src> + struct copy_cv_ { + using type = Dest; + }; + + template <typename Dest, typename Src> + struct copy_cv_<Dest, const Src> { + using type = std::add_const_t<Dest>; + }; + + template <typename Dest, typename Src> + struct copy_cv_<Dest, volatile Src> { + using type = std::add_volatile_t<Dest>; + }; + + template <typename Dest, typename Src> + struct copy_cv_<Dest, const volatile Src> { + using type = std::add_cv_t<Dest>; + }; + + template <typename Dest, typename Src> + using copy_cvref = + copy_ref<copy_ref<copy_cv<std::remove_reference_t<Dest>, std::remove_reference_t<Src>>, Dest>, + Src>; + + template <typename...> + inline constexpr bool always_false = false; + + template <typename T, typename... U> + inline constexpr bool first_is_same = false; + template <typename T, typename... U> + inline constexpr bool first_is_same<T, T, U...> = true; + + template <typename T, bool = std::is_enum_v<T>> + struct underlying_type_ { + using type = std::underlying_type_t<T>; + }; + template <typename T> + struct underlying_type_<T, false> { + using type = T; + }; + template <typename T> + using underlying_type = typename underlying_type_<T>::type; + + // general value traits + // (as they relate to their equivalent native TOML type) + struct default_value_traits { + using native_type = void; + static constexpr bool is_native = false; + static constexpr bool is_losslessly_convertible_to_native = false; + static constexpr bool can_represent_native = false; + static constexpr bool can_partially_represent_native = false; + static constexpr auto type = node_type::none; + }; + + template <typename T> + struct value_traits; + + template <typename T, bool = std::is_enum_v<T>> + struct value_traits_base_selector { + static_assert(!is_cvref<T>); + + using type = default_value_traits; + }; + template <typename T> + struct value_traits_base_selector<T, true> { + static_assert(!is_cvref<T>); + + using type = value_traits<underlying_type<T>>; + }; + + template <typename T> + struct value_traits : value_traits_base_selector<T>::type {}; + template <typename T> + struct value_traits<const T> : value_traits<T> {}; + template <typename T> + struct value_traits<volatile T> : value_traits<T> {}; + template <typename T> + struct value_traits<const volatile T> : value_traits<T> {}; + template <typename T> + struct value_traits<T&> : value_traits<T> {}; + template <typename T> + struct value_traits<T&&> : value_traits<T> {}; + + // integer value_traits specializations - standard types + template <typename T> + struct integer_limits { + static constexpr T min = T{(std::numeric_limits<underlying_type<T>>::min)()}; + static constexpr T max = T{(std::numeric_limits<underlying_type<T>>::max)()}; + }; + template <typename T> + struct integer_traits_base : integer_limits<T> { + using native_type = int64_t; + static constexpr bool is_native = std::is_same_v<underlying_type<T>, native_type>; + static constexpr bool is_signed = static_cast<underlying_type<T>>(-1) < underlying_type<T>{}; + static constexpr auto type = node_type::integer; + static constexpr bool can_partially_represent_native = true; + }; + template <typename T> + struct unsigned_integer_traits : integer_traits_base<T> { + static constexpr bool is_losslessly_convertible_to_native = + integer_limits<underlying_type<T>>::max <= 9223372036854775807ULL; + static constexpr bool can_represent_native = false; + }; + template <typename T> + struct signed_integer_traits : integer_traits_base<T> { + using native_type = int64_t; + static constexpr bool is_losslessly_convertible_to_native = + integer_limits<underlying_type<T>>::min >= (-9223372036854775807LL - 1LL) && + integer_limits<underlying_type<T>>::max <= 9223372036854775807LL; + static constexpr bool can_represent_native = + integer_limits<underlying_type<T>>::min <= (-9223372036854775807LL - 1LL) && + integer_limits<underlying_type<T>>::max >= 9223372036854775807LL; + }; + template <typename T, bool S = integer_traits_base<T>::is_signed> + struct integer_traits : signed_integer_traits<T> {}; + template <typename T> + struct integer_traits<T, false> : unsigned_integer_traits<T> {}; + template <> + struct value_traits<signed char> : integer_traits<signed char> {}; + template <> + struct value_traits<unsigned char> : integer_traits<unsigned char> {}; + template <> + struct value_traits<signed short> : integer_traits<signed short> {}; + template <> + struct value_traits<unsigned short> : integer_traits<unsigned short> {}; + template <> + struct value_traits<signed int> : integer_traits<signed int> {}; + template <> + struct value_traits<unsigned int> : integer_traits<unsigned int> {}; + template <> + struct value_traits<signed long> : integer_traits<signed long> {}; + template <> + struct value_traits<unsigned long> : integer_traits<unsigned long> {}; + template <> + struct value_traits<signed long long> : integer_traits<signed long long> {}; + template <> + struct value_traits<unsigned long long> : integer_traits<unsigned long long> {}; + static_assert(value_traits<int64_t>::is_native); + static_assert(value_traits<int64_t>::is_signed); + static_assert(value_traits<int64_t>::is_losslessly_convertible_to_native); + static_assert(value_traits<int64_t>::can_represent_native); + static_assert(value_traits<int64_t>::can_partially_represent_native); + + // integer value_traits specializations - non-standard types #ifdef TOML_INT128 - template <> - struct integer_limits<TOML_INT128> - { - static constexpr TOML_INT128 max = - static_cast<TOML_INT128>((TOML_UINT128{ 1u } << ((__SIZEOF_INT128__ * CHAR_BIT) - 1)) - 1); - static constexpr TOML_INT128 min = -max - TOML_INT128{ 1 }; - }; - template <> - struct integer_limits<TOML_UINT128> - { - static constexpr TOML_UINT128 min = TOML_UINT128{}; - static constexpr TOML_UINT128 max = (2u * static_cast<TOML_UINT128>(integer_limits<TOML_INT128>::max)) + 1u; - }; - template <> - struct value_traits<TOML_INT128> : integer_traits<TOML_INT128> - {}; - template <> - struct value_traits<TOML_UINT128> : integer_traits<TOML_UINT128> - {}; + template <> + struct integer_limits<TOML_INT128> { + static constexpr TOML_INT128 max = + static_cast<TOML_INT128>((TOML_UINT128{1u} << ((__SIZEOF_INT128__ * CHAR_BIT) - 1)) - 1); + static constexpr TOML_INT128 min = -max - TOML_INT128{1}; + }; + template <> + struct integer_limits<TOML_UINT128> { + static constexpr TOML_UINT128 min = TOML_UINT128{}; + static constexpr TOML_UINT128 max = + (2u * static_cast<TOML_UINT128>(integer_limits<TOML_INT128>::max)) + 1u; + }; + template <> + struct value_traits<TOML_INT128> : integer_traits<TOML_INT128> {}; + template <> + struct value_traits<TOML_UINT128> : integer_traits<TOML_UINT128> {}; #endif #ifdef TOML_SMALL_INT_TYPE - template <> - struct value_traits<TOML_SMALL_INT_TYPE> : signed_integer_traits<TOML_SMALL_INT_TYPE> - {}; + template <> + struct value_traits<TOML_SMALL_INT_TYPE> : signed_integer_traits<TOML_SMALL_INT_TYPE> {}; #endif - // floating-point traits base - template <typename T, int MantissaDigits, int DecimalDigits> - struct float_traits_base - { - static constexpr auto type = node_type::floating_point; - using native_type = double; - static constexpr bool is_native = std::is_same_v<T, native_type>; - static constexpr bool is_signed = true; - - static constexpr int bits = static_cast<int>(sizeof(T) * CHAR_BIT); - static constexpr int digits = MantissaDigits; - static constexpr int digits10 = DecimalDigits; - - static constexpr bool is_losslessly_convertible_to_native = bits <= 64 // - && digits <= 53 // DBL_MANT_DIG - && digits10 <= 15; // DBL_DIG - - static constexpr bool can_represent_native = digits >= 53 // DBL_MANT_DIG - && digits10 >= 15; // DBL_DIG - - static constexpr bool can_partially_represent_native = digits > 0 && digits10 > 0; - }; - template <typename T> - struct float_traits : float_traits_base<T, std::numeric_limits<T>::digits, std::numeric_limits<T>::digits10> - {}; + // floating-point traits base + template <typename T, int MantissaDigits, int DecimalDigits> + struct float_traits_base { + static constexpr auto type = node_type::floating_point; + using native_type = double; + static constexpr bool is_native = std::is_same_v<T, native_type>; + static constexpr bool is_signed = true; + + static constexpr int bits = static_cast<int>(sizeof(T) * CHAR_BIT); + static constexpr int digits = MantissaDigits; + static constexpr int digits10 = DecimalDigits; + + static constexpr bool is_losslessly_convertible_to_native = bits <= 64 // + && digits <= 53 // DBL_MANT_DIG + && digits10 <= 15; // DBL_DIG + + static constexpr bool can_represent_native = digits >= 53 // DBL_MANT_DIG + && digits10 >= 15; // DBL_DIG + + static constexpr bool can_partially_represent_native = digits > 0 && digits10 > 0; + }; + template <typename T> + struct float_traits + : float_traits_base<T, std::numeric_limits<T>::digits, std::numeric_limits<T>::digits10> {}; #if TOML_ENABLE_FLOAT16 - template <> - struct float_traits<_Float16> : float_traits_base<_Float16, __FLT16_MANT_DIG__, __FLT16_DIG__> - {}; + template <> + struct float_traits<_Float16> : float_traits_base<_Float16, __FLT16_MANT_DIG__, __FLT16_DIG__> {}; #endif #ifdef TOML_FLOAT128 - template <> - struct float_traits<TOML_FLOAT128> : float_traits_base<TOML_FLOAT128, __FLT128_MANT_DIG__, __FLT128_DIG__> - {}; + template <> + struct float_traits<TOML_FLOAT128> + : float_traits_base<TOML_FLOAT128, __FLT128_MANT_DIG__, __FLT128_DIG__> {}; #endif - // floating-point traits - template <> - struct value_traits<float> : float_traits<float> - {}; - template <> - struct value_traits<double> : float_traits<double> - {}; - template <> - struct value_traits<long double> : float_traits<long double> - {}; + // floating-point traits + template <> + struct value_traits<float> : float_traits<float> {}; + template <> + struct value_traits<double> : float_traits<double> {}; + template <> + struct value_traits<long double> : float_traits<long double> {}; #if TOML_ENABLE_FLOAT16 - template <> - struct value_traits<_Float16> : float_traits<_Float16> - {}; + template <> + struct value_traits<_Float16> : float_traits<_Float16> {}; #endif #ifdef TOML_FLOAT128 - template <> - struct value_traits<TOML_FLOAT128> : float_traits<TOML_FLOAT128> - {}; + template <> + struct value_traits<TOML_FLOAT128> : float_traits<TOML_FLOAT128> {}; #endif #ifdef TOML_SMALL_FLOAT_TYPE - template <> - struct value_traits<TOML_SMALL_FLOAT_TYPE> : float_traits<TOML_SMALL_FLOAT_TYPE> - {}; + template <> + struct value_traits<TOML_SMALL_FLOAT_TYPE> : float_traits<TOML_SMALL_FLOAT_TYPE> {}; #endif - static_assert(value_traits<double>::is_native); - static_assert(value_traits<double>::is_losslessly_convertible_to_native); - static_assert(value_traits<double>::can_represent_native); - static_assert(value_traits<double>::can_partially_represent_native); - - // string value_traits specializations - char-based strings - template <typename T> - struct string_traits - { - using native_type = std::string; - static constexpr bool is_native = std::is_same_v<T, native_type>; - static constexpr bool is_losslessly_convertible_to_native = true; - static constexpr bool can_represent_native = - !std::is_array_v<T> && (!std::is_pointer_v<T> || std::is_const_v<std::remove_pointer_t<T>>); - static constexpr bool can_partially_represent_native = can_represent_native; - static constexpr auto type = node_type::string; - }; - template <> - struct value_traits<std::string> : string_traits<std::string> - {}; - template <> - struct value_traits<std::string_view> : string_traits<std::string_view> - {}; - template <> - struct value_traits<const char*> : string_traits<const char*> - {}; - template <size_t N> - struct value_traits<const char[N]> : string_traits<const char[N]> - {}; - template <> - struct value_traits<char*> : string_traits<char*> - {}; - template <size_t N> - struct value_traits<char[N]> : string_traits<char[N]> - {}; - - // string value_traits specializations - char8_t-based strings + static_assert(value_traits<double>::is_native); + static_assert(value_traits<double>::is_losslessly_convertible_to_native); + static_assert(value_traits<double>::can_represent_native); + static_assert(value_traits<double>::can_partially_represent_native); + + // string value_traits specializations - char-based strings + template <typename T> + struct string_traits { + using native_type = std::string; + static constexpr bool is_native = std::is_same_v<T, native_type>; + static constexpr bool is_losslessly_convertible_to_native = true; + static constexpr bool can_represent_native = + !std::is_array_v<T> && (!std::is_pointer_v<T> || std::is_const_v<std::remove_pointer_t<T>>); + static constexpr bool can_partially_represent_native = can_represent_native; + static constexpr auto type = node_type::string; + }; + template <> + struct value_traits<std::string> : string_traits<std::string> {}; + template <> + struct value_traits<std::string_view> : string_traits<std::string_view> {}; + template <> + struct value_traits<const char*> : string_traits<const char*> {}; + template <size_t N> + struct value_traits<const char[N]> : string_traits<const char[N]> {}; + template <> + struct value_traits<char*> : string_traits<char*> {}; + template <size_t N> + struct value_traits<char[N]> : string_traits<char[N]> {}; + + // string value_traits specializations - char8_t-based strings #if TOML_HAS_CHAR8 - template <> - struct value_traits<std::u8string> : string_traits<std::u8string> - {}; - template <> - struct value_traits<std::u8string_view> : string_traits<std::u8string_view> - {}; - template <> - struct value_traits<const char8_t*> : string_traits<const char8_t*> - {}; - template <size_t N> - struct value_traits<const char8_t[N]> : string_traits<const char8_t[N]> - {}; - template <> - struct value_traits<char8_t*> : string_traits<char8_t*> - {}; - template <size_t N> - struct value_traits<char8_t[N]> : string_traits<char8_t[N]> - {}; + template <> + struct value_traits<std::u8string> : string_traits<std::u8string> {}; + template <> + struct value_traits<std::u8string_view> : string_traits<std::u8string_view> {}; + template <> + struct value_traits<const char8_t*> : string_traits<const char8_t*> {}; + template <size_t N> + struct value_traits<const char8_t[N]> : string_traits<const char8_t[N]> {}; + template <> + struct value_traits<char8_t*> : string_traits<char8_t*> {}; + template <size_t N> + struct value_traits<char8_t[N]> : string_traits<char8_t[N]> {}; #endif - // string value_traits specializations - wchar_t-based strings on Windows + // string value_traits specializations - wchar_t-based strings on Windows #if TOML_ENABLE_WINDOWS_COMPAT - template <typename T> - struct wstring_traits - { - using native_type = std::string; - static constexpr bool is_native = false; - static constexpr bool is_losslessly_convertible_to_native = true; // narrow - static constexpr bool can_represent_native = std::is_same_v<T, std::wstring>; // widen - static constexpr bool can_partially_represent_native = can_represent_native; - static constexpr auto type = node_type::string; - }; - template <> - struct value_traits<std::wstring> : wstring_traits<std::wstring> - {}; - template <> - struct value_traits<std::wstring_view> : wstring_traits<std::wstring_view> - {}; - template <> - struct value_traits<const wchar_t*> : wstring_traits<const wchar_t*> - {}; - template <size_t N> - struct value_traits<const wchar_t[N]> : wstring_traits<const wchar_t[N]> - {}; - template <> - struct value_traits<wchar_t*> : wstring_traits<wchar_t*> - {}; - template <size_t N> - struct value_traits<wchar_t[N]> : wstring_traits<wchar_t[N]> - {}; + template <typename T> + struct wstring_traits { + using native_type = std::string; + static constexpr bool is_native = false; + static constexpr bool is_losslessly_convertible_to_native = true; // narrow + static constexpr bool can_represent_native = std::is_same_v<T, std::wstring>; // widen + static constexpr bool can_partially_represent_native = can_represent_native; + static constexpr auto type = node_type::string; + }; + template <> + struct value_traits<std::wstring> : wstring_traits<std::wstring> {}; + template <> + struct value_traits<std::wstring_view> : wstring_traits<std::wstring_view> {}; + template <> + struct value_traits<const wchar_t*> : wstring_traits<const wchar_t*> {}; + template <size_t N> + struct value_traits<const wchar_t[N]> : wstring_traits<const wchar_t[N]> {}; + template <> + struct value_traits<wchar_t*> : wstring_traits<wchar_t*> {}; + template <size_t N> + struct value_traits<wchar_t[N]> : wstring_traits<wchar_t[N]> {}; #endif - // other 'native' value_traits specializations - template <typename T, node_type NodeType> - struct native_value_traits - { - using native_type = T; - static constexpr bool is_native = true; - static constexpr bool is_losslessly_convertible_to_native = true; - static constexpr bool can_represent_native = true; - static constexpr bool can_partially_represent_native = true; - static constexpr auto type = NodeType; - }; - template <> - struct value_traits<bool> : native_value_traits<bool, node_type::boolean> - {}; - template <> - struct value_traits<date> : native_value_traits<date, node_type::date> - {}; - template <> - struct value_traits<time> : native_value_traits<time, node_type::time> - {}; - template <> - struct value_traits<date_time> : native_value_traits<date_time, node_type::date_time> - {}; - - // native value category queries - template <typename T> - using native_type_of = typename value_traits<T>::native_type; - template <typename T> - inline constexpr bool is_native = value_traits<T>::is_native; - template <typename T> - inline constexpr bool can_represent_native = value_traits<T>::can_represent_native; - template <typename T> - inline constexpr bool can_partially_represent_native = value_traits<T>::can_partially_represent_native; - template <typename T> - inline constexpr bool is_losslessly_convertible_to_native = value_traits<T>::is_losslessly_convertible_to_native; - template <typename T, typename... U> - inline constexpr bool is_natively_one_of = is_one_of<native_type_of<T>, U...>; - - // native value types => nodes - template <typename T> - struct node_wrapper - { - using type = T; - }; - template <typename T> - struct node_wrapper<const T> - { - using type = std::add_const_t<typename node_wrapper<T>::type>; - }; - template <typename T> - struct node_wrapper<volatile T> - { - using type = std::add_volatile_t<typename node_wrapper<T>::type>; - }; - template <typename T> - struct node_wrapper<const volatile T> - { - using type = std::add_const_t<std::add_volatile_t<typename node_wrapper<T>::type>>; - }; - template <> - struct node_wrapper<std::string> - { - using type = value<std::string>; - }; - template <> - struct node_wrapper<int64_t> - { - using type = value<int64_t>; - }; - template <> - struct node_wrapper<double> - { - using type = value<double>; - }; - template <> - struct node_wrapper<bool> - { - using type = value<bool>; - }; - template <> - struct node_wrapper<date> - { - using type = value<date>; - }; - template <> - struct node_wrapper<time> - { - using type = value<time>; - }; - template <> - struct node_wrapper<date_time> - { - using type = value<date_time>; - }; - template <typename T> - using wrap_node = typename node_wrapper<std::remove_reference_t<T>>::type; - - // nodes => native value types - template <typename T> - struct node_unwrapper - { - using type = T; - }; - template <typename T> - struct node_unwrapper<value<T>> - { - using type = T; - }; - template <typename T> - struct node_unwrapper<const value<T>> - { - using type = std::add_const_t<T>; - }; - template <typename T> - struct node_unwrapper<volatile value<T>> - { - using type = std::add_volatile_t<T>; - }; - template <typename T> - struct node_unwrapper<const volatile value<T>> - { - using type = std::add_volatile_t<std::add_const_t<T>>; - }; - template <typename T> - using unwrap_node = typename node_unwrapper<std::remove_reference_t<T>>::type; - - template <typename T> - struct node_type_getter - { - static constexpr auto value = value_traits<T>::type; - }; - template <> - struct node_type_getter<table> - { - static constexpr auto value = node_type::table; - }; - template <> - struct node_type_getter<array> - { - static constexpr auto value = node_type::array; - }; - template <> - struct node_type_getter<void> - { - static constexpr auto value = node_type::none; - }; - template <typename T> - inline constexpr node_type node_type_of = node_type_getter<unwrap_node<remove_cvref<T>>>::value; - - template <typename T, typename ConvertFrom> - inline constexpr bool is_constructible_or_convertible = std::is_constructible_v<T, ConvertFrom> // - || std::is_convertible_v<ConvertFrom, T>; + // other 'native' value_traits specializations + template <typename T, node_type NodeType> + struct native_value_traits { + using native_type = T; + static constexpr bool is_native = true; + static constexpr bool is_losslessly_convertible_to_native = true; + static constexpr bool can_represent_native = true; + static constexpr bool can_partially_represent_native = true; + static constexpr auto type = NodeType; + }; + template <> + struct value_traits<bool> : native_value_traits<bool, node_type::boolean> {}; + template <> + struct value_traits<date> : native_value_traits<date, node_type::date> {}; + template <> + struct value_traits<time> : native_value_traits<time, node_type::time> {}; + template <> + struct value_traits<date_time> : native_value_traits<date_time, node_type::date_time> {}; + + // native value category queries + template <typename T> + using native_type_of = typename value_traits<T>::native_type; + template <typename T> + inline constexpr bool is_native = value_traits<T>::is_native; + template <typename T> + inline constexpr bool can_represent_native = value_traits<T>::can_represent_native; + template <typename T> + inline constexpr bool can_partially_represent_native = + value_traits<T>::can_partially_represent_native; + template <typename T> + inline constexpr bool is_losslessly_convertible_to_native = + value_traits<T>::is_losslessly_convertible_to_native; + template <typename T, typename... U> + inline constexpr bool is_natively_one_of = is_one_of<native_type_of<T>, U...>; + + // native value types => nodes + template <typename T> + struct node_wrapper { + using type = T; + }; + template <typename T> + struct node_wrapper<const T> { + using type = std::add_const_t<typename node_wrapper<T>::type>; + }; + template <typename T> + struct node_wrapper<volatile T> { + using type = std::add_volatile_t<typename node_wrapper<T>::type>; + }; + template <typename T> + struct node_wrapper<const volatile T> { + using type = std::add_const_t<std::add_volatile_t<typename node_wrapper<T>::type>>; + }; + template <> + struct node_wrapper<std::string> { + using type = value<std::string>; + }; + template <> + struct node_wrapper<int64_t> { + using type = value<int64_t>; + }; + template <> + struct node_wrapper<double> { + using type = value<double>; + }; + template <> + struct node_wrapper<bool> { + using type = value<bool>; + }; + template <> + struct node_wrapper<date> { + using type = value<date>; + }; + template <> + struct node_wrapper<time> { + using type = value<time>; + }; + template <> + struct node_wrapper<date_time> { + using type = value<date_time>; + }; + template <typename T> + using wrap_node = typename node_wrapper<std::remove_reference_t<T>>::type; + + // nodes => native value types + template <typename T> + struct node_unwrapper { + using type = T; + }; + template <typename T> + struct node_unwrapper<value<T>> { + using type = T; + }; + template <typename T> + struct node_unwrapper<const value<T>> { + using type = std::add_const_t<T>; + }; + template <typename T> + struct node_unwrapper<volatile value<T>> { + using type = std::add_volatile_t<T>; + }; + template <typename T> + struct node_unwrapper<const volatile value<T>> { + using type = std::add_volatile_t<std::add_const_t<T>>; + }; + template <typename T> + using unwrap_node = typename node_unwrapper<std::remove_reference_t<T>>::type; + + template <typename T> + struct node_type_getter { + static constexpr auto value = value_traits<T>::type; + }; + template <> + struct node_type_getter<table> { + static constexpr auto value = node_type::table; + }; + template <> + struct node_type_getter<array> { + static constexpr auto value = node_type::array; + }; + template <> + struct node_type_getter<void> { + static constexpr auto value = node_type::none; + }; + template <typename T> + inline constexpr node_type node_type_of = node_type_getter<unwrap_node<remove_cvref<T>>>::value; + + template <typename T, typename ConvertFrom> + inline constexpr bool is_constructible_or_convertible = + std::is_constructible_v<T, ConvertFrom> // + || std::is_convertible_v<ConvertFrom, T>; } TOML_IMPL_NAMESPACE_END; /// \endcond -TOML_NAMESPACE_START -{ - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::table. - template <typename T> - inline constexpr bool is_table = std::is_same_v<impl::remove_cvref<T>, table>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::array. - template <typename T> - inline constexpr bool is_array = std::is_same_v<impl::remove_cvref<T>, array>; - - /// \brief Metafunction for determining if a type satisfies either toml::is_table or toml::is_array. - template <typename T> - inline constexpr bool is_container = is_table<T> || is_array<T>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a std::string or toml::value<std::string>. - template <typename T> - inline constexpr bool is_string = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<std::string>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a int64_t or toml::value<int64_t>. - template <typename T> - inline constexpr bool is_integer = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<int64_t>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a double or toml::value<double>. - template <typename T> - inline constexpr bool is_floating_point = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<double>>; - - /// \brief Metafunction for determining if a type satisfies either toml::is_integer or toml::is_floating_point. - template <typename T> - inline constexpr bool is_number = is_integer<T> || is_floating_point<T>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a bool or toml::value<bool>. - template <typename T> - inline constexpr bool is_boolean = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<bool>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::date or toml::value<date>. - template <typename T> - inline constexpr bool is_date = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<date>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::time or toml::value<time>. - template <typename T> - inline constexpr bool is_time = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<time>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::date_time or toml::value<date_time>. - template <typename T> - inline constexpr bool is_date_time = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<date_time>>; - - /// \brief Metafunction for determining if a type satisfies any of toml::is_date, toml::is_time or toml::is_date_time. - template <typename T> - inline constexpr bool is_chronological = is_date<T> || is_time<T> || is_date_time<T>; - - /// \brief Metafunction for determining if a type is, or is a reference to, any of the toml value types. Excludes tables and arrays. - template <typename T> - inline constexpr bool is_value = is_string<T> || is_number<T> || is_boolean<T> || is_chronological<T>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::node (or one of its subclasses). - template <typename T> - inline constexpr bool is_node = std::is_same_v<toml::node, impl::remove_cvref<T>> // - || std::is_base_of_v<toml::node, impl::remove_cvref<T>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::node_view. - template <typename T> - inline constexpr bool is_node_view = impl::is_one_of<impl::remove_cvref<T>, node_view<node>, node_view<const node>>; +TOML_NAMESPACE_START { + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::table. + template <typename T> + inline constexpr bool is_table = std::is_same_v<impl::remove_cvref<T>, table>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::array. + template <typename T> + inline constexpr bool is_array = std::is_same_v<impl::remove_cvref<T>, array>; + + /// \brief Metafunction for determining if a type satisfies either toml::is_table or + /// toml::is_array. + template <typename T> + inline constexpr bool is_container = is_table<T> || is_array<T>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a std::string or + /// toml::value<std::string>. + template <typename T> + inline constexpr bool is_string = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<std::string>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a int64_t or + /// toml::value<int64_t>. + template <typename T> + inline constexpr bool is_integer = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<int64_t>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a double or + /// toml::value<double>. + template <typename T> + inline constexpr bool is_floating_point = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<double>>; + + /// \brief Metafunction for determining if a type satisfies either toml::is_integer or + /// toml::is_floating_point. + template <typename T> + inline constexpr bool is_number = is_integer<T> || is_floating_point<T>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a bool or + /// toml::value<bool>. + template <typename T> + inline constexpr bool is_boolean = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<bool>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::date or + /// toml::value<date>. + template <typename T> + inline constexpr bool is_date = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<date>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::time or + /// toml::value<time>. + template <typename T> + inline constexpr bool is_time = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<time>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::date_time or + /// toml::value<date_time>. + template <typename T> + inline constexpr bool is_date_time = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<date_time>>; + + /// \brief Metafunction for determining if a type satisfies any of toml::is_date, toml::is_time + /// or toml::is_date_time. + template <typename T> + inline constexpr bool is_chronological = is_date<T> || is_time<T> || is_date_time<T>; + + /// \brief Metafunction for determining if a type is, or is a reference to, any of the toml value + /// types. Excludes tables and arrays. + template <typename T> + inline constexpr bool is_value = + is_string<T> || is_number<T> || is_boolean<T> || is_chronological<T>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::node (or one + /// of its subclasses). + template <typename T> + inline constexpr bool is_node = std::is_same_v<toml::node, impl::remove_cvref<T>> // + || std::is_base_of_v<toml::node, impl::remove_cvref<T>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::node_view. + template <typename T> + inline constexpr bool is_node_view = + impl::is_one_of<impl::remove_cvref<T>, node_view<node>, node_view<const node>>; } TOML_NAMESPACE_END; -//#--------------------------------------------------------------------------------------------------------------------- -//# INTERNAL HELPERS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # INTERNAL HELPERS +// #--------------------------------------------------------------------------------------------------------------------- /// \cond -TOML_IMPL_NAMESPACE_START -{ - template <typename T> - TOML_CONST_INLINE_GETTER - constexpr std::underlying_type_t<T> unwrap_enum(T val) noexcept - { - return static_cast<std::underlying_type_t<T>>(val); - } - - // Q: "why not use std::fpclassify?" - // A: Because it gets broken by -ffast-math and friends - enum class TOML_CLOSED_ENUM fp_class : unsigned - { - ok, - neg_inf, - pos_inf, - nan - }; - - TOML_PURE_GETTER - inline fp_class fpclassify(const double& val) noexcept - { - static_assert(sizeof(uint64_t) == sizeof(double)); - - static constexpr uint64_t sign = 0b1000000000000000000000000000000000000000000000000000000000000000ull; - static constexpr uint64_t exponent = 0b0111111111110000000000000000000000000000000000000000000000000000ull; - static constexpr uint64_t mantissa = 0b0000000000001111111111111111111111111111111111111111111111111111ull; - - uint64_t val_bits; - std::memcpy(&val_bits, &val, sizeof(val)); - if ((val_bits & exponent) != exponent) - return fp_class::ok; - if ((val_bits & mantissa)) - return fp_class::nan; - return (val_bits & sign) ? fp_class::neg_inf : fp_class::pos_inf; - } - - // Q: "why not use std::find and std::min?" - // A: Because <algorithm> is _huge_ and these would be the only things I used from it. - // I don't want to impose such a heavy compile-time burden on users. - - template <typename Iterator, typename T> - TOML_PURE_GETTER - inline auto find(Iterator start, Iterator end, const T& needle) noexcept // - ->decltype(&(*start)) - { - for (; start != end; start++) - if (*start == needle) - return &(*start); - return nullptr; - } - - template <typename T> - TOML_PURE_INLINE_GETTER - constexpr const T& min(const T& a, const T& b) noexcept // - { - return a < b ? a : b; - } +TOML_IMPL_NAMESPACE_START { + template <typename T> + TOML_CONST_INLINE_GETTER constexpr std::underlying_type_t<T> unwrap_enum(T val) noexcept { + return static_cast<std::underlying_type_t<T>>(val); + } + + // Q: "why not use std::fpclassify?" + // A: Because it gets broken by -ffast-math and friends + enum class TOML_CLOSED_ENUM fp_class : unsigned { ok, neg_inf, pos_inf, nan }; + + TOML_PURE_GETTER + inline fp_class fpclassify(const double& val) noexcept { + static_assert(sizeof(uint64_t) == sizeof(double)); + + static constexpr uint64_t sign = + 0b1000000000000000000000000000000000000000000000000000000000000000ull; + static constexpr uint64_t exponent = + 0b0111111111110000000000000000000000000000000000000000000000000000ull; + static constexpr uint64_t mantissa = + 0b0000000000001111111111111111111111111111111111111111111111111111ull; + + uint64_t val_bits; + std::memcpy(&val_bits, &val, sizeof(val)); + if ((val_bits & exponent) != exponent) return fp_class::ok; + if ((val_bits & mantissa)) return fp_class::nan; + return (val_bits & sign) ? fp_class::neg_inf : fp_class::pos_inf; + } + + // Q: "why not use std::find and std::min?" + // A: Because <algorithm> is _huge_ and these would be the only things I used from it. + // I don't want to impose such a heavy compile-time burden on users. + + template <typename Iterator, typename T> + TOML_PURE_GETTER inline auto find(Iterator start, Iterator end, const T& needle) noexcept // + -> decltype(&(*start)) { + for (; start != end; start++) + if (*start == needle) return &(*start); + return nullptr; + } + + template <typename T> + TOML_PURE_INLINE_GETTER constexpr const T& min(const T& a, const T& b) noexcept // + { + return a < b ? a : b; + } } TOML_IMPL_NAMESPACE_END; /// \endcond diff --git a/vendor/toml++/impl/header_end.hpp b/vendor/toml++/impl/header_end.hpp index ff0462d..df011a3 100644 --- a/vendor/toml++/impl/header_end.hpp +++ b/vendor/toml++/impl/header_end.hpp @@ -1,8 +1,8 @@ -//# {{ +// # {{ #ifdef __INTELLISENSE__ #include "preprocessor.hpp" #endif -//# }} +// # }} #ifdef _MSC_VER #pragma pop_macro("min") #pragma pop_macro("max") diff --git a/vendor/toml++/impl/header_start.hpp b/vendor/toml++/impl/header_start.hpp index 6e1bb41..789d757 100644 --- a/vendor/toml++/impl/header_start.hpp +++ b/vendor/toml++/impl/header_start.hpp @@ -1,8 +1,8 @@ -//# {{ +// # {{ #ifdef __INTELLISENSE__ #include "preprocessor.hpp" #endif -//# }} +// # }} TOML_PUSH_WARNINGS; #ifdef _MSC_VER #ifndef __clang__ diff --git a/vendor/toml++/impl/json_formatter.hpp b/vendor/toml++/impl/json_formatter.hpp index ca3776a..d403287 100644 --- a/vendor/toml++/impl/json_formatter.hpp +++ b/vendor/toml++/impl/json_formatter.hpp @@ -1,7 +1,7 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" @@ -10,133 +10,128 @@ #include "formatter.hpp" #include "header_start.hpp" -TOML_NAMESPACE_START -{ - /// \brief A wrapper for printing TOML objects out to a stream as formatted JSON. - /// - /// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled. - /// - /// \detail \cpp - /// auto some_toml = toml::parse(R"( - /// [fruit] - /// apple.color = "red" - /// apple.taste.sweet = true - /// - /// [fruit.apple.texture] - /// smooth = true - /// )"sv); - /// std::cout << toml::json_formatter{ some_toml } << "\n"; - /// \ecpp - /// - /// \out - /// { - /// "fruit" : { - /// "apple" : { - /// "color" : "red", - /// "taste" : { - /// "sweet" : true - /// }, - /// "texture" : { - /// "smooth" : true - /// } - /// } - /// } - /// } - /// \eout - class TOML_EXPORTED_CLASS json_formatter : impl::formatter - { - private: - /// \cond - - using base = impl::formatter; - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const toml::table&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const toml::array&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(); - - static constexpr impl::formatter_constants constants = { - format_flags::quote_dates_and_times, // mandatory - format_flags::allow_literal_strings | format_flags::allow_multi_line_strings, // ignored - "Infinity"sv, - "-Infinity"sv, - "NaN"sv, - "true"sv, - "false"sv - }; - - /// \endcond - - public: - /// \brief The default flags for a json_formatter. - static constexpr format_flags default_flags = constants.mandatory_flags // - | format_flags::quote_infinities_and_nans // - | format_flags::allow_unicode_strings // - | format_flags::indentation; - - /// \brief Constructs a JSON formatter and binds it to a TOML object. - /// - /// \param source The source TOML object. - /// \param flags Format option flags. - TOML_NODISCARD_CTOR - explicit json_formatter(const toml::node& source, format_flags flags = default_flags) noexcept - : base{ &source, nullptr, constants, { flags, " "sv } } - {} +TOML_NAMESPACE_START { + /// \brief A wrapper for printing TOML objects out to a stream as formatted JSON. + /// + /// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled. + /// + /// \detail \cpp + /// auto some_toml = toml::parse(R"( + /// [fruit] + /// apple.color = "red" + /// apple.taste.sweet = true + /// + /// [fruit.apple.texture] + /// smooth = true + /// )"sv); + /// std::cout << toml::json_formatter{ some_toml } << "\n"; + /// \ecpp + /// + /// \out + /// { + /// "fruit" : { + /// "apple" : { + /// "color" : "red", + /// "taste" : { + /// "sweet" : true + /// }, + /// "texture" : { + /// "smooth" : true + /// } + /// } + /// } + /// } + /// \eout + class TOML_EXPORTED_CLASS json_formatter : impl::formatter { + private: + /// \cond + + using base = impl::formatter; + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const toml::table&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const toml::array&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(); + + static constexpr impl::formatter_constants constants = { + format_flags::quote_dates_and_times, // mandatory + format_flags::allow_literal_strings | format_flags::allow_multi_line_strings, // ignored + "Infinity"sv, + "-Infinity"sv, + "NaN"sv, + "true"sv, + "false"sv}; + + /// \endcond + + public: + /// \brief The default flags for a json_formatter. + static constexpr format_flags default_flags = constants.mandatory_flags // + | format_flags::quote_infinities_and_nans // + | format_flags::allow_unicode_strings // + | format_flags::indentation; + + /// \brief Constructs a JSON formatter and binds it to a TOML object. + /// + /// \param source The source TOML object. + /// \param flags Format option flags. + TOML_NODISCARD_CTOR + explicit json_formatter(const toml::node& source, format_flags flags = default_flags) noexcept + : base{&source, nullptr, constants, {flags, " "sv}} {} #if TOML_DOXYGEN || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS) - /// \brief Constructs a JSON formatter and binds it to a toml::parse_result. - /// - /// \availability This constructor is only available when exceptions are disabled. - /// - /// \attention Formatting a failed parse result will simply dump the error message out as-is. - /// This will not be valid JSON, but at least gives you something to log or show up in diagnostics: - /// \cpp - /// std::cout << toml::json_formatter{ toml::parse("a = 'b'"sv) } // ok - /// << "\n\n" - /// << toml::json_formatter{ toml::parse("a = "sv) } // malformed - /// << "\n"; - /// \ecpp - /// \out - /// { - /// "a" : "b" - /// } - /// - /// Error while parsing key-value pair: encountered end-of-file - /// (error occurred at line 1, column 5) - /// \eout - /// Use the library with exceptions if you want to avoid this scenario. - /// - /// \param result The parse result. - /// \param flags Format option flags. - TOML_NODISCARD_CTOR - explicit json_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept - : base{ nullptr, &result, constants, { flags, " "sv } } - {} + /// \brief Constructs a JSON formatter and binds it to a toml::parse_result. + /// + /// \availability This constructor is only available when exceptions are disabled. + /// + /// \attention Formatting a failed parse result will simply dump the error message out as-is. + /// This will not be valid JSON, but at least gives you something to log or show up in + ///diagnostics: + /// \cpp + /// std::cout << toml::json_formatter{ toml::parse("a = 'b'"sv) } // ok + /// << "\n\n" + /// << toml::json_formatter{ toml::parse("a = "sv) } // malformed + /// << "\n"; + /// \ecpp + /// \out + /// { + /// "a" : "b" + /// } + /// + /// Error while parsing key-value pair: encountered end-of-file + /// (error occurred at line 1, column 5) + /// \eout + /// Use the library with exceptions if you want to avoid this scenario. + /// + /// \param result The parse result. + /// \param flags Format option flags. + TOML_NODISCARD_CTOR + explicit json_formatter(const toml::parse_result& result, + format_flags flags = default_flags) noexcept + : base{nullptr, &result, constants, {flags, " "sv}} {} #endif - /// \brief Prints the bound TOML object out to the stream as JSON. - friend std::ostream& operator<<(std::ostream& lhs, json_formatter& rhs) - { - rhs.attach(lhs); - rhs.print(); - rhs.detach(); - return lhs; - } - - /// \brief Prints the bound TOML object out to the stream as JSON (rvalue overload). - friend std::ostream& operator<<(std::ostream& lhs, json_formatter&& rhs) - { - return lhs << rhs; // as lvalue - } - }; + /// \brief Prints the bound TOML object out to the stream as JSON. + friend std::ostream& operator<<(std::ostream& lhs, json_formatter& rhs) { + rhs.attach(lhs); + rhs.print(); + rhs.detach(); + return lhs; + } + + /// \brief Prints the bound TOML object out to the stream as JSON (rvalue overload). + friend std::ostream& operator<<(std::ostream& lhs, json_formatter&& rhs) { + return lhs << rhs; // as lvalue + } + }; } TOML_NAMESPACE_END; #include "header_end.hpp" -#endif // TOML_ENABLE_FORMATTERS +#endif // TOML_ENABLE_FORMATTERS diff --git a/vendor/toml++/impl/key.hpp b/vendor/toml++/impl/key.hpp index 575017a..ccfd72e 100644 --- a/vendor/toml++/impl/key.hpp +++ b/vendor/toml++/impl/key.hpp @@ -1,334 +1,257 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once +#include "header_start.hpp" +#include "print_to_stream.hpp" #include "source_region.hpp" #include "std_utility.hpp" -#include "print_to_stream.hpp" -#include "header_start.hpp" -TOML_NAMESPACE_START -{ - /// \brief A key parsed from a TOML document. - /// - /// \detail These are used as the internal keys for a toml::table: \cpp - /// const toml::table tbl = R"( - /// a = 1 - /// b = 2 - /// c = 3 - /// )"_toml; - /// - /// for (auto&& [k, v] : tbl) - /// std::cout << "key '"sv << k << "' defined at "sv << k.source() << "\n"; - /// \ecpp - /// \out - /// key 'a' defined at line 2, column 5 - /// key 'b' defined at line 3, column 7 - /// key 'c' defined at line 4, column 9 - /// \eout - class key - { - private: - std::string key_; - source_region source_; - - public: - /// \brief Default constructor. - TOML_NODISCARD_CTOR - key() noexcept = default; - - /// \brief Constructs a key from a string view and source region. - TOML_NODISCARD_CTOR - explicit key(std::string_view k, source_region&& src = {}) // - : key_{ k }, - source_{ std::move(src) } - {} - - /// \brief Constructs a key from a string view and source region. - TOML_NODISCARD_CTOR - explicit key(std::string_view k, const source_region& src) // - : key_{ k }, - source_{ src } - {} - - /// \brief Constructs a key from a string and source region. - TOML_NODISCARD_CTOR - explicit key(std::string&& k, source_region&& src = {}) noexcept // - : key_{ std::move(k) }, - source_{ std::move(src) } - {} - - /// \brief Constructs a key from a string and source region. - TOML_NODISCARD_CTOR - explicit key(std::string&& k, const source_region& src) noexcept // - : key_{ std::move(k) }, - source_{ src } - {} - - /// \brief Constructs a key from a c-string and source region. - TOML_NODISCARD_CTOR - explicit key(const char* k, source_region&& src = {}) // - : key_{ k }, - source_{ std::move(src) } - {} - - /// \brief Constructs a key from a c-string view and source region. - TOML_NODISCARD_CTOR - explicit key(const char* k, const source_region& src) // - : key_{ k }, - source_{ src } - {} +TOML_NAMESPACE_START { + /// \brief A key parsed from a TOML document. + /// + /// \detail These are used as the internal keys for a toml::table: \cpp + /// const toml::table tbl = R"( + /// a = 1 + /// b = 2 + /// c = 3 + /// )"_toml; + /// + /// for (auto&& [k, v] : tbl) + /// std::cout << "key '"sv << k << "' defined at "sv << k.source() << "\n"; + /// \ecpp + /// \out + /// key 'a' defined at line 2, column 5 + /// key 'b' defined at line 3, column 7 + /// key 'c' defined at line 4, column 9 + /// \eout + class key { + private: + std::string key_; + source_region source_; + + public: + /// \brief Default constructor. + TOML_NODISCARD_CTOR + key() noexcept = default; + + /// \brief Constructs a key from a string view and source region. + TOML_NODISCARD_CTOR + explicit key(std::string_view k, source_region&& src = {}) // + : key_{k}, source_{std::move(src)} {} + + /// \brief Constructs a key from a string view and source region. + TOML_NODISCARD_CTOR + explicit key(std::string_view k, const source_region& src) // + : key_{k}, source_{src} {} + + /// \brief Constructs a key from a string and source region. + TOML_NODISCARD_CTOR + explicit key(std::string&& k, source_region&& src = {}) noexcept // + : key_{std::move(k)}, source_{std::move(src)} {} + + /// \brief Constructs a key from a string and source region. + TOML_NODISCARD_CTOR + explicit key(std::string&& k, const source_region& src) noexcept // + : key_{std::move(k)}, source_{src} {} + + /// \brief Constructs a key from a c-string and source region. + TOML_NODISCARD_CTOR + explicit key(const char* k, source_region&& src = {}) // + : key_{k}, source_{std::move(src)} {} + + /// \brief Constructs a key from a c-string view and source region. + TOML_NODISCARD_CTOR + explicit key(const char* k, const source_region& src) // + : key_{k}, source_{src} {} #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Constructs a key from a wide string view and source region. - /// - /// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD_CTOR - explicit key(std::wstring_view k, source_region&& src = {}) // - : key_{ impl::narrow(k) }, - source_{ std::move(src) } - {} - - /// \brief Constructs a key from a wide string and source region. - /// - /// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD_CTOR - explicit key(std::wstring_view k, const source_region& src) // - : key_{ impl::narrow(k) }, - source_{ src } - {} + /// \brief Constructs a key from a wide string view and source region. + /// + /// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is + /// enabled. + TOML_NODISCARD_CTOR + explicit key(std::wstring_view k, source_region&& src = {}) // + : key_{impl::narrow(k)}, source_{std::move(src)} {} + + /// \brief Constructs a key from a wide string and source region. + /// + /// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is + /// enabled. + TOML_NODISCARD_CTOR + explicit key(std::wstring_view k, const source_region& src) // + : key_{impl::narrow(k)}, source_{src} {} #endif - /// \name String operations - /// @{ - - /// \brief Returns a view of the key's underlying string. - TOML_PURE_INLINE_GETTER - std::string_view str() const noexcept - { - return std::string_view{ key_ }; - } - - /// \brief Returns a view of the key's underlying string. - TOML_PURE_INLINE_GETTER - /*implicit*/ operator std::string_view() const noexcept - { - return str(); - } - - /// \brief Returns true if the key's underlying string is empty. - TOML_PURE_INLINE_GETTER - bool empty() const noexcept - { - return key_.empty(); - } - - /// \brief Returns a pointer to the start of the key's underlying string. - TOML_PURE_INLINE_GETTER - const char* data() const noexcept - { - return key_.data(); - } - - /// \brief Returns the length of the key's underlying string. - TOML_PURE_INLINE_GETTER - size_t length() const noexcept - { - return key_.length(); - } - - /// @} - - /// \name Metadata - /// @{ - - /// \brief Returns the source region responsible for specifying this key during parsing. - TOML_PURE_INLINE_GETTER - const source_region& source() const noexcept - { - return source_; - } - - /// @} - - /// \name Equality and Comparison - /// \attention These operations only compare the underlying strings; source regions are ignored for the purposes of all comparison! - /// @{ - - /// \brief Returns true if `lhs.str() == rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator==(const key& lhs, const key& rhs) noexcept - { - return lhs.key_ == rhs.key_; - } - - /// \brief Returns true if `lhs.str() != rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator!=(const key& lhs, const key& rhs) noexcept - { - return lhs.key_ != rhs.key_; - } - - /// \brief Returns true if `lhs.str() < rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator<(const key& lhs, const key& rhs) noexcept - { - return lhs.key_ < rhs.key_; - } - - /// \brief Returns true if `lhs.str() <= rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator<=(const key& lhs, const key& rhs) noexcept - { - return lhs.key_ <= rhs.key_; - } - - /// \brief Returns true if `lhs.str() > rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator>(const key& lhs, const key& rhs) noexcept - { - return lhs.key_ > rhs.key_; - } - - /// \brief Returns true if `lhs.str() >= rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator>=(const key& lhs, const key& rhs) noexcept - { - return lhs.key_ >= rhs.key_; - } - - /// \brief Returns true if `lhs.str() == rhs`. - TOML_PURE_INLINE_GETTER - friend bool operator==(const key& lhs, std::string_view rhs) noexcept - { - return lhs.key_ == rhs; - } - - /// \brief Returns true if `lhs.str() != rhs`. - TOML_PURE_INLINE_GETTER - friend bool operator!=(const key& lhs, std::string_view rhs) noexcept - { - return lhs.key_ != rhs; - } - - /// \brief Returns true if `lhs.str() < rhs`. - TOML_PURE_INLINE_GETTER - friend bool operator<(const key& lhs, std::string_view rhs) noexcept - { - return lhs.key_ < rhs; - } - - /// \brief Returns true if `lhs.str() <= rhs`. - TOML_PURE_INLINE_GETTER - friend bool operator<=(const key& lhs, std::string_view rhs) noexcept - { - return lhs.key_ <= rhs; - } - - /// \brief Returns true if `lhs.str() > rhs`. - TOML_PURE_INLINE_GETTER - friend bool operator>(const key& lhs, std::string_view rhs) noexcept - { - return lhs.key_ > rhs; - } - - /// \brief Returns true if `lhs.str() >= rhs`. - TOML_PURE_INLINE_GETTER - friend bool operator>=(const key& lhs, std::string_view rhs) noexcept - { - return lhs.key_ >= rhs; - } - - /// \brief Returns true if `lhs == rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator==(std::string_view lhs, const key& rhs) noexcept - { - return lhs == rhs.key_; - } - - /// \brief Returns true if `lhs != rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator!=(std::string_view lhs, const key& rhs) noexcept - { - return lhs != rhs.key_; - } - - /// \brief Returns true if `lhs < rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator<(std::string_view lhs, const key& rhs) noexcept - { - return lhs < rhs.key_; - } - - /// \brief Returns true if `lhs <= rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator<=(std::string_view lhs, const key& rhs) noexcept - { - return lhs <= rhs.key_; - } - - /// \brief Returns true if `lhs > rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator>(std::string_view lhs, const key& rhs) noexcept - { - return lhs > rhs.key_; - } - - /// \brief Returns true if `lhs >= rhs.str()`. - TOML_PURE_INLINE_GETTER - friend bool operator>=(std::string_view lhs, const key& rhs) noexcept - { - return lhs >= rhs.key_; - } - - /// @} - - /// \name Iteration - /// @{ - - /// \brief A const iterator for iterating over the characters in the key. - using const_iterator = const char*; - - /// \brief A const iterator for iterating over the characters in the key. - using iterator = const_iterator; - - /// \brief Returns an iterator to the first character in the key's backing string. - TOML_PURE_INLINE_GETTER - const_iterator begin() const noexcept - { - return key_.data(); - } - - /// \brief Returns an iterator to one-past-the-last character in the key's backing string. - TOML_PURE_INLINE_GETTER - const_iterator end() const noexcept - { - return key_.data() + key_.length(); - } - - /// @} - - /// \brief Prints the key's underlying string out to the stream. - friend std::ostream& operator<<(std::ostream& lhs, const key& rhs) - { - impl::print_to_stream(lhs, rhs.key_); - return lhs; - } - }; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::key. - template <typename T> - inline constexpr bool is_key = std::is_same_v<impl::remove_cvref<T>, toml::key>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::key, - /// or is implicitly or explicitly convertible to one. - template <typename T> - inline constexpr bool is_key_or_convertible = is_key<T> // - || impl::is_constructible_or_convertible<toml::key, T>; + /// \name String operations + /// @{ + + /// \brief Returns a view of the key's underlying string. + TOML_PURE_INLINE_GETTER + std::string_view str() const noexcept { return std::string_view{key_}; } + + /// \brief Returns a view of the key's underlying string. + TOML_PURE_INLINE_GETTER + /*implicit*/ operator std::string_view() const noexcept { return str(); } + + /// \brief Returns true if the key's underlying string is empty. + TOML_PURE_INLINE_GETTER + bool empty() const noexcept { return key_.empty(); } + + /// \brief Returns a pointer to the start of the key's underlying string. + TOML_PURE_INLINE_GETTER + const char* data() const noexcept { return key_.data(); } + + /// \brief Returns the length of the key's underlying string. + TOML_PURE_INLINE_GETTER + size_t length() const noexcept { return key_.length(); } + + /// @} + + /// \name Metadata + /// @{ + + /// \brief Returns the source region responsible for specifying this key during parsing. + TOML_PURE_INLINE_GETTER + const source_region& source() const noexcept { return source_; } + + /// @} + + /// \name Equality and Comparison + /// \attention These operations only compare the underlying strings; source regions are ignored + /// for the purposes of all comparison! + /// @{ + + /// \brief Returns true if `lhs.str() == rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator==(const key& lhs, const key& rhs) noexcept { return lhs.key_ == rhs.key_; } + + /// \brief Returns true if `lhs.str() != rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator!=(const key& lhs, const key& rhs) noexcept { return lhs.key_ != rhs.key_; } + + /// \brief Returns true if `lhs.str() < rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator<(const key& lhs, const key& rhs) noexcept { return lhs.key_ < rhs.key_; } + + /// \brief Returns true if `lhs.str() <= rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator<=(const key& lhs, const key& rhs) noexcept { return lhs.key_ <= rhs.key_; } + + /// \brief Returns true if `lhs.str() > rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator>(const key& lhs, const key& rhs) noexcept { return lhs.key_ > rhs.key_; } + + /// \brief Returns true if `lhs.str() >= rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator>=(const key& lhs, const key& rhs) noexcept { return lhs.key_ >= rhs.key_; } + + /// \brief Returns true if `lhs.str() == rhs`. + TOML_PURE_INLINE_GETTER + friend bool operator==(const key& lhs, std::string_view rhs) noexcept { + return lhs.key_ == rhs; + } + + /// \brief Returns true if `lhs.str() != rhs`. + TOML_PURE_INLINE_GETTER + friend bool operator!=(const key& lhs, std::string_view rhs) noexcept { + return lhs.key_ != rhs; + } + + /// \brief Returns true if `lhs.str() < rhs`. + TOML_PURE_INLINE_GETTER + friend bool operator<(const key& lhs, std::string_view rhs) noexcept { return lhs.key_ < rhs; } + + /// \brief Returns true if `lhs.str() <= rhs`. + TOML_PURE_INLINE_GETTER + friend bool operator<=(const key& lhs, std::string_view rhs) noexcept { + return lhs.key_ <= rhs; + } + + /// \brief Returns true if `lhs.str() > rhs`. + TOML_PURE_INLINE_GETTER + friend bool operator>(const key& lhs, std::string_view rhs) noexcept { return lhs.key_ > rhs; } + + /// \brief Returns true if `lhs.str() >= rhs`. + TOML_PURE_INLINE_GETTER + friend bool operator>=(const key& lhs, std::string_view rhs) noexcept { + return lhs.key_ >= rhs; + } + + /// \brief Returns true if `lhs == rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator==(std::string_view lhs, const key& rhs) noexcept { + return lhs == rhs.key_; + } + + /// \brief Returns true if `lhs != rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator!=(std::string_view lhs, const key& rhs) noexcept { + return lhs != rhs.key_; + } + + /// \brief Returns true if `lhs < rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator<(std::string_view lhs, const key& rhs) noexcept { return lhs < rhs.key_; } + + /// \brief Returns true if `lhs <= rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator<=(std::string_view lhs, const key& rhs) noexcept { + return lhs <= rhs.key_; + } + + /// \brief Returns true if `lhs > rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator>(std::string_view lhs, const key& rhs) noexcept { return lhs > rhs.key_; } + + /// \brief Returns true if `lhs >= rhs.str()`. + TOML_PURE_INLINE_GETTER + friend bool operator>=(std::string_view lhs, const key& rhs) noexcept { + return lhs >= rhs.key_; + } + + /// @} + + /// \name Iteration + /// @{ + + /// \brief A const iterator for iterating over the characters in the key. + using const_iterator = const char*; + + /// \brief A const iterator for iterating over the characters in the key. + using iterator = const_iterator; + + /// \brief Returns an iterator to the first character in the key's backing string. + TOML_PURE_INLINE_GETTER + const_iterator begin() const noexcept { return key_.data(); } + + /// \brief Returns an iterator to one-past-the-last character in the key's backing string. + TOML_PURE_INLINE_GETTER + const_iterator end() const noexcept { return key_.data() + key_.length(); } + + /// @} + + /// \brief Prints the key's underlying string out to the stream. + friend std::ostream& operator<<(std::ostream& lhs, const key& rhs) { + impl::print_to_stream(lhs, rhs.key_); + return lhs; + } + }; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::key. + template <typename T> + inline constexpr bool is_key = std::is_same_v<impl::remove_cvref<T>, toml::key>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::key, + /// or is implicitly or explicitly convertible to one. + template <typename T> + inline constexpr bool is_key_or_convertible = + is_key<T> // + || impl::is_constructible_or_convertible<toml::key, T>; } TOML_NAMESPACE_END; diff --git a/vendor/toml++/impl/make_node.hpp b/vendor/toml++/impl/make_node.hpp index 69a566a..4debabf 100644 --- a/vendor/toml++/impl/make_node.hpp +++ b/vendor/toml++/impl/make_node.hpp @@ -1,181 +1,156 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "forward_declarations.hpp" #include "header_start.hpp" /// \cond -TOML_IMPL_NAMESPACE_START -{ - template <typename T> - TOML_NODISCARD - TOML_ATTR(returns_nonnull) - auto* make_node_impl_specialized(T && val, [[maybe_unused]] value_flags flags) - { - using unwrapped_type = unwrap_node<remove_cvref<T>>; - static_assert(!std::is_same_v<unwrapped_type, node>); - static_assert(!is_node_view<unwrapped_type>); - - // arrays + tables - invoke copy/move ctor - if constexpr (is_one_of<unwrapped_type, array, table>) - { - return new unwrapped_type(static_cast<T&&>(val)); - } - - // values - else - { - using native_type = native_type_of<unwrapped_type>; - using value_type = value<native_type>; - - value_type* out; - - // copy/move ctor - if constexpr (std::is_same_v<remove_cvref<T>, value_type>) - { - out = new value_type{ static_cast<T&&>(val), flags }; - } - - // creating from raw value - else - { - static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, - "Instantiating values from wide-character strings is only " - "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); - - if constexpr (!is_losslessly_convertible_to_native<unwrapped_type>) - { - if constexpr (std::is_same_v<native_type, int64_t>) - static_assert(always_false<T>, - "Integral value initializers must be losslessly convertible to int64_t"); - else if constexpr (std::is_same_v<native_type, double>) - static_assert(always_false<T>, - "Floating-point value initializers must be losslessly convertible to double"); - else - static_assert( - always_false<T>, - "Value initializers must be losslessly convertible to one of the TOML value types"); - } - - if constexpr (is_wide_string<T>) - { +TOML_IMPL_NAMESPACE_START { + template <typename T> + TOML_NODISCARD TOML_ATTR(returns_nonnull) auto* make_node_impl_specialized( + T && val, [[maybe_unused]] value_flags flags) { + using unwrapped_type = unwrap_node<remove_cvref<T>>; + static_assert(!std::is_same_v<unwrapped_type, node>); + static_assert(!is_node_view<unwrapped_type>); + + // arrays + tables - invoke copy/move ctor + if constexpr (is_one_of<unwrapped_type, array, table>) { + return new unwrapped_type(static_cast<T&&>(val)); + } + + // values + else { + using native_type = native_type_of<unwrapped_type>; + using value_type = value<native_type>; + + value_type* out; + + // copy/move ctor + if constexpr (std::is_same_v<remove_cvref<T>, value_type>) { + out = new value_type{static_cast<T&&>(val), flags}; + } + + // creating from raw value + else { + static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, + "Instantiating values from wide-character strings is only " + "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); + + if constexpr (!is_losslessly_convertible_to_native<unwrapped_type>) { + if constexpr (std::is_same_v<native_type, int64_t>) + static_assert(always_false<T>, + "Integral value initializers must be losslessly convertible to int64_t"); + else if constexpr (std::is_same_v<native_type, double>) + static_assert( + always_false<T>, + "Floating-point value initializers must be losslessly convertible to double"); + else + static_assert( + always_false<T>, + "Value initializers must be losslessly convertible to one of the TOML value types"); + } + + if constexpr (is_wide_string<T>) { #if TOML_ENABLE_WINDOWS_COMPAT - out = new value_type{ narrow(static_cast<T&&>(val)) }; + out = new value_type{narrow(static_cast<T&&>(val))}; #else - static_assert(always_false<T>, "Evaluated unreachable branch!"); + static_assert(always_false<T>, "Evaluated unreachable branch!"); #endif - } - else - out = new value_type{ static_cast<T&&>(val) }; - - if (flags != preserve_source_value_flags) - out->flags(flags); - } - - return out; - } - } - - template <typename T> - TOML_NODISCARD - auto* make_node_impl(T && val, value_flags flags = preserve_source_value_flags) - { - using unwrapped_type = unwrap_node<remove_cvref<T>>; - if constexpr (std::is_same_v<unwrapped_type, node> || is_node_view<unwrapped_type>) - { - if constexpr (is_node_view<unwrapped_type>) - { - if (!val) - return static_cast<toml::node*>(nullptr); - } - - return static_cast<T&&>(val).visit( - [flags](auto&& concrete) { - return static_cast<toml::node*>( - make_node_impl_specialized(static_cast<decltype(concrete)&&>(concrete), flags)); - }); - } - else - return make_node_impl_specialized(static_cast<T&&>(val), flags); - } - - template <typename T> - TOML_NODISCARD - auto* make_node_impl(inserter<T> && val, value_flags flags = preserve_source_value_flags) - { - return make_node_impl(static_cast<T&&>(val.value), flags); - } - - template <typename T, bool = (is_node<T> || is_node_view<T> || is_value<T> || can_partially_represent_native<T>)> - struct inserted_type_of_ - { - using type = std::remove_pointer_t<decltype(make_node_impl(std::declval<T>()))>; - }; - - template <typename T> - struct inserted_type_of_<inserter<T>, false> - { - using type = typename inserted_type_of_<remove_cvref<T>>::type; - }; - - template <typename T> - struct inserted_type_of_<T, false> - { - using type = void; - }; - - template <typename T> - TOML_NODISCARD - node_ptr make_node(T && val, value_flags flags = preserve_source_value_flags) - { - return node_ptr{ make_node_impl(static_cast<T&&>(val), flags) }; - } - - template <typename... T> - struct emplaced_type_of_ - { - using type = void; - }; - - template <typename T> - struct emplaced_type_of_<T> - { - using type = std::conditional_t<is_one_of<T, node, node_view<node>, node_view<const node>>, - void, - typename inserted_type_of_<T>::type>; - }; - - template <typename T> - struct emplaced_type_of_<inserter<T>> - { - using type = typename emplaced_type_of_<remove_cvref<T>>::type; - }; - - template <typename... T> - using emplaced_type_of = typename emplaced_type_of_<remove_cvref<T>...>::type; + } else + out = new value_type{static_cast<T&&>(val)}; + + if (flags != preserve_source_value_flags) out->flags(flags); + } + + return out; + } + } + + template <typename T> + TOML_NODISCARD auto* make_node_impl(T && val, value_flags flags = preserve_source_value_flags) { + using unwrapped_type = unwrap_node<remove_cvref<T>>; + if constexpr (std::is_same_v<unwrapped_type, node> || is_node_view<unwrapped_type>) { + if constexpr (is_node_view<unwrapped_type>) { + if (!val) return static_cast<toml::node*>(nullptr); + } + + return static_cast<T&&>(val).visit([flags](auto&& concrete) { + return static_cast<toml::node*>( + make_node_impl_specialized(static_cast<decltype(concrete)&&>(concrete), flags)); + }); + } else + return make_node_impl_specialized(static_cast<T&&>(val), flags); + } + + template <typename T> + TOML_NODISCARD auto* make_node_impl(inserter<T> && val, + value_flags flags = preserve_source_value_flags) { + return make_node_impl(static_cast<T&&>(val.value), flags); + } + + template <typename T, bool = (is_node<T> || is_node_view<T> || is_value<T> || + can_partially_represent_native<T>)> + struct inserted_type_of_ { + using type = std::remove_pointer_t<decltype(make_node_impl(std::declval<T>()))>; + }; + + template <typename T> + struct inserted_type_of_<inserter<T>, false> { + using type = typename inserted_type_of_<remove_cvref<T>>::type; + }; + + template <typename T> + struct inserted_type_of_<T, false> { + using type = void; + }; + + template <typename T> + TOML_NODISCARD node_ptr make_node(T && val, value_flags flags = preserve_source_value_flags) { + return node_ptr{make_node_impl(static_cast<T&&>(val), flags)}; + } + + template <typename... T> + struct emplaced_type_of_ { + using type = void; + }; + + template <typename T> + struct emplaced_type_of_<T> { + using type = std::conditional_t<is_one_of<T, node, node_view<node>, node_view<const node>>, + void, typename inserted_type_of_<T>::type>; + }; + + template <typename T> + struct emplaced_type_of_<inserter<T>> { + using type = typename emplaced_type_of_<remove_cvref<T>>::type; + }; + + template <typename... T> + using emplaced_type_of = typename emplaced_type_of_<remove_cvref<T>...>::type; } TOML_IMPL_NAMESPACE_END; /// \endcond -TOML_NAMESPACE_START -{ - /// \brief Metafunction for determining which node type would be constructed - /// if an object of this type was inserted into a toml::table or toml::array. - /// - /// \detail \cpp - /// static_assert(std::is_same_v<toml::inserted_type_of<const char*>, toml::value<std::string>); - /// static_assert(std::is_same_v<toml::inserted_type_of<int>, toml::value<int64_t>); - /// static_assert(std::is_same_v<toml::inserted_type_of<float>, toml::value<double>); - /// static_assert(std::is_same_v<toml::inserted_type_of<bool>, toml::value<bool>); - /// \ecpp - /// - /// \note This will return toml::node for nodes and node_views, even though a more specific node subclass - /// would actually be inserted. There is no way around this in a compile-time metafunction. - template <typename T> - using inserted_type_of = POXY_IMPLEMENTATION_DETAIL(typename impl::inserted_type_of_<impl::remove_cvref<T>>::type); +TOML_NAMESPACE_START { + /// \brief Metafunction for determining which node type would be constructed + /// if an object of this type was inserted into a toml::table or toml::array. + /// + /// \detail \cpp + /// static_assert(std::is_same_v<toml::inserted_type_of<const char*>, toml::value<std::string>); + /// static_assert(std::is_same_v<toml::inserted_type_of<int>, toml::value<int64_t>); + /// static_assert(std::is_same_v<toml::inserted_type_of<float>, toml::value<double>); + /// static_assert(std::is_same_v<toml::inserted_type_of<bool>, toml::value<bool>); + /// \ecpp + /// + /// \note This will return toml::node for nodes and node_views, even though a more specific node + /// subclass + /// would actually be inserted. There is no way around this in a compile-time metafunction. + template <typename T> + using inserted_type_of = + POXY_IMPLEMENTATION_DETAIL(typename impl::inserted_type_of_<impl::remove_cvref<T>>::type); } TOML_NAMESPACE_END; diff --git a/vendor/toml++/impl/node.hpp b/vendor/toml++/impl/node.hpp index e4e316a..3ed1429 100644 --- a/vendor/toml++/impl/node.hpp +++ b/vendor/toml++/impl/node.hpp @@ -1,754 +1,733 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once -#include "std_utility.hpp" #include "forward_declarations.hpp" -#include "source_region.hpp" #include "header_start.hpp" +#include "source_region.hpp" +#include "std_utility.hpp" -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_INTERFACE TOML_EXPORTED_CLASS node - { - private: - /// \cond - - friend class TOML_PARSER_TYPENAME; - source_region source_{}; - - template <typename T> - TOML_NODISCARD - decltype(auto) get_value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>); - - template <typename T, typename N> - using ref_type_ = std::conditional_t< // - std::is_reference_v<T>, // - impl::copy_ref<impl::copy_cv<impl::unwrap_node<T>, std::remove_reference_t<N>>, T>, // - impl::copy_cvref<impl::unwrap_node<T>, N> // - >; - - template <typename T, typename N> - using ref_type = std::conditional_t< // - std::is_reference_v<N>, // - ref_type_<T, N>, // - ref_type_<T, std::add_lvalue_reference_t<N>> // - >; - - template <typename T, typename N> - TOML_PURE_GETTER - static ref_type<T, N&&> do_ref(N&& n) noexcept - { - using unwrapped_type = impl::unwrap_node<T>; - static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>, - "The template type argument of node::ref() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - TOML_ASSERT_ASSUME( - n.template is<unwrapped_type>() - && "template type argument provided to toml::node::ref() didn't match the node's actual type"); - - using node_ref = std::remove_volatile_t<std::remove_reference_t<N>>&; - using val_type = std::remove_volatile_t<unwrapped_type>; - using out_ref = ref_type<T, N&&>; - static_assert(std::is_reference_v<out_ref>); - - if constexpr (toml::is_value<unwrapped_type>) - return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>().get()); - else - return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>()); - } - - 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 <typename T, typename N> - using ref_cast_type_ = std::conditional_t< // - std::is_reference_v<T>, // - impl::copy_ref<impl::copy_cv<impl::wrap_node<T>, std::remove_reference_t<N>>, T>, // - impl::copy_cvref<impl::wrap_node<T>, N> // - >; - - template <typename T, typename N> - using ref_cast_type = std::conditional_t< // - std::is_reference_v<N>, // - ref_cast_type_<T, N>, // - ref_cast_type_<T, std::add_lvalue_reference_t<N>> // - >; - - template <typename T> - TOML_PURE_INLINE_GETTER - ref_cast_type<T, node&> ref_cast() & noexcept - { - using out_ref = ref_cast_type<T, node&>; - using out_type = std::remove_reference_t<out_ref>; - return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); - } - - template <typename T> - TOML_PURE_INLINE_GETTER - ref_cast_type<T, node&&> ref_cast() && noexcept - { - using out_ref = ref_cast_type<T, node&&>; - using out_type = std::remove_reference_t<out_ref>; - return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); - } - - template <typename T> - TOML_PURE_INLINE_GETTER - ref_cast_type<T, const node&> ref_cast() const& noexcept - { - using out_ref = ref_cast_type<T, const node&>; - using out_type = std::remove_reference_t<out_ref>; - return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); - } - - template <typename T> - TOML_PURE_INLINE_GETTER - ref_cast_type<T, const node&&> ref_cast() const&& noexcept - { - using out_ref = ref_cast_type<T, const node&&>; - using out_type = std::remove_reference_t<out_ref>; - return static_cast<out_ref>(*reinterpret_cast<out_type*>(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. <br> - /// \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. <br> - /// \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<double>() << "\n"; - /// std::cout << "all arrays: "sv << arr.is_homogeneous<toml::array>() << "\n"; - /// std::cout << "all integers: "sv << arr.is_homogeneous<int64_t>() << "\n"; - /// \ecpp - /// - /// \out - /// homogeneous: true - /// all floats: false - /// all arrays: false - /// all ints: true - /// \eout - /// - /// \tparam ElemType A TOML node or value type. <br> - /// \conditional_return{Left as `void`} - /// "is every element the same type?" <br> - /// \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 <typename ElemType = void> - TOML_PURE_GETTER - bool is_homogeneous() const noexcept - { - using type = impl::remove_cvref<impl::unwrap_node<ElemType>>; - static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>, - "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<type>); - } - - /// \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 <typename T> - TOML_PURE_INLINE_GETTER - bool is() const noexcept - { - using type = impl::remove_cvref<impl::unwrap_node<T>>; - static_assert(toml::is_value<type> || toml::is_container<type>, - "The template type argument of node::is() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - if constexpr (std::is_same_v<type, table>) - return is_table(); - else if constexpr (std::is_same_v<type, array>) - return is_array(); - else if constexpr (std::is_same_v<type, std::string>) - return is_string(); - else if constexpr (std::is_same_v<type, int64_t>) - return is_integer(); - else if constexpr (std::is_same_v<type, double>) - return is_floating_point(); - else if constexpr (std::is_same_v<type, bool>) - return is_boolean(); - else if constexpr (std::is_same_v<type, date>) - return is_date(); - else if constexpr (std::is_same_v<type, time>) - return is_time(); - else if constexpr (std::is_same_v<type, date_time>) - 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<std::string>, if it is one. - TOML_PURE_GETTER - virtual toml::value<std::string>* as_string() noexcept = 0; - - /// \brief Returns a pointer to the node as a toml::value<int64_t>, if it is one. - TOML_PURE_GETTER - virtual toml::value<int64_t>* as_integer() noexcept = 0; - - /// \brief Returns a pointer to the node as a toml::value<double>, if it is one. - TOML_PURE_GETTER - virtual toml::value<double>* as_floating_point() noexcept = 0; - - /// \brief Returns a pointer to the node as a toml::value<bool>, if it is one. - TOML_PURE_GETTER - virtual toml::value<bool>* as_boolean() noexcept = 0; - - /// \brief Returns a pointer to the node as a toml::value<toml::date>, if it is one. - TOML_PURE_GETTER - virtual toml::value<date>* as_date() noexcept = 0; - - /// \brief Returns a pointer to the node as a toml::value<toml::time>, if it is one. - TOML_PURE_GETTER - virtual toml::value<time>* as_time() noexcept = 0; - - /// \brief Returns a pointer to the node as a toml::value<toml::date_time>, if it is one. - TOML_PURE_GETTER - virtual toml::value<date_time>* as_date_time() noexcept = 0; - - /// \brief Returns a const-qualified pointer to the node as a toml::table, if it is one. - TOML_PURE_GETTER - virtual const table* as_table() const noexcept = 0; - - /// \brief Returns a const-qualified pointer to the node as a toml::array, if it is one. - TOML_PURE_GETTER - virtual const array* as_array() const noexcept = 0; - - /// \brief Returns a const-qualified pointer to the node as a toml::value<std::string>, if it is one. - TOML_PURE_GETTER - virtual const toml::value<std::string>* as_string() const noexcept = 0; - - /// \brief Returns a const-qualified pointer to the node as a toml::value<int64_t>, if it is one. - TOML_PURE_GETTER - virtual const toml::value<int64_t>* as_integer() const noexcept = 0; - - /// \brief Returns a const-qualified pointer to the node as a toml::value<double>, if it is one. - TOML_PURE_GETTER - virtual const toml::value<double>* as_floating_point() const noexcept = 0; - - /// \brief Returns a const-qualified pointer to the node as a toml::value<bool>, if it is one. - TOML_PURE_GETTER - virtual const toml::value<bool>* as_boolean() const noexcept = 0; - - /// \brief Returns a const-qualified pointer to the node as a toml::value<toml::date>, if it is one. - TOML_PURE_GETTER - virtual const toml::value<date>* as_date() const noexcept = 0; - - /// \brief Returns a const-qualified pointer to the node as a toml::value<toml::time>, if it is one. - TOML_PURE_GETTER - virtual const toml::value<time>* as_time() const noexcept = 0; - - /// \brief Returns a const-qualified pointer to the node as a toml::value<toml::date_time>, if it is one. - TOML_PURE_GETTER - virtual const toml::value<date_time>* as_date_time() const noexcept = 0; - - /// \brief Gets a pointer to the node as a more specific node type. - /// - /// \details \cpp - /// - /// toml::value<int64_t>* int_value = node->as<int64_t>(); - /// toml::table* tbl = node->as<toml::table>(); - /// if (int_value) - /// std::cout << "Node is a value<int64_t>\n"; - /// else if (tbl) - /// std::cout << "Node is a table\n"; - /// - /// // fully-qualified value node types also work (useful for template code): - /// toml::value<int64_t>* int_value2 = node->as<toml::value<int64_t>>(); - /// if (int_value2) - /// std::cout << "Node is a value<int64_t>\n"; - /// \ecpp - /// - /// \tparam T The node type or TOML value type to cast to. - /// - /// \returns A pointer to the node as the given type, or nullptr if it was a different type. - template <typename T> - TOML_PURE_INLINE_GETTER - impl::wrap_node<T>* as() noexcept - { - using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>; - static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>, - "The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - if constexpr (std::is_same_v<unwrapped_type, table>) - return as_table(); - else if constexpr (std::is_same_v<unwrapped_type, array>) - return as_array(); - else if constexpr (std::is_same_v<unwrapped_type, std::string>) - return as_string(); - else if constexpr (std::is_same_v<unwrapped_type, int64_t>) - return as_integer(); - else if constexpr (std::is_same_v<unwrapped_type, double>) - return as_floating_point(); - else if constexpr (std::is_same_v<unwrapped_type, bool>) - return as_boolean(); - else if constexpr (std::is_same_v<unwrapped_type, date>) - return as_date(); - else if constexpr (std::is_same_v<unwrapped_type, time>) - return as_time(); - else if constexpr (std::is_same_v<unwrapped_type, date_time>) - return as_date_time(); - } - - /// \brief Gets a pointer to the node as a more specific node type (const overload). - template <typename T> - TOML_PURE_INLINE_GETTER - const impl::wrap_node<T>* as() const noexcept - { - using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>; - static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>, - "The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - if constexpr (std::is_same_v<unwrapped_type, table>) - return as_table(); - else if constexpr (std::is_same_v<unwrapped_type, array>) - return as_array(); - else if constexpr (std::is_same_v<unwrapped_type, std::string>) - return as_string(); - else if constexpr (std::is_same_v<unwrapped_type, int64_t>) - return as_integer(); - else if constexpr (std::is_same_v<unwrapped_type, double>) - return as_floating_point(); - else if constexpr (std::is_same_v<unwrapped_type, bool>) - return as_boolean(); - else if constexpr (std::is_same_v<unwrapped_type, date>) - return as_date(); - else if constexpr (std::is_same_v<unwrapped_type, time>) - return as_time(); - else if constexpr (std::is_same_v<unwrapped_type, date_time>) - return as_date_time(); - } - - /// @} - - /// \name Value retrieval - /// @{ - - /// \brief Gets the value contained by this node. - /// - /// \detail This function has 'exact' retrieval semantics; the only return value types allowed are the - /// TOML native value types, or types that can losslessly represent a native value type (e.g. - /// std::wstring on Windows). - /// - /// \tparam T One of the native TOML value types, or a type capable of losslessly representing one. - /// - /// \returns The underlying value if the node was a value of the - /// matching type (or losslessly convertible to it), or an empty optional. - /// - /// \see node::value() - template <typename T> - TOML_NODISCARD - optional<T> value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>); - - /// \brief Gets the value contained by this node. - /// - /// \detail This function has 'permissive' retrieval semantics; some value types are allowed - /// to convert to others (e.g. retrieving a boolean as an integer), and the specified return value - /// type can be any type where a reasonable conversion from a native TOML value exists - /// (e.g. std::wstring on Windows). If the source value cannot be represented by - /// the destination type, an empty optional is returned. - /// - /// \godbolt{zzG81K} - /// - /// \cpp - /// auto tbl = toml::parse(R"( - /// int = -10 - /// flt = 25.0 - /// pi = 3.14159 - /// bool = false - /// huge = 9223372036854775807 - /// str = "foo" - /// )"sv); - /// - /// const auto print_value_with_typename = - /// [&](std::string_view key, std::string_view type_name, auto* dummy) - /// { - /// std::cout << "- " << std::setw(18) << std::left << type_name; - /// using type = std::remove_pointer_t<decltype(dummy)>; - /// if (auto val = tbl.get(key)->value<type>(); val) - /// std::cout << *val << "\n"; - /// else - /// std::cout << "n/a\n"; - /// }; - /// - /// #define print_value(key, T) print_value_with_typename(key, #T, (T*)nullptr) - /// - /// for (auto key : { "int", "flt", "pi", "bool", "huge", "str" }) - /// { - /// std::cout << tbl[key].type() << " value '" << key << "' as:\n"; - /// print_value(key, bool); - /// print_value(key, int); - /// print_value(key, unsigned int); - /// print_value(key, long long); - /// print_value(key, float); - /// print_value(key, double); - /// print_value(key, std::string); - /// print_value(key, std::string_view); - /// print_value(key, const char*); - /// std::cout << "\n"; - /// } - /// \ecpp - /// - /// \out - /// integer value 'int' as: - /// - bool true - /// - int -10 - /// - unsigned int n/a - /// - long long -10 - /// - float -10 - /// - double -10 - /// - std::string n/a - /// - std::string_view n/a - /// - const char* n/a - /// - /// floating-point value 'flt' as: - /// - bool n/a - /// - int 25 - /// - unsigned int 25 - /// - long long 25 - /// - float 25 - /// - double 25 - /// - std::string n/a - /// - std::string_view n/a - /// - const char* n/a - /// - /// floating-point value 'pi' as: - /// - bool n/a - /// - int n/a - /// - unsigned int n/a - /// - long long n/a - /// - float 3.14159 - /// - double 3.14159 - /// - std::string n/a - /// - std::string_view n/a - /// - const char* n/a - /// - /// boolean value 'bool' as: - /// - bool false - /// - int 0 - /// - unsigned int 0 - /// - long long 0 - /// - float n/a - /// - double n/a - /// - std::string n/a - /// - std::string_view n/a - /// - const char* n/a - /// - /// integer value 'huge' as: - /// - bool true - /// - int n/a - /// - unsigned int n/a - /// - long long 9223372036854775807 - /// - float n/a - /// - double n/a - /// - std::string n/a - /// - std::string_view n/a - /// - const char* n/a - /// - /// string value 'str' as: - /// - bool n/a - /// - int n/a - /// - unsigned int n/a - /// - long long n/a - /// - float n/a - /// - double n/a - /// - std::string foo - /// - std::string_view foo - /// - const char* foo - /// \eout - /// - /// \tparam T One of the native TOML value types, or a type capable of converting to one. - /// - /// \returns The underlying value if the node was a value of the matching type (or convertible to it) - /// and within the range of the output type, or an empty optional. - /// - /// \note If you want strict value retrieval semantics that do not allow for any type conversions, - /// use node::value_exact() instead. - /// - /// \see node::value_exact() - template <typename T> - TOML_NODISCARD - optional<T> value() const noexcept(impl::value_retrieval_is_nothrow<T>); - - /// \brief Gets the raw value contained by this node, or a default. - /// - /// \tparam T Default value type. Must be one of the native TOML value types, - /// or convertible to it. - /// \param default_value The default value to return if the node wasn't a value, wasn't the - /// correct type, or no conversion was possible. - /// - /// \returns The underlying value if the node was a value of the matching type (or convertible to it) - /// and within the range of the output type, or the provided default. - /// - /// \note This function has the same permissive retrieval semantics as node::value(). If you want strict - /// value retrieval semantics that do not allow for any type conversions, use node::value_exact() - /// instead. - /// - /// \see - /// - node::value() - /// - node::value_exact() - template <typename T> - TOML_NODISCARD - auto value_or(T&& default_value) const noexcept(impl::value_retrieval_is_nothrow<T>); - - /// \brief Gets a raw reference to a node's underlying data. - /// - /// \warning This function is dangerous if used carelessly and **WILL** break your code if the - /// chosen value type doesn't match the node's actual type. In debug builds an assertion - /// will fire when invalid accesses are attempted: \cpp - /// - /// auto tbl = toml::parse(R"( - /// min = 32 - /// max = 45 - /// )"sv); - /// - /// int64_t& min_ref = tbl.at("min").ref<int64_t>(); // matching type - /// double& max_ref = tbl.at("max").ref<double>(); // mismatched type, hits assert() - /// \ecpp - /// - /// \note Specifying explicit ref qualifiers acts as an explicit ref-category cast, - /// whereas specifying explicit cv-ref qualifiers merges them with whatever - /// the cv qualification of the node is (to ensure cv-correctness is propagated), e.g.: - /// | node | T | return type | - /// |-------------|------------------------|------------------------------| - /// | node& | std::string | std::string& | - /// | node& | std::string&& | std::string&& | - /// | const node& | volatile std::string | const volatile std::string& | - /// | const node& | volatile std::string&& | const volatile std::string&& | - /// - /// \tparam T toml::table, toml::array, or one of the TOML value types. - /// - /// \returns A reference to the underlying data. - template <typename T> - TOML_PURE_GETTER - decltype(auto) ref() & noexcept - { - return do_ref<T>(*this); - } - - /// \brief Gets a raw reference to a node's underlying data (rvalue overload). - template <typename T> - TOML_PURE_GETTER - decltype(auto) ref() && noexcept - { - return do_ref<T>(std::move(*this)); - } - - /// \brief Gets a raw reference to a node's underlying data (const lvalue overload). - template <typename T> - TOML_PURE_GETTER - decltype(auto) ref() const& noexcept - { - return do_ref<T>(*this); - } - - /// \brief Gets a raw reference to a node's underlying data (const rvalue overload). - template <typename T> - TOML_PURE_GETTER - decltype(auto) ref() const&& noexcept - { - return do_ref<T>(std::move(*this)); - } - - /// @} - - /// \name Metadata - /// @{ - - /// \brief Returns the source region responsible for generating this node during parsing. - TOML_PURE_INLINE_GETTER - const source_region& source() const noexcept - { - return source_; - } - - /// @} - - private: - /// \cond - - template <typename Func, typename Node, typename T> - static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<T, Node>>; - - template <typename Func, typename Node, typename T> - static constexpr bool can_visit_nothrow = std::is_nothrow_invocable_v<Func, ref_cast_type<T, Node>>; - - template <typename Func, typename Node> - static constexpr bool can_visit_any = can_visit<Func, Node, table> // - || can_visit<Func, Node, array> // - || can_visit<Func, Node, std::string> // - || can_visit<Func, Node, int64_t> // - || can_visit<Func, Node, double> // - || can_visit<Func, Node, bool> // - || can_visit<Func, Node, date> // - || can_visit<Func, Node, time> // - || can_visit<Func, Node, date_time>; - - // clang-format off +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_INTERFACE TOML_EXPORTED_CLASS node { + private: + /// \cond + + friend class TOML_PARSER_TYPENAME; + source_region source_{}; + + template <typename T> + TOML_NODISCARD decltype(auto) get_value_exact() const + noexcept(impl::value_retrieval_is_nothrow<T>); + + template <typename T, typename N> + using ref_type_ = std::conditional_t< // + std::is_reference_v<T>, // + impl::copy_ref<impl::copy_cv<impl::unwrap_node<T>, std::remove_reference_t<N>>, T>, // + impl::copy_cvref<impl::unwrap_node<T>, N> // + >; + + template <typename T, typename N> + using ref_type = std::conditional_t< // + std::is_reference_v<N>, // + ref_type_<T, N>, // + ref_type_<T, std::add_lvalue_reference_t<N>> // + >; + + template <typename T, typename N> + TOML_PURE_GETTER static ref_type<T, N&&> do_ref(N&& n) noexcept { + using unwrapped_type = impl::unwrap_node<T>; + static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>, + "The template type argument of node::ref() must be one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + TOML_ASSERT_ASSUME(n.template is<unwrapped_type>() && + "template type argument provided to toml::node::ref() didn't match the " + "node's actual type"); + + using node_ref = std::remove_volatile_t<std::remove_reference_t<N>>&; + using val_type = std::remove_volatile_t<unwrapped_type>; + using out_ref = ref_type<T, N&&>; + static_assert(std::is_reference_v<out_ref>); + + if constexpr (toml::is_value<unwrapped_type>) + return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>().get()); + else + return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>()); + } + + 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 <typename T, typename N> + using ref_cast_type_ = std::conditional_t< // + std::is_reference_v<T>, // + impl::copy_ref<impl::copy_cv<impl::wrap_node<T>, std::remove_reference_t<N>>, T>, // + impl::copy_cvref<impl::wrap_node<T>, N> // + >; + + template <typename T, typename N> + using ref_cast_type = std::conditional_t< // + std::is_reference_v<N>, // + ref_cast_type_<T, N>, // + ref_cast_type_<T, std::add_lvalue_reference_t<N>> // + >; + + template <typename T> + TOML_PURE_INLINE_GETTER ref_cast_type<T, node&> ref_cast() & noexcept { + using out_ref = ref_cast_type<T, node&>; + using out_type = std::remove_reference_t<out_ref>; + return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); + } + + template <typename T> + TOML_PURE_INLINE_GETTER ref_cast_type<T, node&&> ref_cast() && noexcept { + using out_ref = ref_cast_type<T, node&&>; + using out_type = std::remove_reference_t<out_ref>; + return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); + } + + template <typename T> + TOML_PURE_INLINE_GETTER ref_cast_type<T, const node&> ref_cast() const& noexcept { + using out_ref = ref_cast_type<T, const node&>; + using out_type = std::remove_reference_t<out_ref>; + return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); + } + + template <typename T> + TOML_PURE_INLINE_GETTER ref_cast_type<T, const node&&> ref_cast() const&& noexcept { + using out_ref = ref_cast_type<T, const node&&>; + using out_type = std::remove_reference_t<out_ref>; + return static_cast<out_ref>(*reinterpret_cast<out_type*>(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. <br> + /// \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. <br> + /// \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<double>() << "\n"; + /// std::cout << "all arrays: "sv << arr.is_homogeneous<toml::array>() << "\n"; + /// std::cout << "all integers: "sv << arr.is_homogeneous<int64_t>() << "\n"; + /// \ecpp + /// + /// \out + /// homogeneous: true + /// all floats: false + /// all arrays: false + /// all ints: true + /// \eout + /// + /// \tparam ElemType A TOML node or value type. <br> + /// \conditional_return{Left as `void`} + /// "is every element the same type?" <br> + /// \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 <typename ElemType = void> + TOML_PURE_GETTER bool is_homogeneous() const noexcept { + using type = impl::remove_cvref<impl::unwrap_node<ElemType>>; + static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>, + "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<type>); + } + + /// \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 <typename T> + TOML_PURE_INLINE_GETTER bool is() const noexcept { + using type = impl::remove_cvref<impl::unwrap_node<T>>; + static_assert(toml::is_value<type> || toml::is_container<type>, + "The template type argument of node::is() must be one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + if constexpr (std::is_same_v<type, table>) + return is_table(); + else if constexpr (std::is_same_v<type, array>) + return is_array(); + else if constexpr (std::is_same_v<type, std::string>) + return is_string(); + else if constexpr (std::is_same_v<type, int64_t>) + return is_integer(); + else if constexpr (std::is_same_v<type, double>) + return is_floating_point(); + else if constexpr (std::is_same_v<type, bool>) + return is_boolean(); + else if constexpr (std::is_same_v<type, date>) + return is_date(); + else if constexpr (std::is_same_v<type, time>) + return is_time(); + else if constexpr (std::is_same_v<type, date_time>) + 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<std::string>, if it is one. + TOML_PURE_GETTER + virtual toml::value<std::string>* as_string() noexcept = 0; + + /// \brief Returns a pointer to the node as a toml::value<int64_t>, if it is one. + TOML_PURE_GETTER + virtual toml::value<int64_t>* as_integer() noexcept = 0; + + /// \brief Returns a pointer to the node as a toml::value<double>, if it is one. + TOML_PURE_GETTER + virtual toml::value<double>* as_floating_point() noexcept = 0; + + /// \brief Returns a pointer to the node as a toml::value<bool>, if it is one. + TOML_PURE_GETTER + virtual toml::value<bool>* as_boolean() noexcept = 0; + + /// \brief Returns a pointer to the node as a toml::value<toml::date>, if it is one. + TOML_PURE_GETTER + virtual toml::value<date>* as_date() noexcept = 0; + + /// \brief Returns a pointer to the node as a toml::value<toml::time>, if it is one. + TOML_PURE_GETTER + virtual toml::value<time>* as_time() noexcept = 0; + + /// \brief Returns a pointer to the node as a toml::value<toml::date_time>, if it is one. + TOML_PURE_GETTER + virtual toml::value<date_time>* as_date_time() noexcept = 0; + + /// \brief Returns a const-qualified pointer to the node as a toml::table, if it is one. + TOML_PURE_GETTER + virtual const table* as_table() const noexcept = 0; + + /// \brief Returns a const-qualified pointer to the node as a toml::array, if it is one. + TOML_PURE_GETTER + virtual const array* as_array() const noexcept = 0; + + /// \brief Returns a const-qualified pointer to the node as a toml::value<std::string>, if it + /// is one. + TOML_PURE_GETTER + virtual const toml::value<std::string>* as_string() const noexcept = 0; + + /// \brief Returns a const-qualified pointer to the node as a toml::value<int64_t>, if it is + /// one. + TOML_PURE_GETTER + virtual const toml::value<int64_t>* as_integer() const noexcept = 0; + + /// \brief Returns a const-qualified pointer to the node as a toml::value<double>, if it is + /// one. + TOML_PURE_GETTER + virtual const toml::value<double>* as_floating_point() const noexcept = 0; + + /// \brief Returns a const-qualified pointer to the node as a toml::value<bool>, if it is one. + TOML_PURE_GETTER + virtual const toml::value<bool>* as_boolean() const noexcept = 0; + + /// \brief Returns a const-qualified pointer to the node as a toml::value<toml::date>, if it is + /// one. + TOML_PURE_GETTER + virtual const toml::value<date>* as_date() const noexcept = 0; + + /// \brief Returns a const-qualified pointer to the node as a toml::value<toml::time>, if it is + /// one. + TOML_PURE_GETTER + virtual const toml::value<time>* as_time() const noexcept = 0; + + /// \brief Returns a const-qualified pointer to the node as a toml::value<toml::date_time>, if + /// it is one. + TOML_PURE_GETTER + virtual const toml::value<date_time>* as_date_time() const noexcept = 0; + + /// \brief Gets a pointer to the node as a more specific node type. + /// + /// \details \cpp + /// + /// toml::value<int64_t>* int_value = node->as<int64_t>(); + /// toml::table* tbl = node->as<toml::table>(); + /// if (int_value) + /// std::cout << "Node is a value<int64_t>\n"; + /// else if (tbl) + /// std::cout << "Node is a table\n"; + /// + /// // fully-qualified value node types also work (useful for template code): + /// toml::value<int64_t>* int_value2 = node->as<toml::value<int64_t>>(); + /// if (int_value2) + /// std::cout << "Node is a value<int64_t>\n"; + /// \ecpp + /// + /// \tparam T The node type or TOML value type to cast to. + /// + /// \returns A pointer to the node as the given type, or nullptr if it was a different type. + template <typename T> + TOML_PURE_INLINE_GETTER impl::wrap_node<T>* as() noexcept { + using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>; + static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>, + "The template type argument of node::as() must be one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + if constexpr (std::is_same_v<unwrapped_type, table>) + return as_table(); + else if constexpr (std::is_same_v<unwrapped_type, array>) + return as_array(); + else if constexpr (std::is_same_v<unwrapped_type, std::string>) + return as_string(); + else if constexpr (std::is_same_v<unwrapped_type, int64_t>) + return as_integer(); + else if constexpr (std::is_same_v<unwrapped_type, double>) + return as_floating_point(); + else if constexpr (std::is_same_v<unwrapped_type, bool>) + return as_boolean(); + else if constexpr (std::is_same_v<unwrapped_type, date>) + return as_date(); + else if constexpr (std::is_same_v<unwrapped_type, time>) + return as_time(); + else if constexpr (std::is_same_v<unwrapped_type, date_time>) + return as_date_time(); + } + + /// \brief Gets a pointer to the node as a more specific node type (const overload). + template <typename T> + TOML_PURE_INLINE_GETTER const impl::wrap_node<T>* as() const noexcept { + using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>; + static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>, + "The template type argument of node::as() must be one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + if constexpr (std::is_same_v<unwrapped_type, table>) + return as_table(); + else if constexpr (std::is_same_v<unwrapped_type, array>) + return as_array(); + else if constexpr (std::is_same_v<unwrapped_type, std::string>) + return as_string(); + else if constexpr (std::is_same_v<unwrapped_type, int64_t>) + return as_integer(); + else if constexpr (std::is_same_v<unwrapped_type, double>) + return as_floating_point(); + else if constexpr (std::is_same_v<unwrapped_type, bool>) + return as_boolean(); + else if constexpr (std::is_same_v<unwrapped_type, date>) + return as_date(); + else if constexpr (std::is_same_v<unwrapped_type, time>) + return as_time(); + else if constexpr (std::is_same_v<unwrapped_type, date_time>) + return as_date_time(); + } + + /// @} + + /// \name Value retrieval + /// @{ + + /// \brief Gets the value contained by this node. + /// + /// \detail This function has 'exact' retrieval semantics; the only return value types allowed + /// are the TOML native value types, or types that can losslessly represent a native value type + /// (e.g. std::wstring on Windows). + /// + /// \tparam T One of the native TOML value types, or a type capable of losslessly representing + /// one. + /// + /// \returns The underlying value if the node was a value of the + /// matching type (or losslessly convertible to it), or an empty optional. + /// + /// \see node::value() + template <typename T> + TOML_NODISCARD optional<T> value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>); + + /// \brief Gets the value contained by this node. + /// + /// \detail This function has 'permissive' retrieval semantics; some value types are allowed + /// to convert to others (e.g. retrieving a boolean as an integer), and the specified return + /// value type can be any type where a reasonable conversion from a native TOML value exists + /// (e.g. std::wstring on Windows). If the source value cannot be represented by + /// the destination type, an empty optional is returned. + /// + /// \godbolt{zzG81K} + /// + /// \cpp + /// auto tbl = toml::parse(R"( + /// int = -10 + /// flt = 25.0 + /// pi = 3.14159 + /// bool = false + /// huge = 9223372036854775807 + /// str = "foo" + /// )"sv); + /// + /// const auto print_value_with_typename = + /// [&](std::string_view key, std::string_view type_name, auto* dummy) + /// { + /// std::cout << "- " << std::setw(18) << std::left << type_name; + /// using type = std::remove_pointer_t<decltype(dummy)>; + /// if (auto val = tbl.get(key)->value<type>(); val) + /// std::cout << *val << "\n"; + /// else + /// std::cout << "n/a\n"; + /// }; + /// + /// #define print_value(key, T) print_value_with_typename(key, #T, (T*)nullptr) + /// + /// for (auto key : { "int", "flt", "pi", "bool", "huge", "str" }) + /// { + /// std::cout << tbl[key].type() << " value '" << key << "' as:\n"; + /// print_value(key, bool); + /// print_value(key, int); + /// print_value(key, unsigned int); + /// print_value(key, long long); + /// print_value(key, float); + /// print_value(key, double); + /// print_value(key, std::string); + /// print_value(key, std::string_view); + /// print_value(key, const char*); + /// std::cout << "\n"; + /// } + /// \ecpp + /// + /// \out + /// integer value 'int' as: + /// - bool true + /// - int -10 + /// - unsigned int n/a + /// - long long -10 + /// - float -10 + /// - double -10 + /// - std::string n/a + /// - std::string_view n/a + /// - const char* n/a + /// + /// floating-point value 'flt' as: + /// - bool n/a + /// - int 25 + /// - unsigned int 25 + /// - long long 25 + /// - float 25 + /// - double 25 + /// - std::string n/a + /// - std::string_view n/a + /// - const char* n/a + /// + /// floating-point value 'pi' as: + /// - bool n/a + /// - int n/a + /// - unsigned int n/a + /// - long long n/a + /// - float 3.14159 + /// - double 3.14159 + /// - std::string n/a + /// - std::string_view n/a + /// - const char* n/a + /// + /// boolean value 'bool' as: + /// - bool false + /// - int 0 + /// - unsigned int 0 + /// - long long 0 + /// - float n/a + /// - double n/a + /// - std::string n/a + /// - std::string_view n/a + /// - const char* n/a + /// + /// integer value 'huge' as: + /// - bool true + /// - int n/a + /// - unsigned int n/a + /// - long long 9223372036854775807 + /// - float n/a + /// - double n/a + /// - std::string n/a + /// - std::string_view n/a + /// - const char* n/a + /// + /// string value 'str' as: + /// - bool n/a + /// - int n/a + /// - unsigned int n/a + /// - long long n/a + /// - float n/a + /// - double n/a + /// - std::string foo + /// - std::string_view foo + /// - const char* foo + /// \eout + /// + /// \tparam T One of the native TOML value types, or a type capable of converting to one. + /// + /// \returns The underlying value if the node was a value of the matching type (or convertible + /// to it) and within the range of the output type, or an empty optional. + /// + /// \note If you want strict value retrieval semantics that do not allow for any type + /// conversions, use node::value_exact() instead. + /// + /// \see node::value_exact() + template <typename T> + TOML_NODISCARD optional<T> value() const noexcept(impl::value_retrieval_is_nothrow<T>); + + /// \brief Gets the raw value contained by this node, or a default. + /// + /// \tparam T Default value type. Must be one of the native TOML value types, + /// or convertible to it. + /// \param default_value The default value to return if the node wasn't a value, wasn't the + /// correct type, or no conversion was possible. + /// + /// \returns The underlying value if the node was a value of the matching type (or convertible + /// to it) and within the range of the output type, or the provided default. + /// + /// \note This function has the same permissive retrieval semantics as node::value(). If you + /// want strict value retrieval semantics that do not allow for any type conversions, use + /// node::value_exact() instead. + /// + /// \see + /// - node::value() + /// - node::value_exact() + template <typename T> + TOML_NODISCARD auto value_or(T&& default_value) const + noexcept(impl::value_retrieval_is_nothrow<T>); + + /// \brief Gets a raw reference to a node's underlying data. + /// + /// \warning This function is dangerous if used carelessly and **WILL** break your code if the + /// chosen value type doesn't match the node's actual type. In debug builds an assertion + /// will fire when invalid accesses are attempted: \cpp + /// + /// auto tbl = toml::parse(R"( + /// min = 32 + /// max = 45 + /// )"sv); + /// + /// int64_t& min_ref = tbl.at("min").ref<int64_t>(); // matching type + /// double& max_ref = tbl.at("max").ref<double>(); // mismatched type, hits assert() + /// \ecpp + /// + /// \note Specifying explicit ref qualifiers acts as an explicit ref-category cast, + /// whereas specifying explicit cv-ref qualifiers merges them with whatever + /// the cv qualification of the node is (to ensure cv-correctness is propagated), e.g.: + /// | node | T | return type | + /// |-------------|------------------------|------------------------------| + /// | node& | std::string | std::string& | + /// | node& | std::string&& | std::string&& | + /// | const node& | volatile std::string | const volatile std::string& | + /// | const node& | volatile std::string&& | const volatile std::string&& | + /// + /// \tparam T toml::table, toml::array, or one of the TOML value types. + /// + /// \returns A reference to the underlying data. + template <typename T> + TOML_PURE_GETTER decltype(auto) ref() & noexcept { + return do_ref<T>(*this); + } + + /// \brief Gets a raw reference to a node's underlying data (rvalue overload). + template <typename T> + TOML_PURE_GETTER decltype(auto) ref() && noexcept { + return do_ref<T>(std::move(*this)); + } + + /// \brief Gets a raw reference to a node's underlying data (const lvalue overload). + template <typename T> + TOML_PURE_GETTER decltype(auto) ref() const& noexcept { + return do_ref<T>(*this); + } + + /// \brief Gets a raw reference to a node's underlying data (const rvalue overload). + template <typename T> + TOML_PURE_GETTER decltype(auto) ref() const&& noexcept { + return do_ref<T>(std::move(*this)); + } + + /// @} + + /// \name Metadata + /// @{ + + /// \brief Returns the source region responsible for generating this node during parsing. + TOML_PURE_INLINE_GETTER + const source_region& source() const noexcept { return source_; } + + /// @} + + private: + /// \cond + + template <typename Func, typename Node, typename T> + static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<T, Node>>; + + template <typename Func, typename Node, typename T> + static constexpr bool can_visit_nothrow = + std::is_nothrow_invocable_v<Func, ref_cast_type<T, Node>>; + + template <typename Func, typename Node> + static constexpr bool can_visit_any = can_visit<Func, Node, table> // + || can_visit<Func, Node, array> // + || can_visit<Func, Node, std::string> // + || can_visit<Func, Node, int64_t> // + || can_visit<Func, Node, double> // + || can_visit<Func, Node, bool> // + || can_visit<Func, Node, date> // + || can_visit<Func, Node, time> // + || can_visit<Func, Node, date_time>; + + // clang-format off template <typename Func, typename Node> static constexpr bool can_visit_all = can_visit<Func, Node, table> // @@ -775,86 +754,87 @@ TOML_NAMESPACE_START && visit_is_nothrow_one<Func, Node, time> // && visit_is_nothrow_one<Func, Node, date_time>; - // clang-format on - - template <typename Func, typename Node, typename T, bool = can_visit<Func, Node, T>> - struct visit_return_type_ - { - using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<T, Node>>())); - }; - template <typename Func, typename Node, typename T> - struct visit_return_type_<Func, Node, T, false> - { - using type = void; - }; - - template <typename Func, typename Node, typename T> - using visit_return_type = typename visit_return_type_<Func, Node, T>::type; - - template <typename A, typename B> - using nonvoid = std::conditional_t<std::is_void_v<A>, B, A>; - - template <typename Func, typename Node> - static decltype(auto) do_visit(Func&& visitor, Node&& n) noexcept(visit_is_nothrow<Func&&, Node&&>) - { - static_assert(can_visit_any<Func&&, Node&&>, - "TOML node visitors must be invocable for at least one of the toml::node " - "specializations:" TOML_SA_NODE_TYPE_LIST); - - switch (n.type()) - { - case node_type::table: - if constexpr (can_visit<Func&&, Node&&, table>) - return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<table>()); - break; - - case node_type::array: - if constexpr (can_visit<Func&&, Node&&, array>) - return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<array>()); - break; - - case node_type::string: - if constexpr (can_visit<Func&&, Node&&, std::string>) - return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<std::string>()); - break; - - case node_type::integer: - if constexpr (can_visit<Func&&, Node&&, int64_t>) - return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<int64_t>()); - break; - - case node_type::floating_point: - if constexpr (can_visit<Func&&, Node&&, double>) - return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<double>()); - break; - - case node_type::boolean: - if constexpr (can_visit<Func&&, Node&&, bool>) - return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<bool>()); - break; - - case node_type::date: - if constexpr (can_visit<Func&&, Node&&, date>) - return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<date>()); - break; - - case node_type::time: - if constexpr (can_visit<Func&&, Node&&, time>) - return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<time>()); - break; - - case node_type::date_time: - if constexpr (can_visit<Func&&, Node&&, date_time>) - return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<date_time>()); - break; - - case node_type::none: TOML_UNREACHABLE; - default: TOML_UNREACHABLE; - } - - if constexpr (!can_visit_all<Func&&, Node&&>) - { - // clang-format off + // clang-format on + + template <typename Func, typename Node, typename T, bool = can_visit<Func, Node, T>> + struct visit_return_type_ { + using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<T, Node>>())); + }; + template <typename Func, typename Node, typename T> + struct visit_return_type_<Func, Node, T, false> { + using type = void; + }; + + template <typename Func, typename Node, typename T> + using visit_return_type = typename visit_return_type_<Func, Node, T>::type; + + template <typename A, typename B> + using nonvoid = std::conditional_t<std::is_void_v<A>, B, A>; + + template <typename Func, typename Node> + static decltype(auto) do_visit(Func&& visitor, + Node&& n) noexcept(visit_is_nothrow<Func&&, Node&&>) { + static_assert(can_visit_any<Func&&, Node&&>, + "TOML node visitors must be invocable for at least one of the toml::node " + "specializations:" TOML_SA_NODE_TYPE_LIST); + + switch (n.type()) { + case node_type::table: + if constexpr (can_visit<Func&&, Node&&, table>) + return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<table>()); + break; + + case node_type::array: + if constexpr (can_visit<Func&&, Node&&, array>) + return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<array>()); + break; + + case node_type::string: + if constexpr (can_visit<Func&&, Node&&, std::string>) + return static_cast<Func&&>(visitor)( + static_cast<Node&&>(n).template ref_cast<std::string>()); + break; + + case node_type::integer: + if constexpr (can_visit<Func&&, Node&&, int64_t>) + return static_cast<Func&&>(visitor)( + static_cast<Node&&>(n).template ref_cast<int64_t>()); + break; + + case node_type::floating_point: + if constexpr (can_visit<Func&&, Node&&, double>) + return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<double>()); + break; + + case node_type::boolean: + if constexpr (can_visit<Func&&, Node&&, bool>) + return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<bool>()); + break; + + case node_type::date: + if constexpr (can_visit<Func&&, Node&&, date>) + return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<date>()); + break; + + case node_type::time: + if constexpr (can_visit<Func&&, Node&&, time>) + return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<time>()); + break; + + case node_type::date_time: + if constexpr (can_visit<Func&&, Node&&, date_time>) + return static_cast<Func&&>(visitor)( + static_cast<Node&&>(n).template ref_cast<date_time>()); + break; + + case node_type::none: + TOML_UNREACHABLE; + default: + TOML_UNREACHABLE; + } + + if constexpr (!can_visit_all<Func&&, Node&&>) { + // clang-format off using return_type = nonvoid<visit_return_type<Func&&, Node&&, table>, @@ -868,246 +848,244 @@ TOML_NAMESPACE_START visit_return_type<Func&&, Node&&, date_time> >>>>>>>>; - // clang-format on - - if constexpr (!std::is_void_v<return_type>) - { - static_assert(std::is_default_constructible_v<return_type>, - "Non-exhaustive visitors must return a default-constructible type, or void"); - return return_type{}; - } - } - } - - /// \endcond - - public: - /// \name Visitation - /// @{ - - /// \brief Invokes a visitor on the node based on the node's concrete type. - /// - /// \details Visitation is useful when you expect - /// a node to be one of a set number of types and need - /// to handle these types differently. Using `visit()` allows - /// you to eliminate some of the casting/conversion boilerplate: \cpp - /// - /// node.visit([](auto&& n) - /// { - /// if constexpr (toml::is_string<decltype(n)>) - /// do_something_with_a_string(*n)); //n is a toml::value<std::string> - /// else if constexpr (toml::is_integer<decltype(n)>) - /// do_something_with_an_int(*n); //n is a toml::value<int64_t> - /// }); - /// \ecpp - /// - /// Visitor functions need not be generic; specifying a concrete node type as the input argument type - /// effectively acts a 'filter', only invoking the visitor if the concrete type is compatible. - /// Thus the example above can be re-written as: \cpp - /// node.visit([](toml::value<std::string>& s) { do_something_with_a_string(*s)); }); - /// node.visit([](toml::value<int64_t>& i) { do_something_with_an_int(*i)); }); - /// \ecpp - /// - /// \tparam Func A callable type invocable with one or more of the toml++ node types. - /// - /// \param visitor The visitor object. - /// - /// \returns The return value of the visitor. - /// Can be void. Non-exhaustive visitors must return a default-constructible type. - /// - /// \see https://en.wikipedia.org/wiki/Visitor_pattern - template <typename Func> - decltype(auto) visit(Func&& visitor) & noexcept(visit_is_nothrow<Func&&, node&>) - { - return do_visit(static_cast<Func&&>(visitor), *this); - } - - /// \brief Invokes a visitor on the node based on the node's concrete type (rvalue overload). - template <typename Func> - decltype(auto) visit(Func&& visitor) && noexcept(visit_is_nothrow<Func&&, node&&>) - { - return do_visit(static_cast<Func&&>(visitor), static_cast<node&&>(*this)); - } - - /// \brief Invokes a visitor on the node based on the node's concrete type (const lvalue overload). - template <typename Func> - decltype(auto) visit(Func&& visitor) const& noexcept(visit_is_nothrow<Func&&, const node&>) - { - return do_visit(static_cast<Func&&>(visitor), *this); - } - - /// \brief Invokes a visitor on the node based on the node's concrete type (const rvalue overload). - template <typename Func> - decltype(auto) visit(Func&& visitor) const&& noexcept(visit_is_nothrow<Func&&, const node&&>) - { - return do_visit(static_cast<Func&&>(visitor), static_cast<const node&&>(*this)); - } - - /// @} - - /// \name Node views - /// @{ - - /// \brief Creates a node_view pointing to this node. - TOML_NODISCARD - explicit operator node_view<node>() noexcept; - - /// \brief Creates a node_view pointing to this node (const overload). - TOML_NODISCARD - explicit operator node_view<const node>() const noexcept; - - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \detail \cpp - /// auto config = toml::parse(R"( - /// - /// [foo] - /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] - /// - /// )"sv); - /// - /// std::cout << config.at_path("foo.bar[2]") << "\n"; - /// std::cout << config.at_path("foo.bar[3][0]") << "\n"; - /// std::cout << config.at_path("foo.bar[4].kek") << "\n"; - /// \ecpp - /// - /// \out - /// 2 - /// 3 - /// 4 - /// \eout - /// - /// - /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: - /// \cpp - /// config.at_path( "foo.bar") // same as node_view{ config }["foo"]["bar"] - /// config.at_path( "foo. bar") // same as node_view{ config }["foo"][" bar"] - /// config.at_path( "foo..bar") // same as node_view{ config }["foo"][""]["bar"] - /// config.at_path( ".foo.bar") // same as node_view{ config }[""]["foo"]["bar"] - /// \ecpp - /// <br> - /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted strings. - /// This function makes no allowance for this, instead treating all period characters as sub-table delimiters. - /// If you have periods in your table keys, first consider: - /// 1. Not doing that - /// 2. Using node_view::operator[] instead. - /// - /// \param path The "TOML path" to traverse. - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node_view<node> at_path(std::string_view path) noexcept; - - /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #at_path(std::string_view) - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node_view<const node> at_path(std::string_view path) const noexcept; - - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \detail \cpp - /// auto config = toml::parse(R"( - /// - /// [foo] - /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] - /// - /// )"sv); - /// - /// toml::path path1("foo.bar[2]"); - /// toml::path path2("foo.bar[4].kek"); - /// std::cout << config.at_path(path1) << "\n"; - /// std::cout << config.at_path(path1.parent_path()) << "\n"; - /// std::cout << config.at_path(path2) << "\n"; - /// std::cout << config.at_path(path2.parent_path()) << "\n"; - /// \ecpp - /// - /// \out - /// 2 - /// [ 0, 1, 2, [ 3 ], { kek = 4 } ] - /// 4 - /// { kek = 4 } - /// \eout - /// - /// - /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: - /// \cpp - /// config.at_path(toml::path("foo.bar")) // same as node_view{ config }["foo"]["bar"] - /// config.at_path(toml::path("foo. bar")) // same as node_view{ config }["foo"][" bar"] - /// config.at_path(toml::path("foo..bar")) // same as node_view{ config }["foo"][""]["bar"] - /// config.at_path(toml::path(".foo.bar")) // same as node_view{ config }[""]["foo"]["bar"] - /// \ecpp - /// <br> - /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted strings. - /// This function makes no allowance for this, instead treating all period characters as sub-table delimiters. - /// - /// \param path The "TOML path" to traverse. - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node_view<node> at_path(const toml::path& path) noexcept; - - /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #at_path(const toml::path&) - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node_view<const node> at_path(const toml::path& path) const noexcept; + // clang-format on + + if constexpr (!std::is_void_v<return_type>) { + static_assert( + std::is_default_constructible_v<return_type>, + "Non-exhaustive visitors must return a default-constructible type, or void"); + return return_type{}; + } + } + } + + /// \endcond + + public: + /// \name Visitation + /// @{ + + /// \brief Invokes a visitor on the node based on the node's concrete type. + /// + /// \details Visitation is useful when you expect + /// a node to be one of a set number of types and need + /// to handle these types differently. Using `visit()` allows + /// you to eliminate some of the casting/conversion boilerplate: \cpp + /// + /// node.visit([](auto&& n) + /// { + /// if constexpr (toml::is_string<decltype(n)>) + /// do_something_with_a_string(*n)); //n is a toml::value<std::string> + /// else if constexpr (toml::is_integer<decltype(n)>) + /// do_something_with_an_int(*n); //n is a toml::value<int64_t> + /// }); + /// \ecpp + /// + /// Visitor functions need not be generic; specifying a concrete node type as the input argument + /// type effectively acts a 'filter', only invoking the visitor if the concrete type is + /// compatible. Thus the example above can be re-written as: \cpp + /// node.visit([](toml::value<std::string>& s) { do_something_with_a_string(*s)); }); + /// node.visit([](toml::value<int64_t>& i) { do_something_with_an_int(*i)); }); + /// \ecpp + /// + /// \tparam Func A callable type invocable with one or more of the toml++ node types. + /// + /// \param visitor The visitor object. + /// + /// \returns The return value of the visitor. + /// Can be void. Non-exhaustive visitors must return a default-constructible type. + /// + /// \see https://en.wikipedia.org/wiki/Visitor_pattern + template <typename Func> + decltype(auto) visit(Func&& visitor) & noexcept(visit_is_nothrow<Func&&, node&>) { + return do_visit(static_cast<Func&&>(visitor), *this); + } + + /// \brief Invokes a visitor on the node based on the node's concrete type (rvalue overload). + template <typename Func> + decltype(auto) visit(Func&& visitor) && noexcept(visit_is_nothrow<Func&&, node&&>) { + return do_visit(static_cast<Func&&>(visitor), static_cast<node&&>(*this)); + } + + /// \brief Invokes a visitor on the node based on the node's concrete type (const lvalue + /// overload). + template <typename Func> + decltype(auto) visit(Func&& visitor) const& noexcept(visit_is_nothrow<Func&&, const node&>) { + return do_visit(static_cast<Func&&>(visitor), *this); + } + + /// \brief Invokes a visitor on the node based on the node's concrete type (const rvalue + /// overload). + template <typename Func> + decltype(auto) visit(Func&& visitor) const&& noexcept(visit_is_nothrow<Func&&, const node&&>) { + return do_visit(static_cast<Func&&>(visitor), static_cast<const node&&>(*this)); + } + + /// @} + + /// \name Node views + /// @{ + + /// \brief Creates a node_view pointing to this node. + TOML_NODISCARD + explicit operator node_view<node>() noexcept; + + /// \brief Creates a node_view pointing to this node (const overload). + TOML_NODISCARD + explicit operator node_view<const node>() const noexcept; + + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \detail \cpp + /// auto config = toml::parse(R"( + /// + /// [foo] + /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] + /// + /// )"sv); + /// + /// std::cout << config.at_path("foo.bar[2]") << "\n"; + /// std::cout << config.at_path("foo.bar[3][0]") << "\n"; + /// std::cout << config.at_path("foo.bar[4].kek") << "\n"; + /// \ecpp + /// + /// \out + /// 2 + /// 3 + /// 4 + /// \eout + /// + /// + /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: + /// \cpp + /// config.at_path( "foo.bar") // same as node_view{ config }["foo"]["bar"] + /// config.at_path( "foo. bar") // same as node_view{ config }["foo"][" bar"] + /// config.at_path( "foo..bar") // same as node_view{ config }["foo"][""]["bar"] + /// config.at_path( ".foo.bar") // same as node_view{ config }[""]["foo"]["bar"] + /// \ecpp + /// <br> + /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted + /// strings. This function makes no allowance for this, instead treating all period characters + /// as sub-table delimiters. If you have periods in your table keys, first consider: + /// 1. Not doing that + /// 2. Using node_view::operator[] instead. + /// + /// \param path The "TOML path" to traverse. + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node_view<node> at_path(std::string_view path) noexcept; + + /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #at_path(std::string_view) + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node_view<const node> at_path(std::string_view path) const noexcept; + + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \detail \cpp + /// auto config = toml::parse(R"( + /// + /// [foo] + /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] + /// + /// )"sv); + /// + /// toml::path path1("foo.bar[2]"); + /// toml::path path2("foo.bar[4].kek"); + /// std::cout << config.at_path(path1) << "\n"; + /// std::cout << config.at_path(path1.parent_path()) << "\n"; + /// std::cout << config.at_path(path2) << "\n"; + /// std::cout << config.at_path(path2.parent_path()) << "\n"; + /// \ecpp + /// + /// \out + /// 2 + /// [ 0, 1, 2, [ 3 ], { kek = 4 } ] + /// 4 + /// { kek = 4 } + /// \eout + /// + /// + /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: + /// \cpp + /// config.at_path(toml::path("foo.bar")) // same as node_view{ config }["foo"]["bar"] + /// config.at_path(toml::path("foo. bar")) // same as node_view{ config }["foo"][" bar"] + /// config.at_path(toml::path("foo..bar")) // same as node_view{ config }["foo"][""]["bar"] + /// config.at_path(toml::path(".foo.bar")) // same as node_view{ config }[""]["foo"]["bar"] + /// \ecpp + /// <br> + /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted + /// strings. This function makes no allowance for this, instead treating all period characters + /// as sub-table delimiters. + /// + /// \param path The "TOML path" to traverse. + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node_view<node> at_path(const toml::path& path) noexcept; + + /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #at_path(const toml::path&) + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node_view<const node> at_path(const toml::path& path) const noexcept; #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \see #at_path(std::string_view) - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node_view<node> at_path(std::wstring_view path); - - /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \see #at_path(std::string_view) - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node_view<const node> at_path(std::wstring_view path) const; - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". - /// - /// \param path The "TOML path" to the desired child. - /// - /// \returns A view of the child node at the given path if one existed, or an empty node view. - /// - /// \see toml::node_view - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node_view<node> operator[](const toml::path& path) noexcept; - - /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". - /// - /// \param path The "TOML path" to the desired child. - /// - /// \returns A view of the child node at the given path if one existed, or an empty node view. - /// - /// \see toml::node_view - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node_view<const node> operator[](const toml::path& path) const noexcept; - - /// @} - }; + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \see #at_path(std::string_view) + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node_view<node> at_path(std::wstring_view path); + + /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \see #at_path(std::string_view) + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node_view<const node> at_path(std::wstring_view path) const; + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". + /// + /// \param path The "TOML path" to the desired child. + /// + /// \returns A view of the child node at the given path if one existed, or an empty node view. + /// + /// \see toml::node_view + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node_view<node> operator[](const toml::path& path) noexcept; + + /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". + /// + /// \param path The "TOML path" to the desired child. + /// + /// \returns A view of the child node at the given path if one existed, or an empty node view. + /// + /// \see toml::node_view + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node_view<const node> operator[](const toml::path& path) const noexcept; + + /// @} + }; } TOML_NAMESPACE_END; /// \cond -TOML_IMPL_NAMESPACE_START -{ - TOML_PURE_GETTER - TOML_EXPORTED_FREE_FUNCTION - bool TOML_CALLCONV node_deep_equality(const node*, const node*) noexcept; +TOML_IMPL_NAMESPACE_START { + TOML_PURE_GETTER + TOML_EXPORTED_FREE_FUNCTION + bool TOML_CALLCONV node_deep_equality(const node*, const node*) noexcept; } TOML_IMPL_NAMESPACE_END; /// \endcond diff --git a/vendor/toml++/impl/node_view.hpp b/vendor/toml++/impl/node_view.hpp index fb63025..54599e1 100644 --- a/vendor/toml++/impl/node_view.hpp +++ b/vendor/toml++/impl/node_view.hpp @@ -1,837 +1,717 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once -#include "std_vector.hpp" -#include "std_initializer_list.hpp" -#include "print_to_stream.hpp" -#include "node.hpp" #include "header_start.hpp" +#include "node.hpp" +#include "print_to_stream.hpp" +#include "std_initializer_list.hpp" +#include "std_vector.hpp" TOML_DISABLE_ARITHMETIC_WARNINGS; -TOML_NAMESPACE_START -{ - /// \brief A view of a node. - /// - /// \detail A node_view is like a std::optional<toml::node&> (if such a construct were legal), with lots of - /// toml-specific stuff built-in. It _may_ represent a node, and allows you to do many of the - /// same operations that you'd do on nodes directly, as well as easily traversing the node tree by creating - /// subviews (via node_view::operator[]). \cpp - /// - /// auto tbl = toml::parse(R"( - /// - /// title = "my hardware store" - /// - /// [[products]] - /// name = "Hammer" - /// sku = 738594937 - /// keywords = [ "hammer", "construction", "build" ] - /// - /// [[products]] - /// name = "Nail" - /// sku = 284758393 - /// color = "gray" - /// - /// )"sv); - /// - /// std::cout << tbl["title"] << "\n"; - /// std::cout << tbl["products"][0]["name"] << "\n"; - /// std::cout << tbl["products"][0]["keywords"] << "\n"; - /// std::cout << tbl["products"][0]["keywords"][2] << "\n"; - /// - /// tbl["products"][0]["keywords"].as_array()->push_back("heavy"); - /// std::cout << tbl["products"][0]["keywords"] << "\n"; - /// std::cout << "has product[2]: "sv << !!tbl["products"][2] << "\n"; - /// std::cout << "product[2]: "sv << tbl["products"][2] << "\n"; - /// \ecpp - /// - /// \out - /// "my hardware store" - /// "Hammer" - /// [ "hammer", "construction", "build" ] - /// "build" - /// [ "hammer", "construction", "build", "heavy" ] - /// has product[2]: false - /// product[2]: - /// \eout - template <typename ViewedType> - class TOML_TRIVIAL_ABI node_view - { - static_assert(impl::is_one_of<ViewedType, toml::node, const toml::node>, - "A toml::node_view<> must wrap toml::node or const toml::node."); - - public: - /// \brief The node type being viewed - either `node` or `const node`. - using viewed_type = ViewedType; - - private: - template <typename T> - friend class node_view; - - mutable viewed_type* node_ = nullptr; - - public: - /// \brief Constructs an empty node view. - TOML_NODISCARD_CTOR - node_view() noexcept = default; - - /// \brief Constructs node_view of a specific node. - TOML_NODISCARD_CTOR - explicit node_view(viewed_type* node) noexcept // - : node_{ node } - {} - - /// \brief Constructs node_view of a specific node. - TOML_NODISCARD_CTOR - explicit node_view(viewed_type& node) noexcept // - : node_{ &node } - {} - - /// \brief Copy constructor. - TOML_NODISCARD_CTOR - node_view(const node_view&) noexcept = default; - - /// \brief Move constructor. - TOML_NODISCARD_CTOR - node_view(node_view&&) noexcept = default; - - /// \brief Copy-assignment operator. - node_view& operator=(const node_view&) & noexcept = default; - - /// \brief Move-assignment operator. - node_view& operator=(node_view&&) & noexcept = default; - - /// \brief Returns true if the view references a node. - TOML_PURE_INLINE_GETTER - explicit operator bool() const noexcept - { - return node_ != nullptr; - } - - /// \brief Returns the node that's being referenced by the view. - TOML_PURE_INLINE_GETTER - viewed_type* node() const noexcept - { - return node_; - } - - /// \name Type checks - /// @{ - - /// \brief Returns the type identifier for the viewed node. - TOML_PURE_GETTER - node_type type() const noexcept - { - return node_ ? node_->type() : node_type::none; - } - - /// \brief Returns true if the viewed node is a toml::table. - TOML_PURE_GETTER - bool is_table() const noexcept - { - return node_ && node_->is_table(); - } - - /// \brief Returns true if the viewed node is a toml::array. - TOML_PURE_GETTER - bool is_array() const noexcept - { - return node_ && node_->is_array(); - } - - /// \brief Returns true if the viewed node is a toml::value<>. - TOML_PURE_GETTER - bool is_value() const noexcept - { - return node_ && node_->is_value(); - } - - /// \brief Returns true if the viewed node is a toml::value<string>. - TOML_PURE_GETTER - bool is_string() const noexcept - { - return node_ && node_->is_string(); - } - - /// \brief Returns true if the viewed node is a toml::value<int64_t>. - TOML_PURE_GETTER - bool is_integer() const noexcept - { - return node_ && node_->is_integer(); - } - - /// \brief Returns true if the viewed node is a toml::value<double>. - TOML_PURE_GETTER - bool is_floating_point() const noexcept - { - return node_ && node_->is_floating_point(); - } - - /// \brief Returns true if the viewed node is a toml::value<int64_t> or toml::value<double>. - TOML_PURE_GETTER - bool is_number() const noexcept - { - return node_ && node_->is_number(); - } - - /// \brief Returns true if the viewed node is a toml::value<bool>. - TOML_PURE_GETTER - bool is_boolean() const noexcept - { - return node_ && node_->is_boolean(); - } - - /// \brief Returns true if the viewed node is a toml::value<date>. - TOML_PURE_GETTER - bool is_date() const noexcept - { - return node_ && node_->is_date(); - } - - /// \brief Returns true if the viewed node is a toml::value<time>. - TOML_PURE_GETTER - bool is_time() const noexcept - { - return node_ && node_->is_time(); - } - - /// \brief Returns true if the viewed node is a toml::value<date_time>. - TOML_PURE_GETTER - bool is_date_time() const noexcept - { - return node_ && node_->is_date_time(); - } - - /// \brief Returns true if the viewed node is a toml::array that contains only tables. - TOML_PURE_GETTER - bool is_array_of_tables() const noexcept - { - return node_ && node_->is_array_of_tables(); - } - - /// \brief Checks if this view references a node of a specific type. - /// - /// \tparam T A TOML node or value type. - /// - /// \returns Returns true if the viewed node is an instance of the specified type. - /// - /// \see toml::node::is() - template <typename T> - TOML_PURE_GETTER - bool is() const noexcept - { - return node_ ? node_->template is<impl::unwrap_node<impl::remove_cvref<T>>>() : false; - } - - /// \brief Checks if the viewed node contains values/elements of only one type. - /// - /// \detail \cpp - /// auto cfg = toml::parse("arr = [ 1, 2, 3, 4.0 ]"); - /// - /// toml::node* nonmatch{}; - /// if (cfg["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. <br> - /// \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 viewed node was homogeneous. - /// - /// \remarks Always returns `false` if the view does not reference a node, or if the viewed node is - /// an empty table or array. - TOML_NODISCARD - bool is_homogeneous(node_type ntype, viewed_type*& first_nonmatch) const noexcept - { - if (!node_) - { - first_nonmatch = {}; - return false; - } - return node_->is_homogeneous(ntype, first_nonmatch); - } - - /// \brief Checks if the viewed node contains values/elements of only one type. - /// - /// \detail \cpp - /// auto cfg = toml::parse("arr = [ 1, 2, 3 ]"); - /// std::cout << "homogenous: "sv << cfg["arr"].is_homogeneous(toml::node_type::none) << "\n"; - /// std::cout << "all floats: "sv << cfg["arr"].is_homogeneous(toml::node_type::floating_point) << "\n"; - /// std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous(toml::node_type::array) << "\n"; - /// std::cout << "all ints: "sv << cfg["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. <br> - /// \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 viewed node was homogeneous. - /// - /// \remarks Always returns `false` if the view does not reference a node, or if the viewed node is - /// an empty table or array. - TOML_NODISCARD - bool is_homogeneous(node_type ntype) const noexcept - { - return node_ ? node_->is_homogeneous(ntype) : false; - } - - /// \brief Checks if the viewed node contains values/elements of only one type. - /// - /// \detail \cpp - /// auto cfg = toml::parse("arr = [ 1, 2, 3 ]"); - /// std::cout << "homogenous: "sv << cfg["arr"].is_homogeneous() << "\n"; - /// std::cout << "all doubles: "sv << cfg["arr"].is_homogeneous<double>() << "\n"; - /// std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous<toml::array>() << "\n"; - /// std::cout << "all integers: "sv << cfg["arr"].is_homogeneous<int64_t>() << "\n"; - /// \ecpp - /// - /// \out - /// homogeneous: true - /// all floats: false - /// all arrays: false - /// all ints: true - /// \eout - /// - /// \tparam ElemType A TOML node or value type. <br> - /// \conditional_return{Left as `void`} "is every element the same type?" <br> - /// \conditional_return{Explicitly specified} "is every element a T?" - /// - /// \returns True if the viewed node was homogeneous. - /// - /// \remarks Always returns `false` if the view does not reference a node, or if the viewed node is - /// an empty table or array. - template <typename ElemType = void> - TOML_PURE_GETTER - bool is_homogeneous() const noexcept - { - return node_ ? node_->template is_homogeneous<impl::unwrap_node<impl::remove_cvref<ElemType>>>() : false; - } - - /// @} - - /// \name Type casts - /// @{ - - /// \brief Gets a pointer to the viewed node as a more specific node type. - /// - /// \tparam T The node type or TOML value type to cast to. - /// - /// \returns A pointer to the node as the given type, or nullptr if it was a different type. - /// - /// \see toml::node::as() - template <typename T> - TOML_PURE_GETTER - auto* as() const noexcept - { - return node_ ? node_->template as<T>() : nullptr; - } - - /// \brief Returns a pointer to the viewed node as a toml::table, if it is one. - TOML_PURE_GETTER - auto* as_table() const noexcept - { - return as<table>(); - } - - /// \brief Returns a pointer to the viewed node as a toml::array, if it is one. - TOML_PURE_GETTER - auto* as_array() const noexcept - { - return as<array>(); - } - - /// \brief Returns a pointer to the viewed node as a toml::value<string>, if it is one. - TOML_PURE_GETTER - auto* as_string() const noexcept - { - return as<std::string>(); - } - - /// \brief Returns a pointer to the viewed node as a toml::value<int64_t>, if it is one. - TOML_PURE_GETTER - auto* as_integer() const noexcept - { - return as<int64_t>(); - } - - /// \brief Returns a pointer to the viewed node as a toml::value<double>, if it is one. - TOML_PURE_GETTER - auto* as_floating_point() const noexcept - { - return as<double>(); - } - - /// \brief Returns a pointer to the viewed node as a toml::value<bool>, if it is one. - TOML_PURE_GETTER - auto* as_boolean() const noexcept - { - return as<bool>(); - } - - /// \brief Returns a pointer to the viewed node as a toml::value<date>, if it is one. - TOML_PURE_GETTER - auto* as_date() const noexcept - { - return as<date>(); - } - - /// \brief Returns a pointer to the viewed node as a toml::value<time>, if it is one. - TOML_PURE_GETTER - auto* as_time() const noexcept - { - return as<time>(); - } - - /// \brief Returns a pointer to the viewed node as a toml::value<date_time>, if it is one. - TOML_PURE_GETTER - auto* as_date_time() const noexcept - { - return as<date_time>(); - } - - /// @} - - /// \name Value retrieval - /// @{ - - /// \brief Gets the value contained by the referenced node. - /// - /// \detail This function has 'exact' retrieval semantics; the only return value types allowed are the - /// TOML native value types, or types that can losslessly represent a native value type (e.g. - /// std::wstring on Windows). - /// - /// \tparam T One of the native TOML value types, or a type capable of losslessly representing one. - /// - /// \returns The underlying value if the node was a value of the - /// matching type (or losslessly convertible to it), or an empty optional. - /// - /// \see node_view::value() - template <typename T> - TOML_NODISCARD - optional<T> value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>) - { - if (node_) - return node_->template value_exact<T>(); - return {}; - } - - /// \brief Gets the value contained by the referenced node. - /// - /// \detail This function has 'permissive' retrieval semantics; some value types are allowed - /// to convert to others (e.g. retrieving a boolean as an integer), and the specified return value - /// type can be any type where a reasonable conversion from a native TOML value exists - /// (e.g. std::wstring on Windows). If the source value cannot be represented by - /// the destination type, an empty optional is returned. See node::value() for examples. - /// - /// \tparam T One of the native TOML value types, or a type capable of convertible to one. - /// - /// \returns The underlying value if the node was a value of the matching type (or convertible to it) - /// and within the range of the output type, or an empty optional. - /// - /// \note If you want strict value retrieval semantics that do not allow for any type conversions, - /// use node_view::value_exact() instead. - /// - /// \see - /// - node_view::value() - /// - node_view::value_exact() - template <typename T> - TOML_NODISCARD - optional<T> value() const noexcept(impl::value_retrieval_is_nothrow<T>) - { - if (node_) - return node_->template value<T>(); - return {}; - } - - /// \brief Gets the raw value contained by the referenced node, or a default. - /// - /// \tparam T Default value type. Must be one of the native TOML value types, - /// or convertible to it. - /// \param default_value The default value to return if the node wasn't a value, wasn't the - /// correct type, or no conversion was possible. - /// - /// \returns The underlying value if the node was a value of the matching type (or convertible to it) - /// and within the range of the output type, or the provided default. - /// - /// \note This function has the same permissive retrieval semantics as node::value(). If you want strict - /// value retrieval semantics that do not allow for any type conversions, use node_view::value_exact() - /// instead. - /// - /// \see - /// - node_view::value() - /// - node_view::value_exact() - template <typename T> - TOML_NODISCARD - auto value_or(T&& default_value) const noexcept(impl::value_retrieval_is_nothrow<T>) - { - using namespace ::toml::impl; - - static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, - "Retrieving values as wide-character strings is only " - "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); - - if constexpr (is_wide_string<T>) - { +TOML_NAMESPACE_START { + /// \brief A view of a node. + /// + /// \detail A node_view is like a std::optional<toml::node&> (if such a construct were legal), + /// with lots of + /// toml-specific stuff built-in. It _may_ represent a node, and allows you to do many of the + /// same operations that you'd do on nodes directly, as well as easily traversing the node + ///tree by creating + /// subviews (via node_view::operator[]). \cpp + /// + /// auto tbl = toml::parse(R"( + /// + /// title = "my hardware store" + /// + /// [[products]] + /// name = "Hammer" + /// sku = 738594937 + /// keywords = [ "hammer", "construction", "build" ] + /// + /// [[products]] + /// name = "Nail" + /// sku = 284758393 + /// color = "gray" + /// + /// )"sv); + /// + /// std::cout << tbl["title"] << "\n"; + /// std::cout << tbl["products"][0]["name"] << "\n"; + /// std::cout << tbl["products"][0]["keywords"] << "\n"; + /// std::cout << tbl["products"][0]["keywords"][2] << "\n"; + /// + /// tbl["products"][0]["keywords"].as_array()->push_back("heavy"); + /// std::cout << tbl["products"][0]["keywords"] << "\n"; + /// std::cout << "has product[2]: "sv << !!tbl["products"][2] << "\n"; + /// std::cout << "product[2]: "sv << tbl["products"][2] << "\n"; + /// \ecpp + /// + /// \out + /// "my hardware store" + /// "Hammer" + /// [ "hammer", "construction", "build" ] + /// "build" + /// [ "hammer", "construction", "build", "heavy" ] + /// has product[2]: false + /// product[2]: + /// \eout + template <typename ViewedType> + class TOML_TRIVIAL_ABI node_view { + static_assert(impl::is_one_of<ViewedType, toml::node, const toml::node>, + "A toml::node_view<> must wrap toml::node or const toml::node."); + + public: + /// \brief The node type being viewed - either `node` or `const node`. + using viewed_type = ViewedType; + + private: + template <typename T> + friend class node_view; + + mutable viewed_type* node_ = nullptr; + + public: + /// \brief Constructs an empty node view. + TOML_NODISCARD_CTOR + node_view() noexcept = default; + + /// \brief Constructs node_view of a specific node. + TOML_NODISCARD_CTOR + explicit node_view(viewed_type* node) noexcept // + : node_{node} {} + + /// \brief Constructs node_view of a specific node. + TOML_NODISCARD_CTOR + explicit node_view(viewed_type& node) noexcept // + : node_{&node} {} + + /// \brief Copy constructor. + TOML_NODISCARD_CTOR + node_view(const node_view&) noexcept = default; + + /// \brief Move constructor. + TOML_NODISCARD_CTOR + node_view(node_view&&) noexcept = default; + + /// \brief Copy-assignment operator. + node_view& operator=(const node_view&) & noexcept = default; + + /// \brief Move-assignment operator. + node_view& operator=(node_view&&) & noexcept = default; + + /// \brief Returns true if the view references a node. + TOML_PURE_INLINE_GETTER + explicit operator bool() const noexcept { return node_ != nullptr; } + + /// \brief Returns the node that's being referenced by the view. + TOML_PURE_INLINE_GETTER + viewed_type* node() const noexcept { return node_; } + + /// \name Type checks + /// @{ + + /// \brief Returns the type identifier for the viewed node. + TOML_PURE_GETTER + node_type type() const noexcept { return node_ ? node_->type() : node_type::none; } + + /// \brief Returns true if the viewed node is a toml::table. + TOML_PURE_GETTER + bool is_table() const noexcept { return node_ && node_->is_table(); } + + /// \brief Returns true if the viewed node is a toml::array. + TOML_PURE_GETTER + bool is_array() const noexcept { return node_ && node_->is_array(); } + + /// \brief Returns true if the viewed node is a toml::value<>. + TOML_PURE_GETTER + bool is_value() const noexcept { return node_ && node_->is_value(); } + + /// \brief Returns true if the viewed node is a toml::value<string>. + TOML_PURE_GETTER + bool is_string() const noexcept { return node_ && node_->is_string(); } + + /// \brief Returns true if the viewed node is a toml::value<int64_t>. + TOML_PURE_GETTER + bool is_integer() const noexcept { return node_ && node_->is_integer(); } + + /// \brief Returns true if the viewed node is a toml::value<double>. + TOML_PURE_GETTER + bool is_floating_point() const noexcept { return node_ && node_->is_floating_point(); } + + /// \brief Returns true if the viewed node is a toml::value<int64_t> or toml::value<double>. + TOML_PURE_GETTER + bool is_number() const noexcept { return node_ && node_->is_number(); } + + /// \brief Returns true if the viewed node is a toml::value<bool>. + TOML_PURE_GETTER + bool is_boolean() const noexcept { return node_ && node_->is_boolean(); } + + /// \brief Returns true if the viewed node is a toml::value<date>. + TOML_PURE_GETTER + bool is_date() const noexcept { return node_ && node_->is_date(); } + + /// \brief Returns true if the viewed node is a toml::value<time>. + TOML_PURE_GETTER + bool is_time() const noexcept { return node_ && node_->is_time(); } + + /// \brief Returns true if the viewed node is a toml::value<date_time>. + TOML_PURE_GETTER + bool is_date_time() const noexcept { return node_ && node_->is_date_time(); } + + /// \brief Returns true if the viewed node is a toml::array that contains only tables. + TOML_PURE_GETTER + bool is_array_of_tables() const noexcept { return node_ && node_->is_array_of_tables(); } + + /// \brief Checks if this view references a node of a specific type. + /// + /// \tparam T A TOML node or value type. + /// + /// \returns Returns true if the viewed node is an instance of the specified type. + /// + /// \see toml::node::is() + template <typename T> + TOML_PURE_GETTER bool is() const noexcept { + return node_ ? node_->template is<impl::unwrap_node<impl::remove_cvref<T>>>() : false; + } + + /// \brief Checks if the viewed node contains values/elements of only one type. + /// + /// \detail \cpp + /// auto cfg = toml::parse("arr = [ 1, 2, 3, 4.0 ]"); + /// + /// toml::node* nonmatch{}; + /// if (cfg["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. <br> + /// \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 viewed node was homogeneous. + /// + /// \remarks Always returns `false` if the view does not reference a node, or if the viewed + /// node is an empty table or array. + TOML_NODISCARD + bool is_homogeneous(node_type ntype, viewed_type*& first_nonmatch) const noexcept { + if (!node_) { + first_nonmatch = {}; + return false; + } + return node_->is_homogeneous(ntype, first_nonmatch); + } + + /// \brief Checks if the viewed node contains values/elements of only one type. + /// + /// \detail \cpp + /// auto cfg = toml::parse("arr = [ 1, 2, 3 ]"); + /// std::cout << "homogenous: "sv << cfg["arr"].is_homogeneous(toml::node_type::none) << "\n"; + /// std::cout << "all floats: "sv << cfg["arr"].is_homogeneous(toml::node_type::floating_point) + /// << "\n"; std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous(toml::node_type::array) + /// << "\n"; std::cout << "all ints: "sv << + /// cfg["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. <br> + /// \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 viewed node was homogeneous. + /// + /// \remarks Always returns `false` if the view does not reference a node, or if the viewed + /// node is an empty table or array. + TOML_NODISCARD + bool is_homogeneous(node_type ntype) const noexcept { + return node_ ? node_->is_homogeneous(ntype) : false; + } + + /// \brief Checks if the viewed node contains values/elements of only one type. + /// + /// \detail \cpp + /// auto cfg = toml::parse("arr = [ 1, 2, 3 ]"); + /// std::cout << "homogenous: "sv << cfg["arr"].is_homogeneous() << "\n"; + /// std::cout << "all doubles: "sv << cfg["arr"].is_homogeneous<double>() << "\n"; + /// std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous<toml::array>() << "\n"; + /// std::cout << "all integers: "sv << cfg["arr"].is_homogeneous<int64_t>() << "\n"; + /// \ecpp + /// + /// \out + /// homogeneous: true + /// all floats: false + /// all arrays: false + /// all ints: true + /// \eout + /// + /// \tparam ElemType A TOML node or value type. <br> + /// \conditional_return{Left as `void`} "is every element the same type?" <br> + /// \conditional_return{Explicitly specified} "is every element a T?" + /// + /// \returns True if the viewed node was homogeneous. + /// + /// \remarks Always returns `false` if the view does not reference a node, or if the viewed + /// node is an empty table or array. + template <typename ElemType = void> + TOML_PURE_GETTER bool is_homogeneous() const noexcept { + return node_ + ? node_->template is_homogeneous<impl::unwrap_node<impl::remove_cvref<ElemType>>>() + : false; + } + + /// @} + + /// \name Type casts + /// @{ + + /// \brief Gets a pointer to the viewed node as a more specific node type. + /// + /// \tparam T The node type or TOML value type to cast to. + /// + /// \returns A pointer to the node as the given type, or nullptr if it was a different type. + /// + /// \see toml::node::as() + template <typename T> + TOML_PURE_GETTER auto* as() const noexcept { + return node_ ? node_->template as<T>() : nullptr; + } + + /// \brief Returns a pointer to the viewed node as a toml::table, if it is one. + TOML_PURE_GETTER + auto* as_table() const noexcept { return as<table>(); } + + /// \brief Returns a pointer to the viewed node as a toml::array, if it is one. + TOML_PURE_GETTER + auto* as_array() const noexcept { return as<array>(); } + + /// \brief Returns a pointer to the viewed node as a toml::value<string>, if it is one. + TOML_PURE_GETTER + auto* as_string() const noexcept { return as<std::string>(); } + + /// \brief Returns a pointer to the viewed node as a toml::value<int64_t>, if it is one. + TOML_PURE_GETTER + auto* as_integer() const noexcept { return as<int64_t>(); } + + /// \brief Returns a pointer to the viewed node as a toml::value<double>, if it is one. + TOML_PURE_GETTER + auto* as_floating_point() const noexcept { return as<double>(); } + + /// \brief Returns a pointer to the viewed node as a toml::value<bool>, if it is one. + TOML_PURE_GETTER + auto* as_boolean() const noexcept { return as<bool>(); } + + /// \brief Returns a pointer to the viewed node as a toml::value<date>, if it is one. + TOML_PURE_GETTER + auto* as_date() const noexcept { return as<date>(); } + + /// \brief Returns a pointer to the viewed node as a toml::value<time>, if it is one. + TOML_PURE_GETTER + auto* as_time() const noexcept { return as<time>(); } + + /// \brief Returns a pointer to the viewed node as a toml::value<date_time>, if it is one. + TOML_PURE_GETTER + auto* as_date_time() const noexcept { return as<date_time>(); } + + /// @} + + /// \name Value retrieval + /// @{ + + /// \brief Gets the value contained by the referenced node. + /// + /// \detail This function has 'exact' retrieval semantics; the only return value types allowed + /// are the TOML native value types, or types that can losslessly represent a native value type + /// (e.g. std::wstring on Windows). + /// + /// \tparam T One of the native TOML value types, or a type capable of losslessly representing + /// one. + /// + /// \returns The underlying value if the node was a value of the + /// matching type (or losslessly convertible to it), or an empty optional. + /// + /// \see node_view::value() + template <typename T> + TOML_NODISCARD optional<T> value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>) { + if (node_) return node_->template value_exact<T>(); + return {}; + } + + /// \brief Gets the value contained by the referenced node. + /// + /// \detail This function has 'permissive' retrieval semantics; some value types are allowed + /// to convert to others (e.g. retrieving a boolean as an integer), and the specified return + /// value type can be any type where a reasonable conversion from a native TOML value exists + /// (e.g. std::wstring on Windows). If the source value cannot be represented by + /// the destination type, an empty optional is returned. See node::value() for examples. + /// + /// \tparam T One of the native TOML value types, or a type capable of convertible to one. + /// + /// \returns The underlying value if the node was a value of the matching type (or convertible + /// to it) and within the range of the output type, or an empty optional. + /// + /// \note If you want strict value retrieval semantics that do not allow for any type + /// conversions, use node_view::value_exact() instead. + /// + /// \see + /// - node_view::value() + /// - node_view::value_exact() + template <typename T> + TOML_NODISCARD optional<T> value() const noexcept(impl::value_retrieval_is_nothrow<T>) { + if (node_) return node_->template value<T>(); + return {}; + } + + /// \brief Gets the raw value contained by the referenced node, or a default. + /// + /// \tparam T Default value type. Must be one of the native TOML value types, + /// or convertible to it. + /// \param default_value The default value to return if the node wasn't a value, wasn't the + /// correct type, or no conversion was possible. + /// + /// \returns The underlying value if the node was a value of the matching type (or convertible + /// to it) and within the range of the output type, or the provided default. + /// + /// \note This function has the same permissive retrieval semantics as node::value(). If you + /// want strict value retrieval semantics that do not allow for any type conversions, use + /// node_view::value_exact() instead. + /// + /// \see + /// - node_view::value() + /// - node_view::value_exact() + template <typename T> + TOML_NODISCARD auto value_or(T&& default_value) const + noexcept(impl::value_retrieval_is_nothrow<T>) { + using namespace ::toml::impl; + + static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, + "Retrieving values as wide-character strings is only " + "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); + + if constexpr (is_wide_string<T>) { #if TOML_ENABLE_WINDOWS_COMPAT - if (node_) - return node_->value_or(static_cast<T&&>(default_value)); - return std::wstring{ static_cast<T&&>(default_value) }; + if (node_) return node_->value_or(static_cast<T&&>(default_value)); + return std::wstring{static_cast<T&&>(default_value)}; #else - static_assert(impl::always_false<T>, "Evaluated unreachable branch!"); + static_assert(impl::always_false<T>, "Evaluated unreachable branch!"); #endif - } - else - { - using value_type = - std::conditional_t<std::is_pointer_v<std::decay_t<T>>, - std::add_pointer_t<std::add_const_t<std::remove_pointer_t<std::decay_t<T>>>>, - std::decay_t<T>>; - - if (node_) - return node_->value_or(static_cast<T&&>(default_value)); - if constexpr (std::is_pointer_v<value_type>) - return value_type{ default_value }; - else - return static_cast<T&&>(default_value); - } - } - - /// \brief Gets a raw reference to the viewed node's underlying data. - /// - /// \warning This function is dangerous if used carelessly and **WILL** break your code if the - /// node_view didn't reference a node, or the chosen value type doesn't match the node's - /// actual type. In debug builds an assertion will fire when invalid accesses are attempted: \cpp - /// - /// auto tbl = toml::parse(R"( - /// min = 32 - /// max = 45 - /// )"sv); - /// - /// int64_t& min_ref = tbl["min"].ref<int64_t>(); // matching type - /// double& max_ref = tbl["max"].ref<double>(); // mismatched type, hits assert() - /// int64_t& foo_ref = tbl["foo"].ref<int64_t>(); // nonexistent key, hits assert() - /// \ecpp - /// - /// \note Specifying explicit ref qualifiers acts as an explicit ref-category cast, - /// whereas specifying explicit cv-ref qualifiers merges them with whatever - /// the cv qualification of the viewed node is (to ensure cv-correctness is propagated), e.g.: - /// | node_view | T | return type | - /// |-----------------------|------------------------|------------------------------| - /// | node_view<node> | std::string | std::string& | - /// | node_view<node> | std::string&& | std::string&& | - /// | node_view<const node> | volatile std::string | const volatile std::string& | - /// | node_view<const node> | volatile std::string&& | const volatile std::string&& | - /// - /// - /// \tparam T One of the TOML value types. - /// - /// \returns A reference to the underlying data. - template <typename T> - TOML_PURE_INLINE_GETTER - decltype(auto) ref() const noexcept - { - TOML_ASSERT_ASSUME(node_ && "toml::node_view::ref() called on a node_view that did not reference a node"); - return node_->template ref<T>(); - } - - /// @} - - /// \name Visitation - /// @{ - - private: - /// \cond - template <typename Func> - static constexpr bool visit_is_nothrow = noexcept(std::declval<viewed_type*>()->visit(std::declval<Func>())); - /// \endcond - - public: - /// \brief Invokes a visitor on the viewed node based on its concrete type. - /// - /// \remarks Has no effect if the view does not reference a node. - /// - /// \see node::visit() - template <typename Func> - decltype(auto) visit(Func&& visitor) const noexcept(visit_is_nothrow<Func&&>) - { - using return_type = decltype(node_->visit(static_cast<Func&&>(visitor))); - if (node_) - return node_->visit(static_cast<Func&&>(visitor)); - if constexpr (!std::is_void_v<return_type>) - return return_type{}; - } - - /// @} - - /// \name Equality - /// @{ - - public: - /// \brief Returns true if the two views refer to nodes of the same type and value. - template <typename T> - TOML_PURE_GETTER - friend bool operator==(const node_view& lhs, const node_view<T>& rhs) noexcept - { - return impl::node_deep_equality(lhs.node_, rhs.node_); - } - - /// \brief Returns true if the two views do not refer to nodes of the same type and value. - template <typename T> - TOML_PURE_GETTER - friend bool operator!=(const node_view& lhs, const node_view<T>& rhs) noexcept - { - return !impl::node_deep_equality(lhs.node_, rhs.node_); - } - - /// \brief Returns true if the viewed node is a table with the same contents as RHS. - TOML_NODISCARD - friend bool operator==(const node_view& lhs, const table& rhs) noexcept - { - if (lhs.node_ == &rhs) - return true; - const auto tbl = lhs.as<table>(); - return tbl && *tbl == rhs; - } - TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const table&, ); - - /// \brief Returns true if the viewed node is an array with the same contents as RHS. - TOML_NODISCARD - friend bool operator==(const node_view& lhs, const array& rhs) noexcept - { - if (lhs.node_ == &rhs) - return true; - const auto arr = lhs.as<array>(); - return arr && *arr == rhs; - } - TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const array&, ); - - /// \brief Returns true if the viewed node is a value with the same value as RHS. - template <typename T> - TOML_NODISCARD - friend bool operator==(const node_view& lhs, const toml::value<T>& rhs) noexcept - { - if (lhs.node_ == &rhs) - return true; - const auto val = lhs.as<T>(); - return val && *val == rhs; - } - TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const toml::value<T>&, template <typename T>); - - /// \brief Returns true if the viewed node is a value with the same value as RHS. - TOML_CONSTRAINED_TEMPLATE(impl::is_losslessly_convertible_to_native<T>, typename T) - TOML_NODISCARD - friend bool operator==(const node_view& lhs, const T& rhs) noexcept(!impl::is_wide_string<T>) - { - static_assert(!impl::is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, - "Comparison with wide-character strings is only " - "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); - - if constexpr (impl::is_wide_string<T>) - { + } else { + using value_type = std::conditional_t< + std::is_pointer_v<std::decay_t<T>>, + std::add_pointer_t<std::add_const_t<std::remove_pointer_t<std::decay_t<T>>>>, + std::decay_t<T>>; + + if (node_) return node_->value_or(static_cast<T&&>(default_value)); + if constexpr (std::is_pointer_v<value_type>) + return value_type{default_value}; + else + return static_cast<T&&>(default_value); + } + } + + /// \brief Gets a raw reference to the viewed node's underlying data. + /// + /// \warning This function is dangerous if used carelessly and **WILL** break your code if the + /// node_view didn't reference a node, or the chosen value type doesn't match the node's + /// actual type. In debug builds an assertion will fire when invalid accesses are + /// attempted: \cpp + /// + /// auto tbl = toml::parse(R"( + /// min = 32 + /// max = 45 + /// )"sv); + /// + /// int64_t& min_ref = tbl["min"].ref<int64_t>(); // matching type + /// double& max_ref = tbl["max"].ref<double>(); // mismatched type, hits assert() + /// int64_t& foo_ref = tbl["foo"].ref<int64_t>(); // nonexistent key, hits assert() + /// \ecpp + /// + /// \note Specifying explicit ref qualifiers acts as an explicit ref-category cast, + /// whereas specifying explicit cv-ref qualifiers merges them with whatever + /// the cv qualification of the viewed node is (to ensure cv-correctness is propagated), + ///e.g.: | node_view | T | return type | + /// |-----------------------|------------------------|------------------------------| + /// | node_view<node> | std::string | std::string& | + /// | node_view<node> | std::string&& | std::string&& | + /// | node_view<const node> | volatile std::string | const volatile std::string& | + /// | node_view<const node> | volatile std::string&& | const volatile std::string&& | + /// + /// + /// \tparam T One of the TOML value types. + /// + /// \returns A reference to the underlying data. + template <typename T> + TOML_PURE_INLINE_GETTER decltype(auto) ref() const noexcept { + TOML_ASSERT_ASSUME( + node_ && "toml::node_view::ref() called on a node_view that did not reference a node"); + return node_->template ref<T>(); + } + + /// @} + + /// \name Visitation + /// @{ + + private: + /// \cond + template <typename Func> + static constexpr bool visit_is_nothrow = + noexcept(std::declval<viewed_type*>()->visit(std::declval<Func>())); + /// \endcond + + public: + /// \brief Invokes a visitor on the viewed node based on its concrete type. + /// + /// \remarks Has no effect if the view does not reference a node. + /// + /// \see node::visit() + template <typename Func> + decltype(auto) visit(Func&& visitor) const noexcept(visit_is_nothrow<Func&&>) { + using return_type = decltype(node_->visit(static_cast<Func&&>(visitor))); + if (node_) return node_->visit(static_cast<Func&&>(visitor)); + if constexpr (!std::is_void_v<return_type>) return return_type{}; + } + + /// @} + + /// \name Equality + /// @{ + + public: + /// \brief Returns true if the two views refer to nodes of the same type and value. + template <typename T> + TOML_PURE_GETTER friend bool operator==(const node_view& lhs, + const node_view<T>& rhs) noexcept { + return impl::node_deep_equality(lhs.node_, rhs.node_); + } + + /// \brief Returns true if the two views do not refer to nodes of the same type and value. + template <typename T> + TOML_PURE_GETTER friend bool operator!=(const node_view& lhs, + const node_view<T>& rhs) noexcept { + return !impl::node_deep_equality(lhs.node_, rhs.node_); + } + + /// \brief Returns true if the viewed node is a table with the same contents as RHS. + TOML_NODISCARD + friend bool operator==(const node_view& lhs, const table& rhs) noexcept { + if (lhs.node_ == &rhs) return true; + const auto tbl = lhs.as<table>(); + return tbl && *tbl == rhs; + } + TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const table&, ); + + /// \brief Returns true if the viewed node is an array with the same contents as RHS. + TOML_NODISCARD + friend bool operator==(const node_view& lhs, const array& rhs) noexcept { + if (lhs.node_ == &rhs) return true; + const auto arr = lhs.as<array>(); + return arr && *arr == rhs; + } + TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const array&, ); + + /// \brief Returns true if the viewed node is a value with the same value as RHS. + template <typename T> + TOML_NODISCARD friend bool operator==(const node_view& lhs, + const toml::value<T>& rhs) noexcept { + if (lhs.node_ == &rhs) return true; + const auto val = lhs.as<T>(); + return val && *val == rhs; + } + TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const toml::value<T>&, template <typename T>); + + /// \brief Returns true if the viewed node is a value with the same value as RHS. + TOML_CONSTRAINED_TEMPLATE(impl::is_losslessly_convertible_to_native<T>, typename T) + TOML_NODISCARD + friend bool operator==(const node_view& lhs, const T& rhs) noexcept(!impl::is_wide_string<T>) { + static_assert(!impl::is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, + "Comparison with wide-character strings is only " + "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); + + if constexpr (impl::is_wide_string<T>) { #if TOML_ENABLE_WINDOWS_COMPAT - return lhs == impl::narrow(rhs); + return lhs == impl::narrow(rhs); #else - static_assert(impl::always_false<T>, "Evaluated unreachable branch!"); + static_assert(impl::always_false<T>, "Evaluated unreachable branch!"); #endif - } - else - { - const auto val = lhs.as<impl::native_type_of<T>>(); - return val && *val == rhs; - } - } - TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, - const T&, - TOML_CONSTRAINED_TEMPLATE(impl::is_losslessly_convertible_to_native<T>, - typename T)); - - /// \brief Returns true if the viewed node is an array with the same contents as the RHS initializer list. - template <typename T> - TOML_NODISCARD - friend bool operator==(const node_view& lhs, - const std::initializer_list<T>& rhs) noexcept(!impl::is_wide_string<T>) - { - const auto arr = lhs.as<array>(); - return arr && *arr == rhs; - } - TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::initializer_list<T>&, template <typename T>); - - /// \brief Returns true if the viewed node is an array with the same contents as the RHS vector. - template <typename T> - TOML_NODISCARD - friend bool operator==(const node_view& lhs, const std::vector<T>& rhs) noexcept(!impl::is_wide_string<T>) - { - const auto arr = lhs.as<array>(); - return arr && *arr == rhs; - } - TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::vector<T>&, template <typename T>); - - /// @} - - /// \name Subviews - /// @{ - - /// \brief Returns a view of the selected subnode. - /// - /// \param key The key of the node to retrieve - /// - /// \returns A view of the selected node if this node represented a table and it contained a - /// value at the given key, or an empty view. - TOML_NODISCARD - node_view operator[](std::string_view key) const noexcept - { - if (auto tbl = this->as_table()) - return node_view{ tbl->get(key) }; - return {}; - } - - /// \brief Returns a view of the selected subnode. - /// - /// \param path A "TOML path" to the desired subnode - /// - /// \returns A view of the selected node if this node represented a table and it contained a - /// value at the given key, or an empty view. - TOML_NODISCARD - node_view operator[](const toml::path& path) const noexcept - { - return node_ ? node_->at_path(path) : node_view{}; - } - - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #toml::node::at_path(std::string_view) - TOML_NODISCARD - node_view at_path(std::string_view path) const noexcept - { - return node_ ? node_->at_path(path) : node_view{}; - } - - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #toml::node::at_path(const toml::path&) - TOML_NODISCARD - node_view at_path(const toml::path& path) const noexcept - { - return node_ ? node_->at_path(path) : node_view{}; - } + } else { + const auto val = lhs.as<impl::native_type_of<T>>(); + return val && *val == rhs; + } + } + TOML_ASYMMETRICAL_EQUALITY_OPS( + const node_view&, const T&, + TOML_CONSTRAINED_TEMPLATE(impl::is_losslessly_convertible_to_native<T>, typename T)); + + /// \brief Returns true if the viewed node is an array with the same contents as the RHS + /// initializer list. + template <typename T> + TOML_NODISCARD friend bool operator==( + const node_view& lhs, + const std::initializer_list<T>& rhs) noexcept(!impl::is_wide_string<T>) { + const auto arr = lhs.as<array>(); + return arr && *arr == rhs; + } + TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::initializer_list<T>&, + template <typename T>); + + /// \brief Returns true if the viewed node is an array with the same contents as the RHS + /// vector. + template <typename T> + TOML_NODISCARD friend bool operator==(const node_view& lhs, const std::vector<T>& rhs) noexcept( + !impl::is_wide_string<T>) { + const auto arr = lhs.as<array>(); + return arr && *arr == rhs; + } + TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::vector<T>&, template <typename T>); + + /// @} + + /// \name Subviews + /// @{ + + /// \brief Returns a view of the selected subnode. + /// + /// \param key The key of the node to retrieve + /// + /// \returns A view of the selected node if this node represented a table and it contained a + /// value at the given key, or an empty view. + TOML_NODISCARD + node_view operator[](std::string_view key) const noexcept { + if (auto tbl = this->as_table()) return node_view{tbl->get(key)}; + return {}; + } + + /// \brief Returns a view of the selected subnode. + /// + /// \param path A "TOML path" to the desired subnode + /// + /// \returns A view of the selected node if this node represented a table and it contained a + /// value at the given key, or an empty view. + TOML_NODISCARD + node_view operator[](const toml::path& path) const noexcept { + return node_ ? node_->at_path(path) : node_view{}; + } + + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #toml::node::at_path(std::string_view) + TOML_NODISCARD + node_view at_path(std::string_view path) const noexcept { + return node_ ? node_->at_path(path) : node_view{}; + } + + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #toml::node::at_path(const toml::path&) + TOML_NODISCARD + node_view at_path(const toml::path& path) const noexcept { + return node_ ? node_->at_path(path) : node_view{}; + } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Returns a view of the selected subnode. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key The key of the node to retrieve - /// - /// \returns A view of the selected node if this node represented a table and it contained a - /// value at the given key, or an empty view. - TOML_NODISCARD - node_view operator[](std::wstring_view key) const - { - if (auto tbl = this->as_table()) - return node_view{ tbl->get(key) }; - return {}; - } - - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \see #toml::node::at_path(std::string_view) - TOML_NODISCARD - node_view at_path(std::wstring_view path) const - { - return node_ ? node_->at_path(path) : node_view{}; - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// \brief Returns a view of the selected subnode. - /// - /// \param index The index of the node to retrieve - /// - /// \returns A view of the selected node if this node represented an array and it contained a - /// value at the given index, or an empty view. - TOML_NODISCARD - node_view operator[](size_t index) const noexcept - { - if (auto arr = this->as_array()) - return node_view{ arr->get(index) }; - return {}; - } - - /// @} + /// \brief Returns a view of the selected subnode. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key The key of the node to retrieve + /// + /// \returns A view of the selected node if this node represented a table and it contained a + /// value at the given key, or an empty view. + TOML_NODISCARD + node_view operator[](std::wstring_view key) const { + if (auto tbl = this->as_table()) return node_view{tbl->get(key)}; + return {}; + } + + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \see #toml::node::at_path(std::string_view) + TOML_NODISCARD + node_view at_path(std::wstring_view path) const { + return node_ ? node_->at_path(path) : node_view{}; + } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// \brief Returns a view of the selected subnode. + /// + /// \param index The index of the node to retrieve + /// + /// \returns A view of the selected node if this node represented an array and it contained a + /// value at the given index, or an empty view. + TOML_NODISCARD + node_view operator[](size_t index) const noexcept { + if (auto arr = this->as_array()) return node_view{arr->get(index)}; + return {}; + } + + /// @} #if TOML_ENABLE_FORMATTERS - /// \brief Prints the viewed node out to a stream. - /// - /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. - friend std::ostream& operator<<(std::ostream& os, const node_view& nv) - { - if (nv.node_) - nv.node_->visit([&os](const auto& n) { os << n; }); - return os; - } + /// \brief Prints the viewed node out to a stream. + /// + /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. + friend std::ostream& operator<<(std::ostream& os, const node_view& nv) { + if (nv.node_) nv.node_->visit([&os](const auto& n) { os << n; }); + return os; + } #endif - }; + }; - /// \cond + /// \cond - template <typename T> - node_view(const T&) -> node_view<const node>; + template <typename T> + node_view(const T&) -> node_view<const node>; - template <typename T> - node_view(const T*) -> node_view<const node>; + template <typename T> + node_view(const T*) -> node_view<const node>; - template <typename T> - node_view(T&) -> node_view<node>; + template <typename T> + node_view(T&) -> node_view<node>; - template <typename T> - node_view(T*) -> node_view<node>; + template <typename T> + node_view(T*) -> node_view<node>; - /// \endcond + /// \endcond } TOML_NAMESPACE_END; /// \cond -TOML_NAMESPACE_START -{ - inline node::operator node_view<node>() noexcept - { - return node_view<node>{ this }; - } - - inline node::operator node_view<const node>() const noexcept - { - return node_view<const node>{ this }; - } +TOML_NAMESPACE_START { + inline node::operator node_view<node>() noexcept { + return node_view<node>{this}; + } + + inline node::operator node_view<const node>() const noexcept { + return node_view<const node>{this}; + } } TOML_NAMESPACE_END; /// \endcond diff --git a/vendor/toml++/impl/parse_error.hpp b/vendor/toml++/impl/parse_error.hpp index 05f2b6d..ef0a833 100644 --- a/vendor/toml++/impl/parse_error.hpp +++ b/vendor/toml++/impl/parse_error.hpp @@ -1,16 +1,16 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" #if TOML_ENABLE_PARSER -#include "std_except.hpp" -#include "source_region.hpp" -#include "print_to_stream.hpp" #include "header_start.hpp" +#include "print_to_stream.hpp" +#include "source_region.hpp" +#include "std_except.hpp" #if TOML_DOXYGEN || !TOML_EXCEPTIONS #define TOML_PARSE_ERROR_BASE @@ -18,122 +18,109 @@ #define TOML_PARSE_ERROR_BASE : public std::runtime_error #endif -TOML_NAMESPACE_START -{ - TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex); - - /// \brief An error generated when parsing fails. - /// - /// \remarks This class inherits from std::runtime_error when exceptions are enabled. - /// The public interface is the same regardless of exception mode. - class parse_error TOML_PARSE_ERROR_BASE - { - private: +TOML_NAMESPACE_START { + TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex); + + /// \brief An error generated when parsing fails. + /// + /// \remarks This class inherits from std::runtime_error when exceptions are enabled. + /// The public interface is the same regardless of exception mode. + class parse_error TOML_PARSE_ERROR_BASE { + private: #if !TOML_EXCEPTIONS - std::string description_; + std::string description_; #endif - source_region source_; + source_region source_; - public: + public: #if TOML_EXCEPTIONS - TOML_NODISCARD_CTOR - TOML_ATTR(nonnull) - parse_error(const char* desc, source_region&& src) noexcept // - : std::runtime_error{ desc }, - source_{ std::move(src) } - {} - - TOML_NODISCARD_CTOR - TOML_ATTR(nonnull) - parse_error(const char* desc, const source_region& src) noexcept // - : parse_error{ desc, source_region{ src } } - {} - - TOML_NODISCARD_CTOR - TOML_ATTR(nonnull) - parse_error(const char* desc, const source_position& position, const source_path_ptr& path = {}) noexcept - : parse_error{ desc, source_region{ position, position, path } } - {} + TOML_NODISCARD_CTOR + TOML_ATTR(nonnull) + parse_error(const char* desc, source_region&& src) noexcept // + : std::runtime_error{desc}, source_{std::move(src)} {} + + TOML_NODISCARD_CTOR + TOML_ATTR(nonnull) + parse_error(const char* desc, const source_region& src) noexcept // + : parse_error{desc, source_region{src}} {} + + TOML_NODISCARD_CTOR + TOML_ATTR(nonnull) + parse_error(const char* desc, const source_position& position, + const source_path_ptr& path = {}) noexcept + : parse_error{desc, source_region{position, position, path}} {} #else - TOML_NODISCARD_CTOR - parse_error(std::string&& desc, source_region&& src) noexcept // - : description_{ std::move(desc) }, - source_{ std::move(src) } - {} + TOML_NODISCARD_CTOR + parse_error(std::string&& desc, source_region&& src) noexcept // + : description_{std::move(desc)}, source_{std::move(src)} {} - TOML_NODISCARD_CTOR - parse_error(std::string&& desc, const source_region& src) noexcept // - : parse_error{ std::move(desc), source_region{ src } } - {} + TOML_NODISCARD_CTOR + parse_error(std::string&& desc, const source_region& src) noexcept // + : parse_error{std::move(desc), source_region{src}} {} - TOML_NODISCARD_CTOR - parse_error(std::string&& desc, const source_position& position, const source_path_ptr& path = {}) noexcept - : parse_error{ std::move(desc), source_region{ position, position, path } } - {} + TOML_NODISCARD_CTOR + parse_error(std::string&& desc, const source_position& position, + const source_path_ptr& path = {}) noexcept + : parse_error{std::move(desc), source_region{position, position, path}} {} #endif - /// \brief Returns a textual description of the error. - /// \remark The backing string is guaranteed to be null-terminated. - TOML_NODISCARD - std::string_view description() const noexcept - { + /// \brief Returns a textual description of the error. + /// \remark The backing string is guaranteed to be null-terminated. + TOML_NODISCARD + std::string_view description() const noexcept { #if TOML_EXCEPTIONS - return std::string_view{ what() }; + return std::string_view{what()}; #else - return description_; + return description_; #endif - } - - /// \brief Returns the region of the source document responsible for the error. - TOML_NODISCARD - const source_region& source() const noexcept - { - return source_; - } - - /// \brief Prints a parse_error to a stream. - /// - /// \detail \cpp - /// try - /// { - /// auto tbl = toml::parse("enabled = trUe"sv); - /// } - /// catch (const toml::parse_error & err) - /// { - /// std::cerr << "Parsing failed:\n"sv << err << "\n"; - /// } - /// \ecpp - /// - /// \out - /// Parsing failed: - /// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU' - /// (error occurred at line 1, column 13) - /// \eout - /// - /// \tparam Char The output stream's underlying character type. Must be 1 byte in size. - /// \param lhs The stream. - /// \param rhs The parse_error. - /// - /// \returns The input stream. - friend std::ostream& operator<<(std::ostream& lhs, const parse_error& rhs) - { - impl::print_to_stream(lhs, rhs.description()); - impl::print_to_stream(lhs, "\n\t(error occurred at "sv); - impl::print_to_stream(lhs, rhs.source()); - impl::print_to_stream(lhs, ")"sv); - return lhs; - } - }; - - TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS + } + + /// \brief Returns the region of the source document responsible for the error. + TOML_NODISCARD + const source_region& source() const noexcept { return source_; } + + /// \brief Prints a parse_error to a stream. + /// + /// \detail \cpp + /// try + /// { + /// auto tbl = toml::parse("enabled = trUe"sv); + /// } + /// catch (const toml::parse_error & err) + /// { + /// std::cerr << "Parsing failed:\n"sv << err << "\n"; + /// } + /// \ecpp + /// + /// \out + /// Parsing failed: + /// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU' + /// (error occurred at line 1, column 13) + /// \eout + /// + /// \tparam Char The output stream's underlying character type. Must be 1 byte in size. + /// \param lhs The stream. + /// \param rhs The parse_error. + /// + /// \returns The input stream. + friend std::ostream& operator<<(std::ostream& lhs, const parse_error& rhs) { + impl::print_to_stream(lhs, rhs.description()); + impl::print_to_stream(lhs, "\n\t(error occurred at "sv); + impl::print_to_stream(lhs, rhs.source()); + impl::print_to_stream(lhs, ")"sv); + return lhs; + } + }; + + TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS } TOML_NAMESPACE_END; #undef TOML_PARSE_ERROR_BASE #include "header_end.hpp" -#endif // TOML_ENABLE_PARSER +#endif // TOML_ENABLE_PARSER diff --git a/vendor/toml++/impl/parse_result.hpp b/vendor/toml++/impl/parse_result.hpp index 5837a0b..ca0e3f5 100644 --- a/vendor/toml++/impl/parse_result.hpp +++ b/vendor/toml++/impl/parse_result.hpp @@ -1,499 +1,431 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" #if TOML_DOXYGEN || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS) -#include "table.hpp" -#include "parse_error.hpp" #include "header_start.hpp" +#include "parse_error.hpp" +#include "table.hpp" -TOML_NAMESPACE_START -{ - TOML_ABI_NAMESPACE_START(noex); - - /// \brief The result of a parsing operation. - /// - /// \availability <strong>This type only exists when exceptions are disabled.</strong> - /// Otherwise parse_result is just an alias for toml::table: \cpp - /// #if TOML_EXCEPTIONS - /// using parse_result = table; - /// #else - /// class parse_result { // ... - /// #endif - /// \ecpp - /// - /// \detail A parse_result is effectively a discriminated union containing either a toml::table - /// or a toml::parse_error. Most member functions assume a particular one of these two states, - /// and calling them when in the wrong state will cause errors (e.g. attempting to access the - /// error object when parsing was successful). \cpp - /// toml::parse_result result = toml::parse_file("config.toml"); - /// if (result) - /// do_stuff_with_a_table(result); //implicitly converts to table& - /// else - /// std::cerr << "Parse failed:\n"sv << result.error() << "\n"; - /// \ecpp - /// - /// \out - /// example output: - /// - /// Parse failed: - /// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU' - /// (error occurred at line 1, column 13 of 'config.toml') - /// \eout - /// - /// Getting node_views (`operator[]`, `at_path()`) and using the iterator accessor functions (`begin()`, `end()` etc.) are - /// unconditionally safe; when parsing fails these just return 'empty' values. A ranged-for loop on a failed - /// parse_result is also safe since `begin()` and `end()` return the same iterator and will not lead to any - /// dereferences and iterations. - class parse_result - { - private: - struct storage_t - { - static constexpr size_t size = - (sizeof(toml::table) < sizeof(parse_error) ? sizeof(parse_error) : sizeof(toml::table)); - static constexpr size_t align = - (alignof(toml::table) < alignof(parse_error) ? alignof(parse_error) : alignof(toml::table)); - - alignas(align) unsigned char bytes[size]; - }; - - alignas(storage_t::align) mutable storage_t storage_; - bool err_; - - template <typename Type> - TOML_NODISCARD - TOML_ALWAYS_INLINE - static Type* get_as(storage_t& s) noexcept - { - return TOML_LAUNDER(reinterpret_cast<Type*>(s.bytes)); - } - - void destroy() noexcept - { - if (err_) - get_as<parse_error>(storage_)->~parse_error(); - else - get_as<toml::table>(storage_)->~table(); - } - - public: - /// \brief Default constructs an 'error' result. - TOML_NODISCARD_CTOR - parse_result() noexcept // - : err_{ true } - { - ::new (static_cast<void*>(storage_.bytes)) parse_error{ std::string{}, source_region{} }; - } - - TOML_NODISCARD_CTOR - explicit parse_result(toml::table&& tbl) noexcept // - : err_{ false } - { - ::new (static_cast<void*>(storage_.bytes)) toml::table{ std::move(tbl) }; - } - - TOML_NODISCARD_CTOR - explicit parse_result(parse_error&& err) noexcept // - : err_{ true } - { - ::new (static_cast<void*>(storage_.bytes)) parse_error{ std::move(err) }; - } - - /// \brief Move constructor. - TOML_NODISCARD_CTOR - parse_result(parse_result&& res) noexcept // - : err_{ res.err_ } - { - if (err_) - ::new (static_cast<void*>(storage_.bytes)) parse_error{ std::move(res).error() }; - else - ::new (static_cast<void*>(storage_.bytes)) toml::table{ std::move(res).table() }; - } - - /// \brief Move-assignment operator. - parse_result& operator=(parse_result&& rhs) noexcept - { - if (err_ != rhs.err_) - { - destroy(); - err_ = rhs.err_; - if (err_) - ::new (static_cast<void*>(storage_.bytes)) parse_error{ std::move(rhs).error() }; - else - ::new (static_cast<void*>(storage_.bytes)) toml::table{ std::move(rhs).table() }; - } - else - { - if (err_) - error() = std::move(rhs).error(); - else - table() = std::move(rhs).table(); - } - return *this; - } - - /// \brief Destructor. - ~parse_result() noexcept - { - destroy(); - } - - /// \name Result state - /// @{ - - /// \brief Returns true if parsing succeeeded. - TOML_NODISCARD - bool succeeded() const noexcept - { - return !err_; - } - - /// \brief Returns true if parsing failed. - TOML_NODISCARD - bool failed() const noexcept - { - return err_; - } - - /// \brief Returns true if parsing succeeded. - TOML_NODISCARD - explicit operator bool() const noexcept - { - return !err_; - } - - /// @} - - /// \name Successful parses - /// \warning It is undefined behaviour to call these functions when the result respresents a failed parse. - /// Check #failed(), #succeeded or #operator bool() to determine the result's state. - /// @{ - - /// \brief Returns the internal toml::table. - TOML_NODISCARD - toml::table& table() & noexcept - { - TOML_ASSERT_ASSUME(!err_); - return *get_as<toml::table>(storage_); - } - - /// \brief Returns the internal toml::table (rvalue overload). - TOML_NODISCARD - toml::table&& table() && noexcept - { - TOML_ASSERT_ASSUME(!err_); - return static_cast<toml::table&&>(*get_as<toml::table>(storage_)); - } - - /// \brief Returns the internal toml::table (const lvalue overload). - TOML_NODISCARD - const toml::table& table() const& noexcept - { - TOML_ASSERT_ASSUME(!err_); - return *get_as<const toml::table>(storage_); - } - - /// \brief Returns the internal toml::table. - TOML_NODISCARD - /* implicit */ operator toml::table&() noexcept - { - return table(); - } - - /// \brief Returns the internal toml::table (rvalue overload). - TOML_NODISCARD - /* implicit */ operator toml::table&&() noexcept - { - return std::move(table()); - } - - /// \brief Returns the internal toml::table (const lvalue overload). - TOML_NODISCARD - /* implicit */ operator const toml::table&() const noexcept - { - return table(); - } - - /// @} - - /// \name Failed parses - /// \warning It is undefined behaviour to call these functions when the result respresents a successful parse. - /// Check #failed(), #succeeded or #operator bool() to determine the result's state. - /// @{ - - /// \brief Returns the internal toml::parse_error. - TOML_NODISCARD - parse_error& error() & noexcept - { - TOML_ASSERT_ASSUME(err_); - return *get_as<parse_error>(storage_); - } - - /// \brief Returns the internal toml::parse_error (rvalue overload). - TOML_NODISCARD - parse_error&& error() && noexcept - { - TOML_ASSERT_ASSUME(err_); - return static_cast<parse_error&&>(*get_as<parse_error>(storage_)); - } - - /// \brief Returns the internal toml::parse_error (const lvalue overload). - TOML_NODISCARD - const parse_error& error() const& noexcept - { - TOML_ASSERT_ASSUME(err_); - return *get_as<const parse_error>(storage_); - } - - /// \brief Returns the internal toml::parse_error. - TOML_NODISCARD - explicit operator parse_error&() noexcept - { - return error(); - } - - /// \brief Returns the internal toml::parse_error (rvalue overload). - TOML_NODISCARD - explicit operator parse_error&&() noexcept - { - return std::move(error()); - } - - /// \brief Returns the internal toml::parse_error (const lvalue overload). - TOML_NODISCARD - explicit operator const parse_error&() const noexcept - { - return error(); - } - - /// @} - - /// \name Iteration - /// @{ - - /// \brief A BidirectionalIterator for iterating over key-value pairs in a wrapped toml::table. - using iterator = table_iterator; - - /// \brief A BidirectionalIterator for iterating over const key-value pairs in a wrapped toml::table. - using const_iterator = const_table_iterator; - - /// \brief Returns an iterator to the first key-value pair in the wrapped table. - /// \remarks Always returns the same value as #end() if parsing failed. - TOML_NODISCARD - table_iterator begin() noexcept - { - return err_ ? table_iterator{} : table().begin(); - } - - /// \brief Returns an iterator to the first key-value pair in the wrapped table. - /// \remarks Always returns the same value as #end() if parsing failed. - TOML_NODISCARD - const_table_iterator begin() const noexcept - { - return err_ ? const_table_iterator{} : table().begin(); - } - - /// \brief Returns an iterator to the first key-value pair in the wrapped table. - /// \remarks Always returns the same value as #cend() if parsing failed. - TOML_NODISCARD - const_table_iterator cbegin() const noexcept - { - return err_ ? const_table_iterator{} : table().cbegin(); - } - - /// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table. - TOML_NODISCARD - table_iterator end() noexcept - { - return err_ ? table_iterator{} : table().end(); - } - - /// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table. - TOML_NODISCARD - const_table_iterator end() const noexcept - { - return err_ ? const_table_iterator{} : table().end(); - } - - /// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table. - TOML_NODISCARD - const_table_iterator cend() const noexcept - { - return err_ ? const_table_iterator{} : table().cend(); - } - - /// @} - - /// \name Node views - /// @{ - - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #toml::node::at_path(std::string_view) - TOML_NODISCARD - node_view<node> at_path(std::string_view path) noexcept - { - return err_ ? node_view<node>{} : table().at_path(path); - } - - /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #toml::node::at_path(std::string_view) - TOML_NODISCARD - node_view<const node> at_path(std::string_view path) const noexcept - { - return err_ ? node_view<const node>{} : table().at_path(path); - } - - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #toml::node::at_path(const toml::path&) - TOML_NODISCARD - node_view<node> at_path(const toml::path& path) noexcept - { - return err_ ? node_view<node>{} : table().at_path(path); - } - - /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #toml::node::at_path(const toml::path&) - TOML_NODISCARD - node_view<const node> at_path(const toml::path& path) const noexcept - { - return err_ ? node_view<const node>{} : table().at_path(path); - } +TOML_NAMESPACE_START { + TOML_ABI_NAMESPACE_START(noex); + + /// \brief The result of a parsing operation. + /// + /// \availability <strong>This type only exists when exceptions are disabled.</strong> + /// Otherwise parse_result is just an alias for toml::table: \cpp + /// #if TOML_EXCEPTIONS + /// using parse_result = table; + /// #else + /// class parse_result { // ... + /// #endif + /// \ecpp + /// + /// \detail A parse_result is effectively a discriminated union containing either a toml::table + /// or a toml::parse_error. Most member functions assume a particular one of these two states, + /// and calling them when in the wrong state will cause errors (e.g. attempting to access the + /// error object when parsing was successful). \cpp + /// toml::parse_result result = toml::parse_file("config.toml"); + /// if (result) + /// do_stuff_with_a_table(result); //implicitly converts to table& + /// else + /// std::cerr << "Parse failed:\n"sv << result.error() << "\n"; + /// \ecpp + /// + /// \out + /// example output: + /// + /// Parse failed: + /// Encountered unexpected character while parsing boolean; expected 'true', saw 'trU' + /// (error occurred at line 1, column 13 of 'config.toml') + /// \eout + /// + /// Getting node_views (`operator[]`, `at_path()`) and using the iterator accessor functions + /// (`begin()`, `end()` etc.) are unconditionally safe; when parsing fails these just return + /// 'empty' values. A ranged-for loop on a failed parse_result is also safe since `begin()` and + /// `end()` return the same iterator and will not lead to any dereferences and iterations. + class parse_result { + private: + struct storage_t { + static constexpr size_t size = + (sizeof(toml::table) < sizeof(parse_error) ? sizeof(parse_error) : sizeof(toml::table)); + static constexpr size_t align = + (alignof(toml::table) < alignof(parse_error) ? alignof(parse_error) + : alignof(toml::table)); + + alignas(align) unsigned char bytes[size]; + }; + + alignas(storage_t::align) mutable storage_t storage_; + bool err_; + + template <typename Type> + TOML_NODISCARD TOML_ALWAYS_INLINE static Type* get_as(storage_t& s) noexcept { + return TOML_LAUNDER(reinterpret_cast<Type*>(s.bytes)); + } + + void destroy() noexcept { + if (err_) + get_as<parse_error>(storage_)->~parse_error(); + else + get_as<toml::table>(storage_)->~table(); + } + + public: + /// \brief Default constructs an 'error' result. + TOML_NODISCARD_CTOR + parse_result() noexcept // + : err_{true} { + ::new (static_cast<void*>(storage_.bytes)) parse_error{std::string{}, source_region{}}; + } + + TOML_NODISCARD_CTOR + explicit parse_result(toml::table&& tbl) noexcept // + : err_{false} { + ::new (static_cast<void*>(storage_.bytes)) toml::table{std::move(tbl)}; + } + + TOML_NODISCARD_CTOR + explicit parse_result(parse_error&& err) noexcept // + : err_{true} { + ::new (static_cast<void*>(storage_.bytes)) parse_error{std::move(err)}; + } + + /// \brief Move constructor. + TOML_NODISCARD_CTOR + parse_result(parse_result&& res) noexcept // + : err_{res.err_} { + if (err_) + ::new (static_cast<void*>(storage_.bytes)) parse_error{std::move(res).error()}; + else + ::new (static_cast<void*>(storage_.bytes)) toml::table{std::move(res).table()}; + } + + /// \brief Move-assignment operator. + parse_result& operator=(parse_result&& rhs) noexcept { + if (err_ != rhs.err_) { + destroy(); + err_ = rhs.err_; + if (err_) + ::new (static_cast<void*>(storage_.bytes)) parse_error{std::move(rhs).error()}; + else + ::new (static_cast<void*>(storage_.bytes)) toml::table{std::move(rhs).table()}; + } else { + if (err_) + error() = std::move(rhs).error(); + else + table() = std::move(rhs).table(); + } + return *this; + } + + /// \brief Destructor. + ~parse_result() noexcept { destroy(); } + + /// \name Result state + /// @{ + + /// \brief Returns true if parsing succeeeded. + TOML_NODISCARD + bool succeeded() const noexcept { return !err_; } + + /// \brief Returns true if parsing failed. + TOML_NODISCARD + bool failed() const noexcept { return err_; } + + /// \brief Returns true if parsing succeeded. + TOML_NODISCARD + explicit operator bool() const noexcept { return !err_; } + + /// @} + + /// \name Successful parses + /// \warning It is undefined behaviour to call these functions when the result respresents a + /// failed parse. Check #failed(), #succeeded or #operator bool() to determine the result's + /// state. + /// @{ + + /// \brief Returns the internal toml::table. + TOML_NODISCARD + toml::table& table() & noexcept { + TOML_ASSERT_ASSUME(!err_); + return *get_as<toml::table>(storage_); + } + + /// \brief Returns the internal toml::table (rvalue overload). + TOML_NODISCARD + toml::table&& table() && noexcept { + TOML_ASSERT_ASSUME(!err_); + return static_cast<toml::table&&>(*get_as<toml::table>(storage_)); + } + + /// \brief Returns the internal toml::table (const lvalue overload). + TOML_NODISCARD + const toml::table& table() const& noexcept { + TOML_ASSERT_ASSUME(!err_); + return *get_as<const toml::table>(storage_); + } + + /// \brief Returns the internal toml::table. + TOML_NODISCARD + /* implicit */ operator toml::table&() noexcept { return table(); } + + /// \brief Returns the internal toml::table (rvalue overload). + TOML_NODISCARD + /* implicit */ operator toml::table&&() noexcept { return std::move(table()); } + + /// \brief Returns the internal toml::table (const lvalue overload). + TOML_NODISCARD + /* implicit */ operator const toml::table&() const noexcept { return table(); } + + /// @} + + /// \name Failed parses + /// \warning It is undefined behaviour to call these functions when the result respresents a + /// successful parse. Check #failed(), #succeeded or #operator bool() to determine the result's + /// state. + /// @{ + + /// \brief Returns the internal toml::parse_error. + TOML_NODISCARD + parse_error& error() & noexcept { + TOML_ASSERT_ASSUME(err_); + return *get_as<parse_error>(storage_); + } + + /// \brief Returns the internal toml::parse_error (rvalue overload). + TOML_NODISCARD + parse_error&& error() && noexcept { + TOML_ASSERT_ASSUME(err_); + return static_cast<parse_error&&>(*get_as<parse_error>(storage_)); + } + + /// \brief Returns the internal toml::parse_error (const lvalue overload). + TOML_NODISCARD + const parse_error& error() const& noexcept { + TOML_ASSERT_ASSUME(err_); + return *get_as<const parse_error>(storage_); + } + + /// \brief Returns the internal toml::parse_error. + TOML_NODISCARD + explicit operator parse_error&() noexcept { return error(); } + + /// \brief Returns the internal toml::parse_error (rvalue overload). + TOML_NODISCARD + explicit operator parse_error&&() noexcept { return std::move(error()); } + + /// \brief Returns the internal toml::parse_error (const lvalue overload). + TOML_NODISCARD + explicit operator const parse_error&() const noexcept { return error(); } + + /// @} + + /// \name Iteration + /// @{ + + /// \brief A BidirectionalIterator for iterating over key-value pairs in a wrapped toml::table. + using iterator = table_iterator; + + /// \brief A BidirectionalIterator for iterating over const key-value pairs in a wrapped + /// toml::table. + using const_iterator = const_table_iterator; + + /// \brief Returns an iterator to the first key-value pair in the wrapped table. + /// \remarks Always returns the same value as #end() if parsing failed. + TOML_NODISCARD + table_iterator begin() noexcept { return err_ ? table_iterator{} : table().begin(); } + + /// \brief Returns an iterator to the first key-value pair in the wrapped table. + /// \remarks Always returns the same value as #end() if parsing failed. + TOML_NODISCARD + const_table_iterator begin() const noexcept { + return err_ ? const_table_iterator{} : table().begin(); + } + + /// \brief Returns an iterator to the first key-value pair in the wrapped table. + /// \remarks Always returns the same value as #cend() if parsing failed. + TOML_NODISCARD + const_table_iterator cbegin() const noexcept { + return err_ ? const_table_iterator{} : table().cbegin(); + } + + /// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table. + TOML_NODISCARD + table_iterator end() noexcept { return err_ ? table_iterator{} : table().end(); } + + /// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table. + TOML_NODISCARD + const_table_iterator end() const noexcept { + return err_ ? const_table_iterator{} : table().end(); + } + + /// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table. + TOML_NODISCARD + const_table_iterator cend() const noexcept { + return err_ ? const_table_iterator{} : table().cend(); + } + + /// @} + + /// \name Node views + /// @{ + + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #toml::node::at_path(std::string_view) + TOML_NODISCARD + node_view<node> at_path(std::string_view path) noexcept { + return err_ ? node_view<node>{} : table().at_path(path); + } + + /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #toml::node::at_path(std::string_view) + TOML_NODISCARD + node_view<const node> at_path(std::string_view path) const noexcept { + return err_ ? node_view<const node>{} : table().at_path(path); + } + + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #toml::node::at_path(const toml::path&) + TOML_NODISCARD + node_view<node> at_path(const toml::path& path) noexcept { + return err_ ? node_view<node>{} : table().at_path(path); + } + + /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #toml::node::at_path(const toml::path&) + TOML_NODISCARD + node_view<const node> at_path(const toml::path& path) const noexcept { + return err_ ? node_view<const node>{} : table().at_path(path); + } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \see #toml::node::at_path(std::string_view) - TOML_NODISCARD - node_view<node> at_path(std::wstring_view path) - { - return err_ ? node_view<node>{} : table().at_path(path); - } - - /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \see #toml::node::at_path(std::string_view) - TOML_NODISCARD - node_view<const node> at_path(std::wstring_view path) const - { - return err_ ? node_view<const node>{} : table().at_path(path); - } + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \see #toml::node::at_path(std::string_view) + TOML_NODISCARD + node_view<node> at_path(std::wstring_view path) { + return err_ ? node_view<node>{} : table().at_path(path); + } + + /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \see #toml::node::at_path(std::string_view) + TOML_NODISCARD + node_view<const node> at_path(std::wstring_view path) const { + return err_ ? node_view<const node>{} : table().at_path(path); + } #endif - /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #toml::node::operator[](const toml::path&) - TOML_NODISCARD - node_view<node> operator[](const toml::path& path) noexcept - { - return err_ ? node_view<node>{} : table()[path]; - } - - /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". - /// - /// \see #toml::node::operator[](const toml::path&) - TOML_NODISCARD - node_view<const node> operator[](const toml::path& path) const noexcept - { - return err_ ? node_view<const node>{} : table()[path]; - } - - /// \brief Gets a node_view for the selected key-value pair in the wrapped table. - /// - /// \param key The key used for the lookup. - /// - /// \returns A view of the value at the given key if parsing was successful and a matching key existed, - /// or an empty node view. - /// - /// \see toml::node_view - TOML_NODISCARD - node_view<node> operator[](std::string_view key) noexcept - { - return err_ ? node_view<node>{} : table()[key]; - } - - /// \brief Gets a node_view for the selected key-value pair in the wrapped table (const overload). - /// - /// \param key The key used for the lookup. - /// - /// \returns A view of the value at the given key if parsing was successful and a matching key existed, - /// or an empty node view. - /// - /// \see toml::node_view - TOML_NODISCARD - node_view<const node> operator[](std::string_view key) const noexcept - { - return err_ ? node_view<const node>{} : table()[key]; - } + /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #toml::node::operator[](const toml::path&) + TOML_NODISCARD + node_view<node> operator[](const toml::path& path) noexcept { + return err_ ? node_view<node>{} : table()[path]; + } + + /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". + /// + /// \see #toml::node::operator[](const toml::path&) + TOML_NODISCARD + node_view<const node> operator[](const toml::path& path) const noexcept { + return err_ ? node_view<const node>{} : table()[path]; + } + + /// \brief Gets a node_view for the selected key-value pair in the wrapped table. + /// + /// \param key The key used for the lookup. + /// + /// \returns A view of the value at the given key if parsing was successful and a matching key + /// existed, or an empty node view. + /// + /// \see toml::node_view + TOML_NODISCARD + node_view<node> operator[](std::string_view key) noexcept { + return err_ ? node_view<node>{} : table()[key]; + } + + /// \brief Gets a node_view for the selected key-value pair in the wrapped table (const + /// overload). + /// + /// \param key The key used for the lookup. + /// + /// \returns A view of the value at the given key if parsing was successful and a matching key + /// existed, or an empty node view. + /// + /// \see toml::node_view + TOML_NODISCARD + node_view<const node> operator[](std::string_view key) const noexcept { + return err_ ? node_view<const node>{} : table()[key]; + } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Gets a node_view for the selected key-value pair in the wrapped table. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key The key used for the lookup. - /// - /// \returns A view of the value at the given key if parsing was successful and a matching key existed, - /// or an empty node view. - /// - /// \see toml::node_view - TOML_NODISCARD - node_view<node> operator[](std::wstring_view key) - { - return err_ ? node_view<node>{} : table()[key]; - } - - /// \brief Gets a node_view for the selected key-value pair in the wrapped table (const overload). - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key The key used for the lookup. - /// - /// \returns A view of the value at the given key if parsing was successful and a matching key existed, - /// or an empty node view. - /// - /// \see toml::node_view - TOML_NODISCARD - node_view<const node> operator[](std::wstring_view key) const - { - return err_ ? node_view<const node>{} : table()[key]; - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// @} + /// \brief Gets a node_view for the selected key-value pair in the wrapped table. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key The key used for the lookup. + /// + /// \returns A view of the value at the given key if parsing was successful and a matching key + /// existed, or an empty node view. + /// + /// \see toml::node_view + TOML_NODISCARD + node_view<node> operator[](std::wstring_view key) { + return err_ ? node_view<node>{} : table()[key]; + } + + /// \brief Gets a node_view for the selected key-value pair in the wrapped table (const + /// overload). + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key The key used for the lookup. + /// + /// \returns A view of the value at the given key if parsing was successful and a matching key + /// existed, or an empty node view. + /// + /// \see toml::node_view + TOML_NODISCARD + node_view<const node> operator[](std::wstring_view key) const { + return err_ ? node_view<const node>{} : table()[key]; + } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// @} #if TOML_ENABLE_FORMATTERS - /// \brief Prints the held error or table object out to a text stream. - /// - /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. - friend std::ostream& operator<<(std::ostream& os, const parse_result& result) - { - return result.err_ ? (os << result.error()) : (os << result.table()); - } + /// \brief Prints the held error or table object out to a text stream. + /// + /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. + friend std::ostream& operator<<(std::ostream& os, const parse_result& result) { + return result.err_ ? (os << result.error()) : (os << result.table()); + } #endif - }; + }; - TOML_ABI_NAMESPACE_END; + TOML_ABI_NAMESPACE_END; } TOML_NAMESPACE_END; #include "header_end.hpp" -#endif // TOML_ENABLE_PARSER && !TOML_EXCEPTIONS +#endif // TOML_ENABLE_PARSER && !TOML_EXCEPTIONS diff --git a/vendor/toml++/impl/parser.hpp b/vendor/toml++/impl/parser.hpp index c794c5e..281efbc 100644 --- a/vendor/toml++/impl/parser.hpp +++ b/vendor/toml++/impl/parser.hpp @@ -1,390 +1,386 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" #if TOML_ENABLE_PARSER -#include "table.hpp" -#include "parse_result.hpp" #include "header_start.hpp" +#include "parse_result.hpp" +#include "table.hpp" -TOML_NAMESPACE_START -{ - TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex); +TOML_NAMESPACE_START { + TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex); - /// \brief Parses a TOML document from a string view. - /// - /// \detail \cpp - /// auto tbl = toml::parse("a = 3"sv); - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param doc The TOML document to parse. Must be valid UTF-8. - /// \param source_path The path used to initialize each node's `source().path`. - /// If you don't have a path (or you have no intention of using paths in diagnostics) - /// then this parameter can safely be left blank. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse(std::string_view doc, std::string_view source_path = {}); + /// \brief Parses a TOML document from a string view. + /// + /// \detail \cpp + /// auto tbl = toml::parse("a = 3"sv); + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param doc The TOML document to parse. Must be valid UTF-8. + /// \param source_path The path used to initialize each node's `source().path`. + /// If you don't have a path (or you have no intention of using paths in diagnostics) + /// then this parameter can safely be left blank. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse(std::string_view doc, std::string_view source_path = {}); - /// \brief Parses a TOML document from a string view. - /// - /// \detail \cpp - /// auto tbl = toml::parse("a = 3"sv, "foo.toml"); - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param doc The TOML document to parse. Must be valid UTF-8. - /// \param source_path The path used to initialize each node's `source().path`. - /// If you don't have a path (or you have no intention of using paths in diagnostics) - /// then this parameter can safely be left blank. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse(std::string_view doc, std::string && source_path); + /// \brief Parses a TOML document from a string view. + /// + /// \detail \cpp + /// auto tbl = toml::parse("a = 3"sv, "foo.toml"); + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param doc The TOML document to parse. Must be valid UTF-8. + /// \param source_path The path used to initialize each node's `source().path`. + /// If you don't have a path (or you have no intention of using paths in diagnostics) + /// then this parameter can safely be left blank. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse(std::string_view doc, std::string && source_path); - /// \brief Parses a TOML document from a file. - /// - /// \detail \cpp - /// toml::parse_result get_foo_toml() - /// { - /// return toml::parse_file("foo.toml"); - /// } - /// \ecpp - /// - /// \param file_path The TOML document to parse. Must be valid UTF-8. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse_file(std::string_view file_path); + /// \brief Parses a TOML document from a file. + /// + /// \detail \cpp + /// toml::parse_result get_foo_toml() + /// { + /// return toml::parse_file("foo.toml"); + /// } + /// \ecpp + /// + /// \param file_path The TOML document to parse. Must be valid UTF-8. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse_file(std::string_view file_path); #if TOML_HAS_CHAR8 - /// \brief Parses a TOML document from a char8_t string view. - /// - /// \detail \cpp - /// auto tbl = toml::parse(u8"a = 3"sv); - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param doc The TOML document to parse. Must be valid UTF-8. - /// \param source_path The path used to initialize each node's `source().path`. - /// If you don't have a path (or you have no intention of using paths in diagnostics) - /// then this parameter can safely be left blank. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse(std::u8string_view doc, std::string_view source_path = {}); + /// \brief Parses a TOML document from a char8_t string view. + /// + /// \detail \cpp + /// auto tbl = toml::parse(u8"a = 3"sv); + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param doc The TOML document to parse. Must be valid UTF-8. + /// \param source_path The path used to initialize each node's `source().path`. + /// If you don't have a path (or you have no intention of using paths in diagnostics) + /// then this parameter can safely be left blank. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse(std::u8string_view doc, std::string_view source_path = {}); - /// \brief Parses a TOML document from a char8_t string view. - /// - /// \detail \cpp - /// auto tbl = toml::parse(u8"a = 3"sv, "foo.toml"); - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param doc The TOML document to parse. Must be valid UTF-8. - /// \param source_path The path used to initialize each node's `source().path`. - /// If you don't have a path (or you have no intention of using paths in diagnostics) - /// then this parameter can safely be left blank. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse(std::u8string_view doc, std::string && source_path); + /// \brief Parses a TOML document from a char8_t string view. + /// + /// \detail \cpp + /// auto tbl = toml::parse(u8"a = 3"sv, "foo.toml"); + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param doc The TOML document to parse. Must be valid UTF-8. + /// \param source_path The path used to initialize each node's `source().path`. + /// If you don't have a path (or you have no intention of using paths in diagnostics) + /// then this parameter can safely be left blank. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse(std::u8string_view doc, std::string && source_path); - /// \brief Parses a TOML document from a file. - /// - /// \detail \cpp - /// toml::parse_result get_foo_toml() - /// { - /// return toml::parse_file(u8"foo.toml"); - /// } - /// \ecpp - /// - /// \param file_path The TOML document to parse. Must be valid UTF-8. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse_file(std::u8string_view file_path); + /// \brief Parses a TOML document from a file. + /// + /// \detail \cpp + /// toml::parse_result get_foo_toml() + /// { + /// return toml::parse_file(u8"foo.toml"); + /// } + /// \ecpp + /// + /// \param file_path The TOML document to parse. Must be valid UTF-8. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse_file(std::u8string_view file_path); -#endif // TOML_HAS_CHAR8 +#endif // TOML_HAS_CHAR8 #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Parses a TOML document from a string view. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \detail \cpp - /// auto tbl = toml::parse("a = 3"sv, L"foo.toml"); - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param doc The TOML document to parse. Must be valid UTF-8. - /// \param source_path The path used to initialize each node's `source().path`. - /// If you don't have a path (or you have no intention of using paths in diagnostics) - /// then this parameter can safely be left blank. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse(std::string_view doc, std::wstring_view source_path); + /// \brief Parses a TOML document from a string view. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \detail \cpp + /// auto tbl = toml::parse("a = 3"sv, L"foo.toml"); + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param doc The TOML document to parse. Must be valid UTF-8. + /// \param source_path The path used to initialize each node's `source().path`. + /// If you don't have a path (or you have no intention of using paths in diagnostics) + /// then this parameter can safely be left blank. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse(std::string_view doc, std::wstring_view source_path); - /// \brief Parses a TOML document from a stream. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \detail \cpp - /// std::stringstream ss; - /// ss << "a = 3"sv; - /// - /// auto tbl = toml::parse(ss); - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param doc The TOML document to parse. Must be valid UTF-8. - /// \param source_path The path used to initialize each node's `source().path`. - /// If you don't have a path (or you have no intention of using paths in diagnostics) - /// then this parameter can safely be left blank. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse(std::istream & doc, std::wstring_view source_path); + /// \brief Parses a TOML document from a stream. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \detail \cpp + /// std::stringstream ss; + /// ss << "a = 3"sv; + /// + /// auto tbl = toml::parse(ss); + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param doc The TOML document to parse. Must be valid UTF-8. + /// \param source_path The path used to initialize each node's `source().path`. + /// If you don't have a path (or you have no intention of using paths in diagnostics) + /// then this parameter can safely be left blank. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse(std::istream & doc, std::wstring_view source_path); - /// \brief Parses a TOML document from a file. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \detail \cpp - /// toml::parse_result get_foo_toml() - /// { - /// return toml::parse_file(L"foo.toml"); - /// } - /// \ecpp - /// - /// \param file_path The TOML document to parse. Must be valid UTF-8. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse_file(std::wstring_view file_path); + /// \brief Parses a TOML document from a file. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \detail \cpp + /// toml::parse_result get_foo_toml() + /// { + /// return toml::parse_file(L"foo.toml"); + /// } + /// \ecpp + /// + /// \param file_path The TOML document to parse. Must be valid UTF-8. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse_file(std::wstring_view file_path); -#endif // TOML_ENABLE_WINDOWS_COMPAT +#endif // TOML_ENABLE_WINDOWS_COMPAT #if TOML_HAS_CHAR8 && TOML_ENABLE_WINDOWS_COMPAT - /// \brief Parses a TOML document from a char8_t string view. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \detail \cpp - /// auto tbl = toml::parse(u8"a = 3"sv, L"foo.toml"); - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param doc The TOML document to parse. Must be valid UTF-8. - /// \param source_path The path used to initialize each node's `source().path`. - /// If you don't have a path (or you have no intention of using paths in diagnostics) - /// then this parameter can safely be left blank. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse(std::u8string_view doc, std::wstring_view source_path); + /// \brief Parses a TOML document from a char8_t string view. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \detail \cpp + /// auto tbl = toml::parse(u8"a = 3"sv, L"foo.toml"); + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param doc The TOML document to parse. Must be valid UTF-8. + /// \param source_path The path used to initialize each node's `source().path`. + /// If you don't have a path (or you have no intention of using paths in diagnostics) + /// then this parameter can safely be left blank. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse(std::u8string_view doc, std::wstring_view source_path); -#endif // TOML_HAS_CHAR8 && TOML_ENABLE_WINDOWS_COMPAT +#endif // TOML_HAS_CHAR8 && TOML_ENABLE_WINDOWS_COMPAT - /// \brief Parses a TOML document from a stream. - /// - /// \detail \cpp - /// std::stringstream ss; - /// ss << "a = 3"sv; - /// - /// auto tbl = toml::parse(ss); - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param doc The TOML document to parse. Must be valid UTF-8. - /// \param source_path The path used to initialize each node's `source().path`. - /// If you don't have a path (or you have no intention of using paths in diagnostics) - /// then this parameter can safely be left blank. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse(std::istream & doc, std::string_view source_path = {}); + /// \brief Parses a TOML document from a stream. + /// + /// \detail \cpp + /// std::stringstream ss; + /// ss << "a = 3"sv; + /// + /// auto tbl = toml::parse(ss); + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param doc The TOML document to parse. Must be valid UTF-8. + /// \param source_path The path used to initialize each node's `source().path`. + /// If you don't have a path (or you have no intention of using paths in diagnostics) + /// then this parameter can safely be left blank. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse(std::istream & doc, std::string_view source_path = {}); - /// \brief Parses a TOML document from a stream. - /// - /// \detail \cpp - /// std::stringstream ss; - /// ss << "a = 3"sv; - /// - /// auto tbl = toml::parse(ss, "foo.toml"); - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param doc The TOML document to parse. Must be valid UTF-8. - /// \param source_path The path used to initialize each node's `source().path`. - /// If you don't have a path (or you have no intention of using paths in diagnostics) - /// then this parameter can safely be left blank. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - parse_result TOML_CALLCONV parse(std::istream & doc, std::string && source_path); + /// \brief Parses a TOML document from a stream. + /// + /// \detail \cpp + /// std::stringstream ss; + /// ss << "a = 3"sv; + /// + /// auto tbl = toml::parse(ss, "foo.toml"); + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param doc The TOML document to parse. Must be valid UTF-8. + /// \param source_path The path used to initialize each node's `source().path`. + /// If you don't have a path (or you have no intention of using paths in diagnostics) + /// then this parameter can safely be left blank. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + parse_result TOML_CALLCONV parse(std::istream & doc, std::string && source_path); - TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS + TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS - inline namespace literals - { - TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, lit_ex, lit_noex); + inline namespace literals { + TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, lit_ex, lit_noex); - /// \brief Parses TOML data from a string literal. - /// - /// \detail \cpp - /// using namespace toml::literals; - /// - /// auto tbl = "a = 3"_toml; - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param str The string data. Must be valid UTF-8. - /// \param len The string length. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_ALWAYS_INLINE - parse_result operator"" _toml(const char* str, size_t len) - { - return parse(std::string_view{ str, len }); - } + /// \brief Parses TOML data from a string literal. + /// + /// \detail \cpp + /// using namespace toml::literals; + /// + /// auto tbl = "a = 3"_toml; + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param str The string data. Must be valid UTF-8. + /// \param len The string length. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_ALWAYS_INLINE + parse_result operator"" _toml(const char* str, size_t len) { + return parse(std::string_view{str, len}); + } #if TOML_HAS_CHAR8 - /// \brief Parses TOML data from a UTF-8 string literal. - /// - /// \detail \cpp - /// using namespace toml::literals; - /// - /// auto tbl = u8"a = 3"_toml; - /// std::cout << tbl["a"] << "\n"; - /// \ecpp - /// - /// \out - /// 3 - /// \eout - /// - /// \param str The string data. Must be valid UTF-8. - /// \param len The string length. - /// - /// \returns \conditional_return{With exceptions} - /// A toml::table. - /// \conditional_return{Without exceptions} - /// A toml::parse_result. - TOML_NODISCARD - TOML_ALWAYS_INLINE - parse_result operator"" _toml(const char8_t* str, size_t len) - { - return parse(std::u8string_view{ str, len }); - } + /// \brief Parses TOML data from a UTF-8 string literal. + /// + /// \detail \cpp + /// using namespace toml::literals; + /// + /// auto tbl = u8"a = 3"_toml; + /// std::cout << tbl["a"] << "\n"; + /// \ecpp + /// + /// \out + /// 3 + /// \eout + /// + /// \param str The string data. Must be valid UTF-8. + /// \param len The string length. + /// + /// \returns \conditional_return{With exceptions} + /// A toml::table. + /// \conditional_return{Without exceptions} + /// A toml::parse_result. + TOML_NODISCARD + TOML_ALWAYS_INLINE + parse_result operator"" _toml(const char8_t* str, size_t len) { + return parse(std::u8string_view{str, len}); + } -#endif // TOML_HAS_CHAR8 +#endif // TOML_HAS_CHAR8 - TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS - } + TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS + } // namespace literals } TOML_NAMESPACE_END; #include "header_end.hpp" -#endif // TOML_ENABLE_PARSER +#endif // TOML_ENABLE_PARSER diff --git a/vendor/toml++/impl/path.hpp b/vendor/toml++/impl/path.hpp index 5bd0ef3..db3faaa 100644 --- a/vendor/toml++/impl/path.hpp +++ b/vendor/toml++/impl/path.hpp @@ -1,850 +1,725 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "forward_declarations.hpp" -#include "std_vector.hpp" #include "header_start.hpp" +#include "std_vector.hpp" -TOML_NAMESPACE_START -{ - /// \brief Indicates type of path component, either a key, an index in an array, or invalid - enum class TOML_CLOSED_ENUM path_component_type : uint8_t - { - key = 0x1, - array_index = 0x2 - }; - - /// \brief Represents a single component of a complete 'TOML-path': either a key or an array index - class TOML_EXPORTED_CLASS path_component - { - /// \cond - struct storage_t - { - static constexpr size_t size = - (sizeof(size_t) < sizeof(std::string) ? sizeof(std::string) : sizeof(size_t)); - static constexpr size_t align = - (alignof(size_t) < alignof(std::string) ? alignof(std::string) : alignof(size_t)); - - alignas(align) unsigned char bytes[size]; - }; - alignas(storage_t::align) mutable storage_t value_storage_; - - path_component_type type_; - - TOML_PURE_GETTER - TOML_EXPORTED_STATIC_FUNCTION - static bool TOML_CALLCONV equal(const path_component&, const path_component&) noexcept; - - template <typename Type> - TOML_PURE_INLINE_GETTER - static Type* get_as(storage_t& s) noexcept - { - return TOML_LAUNDER(reinterpret_cast<Type*>(s.bytes)); - } - - static void store_key(std::string_view key, storage_t& storage_) - { - ::new (static_cast<void*>(storage_.bytes)) std::string{ key }; - } - - static void store_index(size_t index, storage_t& storage_) noexcept - { - ::new (static_cast<void*>(storage_.bytes)) std::size_t{ index }; - } - - void destroy() noexcept - { - if (type_ == path_component_type::key) - get_as<std::string>(value_storage_)->~basic_string(); - } - - TOML_NODISCARD - size_t& index_ref() noexcept - { - TOML_ASSERT_ASSUME(type_ == path_component_type::array_index); - return *get_as<size_t>(value_storage_); - } - - TOML_NODISCARD - std::string& key_ref() noexcept - { - TOML_ASSERT_ASSUME(type_ == path_component_type::key); - return *get_as<std::string>(value_storage_); - } - /// \endcond - - public: - /// \brief Default constructor (creates an empty key). - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - path_component(); - - /// \brief Constructor for a path component that is an array index - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - path_component(size_t index) noexcept; - - /// \brief Constructor for a path component that is a key string - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - path_component(std::string_view key); +TOML_NAMESPACE_START { + /// \brief Indicates type of path component, either a key, an index in an array, or invalid + enum class TOML_CLOSED_ENUM path_component_type : uint8_t { key = 0x1, array_index = 0x2 }; + + /// \brief Represents a single component of a complete 'TOML-path': either a key or an array index + class TOML_EXPORTED_CLASS path_component { + /// \cond + struct storage_t { + static constexpr size_t size = + (sizeof(size_t) < sizeof(std::string) ? sizeof(std::string) : sizeof(size_t)); + static constexpr size_t align = + (alignof(size_t) < alignof(std::string) ? alignof(std::string) : alignof(size_t)); + + alignas(align) unsigned char bytes[size]; + }; + alignas(storage_t::align) mutable storage_t value_storage_; + + path_component_type type_; + + TOML_PURE_GETTER + TOML_EXPORTED_STATIC_FUNCTION + static bool TOML_CALLCONV equal(const path_component&, const path_component&) noexcept; + + template <typename Type> + TOML_PURE_INLINE_GETTER static Type* get_as(storage_t& s) noexcept { + return TOML_LAUNDER(reinterpret_cast<Type*>(s.bytes)); + } + + static void store_key(std::string_view key, storage_t& storage_) { + ::new (static_cast<void*>(storage_.bytes)) std::string{key}; + } + + static void store_index(size_t index, storage_t& storage_) noexcept { + ::new (static_cast<void*>(storage_.bytes)) std::size_t{index}; + } + + void destroy() noexcept { + if (type_ == path_component_type::key) get_as<std::string>(value_storage_)->~basic_string(); + } + + TOML_NODISCARD + size_t& index_ref() noexcept { + TOML_ASSERT_ASSUME(type_ == path_component_type::array_index); + return *get_as<size_t>(value_storage_); + } + + TOML_NODISCARD + std::string& key_ref() noexcept { + TOML_ASSERT_ASSUME(type_ == path_component_type::key); + return *get_as<std::string>(value_storage_); + } + /// \endcond + + public: + /// \brief Default constructor (creates an empty key). + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + path_component(); + + /// \brief Constructor for a path component that is an array index + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + path_component(size_t index) noexcept; + + /// \brief Constructor for a path component that is a key string + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + path_component(std::string_view key); #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Constructor for a path component that is a key string - /// - /// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - path_component(std::wstring_view key); + /// \brief Constructor for a path component that is a key string + /// + /// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is + /// enabled. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + path_component(std::wstring_view key); #endif - /// \brief Copy constructor. - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - path_component(const path_component& pc); + /// \brief Copy constructor. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + path_component(const path_component& pc); - /// \brief Move constructor. - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - path_component(path_component&& pc) noexcept; + /// \brief Move constructor. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + path_component(path_component&& pc) noexcept; - /// \brief Copy-assignment operator. - TOML_EXPORTED_MEMBER_FUNCTION - path_component& operator=(const path_component& rhs); + /// \brief Copy-assignment operator. + TOML_EXPORTED_MEMBER_FUNCTION + path_component& operator=(const path_component& rhs); - /// \brief Move-assignment operator. - TOML_EXPORTED_MEMBER_FUNCTION - path_component& operator=(path_component&& rhs) noexcept; + /// \brief Move-assignment operator. + TOML_EXPORTED_MEMBER_FUNCTION + path_component& operator=(path_component&& rhs) noexcept; - /// \brief Assigns an array index to this path component. - TOML_EXPORTED_MEMBER_FUNCTION - path_component& operator=(size_t new_index) noexcept; + /// \brief Assigns an array index to this path component. + TOML_EXPORTED_MEMBER_FUNCTION + path_component& operator=(size_t new_index) noexcept; - /// \brief Assigns a path key to this path component. - TOML_EXPORTED_MEMBER_FUNCTION - path_component& operator=(std::string_view new_key); + /// \brief Assigns a path key to this path component. + TOML_EXPORTED_MEMBER_FUNCTION + path_component& operator=(std::string_view new_key); #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Assigns a path key to this path component. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_EXPORTED_MEMBER_FUNCTION - path_component& operator=(std::wstring_view new_key); + /// \brief Assigns a path key to this path component. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_EXPORTED_MEMBER_FUNCTION + path_component& operator=(std::wstring_view new_key); #endif - /// \brief Destructor. - ~path_component() noexcept - { - destroy(); - } - - /// \name Array index accessors - /// \warning It is undefined behaviour to call these functions when the path component does not represent an array index. - /// Check #type() to determine the component's value type. - /// @{ - - /// \brief Returns the array index (const lvalue overload). - TOML_PURE_GETTER - size_t index() const noexcept - { - TOML_ASSERT_ASSUME(type_ == path_component_type::array_index); - return *get_as<const size_t>(value_storage_); - } - - /// \brief Returns the array index (const lvalue). - TOML_PURE_INLINE_GETTER - explicit operator size_t() const noexcept - { - return index(); - } - - /// @} - - /// \name Key accessors - /// \warning It is undefined behaviour to call these functions when the path component does not represent a key. - /// Check #type() to determine the component's value type. - /// @{ - - /// \brief Returns the key string. - TOML_PURE_GETTER - const std::string& key() const noexcept - { - TOML_ASSERT_ASSUME(type_ == path_component_type::key); - return *get_as<const std::string>(value_storage_); - } - - /// \brief Returns the key string. - TOML_PURE_INLINE_GETTER - explicit operator const std::string&() const noexcept - { - return key(); - } - - /// @} - - /// \brief Retrieve the type of this path component, either path_component::key or path_component::array_index - TOML_PURE_INLINE_GETTER - path_component_type type() const noexcept - { - return type_; - } - - /// \name Equality - /// @{ - - /// \brief Returns true if two path components represent the same key or array index. - TOML_PURE_INLINE_GETTER - friend bool operator==(const path_component& lhs, const path_component& rhs) noexcept - { - return equal(lhs, rhs); - } - - /// \brief Returns true if two path components do not represent the same key or array index. - TOML_PURE_INLINE_GETTER - friend bool operator!=(const path_component& lhs, const path_component& rhs) noexcept - { - return !equal(lhs, rhs); - } - - /// @} - }; - - /// \brief A TOML path. - /// - /// \detail This type parses and represents a path to a TOML node. It validates - /// the syntax of the path but does not ensure that the path refers to - /// a valid node in any particular TOML document. If parsing fails, - /// the object will evaluate as 'falsy', and will be empty. - /// - /// \cpp - /// toml::path the_path("animals.cats[1]"); - /// - /// // can use with tbl.at_path or operator[] - /// std::cout << "second cat: " << tbl[the_path] << "\n"; - /// std::cout << "cats: " << tbl.at_path(the_path.parent_path()) << "\n"; - /// \ecpp - /// - /// \out - /// second cat: lion - /// cats: ['tiger', 'lion', 'puma'] - /// \eout - class TOML_EXPORTED_CLASS path - { - private: - /// \cond - - std::vector<path_component> components_; - - TOML_EXPORTED_MEMBER_FUNCTION - void print_to(std::ostream&) const; - - TOML_PURE_GETTER - TOML_EXPORTED_STATIC_FUNCTION - static bool TOML_CALLCONV equal(const path&, const path&) noexcept; - - /// \endcond - - public: - /// \brief Default constructor. - TOML_NODISCARD_CTOR - path() noexcept = default; - - /// \brief Construct a path by parsing from a string. - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - explicit path(std::string_view); + /// \brief Destructor. + ~path_component() noexcept { destroy(); } + + /// \name Array index accessors + /// \warning It is undefined behaviour to call these functions when the path component does not + /// represent an array index. Check #type() to determine the component's value type. + /// @{ + + /// \brief Returns the array index (const lvalue overload). + TOML_PURE_GETTER + size_t index() const noexcept { + TOML_ASSERT_ASSUME(type_ == path_component_type::array_index); + return *get_as<const size_t>(value_storage_); + } + + /// \brief Returns the array index (const lvalue). + TOML_PURE_INLINE_GETTER + explicit operator size_t() const noexcept { return index(); } + + /// @} + + /// \name Key accessors + /// \warning It is undefined behaviour to call these functions when the path component does not + /// represent a key. Check #type() to determine the component's value type. + /// @{ + + /// \brief Returns the key string. + TOML_PURE_GETTER + const std::string& key() const noexcept { + TOML_ASSERT_ASSUME(type_ == path_component_type::key); + return *get_as<const std::string>(value_storage_); + } + + /// \brief Returns the key string. + TOML_PURE_INLINE_GETTER + explicit operator const std::string&() const noexcept { return key(); } + + /// @} + + /// \brief Retrieve the type of this path component, either path_component::key or + /// path_component::array_index + TOML_PURE_INLINE_GETTER + path_component_type type() const noexcept { return type_; } + + /// \name Equality + /// @{ + + /// \brief Returns true if two path components represent the same key or array index. + TOML_PURE_INLINE_GETTER + friend bool operator==(const path_component& lhs, const path_component& rhs) noexcept { + return equal(lhs, rhs); + } + + /// \brief Returns true if two path components do not represent the same key or array index. + TOML_PURE_INLINE_GETTER + friend bool operator!=(const path_component& lhs, const path_component& rhs) noexcept { + return !equal(lhs, rhs); + } + + /// @} + }; + + /// \brief A TOML path. + /// + /// \detail This type parses and represents a path to a TOML node. It validates + /// the syntax of the path but does not ensure that the path refers to + /// a valid node in any particular TOML document. If parsing fails, + /// the object will evaluate as 'falsy', and will be empty. + /// + /// \cpp + /// toml::path the_path("animals.cats[1]"); + /// + /// // can use with tbl.at_path or operator[] + /// std::cout << "second cat: " << tbl[the_path] << "\n"; + /// std::cout << "cats: " << tbl.at_path(the_path.parent_path()) << "\n"; + /// \ecpp + /// + /// \out + /// second cat: lion + /// cats: ['tiger', 'lion', 'puma'] + /// \eout + class TOML_EXPORTED_CLASS path { + private: + /// \cond + + std::vector<path_component> components_; + + TOML_EXPORTED_MEMBER_FUNCTION + void print_to(std::ostream&) const; + + TOML_PURE_GETTER + TOML_EXPORTED_STATIC_FUNCTION + static bool TOML_CALLCONV equal(const path&, const path&) noexcept; + + /// \endcond + + public: + /// \brief Default constructor. + TOML_NODISCARD_CTOR + path() noexcept = default; + + /// \brief Construct a path by parsing from a string. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + explicit path(std::string_view); #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Construct a path by parsing from a string. - /// - /// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD_CTOR - TOML_EXPORTED_MEMBER_FUNCTION - explicit path(std::wstring_view); + /// \brief Construct a path by parsing from a string. + /// + /// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is + /// enabled. + TOML_NODISCARD_CTOR + TOML_EXPORTED_MEMBER_FUNCTION + explicit path(std::wstring_view); #endif - /// \brief Default destructor. - ~path() noexcept = default; - - /// \brief Copy constructor. - TOML_NODISCARD_CTOR - path(const path&) = default; - - /// \brief Move constructor. - TOML_NODISCARD_CTOR - path(path&&) noexcept = default; - - /// \brief Returns the number of components in the path. - TOML_PURE_INLINE_GETTER - size_t size() const noexcept - { - return components_.size(); - } - - /// \brief Returns true if the path has one or more components. - TOML_PURE_INLINE_GETTER - explicit operator bool() const noexcept - { - return !components_.empty(); - } - - /// \brief Whether (true) or not (false) the path is empty - TOML_PURE_INLINE_GETTER - bool empty() const noexcept - { - return components_.empty(); - } - - /// \brief Fetch a path component by index. - TOML_PURE_INLINE_GETTER - path_component& operator[](size_t index) noexcept - { - TOML_ASSERT(index < size()); - return components_[index]; - } - - /// \brief Fetch a path component by index (const overload). - TOML_PURE_INLINE_GETTER - const path_component& operator[](size_t index) const noexcept - { - TOML_ASSERT(index < size()); - return components_[index]; - } - - /// \name Assignment - /// @{ - - /// \brief Copy-assignment operator. - path& operator=(const path&) = default; - - /// \brief Move-assignment operator. - path& operator=(path&&) noexcept = default; - - /// \brief Replaces the contents of the path by parsing from a string. - TOML_EXPORTED_MEMBER_FUNCTION - path& operator=(std::string_view); + /// \brief Default destructor. + ~path() noexcept = default; + + /// \brief Copy constructor. + TOML_NODISCARD_CTOR + path(const path&) = default; + + /// \brief Move constructor. + TOML_NODISCARD_CTOR + path(path&&) noexcept = default; + + /// \brief Returns the number of components in the path. + TOML_PURE_INLINE_GETTER + size_t size() const noexcept { return components_.size(); } + + /// \brief Returns true if the path has one or more components. + TOML_PURE_INLINE_GETTER + explicit operator bool() const noexcept { return !components_.empty(); } + + /// \brief Whether (true) or not (false) the path is empty + TOML_PURE_INLINE_GETTER + bool empty() const noexcept { return components_.empty(); } + + /// \brief Fetch a path component by index. + TOML_PURE_INLINE_GETTER + path_component& operator[](size_t index) noexcept { + TOML_ASSERT(index < size()); + return components_[index]; + } + + /// \brief Fetch a path component by index (const overload). + TOML_PURE_INLINE_GETTER + const path_component& operator[](size_t index) const noexcept { + TOML_ASSERT(index < size()); + return components_[index]; + } + + /// \name Assignment + /// @{ + + /// \brief Copy-assignment operator. + path& operator=(const path&) = default; + + /// \brief Move-assignment operator. + path& operator=(path&&) noexcept = default; + + /// \brief Replaces the contents of the path by parsing from a string. + TOML_EXPORTED_MEMBER_FUNCTION + path& operator=(std::string_view); #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Replaces the contents of the path by parsing from a string. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_EXPORTED_MEMBER_FUNCTION - path& operator=(std::wstring_view); + /// \brief Replaces the contents of the path by parsing from a string. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_EXPORTED_MEMBER_FUNCTION + path& operator=(std::wstring_view); #endif - /// \brief Replaces the contents of the path with that of another. - TOML_ALWAYS_INLINE - path& assign(const path& p) - { - return *this = p; - } - - /// \brief Replaces the contents of the path with that of another. - TOML_ALWAYS_INLINE - path& assign(path&& p) noexcept - { - return *this = std::move(p); - } - - /// \brief Replaces the contents of the path object by a new path - TOML_ALWAYS_INLINE - path& assign(std::string_view str) - { - return *this = str; - } + /// \brief Replaces the contents of the path with that of another. + TOML_ALWAYS_INLINE + path& assign(const path& p) { return *this = p; } + + /// \brief Replaces the contents of the path with that of another. + TOML_ALWAYS_INLINE + path& assign(path&& p) noexcept { return *this = std::move(p); } + + /// \brief Replaces the contents of the path object by a new path + TOML_ALWAYS_INLINE + path& assign(std::string_view str) { return *this = str; } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Replaces the contents of the path object by a new path - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_ALWAYS_INLINE - path& assign(std::wstring_view str) - { - return *this = str; - } + /// \brief Replaces the contents of the path object by a new path + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_ALWAYS_INLINE + path& assign(std::wstring_view str) { return *this = str; } #endif - /// @} + /// @} - /// \name Appending - /// @{ + /// \name Appending + /// @{ - /// \brief Appends another path onto the end of this one. - TOML_EXPORTED_MEMBER_FUNCTION - path& operator+=(const path&); + /// \brief Appends another path onto the end of this one. + TOML_EXPORTED_MEMBER_FUNCTION + path& operator+=(const path&); - /// \brief Appends another path onto the end of this one. - TOML_EXPORTED_MEMBER_FUNCTION - path& operator+=(path&&); + /// \brief Appends another path onto the end of this one. + TOML_EXPORTED_MEMBER_FUNCTION + path& operator+=(path&&); - /// \brief Parses a path and appends it onto the end of this one. - TOML_EXPORTED_MEMBER_FUNCTION - path& operator+=(std::string_view); + /// \brief Parses a path and appends it onto the end of this one. + TOML_EXPORTED_MEMBER_FUNCTION + path& operator+=(std::string_view); #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Parses a path and appends it onto the end of this one. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_EXPORTED_MEMBER_FUNCTION - path& operator+=(std::wstring_view); + /// \brief Parses a path and appends it onto the end of this one. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_EXPORTED_MEMBER_FUNCTION + path& operator+=(std::wstring_view); #endif - /// \brief Appends another path onto the end of this one. - TOML_ALWAYS_INLINE - path& append(const path& p) - { - return *this += p; - } - - /// \brief Appends another path onto the end of this one. - TOML_ALWAYS_INLINE - path& append(path&& p) - { - return *this += std::move(p); - } - - /// \brief Parses a path and appends it onto the end of this one. - TOML_ALWAYS_INLINE - path& append(std::string_view str) - { - return *this += str; - } + /// \brief Appends another path onto the end of this one. + TOML_ALWAYS_INLINE + path& append(const path& p) { return *this += p; } + + /// \brief Appends another path onto the end of this one. + TOML_ALWAYS_INLINE + path& append(path&& p) { return *this += std::move(p); } + + /// \brief Parses a path and appends it onto the end of this one. + TOML_ALWAYS_INLINE + path& append(std::string_view str) { return *this += str; } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Parses a path and appends it onto the end of this one. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_ALWAYS_INLINE - path& append(std::wstring_view str) - { - return *this += str; - } + /// \brief Parses a path and appends it onto the end of this one. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_ALWAYS_INLINE + path& append(std::wstring_view str) { return *this += str; } #endif - /// @} + /// @} - /// \name Prepending - /// @{ + /// \name Prepending + /// @{ - /// \brief Prepends another path onto the beginning of this one. - TOML_EXPORTED_MEMBER_FUNCTION - path& prepend(const path&); + /// \brief Prepends another path onto the beginning of this one. + TOML_EXPORTED_MEMBER_FUNCTION + path& prepend(const path&); - /// \brief Prepends another path onto the beginning of this one. - TOML_EXPORTED_MEMBER_FUNCTION - path& prepend(path&&); + /// \brief Prepends another path onto the beginning of this one. + TOML_EXPORTED_MEMBER_FUNCTION + path& prepend(path&&); - /// \brief Parses a path and prepends it onto the beginning of this one. - TOML_EXPORTED_MEMBER_FUNCTION - path& prepend(std::string_view); + /// \brief Parses a path and prepends it onto the beginning of this one. + TOML_EXPORTED_MEMBER_FUNCTION + path& prepend(std::string_view); #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Parses a path and prepends it onto the beginning of this one. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_EXPORTED_MEMBER_FUNCTION - path& prepend(std::wstring_view); + /// \brief Parses a path and prepends it onto the beginning of this one. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_EXPORTED_MEMBER_FUNCTION + path& prepend(std::wstring_view); #endif - /// @} - - /// \name Concatenation - /// @{ - - /// \brief Concatenates two paths. - TOML_NODISCARD - friend path operator+(const path& lhs, const path& rhs) - { - path result = lhs; - result += rhs; - return result; - } - - /// \brief Concatenates two paths. - TOML_NODISCARD - friend path operator+(const path& lhs, std::string_view rhs) - { - path result = lhs; - result += rhs; - return result; - } - - /// \brief Concatenates two paths. - TOML_NODISCARD - friend path operator+(std::string_view lhs, const path& rhs) - { - path result = rhs; - result.prepend(lhs); - return result; - } + /// @} + + /// \name Concatenation + /// @{ + + /// \brief Concatenates two paths. + TOML_NODISCARD + friend path operator+(const path& lhs, const path& rhs) { + path result = lhs; + result += rhs; + return result; + } + + /// \brief Concatenates two paths. + TOML_NODISCARD + friend path operator+(const path& lhs, std::string_view rhs) { + path result = lhs; + result += rhs; + return result; + } + + /// \brief Concatenates two paths. + TOML_NODISCARD + friend path operator+(std::string_view lhs, const path& rhs) { + path result = rhs; + result.prepend(lhs); + return result; + } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Concatenates two paths. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - friend path operator+(const path& lhs, std::wstring_view rhs) - { - path result = lhs; - result += rhs; - return result; - } - - /// \brief Concatenates two paths. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - friend path operator+(std::wstring_view lhs, const path& rhs) - { - path result = rhs; - result.prepend(lhs); - return result; - } + /// \brief Concatenates two paths. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + friend path operator+(const path& lhs, std::wstring_view rhs) { + path result = lhs; + result += rhs; + return result; + } + + /// \brief Concatenates two paths. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + friend path operator+(std::wstring_view lhs, const path& rhs) { + path result = rhs; + result.prepend(lhs); + return result; + } #endif - /// @} + /// @} - /// \name String conversion - /// @{ + /// \name String conversion + /// @{ - /// \brief Prints the string representation of a #toml::path out to a stream. - TOML_ALWAYS_INLINE - friend std::ostream& operator<<(std::ostream& os, const path& rhs) - { - rhs.print_to(os); - return os; - } + /// \brief Prints the string representation of a #toml::path out to a stream. + TOML_ALWAYS_INLINE + friend std::ostream& operator<<(std::ostream& os, const path& rhs) { + rhs.print_to(os); + return os; + } - /// \brief Returns a string representation of this path. - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - std::string str() const; + /// \brief Returns a string representation of this path. + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + std::string str() const; - /// \brief Returns a string representation of this path. - TOML_NODISCARD - TOML_ALWAYS_INLINE - explicit operator std::string() const - { - return str(); - } + /// \brief Returns a string representation of this path. + TOML_NODISCARD + TOML_ALWAYS_INLINE + explicit operator std::string() const { return str(); } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Returns a string representation of this path. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - std::wstring wide_str() const; - - /// \brief Returns a string representation of this path. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - TOML_ALWAYS_INLINE - explicit operator std::wstring() const - { - return wide_str(); - } + /// \brief Returns a string representation of this path. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + std::wstring wide_str() const; + + /// \brief Returns a string representation of this path. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + TOML_ALWAYS_INLINE + explicit operator std::wstring() const { return wide_str(); } #endif - /// @} - - /// \name Equality - /// @{ - - /// \brief Returns whether two paths are the same. - TOML_PURE_INLINE_GETTER - friend bool operator==(const path& lhs, const path& rhs) noexcept - { - return equal(lhs, rhs); - } - - /// \brief Returns whether two paths are not the same. - TOML_PURE_INLINE_GETTER - friend bool operator!=(const path& lhs, const path& rhs) noexcept - { - return !equal(lhs, rhs); - } - - /// \brief Returns whether two paths are the same. - TOML_NODISCARD - TOML_ALWAYS_INLINE - friend bool operator==(const path& lhs, std::string_view rhs) - { - return lhs == path{ rhs }; - } - - /// \brief Returns whether two paths are the same. - TOML_NODISCARD - TOML_ALWAYS_INLINE - friend bool operator==(std::string_view lhs, const path& rhs) - { - return rhs == lhs; - } - - /// \brief Returns whether two paths are not the same. - TOML_NODISCARD - TOML_ALWAYS_INLINE - friend bool operator!=(const path& lhs, std::string_view rhs) - { - return lhs != path{ rhs }; - } - - /// \brief Returns whether two paths are not the same. - TOML_NODISCARD - TOML_ALWAYS_INLINE - friend bool operator!=(std::string_view lhs, const path& rhs) - { - return rhs != lhs; - } + /// @} + + /// \name Equality + /// @{ + + /// \brief Returns whether two paths are the same. + TOML_PURE_INLINE_GETTER + friend bool operator==(const path& lhs, const path& rhs) noexcept { return equal(lhs, rhs); } + + /// \brief Returns whether two paths are not the same. + TOML_PURE_INLINE_GETTER + friend bool operator!=(const path& lhs, const path& rhs) noexcept { return !equal(lhs, rhs); } + + /// \brief Returns whether two paths are the same. + TOML_NODISCARD + TOML_ALWAYS_INLINE + friend bool operator==(const path& lhs, std::string_view rhs) { return lhs == path{rhs}; } + + /// \brief Returns whether two paths are the same. + TOML_NODISCARD + TOML_ALWAYS_INLINE + friend bool operator==(std::string_view lhs, const path& rhs) { return rhs == lhs; } + + /// \brief Returns whether two paths are not the same. + TOML_NODISCARD + TOML_ALWAYS_INLINE + friend bool operator!=(const path& lhs, std::string_view rhs) { return lhs != path{rhs}; } + + /// \brief Returns whether two paths are not the same. + TOML_NODISCARD + TOML_ALWAYS_INLINE + friend bool operator!=(std::string_view lhs, const path& rhs) { return rhs != lhs; } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Returns whether two paths are the same. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - TOML_ALWAYS_INLINE - friend bool operator==(const path& lhs, std::wstring_view rhs) - { - return lhs == path{ rhs }; - } - - /// \brief Returns whether two paths are the same. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - TOML_ALWAYS_INLINE - friend bool operator==(std::wstring_view lhs, const path& rhs) - { - return rhs == lhs; - } - - /// \brief Returns whether two paths are not the same. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - TOML_ALWAYS_INLINE - friend bool operator!=(const path& lhs, std::wstring_view rhs) - { - return lhs != path{ rhs }; - } - - /// \brief Returns whether two paths are not the same. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - TOML_ALWAYS_INLINE - friend bool operator!=(std::wstring_view lhs, const path& rhs) - { - return rhs != lhs; - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// @} - - /// \name Iteration - /// @{ - - /// An iterator for iterating over the components in the path. - /// \see #toml::path_component - using iterator = std::vector<path_component>::iterator; - - /// A const iterator for iterating over the components in the path. - /// \see #toml::path_component - using const_iterator = std::vector<path_component>::const_iterator; - - /// \brief Returns an iterator to the first component in the path. - /// \see #toml::path_component - TOML_PURE_INLINE_GETTER - iterator begin() noexcept - { - return components_.begin(); - } - - /// \brief Returns an iterator to one-past-the-last component in the path. - /// \see #toml::path_component - TOML_PURE_INLINE_GETTER - iterator end() noexcept - { - return components_.end(); - } - - /// \brief Returns a const iterator to the first component in the path. - /// \see #toml::path_component - TOML_PURE_INLINE_GETTER - const_iterator begin() const noexcept - { - return components_.begin(); - } - - /// \brief Returns a const iterator to one-past-the-last component in the path. - /// \see #toml::path_component - TOML_PURE_INLINE_GETTER - const_iterator end() const noexcept - { - return components_.end(); - } - - /// \brief Returns a const iterator to the first component in the path. - /// \see #toml::path_component - TOML_PURE_INLINE_GETTER - const_iterator cbegin() const noexcept - { - return components_.begin(); - } - - /// \brief Returns a const iterator to one-past-the-last component in the path. - /// \see #toml::path_component - TOML_PURE_INLINE_GETTER - const_iterator cend() const noexcept - { - return components_.end(); - } - - /// @} - - /// \name Subpaths and Truncation - /// @{ - - /// \brief Erases the contents of the path. - TOML_EXPORTED_MEMBER_FUNCTION - void clear() noexcept; - - /// \brief Removes the number of terminal path components specified by n - TOML_EXPORTED_MEMBER_FUNCTION - path& truncate(size_t n); - - /// \brief Returns a toml::path object which has had n terminal path components removed - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - path truncated(size_t n) const; - - /// \brief Returns a toml::path object representing the path of the parent node - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - path parent() const; - - /// \brief Returns a toml::path object representing terminal n-parts of a TOML path - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - path leaf(size_t n = 1) const; - - /// \brief Returns a toml::path object that is a specified subpath of the current path, representing the - /// range of path components from [start, end). - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - path subpath(const_iterator start, const_iterator end) const; - - /// \brief Returns a toml::path object that is a specified subpath of the current path, representing the - /// range of path components with indexes from [start, start + length]. - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - path subpath(size_t start, size_t length) const; - - /// @} - }; - - inline namespace literals - { - /// \brief Parses a TOML path from a string literal. - /// - /// \detail \cpp - /// using namespace toml::literals; - /// - /// auto path = "main.settings.devices[2]"_tpath; - /// std::cout << path.parent_path() << "\n"; - /// \ecpp - /// - /// \out - /// main.settings.devices - /// \eout - /// - /// \param str The string data. - /// \param len The string length. - /// - /// \returns A #toml::path generated from the string literal. - TOML_NODISCARD - TOML_ALWAYS_INLINE - path operator"" _tpath(const char* str, size_t len) - { - return path(std::string_view{ str, len }); - } - } - - /// \brief Returns a view of the node matching a fully-qualified "TOML path". - /// - /// \detail \cpp - /// auto config = toml::parse(R"( - /// - /// [foo] - /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] - /// - /// )"sv); - /// - /// toml::path path1("foo.bar[2]"); - /// toml::path path2("foo.bar[4].kek"); - /// std::cout << toml::at_path(config, path1) << "\n"; - /// std::cout << toml::at_path(config, path1.parent_path()) << "\n"; - /// std::cout << toml::at_path(config, path2) << "\n"; - /// std::cout << toml::at_path(config, path2.parent_path()) << "\n"; - /// \ecpp - /// - /// \out - /// 2 - /// [ 0, 1, 2, [ 3 ], { kek = 4 } ] - /// 4 - /// { kek = 4 } - /// \eout - /// - /// - /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: - /// \cpp - /// toml::at_path(config, toml::path("foo.bar")) // same as config["foo"]["bar"] - /// toml::at_path(config, toml::path("foo. bar")) // same as config["foo"][" bar"] - /// toml::at_path(config, toml::path("foo..bar")) // same as config["foo"][""]["bar"] - /// toml::at_path(config, toml::path(".foo.bar")) // same as config[""]["foo"]["bar"] - /// \ecpp - /// <br> - /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted strings. - /// This function makes no allowance for this, instead treating all period characters as sub-table delimiters. - /// - /// \param root The root node from which the path will be traversed. - /// \param path The "TOML path" to traverse. - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - node_view<node> TOML_CALLCONV at_path(node & root, const toml::path& path) noexcept; - - /// \brief Returns a const view of the node matching a fully-qualified "TOML path". - /// - /// \see #toml::at_path(node&, const toml::path& path) - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - node_view<const node> TOML_CALLCONV at_path(const node& root, const toml::path& path) noexcept; + /// \brief Returns whether two paths are the same. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + TOML_ALWAYS_INLINE + friend bool operator==(const path& lhs, std::wstring_view rhs) { return lhs == path{rhs}; } + + /// \brief Returns whether two paths are the same. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + TOML_ALWAYS_INLINE + friend bool operator==(std::wstring_view lhs, const path& rhs) { return rhs == lhs; } + + /// \brief Returns whether two paths are not the same. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + TOML_ALWAYS_INLINE + friend bool operator!=(const path& lhs, std::wstring_view rhs) { return lhs != path{rhs}; } + + /// \brief Returns whether two paths are not the same. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + TOML_ALWAYS_INLINE + friend bool operator!=(std::wstring_view lhs, const path& rhs) { return rhs != lhs; } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// @} + + /// \name Iteration + /// @{ + + /// An iterator for iterating over the components in the path. + /// \see #toml::path_component + using iterator = std::vector<path_component>::iterator; + + /// A const iterator for iterating over the components in the path. + /// \see #toml::path_component + using const_iterator = std::vector<path_component>::const_iterator; + + /// \brief Returns an iterator to the first component in the path. + /// \see #toml::path_component + TOML_PURE_INLINE_GETTER + iterator begin() noexcept { return components_.begin(); } + + /// \brief Returns an iterator to one-past-the-last component in the path. + /// \see #toml::path_component + TOML_PURE_INLINE_GETTER + iterator end() noexcept { return components_.end(); } + + /// \brief Returns a const iterator to the first component in the path. + /// \see #toml::path_component + TOML_PURE_INLINE_GETTER + const_iterator begin() const noexcept { return components_.begin(); } + + /// \brief Returns a const iterator to one-past-the-last component in the path. + /// \see #toml::path_component + TOML_PURE_INLINE_GETTER + const_iterator end() const noexcept { return components_.end(); } + + /// \brief Returns a const iterator to the first component in the path. + /// \see #toml::path_component + TOML_PURE_INLINE_GETTER + const_iterator cbegin() const noexcept { return components_.begin(); } + + /// \brief Returns a const iterator to one-past-the-last component in the path. + /// \see #toml::path_component + TOML_PURE_INLINE_GETTER + const_iterator cend() const noexcept { return components_.end(); } + + /// @} + + /// \name Subpaths and Truncation + /// @{ + + /// \brief Erases the contents of the path. + TOML_EXPORTED_MEMBER_FUNCTION + void clear() noexcept; + + /// \brief Removes the number of terminal path components specified by n + TOML_EXPORTED_MEMBER_FUNCTION + path& truncate(size_t n); + + /// \brief Returns a toml::path object which has had n terminal path components removed + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + path truncated(size_t n) const; + + /// \brief Returns a toml::path object representing the path of the parent node + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + path parent() const; + + /// \brief Returns a toml::path object representing terminal n-parts of a TOML path + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + path leaf(size_t n = 1) const; + + /// \brief Returns a toml::path object that is a specified subpath of the current path, + /// representing the range of path components from [start, end). + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + path subpath(const_iterator start, const_iterator end) const; + + /// \brief Returns a toml::path object that is a specified subpath of the current path, + /// representing the range of path components with indexes from [start, start + length]. + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + path subpath(size_t start, size_t length) const; + + /// @} + }; + + inline namespace literals { + /// \brief Parses a TOML path from a string literal. + /// + /// \detail \cpp + /// using namespace toml::literals; + /// + /// auto path = "main.settings.devices[2]"_tpath; + /// std::cout << path.parent_path() << "\n"; + /// \ecpp + /// + /// \out + /// main.settings.devices + /// \eout + /// + /// \param str The string data. + /// \param len The string length. + /// + /// \returns A #toml::path generated from the string literal. + TOML_NODISCARD + TOML_ALWAYS_INLINE + path operator"" _tpath(const char* str, size_t len) { + return path(std::string_view{str, len}); + } + } // namespace literals + + /// \brief Returns a view of the node matching a fully-qualified "TOML path". + /// + /// \detail \cpp + /// auto config = toml::parse(R"( + /// + /// [foo] + /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] + /// + /// )"sv); + /// + /// toml::path path1("foo.bar[2]"); + /// toml::path path2("foo.bar[4].kek"); + /// std::cout << toml::at_path(config, path1) << "\n"; + /// std::cout << toml::at_path(config, path1.parent_path()) << "\n"; + /// std::cout << toml::at_path(config, path2) << "\n"; + /// std::cout << toml::at_path(config, path2.parent_path()) << "\n"; + /// \ecpp + /// + /// \out + /// 2 + /// [ 0, 1, 2, [ 3 ], { kek = 4 } ] + /// 4 + /// { kek = 4 } + /// \eout + /// + /// + /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: + /// \cpp + /// toml::at_path(config, toml::path("foo.bar")) // same as config["foo"]["bar"] + /// toml::at_path(config, toml::path("foo. bar")) // same as config["foo"][" bar"] + /// toml::at_path(config, toml::path("foo..bar")) // same as config["foo"][""]["bar"] + /// toml::at_path(config, toml::path(".foo.bar")) // same as config[""]["foo"]["bar"] + /// \ecpp + /// <br> + /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted + /// strings. This function makes no allowance for this, instead treating all period characters as + /// sub-table delimiters. + /// + /// \param root The root node from which the path will be traversed. + /// \param path The "TOML path" to traverse. + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + node_view<node> TOML_CALLCONV at_path(node & root, const toml::path& path) noexcept; + + /// \brief Returns a const view of the node matching a fully-qualified "TOML path". + /// + /// \see #toml::at_path(node&, const toml::path& path) + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + node_view<const node> TOML_CALLCONV at_path(const node& root, const toml::path& path) noexcept; } TOML_NAMESPACE_END; diff --git a/vendor/toml++/impl/preprocessor.hpp b/vendor/toml++/impl/preprocessor.hpp index feeb802..85972d2 100644 --- a/vendor/toml++/impl/preprocessor.hpp +++ b/vendor/toml++/impl/preprocessor.hpp @@ -1,12 +1,12 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once -//#===================================================================================================================== -//# C++ VERSION -//#===================================================================================================================== +// #===================================================================================================================== +// # C++ VERSION +// #===================================================================================================================== #ifndef __cplusplus #error toml++ is a C++ library. @@ -54,12 +54,12 @@ #error toml++ requires C++17 or higher. For a C++11 TOML library see https://github.com/ToruNiina/toml11 #endif -//#===================================================================================================================== -//# COMPILER -//#===================================================================================================================== +// #===================================================================================================================== +// # COMPILER +// #===================================================================================================================== #ifndef TOML_MAKE_VERSION -#define TOML_MAKE_VERSION(major, minor, patch) (((major)*10000) + ((minor)*100) + ((patch))) +#define TOML_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + ((patch))) #endif #ifndef TOML_INTELLISENSE @@ -71,8 +71,8 @@ #endif #ifndef TOML_DOXYGEN -#if defined(DOXYGEN) || defined(__DOXYGEN) || defined(__DOXYGEN__) || defined(__doxygen__) || defined(__POXY__) \ - || defined(__poxy__) +#if defined(DOXYGEN) || defined(__DOXYGEN) || defined(__DOXYGEN__) || defined(__doxygen__) || \ + defined(__POXY__) || defined(__poxy__) #define TOML_DOXYGEN 1 #else #define TOML_DOXYGEN 0 @@ -115,7 +115,7 @@ #elif TOML_CLANG_VERSION >= TOML_MAKE_VERSION(10, 0, 1) #define TOML_CLANG 7 #else -#define TOML_CLANG 6 // not strictly correct but doesn't matter below this +#define TOML_CLANG 6 // not strictly correct but doesn't matter below this #endif #undef TOML_CLANG_VERSION #endif @@ -130,7 +130,7 @@ #define TOML_ICC_CL 0 #endif #else -#define TOML_ICC 0 +#define TOML_ICC 0 #define TOML_ICC_CL 0 #endif #endif @@ -175,9 +175,9 @@ #endif #endif -//#===================================================================================================================== -//# ARCHITECTURE -//#===================================================================================================================== +// #===================================================================================================================== +// # ARCHITECTURE +// #===================================================================================================================== #ifndef TOML_ARCH_ITANIUM #if defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) || defined(_M_IA64) @@ -189,8 +189,9 @@ #endif #ifndef TOML_ARCH_AMD64 -#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) -#define TOML_ARCH_AMD64 1 +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \ + defined(_M_AMD64) +#define TOML_ARCH_AMD64 1 #define TOML_ARCH_BITNESS 64 #else #define TOML_ARCH_AMD64 0 @@ -199,7 +200,7 @@ #ifndef TOML_ARCH_X86 #if defined(__i386__) || defined(_M_IX86) -#define TOML_ARCH_X86 1 +#define TOML_ARCH_X86 1 #define TOML_ARCH_BITNESS 32 #else #define TOML_ARCH_X86 0 @@ -207,21 +208,21 @@ #endif #ifndef TOML_ARCH_ARM -#if defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) || defined(_M_ARM64) || defined(__ARM_64BIT_STATE) \ - || defined(_M_ARM64EC) -#define TOML_ARCH_ARM32 0 -#define TOML_ARCH_ARM64 1 -#define TOML_ARCH_ARM 1 +#if defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) || defined(_M_ARM64) || \ + defined(__ARM_64BIT_STATE) || defined(_M_ARM64EC) +#define TOML_ARCH_ARM32 0 +#define TOML_ARCH_ARM64 1 +#define TOML_ARCH_ARM 1 #define TOML_ARCH_BITNESS 64 #elif defined(__arm__) || defined(_M_ARM) || defined(__ARM_32BIT_STATE) -#define TOML_ARCH_ARM32 1 -#define TOML_ARCH_ARM64 0 -#define TOML_ARCH_ARM 1 +#define TOML_ARCH_ARM32 1 +#define TOML_ARCH_ARM64 0 +#define TOML_ARCH_ARM 1 #define TOML_ARCH_BITNESS 32 #else #define TOML_ARCH_ARM32 0 #define TOML_ARCH_ARM64 0 -#define TOML_ARCH_ARM 0 +#define TOML_ARCH_ARM 0 #endif #endif @@ -237,11 +238,12 @@ #endif #endif -//#===================================================================================================================== -//# OS -//#===================================================================================================================== +// #===================================================================================================================== +// # OS +// #===================================================================================================================== -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__CYGWIN__) +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ + defined(__CYGWIN__) #define TOML_WINDOWS 1 #else #define TOML_WINDOWS 0 @@ -259,9 +261,9 @@ #define TOML_LINUX 0 #endif -//#===================================================================================================================== -//# ATTRIBUTES / FEATURE DETECTION / UTILITY MACROS -//#===================================================================================================================== +// #===================================================================================================================== +// # ATTRIBUTES / FEATURE DETECTION / UTILITY MACROS +// #===================================================================================================================== // TOML_HAS_INCLUDE #ifndef TOML_HAS_INCLUDE @@ -346,11 +348,11 @@ // TOML_CONCAT #define TOML_CONCAT_1(x, y) x##y -#define TOML_CONCAT(x, y) TOML_CONCAT_1(x, y) +#define TOML_CONCAT(x, y) TOML_CONCAT_1(x, y) // TOML_MAKE_STRING #define TOML_MAKE_STRING_1(s) #s -#define TOML_MAKE_STRING(s) TOML_MAKE_STRING_1(s) +#define TOML_MAKE_STRING(s) TOML_MAKE_STRING_1(s) // TOML_PRAGMA_XXXX (compiler-specific pragmas) #if TOML_CLANG @@ -398,9 +400,9 @@ #ifdef _MSC_VER #define TOML_ALWAYS_INLINE __forceinline #elif TOML_GCC || TOML_CLANG || TOML_HAS_ATTR(__always_inline__) -#define TOML_ALWAYS_INLINE \ - TOML_ATTR(__always_inline__) \ - inline +#define TOML_ALWAYS_INLINE \ + TOML_ATTR(__always_inline__) \ + inline #else #define TOML_ALWAYS_INLINE inline #endif @@ -408,7 +410,7 @@ // TOML_NEVER_INLINE #ifdef _MSC_VER #define TOML_NEVER_INLINE TOML_DECLSPEC(noinline) -#elif TOML_CUDA // https://gitlab.gnome.org/GNOME/glib/-/issues/2555 +#elif TOML_CUDA // https://gitlab.gnome.org/GNOME/glib/-/issues/2555 #define TOML_NEVER_INLINE TOML_ATTR(noinline) #else #if TOML_GCC || TOML_CLANG || TOML_HAS_ATTR(__noinline__) @@ -421,7 +423,7 @@ // MSVC attributes #define TOML_ABSTRACT_INTERFACE TOML_DECLSPEC(novtable) -#define TOML_EMPTY_BASES TOML_DECLSPEC(empty_bases) +#define TOML_EMPTY_BASES TOML_DECLSPEC(empty_bases) // TOML_TRIVIAL_ABI #if TOML_CLANG || TOML_HAS_ATTR(__trivial_abi__) @@ -449,48 +451,48 @@ // pure + const #ifndef TOML_PURE #ifdef NDEBUG -#define TOML_PURE \ - TOML_DECLSPEC(noalias) \ - TOML_ATTR(pure) +#define TOML_PURE \ + TOML_DECLSPEC(noalias) \ + TOML_ATTR(pure) #else #define TOML_PURE #endif #endif #ifndef TOML_CONST #ifdef NDEBUG -#define TOML_CONST \ - TOML_DECLSPEC(noalias) \ - TOML_ATTR(const) +#define TOML_CONST \ + TOML_DECLSPEC(noalias) \ + TOML_ATTR(const) #else #define TOML_CONST #endif #endif #ifndef TOML_INLINE_GETTER -#define TOML_INLINE_GETTER \ - TOML_NODISCARD \ - TOML_ALWAYS_INLINE +#define TOML_INLINE_GETTER \ + TOML_NODISCARD \ + TOML_ALWAYS_INLINE #endif #ifndef TOML_PURE_GETTER -#define TOML_PURE_GETTER \ - TOML_NODISCARD \ - TOML_PURE +#define TOML_PURE_GETTER \ + TOML_NODISCARD \ + TOML_PURE #endif #ifndef TOML_PURE_INLINE_GETTER -#define TOML_PURE_INLINE_GETTER \ - TOML_NODISCARD \ - TOML_ALWAYS_INLINE \ - TOML_PURE +#define TOML_PURE_INLINE_GETTER \ + TOML_NODISCARD \ + TOML_ALWAYS_INLINE \ + TOML_PURE #endif #ifndef TOML_CONST_GETTER -#define TOML_CONST_GETTER \ - TOML_NODISCARD \ - TOML_CONST +#define TOML_CONST_GETTER \ + TOML_NODISCARD \ + TOML_CONST #endif #ifndef TOML_CONST_INLINE_GETTER -#define TOML_CONST_INLINE_GETTER \ - TOML_NODISCARD \ - TOML_ALWAYS_INLINE \ - TOML_CONST +#define TOML_CONST_INLINE_GETTER \ + TOML_NODISCARD \ + TOML_ALWAYS_INLINE \ + TOML_CONST #endif // TOML_ASSUME @@ -550,7 +552,7 @@ // TOML_OPEN_ENUM + TOML_CLOSED_ENUM #if TOML_CLANG || TOML_HAS_ATTR(enum_extensibility) -#define TOML_OPEN_ENUM __attribute__((enum_extensibility(open))) +#define TOML_OPEN_ENUM __attribute__((enum_extensibility(open))) #define TOML_CLOSED_ENUM __attribute__((enum_extensibility(closed))) #else #define TOML_OPEN_ENUM @@ -558,73 +560,63 @@ #endif // TOML_OPEN_FLAGS_ENUM + TOML_CLOSED_FLAGS_ENUM -#define TOML_OPEN_FLAGS_ENUM TOML_OPEN_ENUM TOML_FLAGS_ENUM +#define TOML_OPEN_FLAGS_ENUM TOML_OPEN_ENUM TOML_FLAGS_ENUM #define TOML_CLOSED_FLAGS_ENUM TOML_CLOSED_ENUM TOML_FLAGS_ENUM // TOML_MAKE_FLAGS -#define TOML_MAKE_FLAGS_2(T, op, linkage) \ - TOML_CONST_INLINE_GETTER \ - linkage constexpr T operator op(T lhs, T rhs) noexcept \ - { \ - using under = std::underlying_type_t<T>; \ - return static_cast<T>(static_cast<under>(lhs) op static_cast<under>(rhs)); \ - } \ - \ - linkage constexpr T& operator TOML_CONCAT(op, =)(T & lhs, T rhs) noexcept \ - { \ - return lhs = (lhs op rhs); \ - } \ - \ - static_assert(true) -#define TOML_MAKE_FLAGS_1(T, linkage) \ - static_assert(std::is_enum_v<T>); \ - \ - TOML_MAKE_FLAGS_2(T, &, linkage); \ - TOML_MAKE_FLAGS_2(T, |, linkage); \ - TOML_MAKE_FLAGS_2(T, ^, linkage); \ - \ - TOML_CONST_INLINE_GETTER \ - linkage constexpr T operator~(T val) noexcept \ - { \ - using under = std::underlying_type_t<T>; \ - return static_cast<T>(~static_cast<under>(val)); \ - } \ - \ - TOML_CONST_INLINE_GETTER \ - linkage constexpr bool operator!(T val) noexcept \ - { \ - using under = std::underlying_type_t<T>; \ - return !static_cast<under>(val); \ - } \ - \ - static_assert(true) +#define TOML_MAKE_FLAGS_2(T, op, linkage) \ + TOML_CONST_INLINE_GETTER \ + linkage constexpr T operator op(T lhs, T rhs) noexcept { \ + using under = std::underlying_type_t<T>; \ + return static_cast<T>(static_cast<under>(lhs) op static_cast<under>(rhs)); \ + } \ + \ + linkage constexpr T& operator TOML_CONCAT(op, =)(T & lhs, T rhs) noexcept { \ + return lhs = (lhs op rhs); \ + } \ + \ + static_assert(true) +#define TOML_MAKE_FLAGS_1(T, linkage) \ + static_assert(std::is_enum_v<T>); \ + \ + TOML_MAKE_FLAGS_2(T, &, linkage); \ + TOML_MAKE_FLAGS_2(T, |, linkage); \ + TOML_MAKE_FLAGS_2(T, ^, linkage); \ + \ + TOML_CONST_INLINE_GETTER \ + linkage constexpr T operator~(T val) noexcept { \ + using under = std::underlying_type_t<T>; \ + return static_cast<T>(~static_cast<under>(val)); \ + } \ + \ + TOML_CONST_INLINE_GETTER \ + linkage constexpr bool operator!(T val) noexcept { \ + using under = std::underlying_type_t<T>; \ + return !static_cast<under>(val); \ + } \ + \ + static_assert(true) #define TOML_MAKE_FLAGS(T) TOML_MAKE_FLAGS_1(T, ) #define TOML_UNUSED(...) static_cast<void>(__VA_ARGS__) -#define TOML_DELETE_DEFAULTS(T) \ - T(const T&) = delete; \ - T(T&&) = delete; \ - T& operator=(const T&) = delete; \ - T& operator=(T&&) = delete - -#define TOML_ASYMMETRICAL_EQUALITY_OPS(LHS, RHS, ...) \ - __VA_ARGS__ TOML_NODISCARD \ - friend bool operator==(RHS rhs, LHS lhs) noexcept \ - { \ - return lhs == rhs; \ - } \ - __VA_ARGS__ TOML_NODISCARD \ - friend bool operator!=(LHS lhs, RHS rhs) noexcept \ - { \ - return !(lhs == rhs); \ - } \ - __VA_ARGS__ TOML_NODISCARD \ - friend bool operator!=(RHS rhs, LHS lhs) noexcept \ - { \ - return !(lhs == rhs); \ - } \ - static_assert(true) +#define TOML_DELETE_DEFAULTS(T) \ + T(const T&) = delete; \ + T(T&&) = delete; \ + T& operator=(const T&) = delete; \ + T& operator=(T&&) = delete + +#define TOML_ASYMMETRICAL_EQUALITY_OPS(LHS, RHS, ...) \ + __VA_ARGS__ TOML_NODISCARD friend bool operator==(RHS rhs, LHS lhs) noexcept { \ + return lhs == rhs; \ + } \ + __VA_ARGS__ TOML_NODISCARD friend bool operator!=(LHS lhs, RHS rhs) noexcept { \ + return !(lhs == rhs); \ + } \ + __VA_ARGS__ TOML_NODISCARD friend bool operator!=(RHS rhs, LHS lhs) noexcept { \ + return !(lhs == rhs); \ + } \ + static_assert(true) #define TOML_EVAL_BOOL_1(T, F) T #define TOML_EVAL_BOOL_0(T, F) F @@ -639,210 +631,194 @@ #if TOML_CLANG -#define TOML_PUSH_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic push) \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wunknown-warning-option") \ - static_assert(true) - -#define TOML_DISABLE_SWITCH_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wswitch") \ - static_assert(true) - -#define TOML_DISABLE_ARITHMETIC_WARNINGS \ - TOML_PRAGMA_CLANG_GE_10(diagnostic ignored "-Wimplicit-int-float-conversion") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wfloat-equal") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wdouble-promotion") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wchar-subscripts") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wshift-sign-overflow") \ - static_assert(true) - -#define TOML_DISABLE_SPAM_WARNINGS \ - TOML_PRAGMA_CLANG_GE_8(diagnostic ignored "-Wdefaulted-function-deleted") \ - TOML_PRAGMA_CLANG_GE_9(diagnostic ignored "-Wctad-maybe-unsupported") \ - TOML_PRAGMA_CLANG_GE_10(diagnostic ignored "-Wzero-as-null-pointer-constant") \ - TOML_PRAGMA_CLANG_GE_11(diagnostic ignored "-Wsuggest-destructor-override") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wweak-vtables") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wweak-template-vtables") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wdouble-promotion") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wchar-subscripts") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wmissing-field-initializers") \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Wpadded") \ - static_assert(true) - -#define TOML_POP_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic pop) \ - static_assert(true) - -#define TOML_DISABLE_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic push) \ - TOML_PRAGMA_CLANG(diagnostic ignored "-Weverything") \ - static_assert(true, "") - -#define TOML_ENABLE_WARNINGS \ - TOML_PRAGMA_CLANG(diagnostic pop) \ - static_assert(true) +#define TOML_PUSH_WARNINGS \ + TOML_PRAGMA_CLANG(diagnostic push) \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wunknown-warning-option") \ + static_assert(true) + +#define TOML_DISABLE_SWITCH_WARNINGS \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wswitch") \ + static_assert(true) + +#define TOML_DISABLE_ARITHMETIC_WARNINGS \ + TOML_PRAGMA_CLANG_GE_10(diagnostic ignored "-Wimplicit-int-float-conversion") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wfloat-equal") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wdouble-promotion") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wchar-subscripts") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wshift-sign-overflow") \ + static_assert(true) + +#define TOML_DISABLE_SPAM_WARNINGS \ + TOML_PRAGMA_CLANG_GE_8(diagnostic ignored "-Wdefaulted-function-deleted") \ + TOML_PRAGMA_CLANG_GE_9(diagnostic ignored "-Wctad-maybe-unsupported") \ + TOML_PRAGMA_CLANG_GE_10(diagnostic ignored "-Wzero-as-null-pointer-constant") \ + TOML_PRAGMA_CLANG_GE_11(diagnostic ignored "-Wsuggest-destructor-override") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wweak-vtables") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wweak-template-vtables") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wdouble-promotion") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wchar-subscripts") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wmissing-field-initializers") \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Wpadded") \ + static_assert(true) + +#define TOML_POP_WARNINGS \ + TOML_PRAGMA_CLANG(diagnostic pop) \ + static_assert(true) + +#define TOML_DISABLE_WARNINGS \ + TOML_PRAGMA_CLANG(diagnostic push) \ + TOML_PRAGMA_CLANG(diagnostic ignored "-Weverything") \ + static_assert(true, "") + +#define TOML_ENABLE_WARNINGS \ + TOML_PRAGMA_CLANG(diagnostic pop) \ + static_assert(true) #define TOML_SIMPLE_STATIC_ASSERT_MESSAGES 1 #elif TOML_MSVC -#define TOML_PUSH_WARNINGS \ - __pragma(warning(push)) \ - static_assert(true) +#define TOML_PUSH_WARNINGS __pragma(warning(push)) static_assert(true) -#if TOML_HAS_INCLUDE(<CodeAnalysis/Warnings.h>) +#if TOML_HAS_INCLUDE(<CodeAnalysis / Warnings.h>) #pragma warning(push, 0) #include <CodeAnalysis/Warnings.h> #pragma warning(pop) -#define TOML_DISABLE_CODE_ANALYSIS_WARNINGS \ - __pragma(warning(disable : ALL_CODE_ANALYSIS_WARNINGS)) \ - static_assert(true) +#define TOML_DISABLE_CODE_ANALYSIS_WARNINGS \ + __pragma(warning(disable : ALL_CODE_ANALYSIS_WARNINGS)) static_assert(true) #else #define TOML_DISABLE_CODE_ANALYSIS_WARNINGS static_assert(true) #endif -#define TOML_DISABLE_SWITCH_WARNINGS \ - __pragma(warning(disable : 4061)) \ - __pragma(warning(disable : 4062)) \ - __pragma(warning(disable : 4063)) \ - __pragma(warning(disable : 5262)) /* switch-case implicit fallthrough (false-positive) */ \ - __pragma(warning(disable : 26819)) /* cg: unannotated fallthrough */ \ - static_assert(true) - -#define TOML_DISABLE_SPAM_WARNINGS \ - __pragma(warning(disable : 4127)) /* conditional expr is constant */ \ - __pragma(warning(disable : 4324)) /* structure was padded due to alignment specifier */ \ - __pragma(warning(disable : 4348)) \ - __pragma(warning(disable : 4464)) /* relative include path contains '..' */ \ - __pragma(warning(disable : 4505)) /* unreferenced local function removed */ \ - __pragma(warning(disable : 4514)) /* unreferenced inline function has been removed */ \ - __pragma(warning(disable : 4582)) /* constructor is not implicitly called */ \ - __pragma(warning(disable : 4619)) /* there is no warning number 'XXXX' */ \ - __pragma(warning(disable : 4623)) /* default constructor was implicitly defined as deleted */ \ - __pragma(warning(disable : 4625)) /* copy constructor was implicitly defined as deleted */ \ - __pragma(warning(disable : 4626)) /* assignment operator was implicitly defined as deleted */ \ - __pragma(warning(disable : 4710)) /* function not inlined */ \ - __pragma(warning(disable : 4711)) /* function selected for automatic expansion */ \ - __pragma(warning(disable : 4820)) /* N bytes padding added */ \ - __pragma(warning(disable : 4946)) /* reinterpret_cast used between related classes */ \ - __pragma(warning(disable : 5026)) /* move constructor was implicitly defined as deleted */ \ - __pragma(warning(disable : 5027)) /* move assignment operator was implicitly defined as deleted */ \ - __pragma(warning(disable : 5039)) /* potentially throwing function passed to 'extern "C"' function */ \ - __pragma(warning(disable : 5045)) /* Compiler will insert Spectre mitigation */ \ - __pragma(warning(disable : 5264)) /* const variable is not used (false-positive) */ \ - __pragma(warning(disable : 26451)) \ - __pragma(warning(disable : 26490)) \ - __pragma(warning(disable : 26495)) \ - __pragma(warning(disable : 26812)) \ - __pragma(warning(disable : 26819)) \ - static_assert(true) - -#define TOML_DISABLE_ARITHMETIC_WARNINGS \ - __pragma(warning(disable : 4365)) /* argument signed/unsigned mismatch */ \ - __pragma(warning(disable : 4738)) /* storing 32-bit float result in memory */ \ - __pragma(warning(disable : 5219)) /* implicit conversion from integral to float */ \ - static_assert(true) - -#define TOML_POP_WARNINGS \ - __pragma(warning(pop)) \ - static_assert(true) - -#define TOML_DISABLE_WARNINGS \ - __pragma(warning(push, 0)) \ - __pragma(warning(disable : 4348)) \ - __pragma(warning(disable : 4668)) \ - __pragma(warning(disable : 5105)) \ - __pragma(warning(disable : 5264)) \ - TOML_DISABLE_CODE_ANALYSIS_WARNINGS; \ - TOML_DISABLE_SWITCH_WARNINGS; \ - TOML_DISABLE_SPAM_WARNINGS; \ - TOML_DISABLE_ARITHMETIC_WARNINGS; \ - static_assert(true) +#define TOML_DISABLE_SWITCH_WARNINGS \ + __pragma(warning(disable : 4061)) __pragma(warning(disable : 4062)) \ + __pragma(warning(disable : 4063)) __pragma( \ + warning(disable : 5262)) /* switch-case implicit fallthrough (false-positive) */ \ + __pragma(warning(disable : 26819)) /* cg: unannotated fallthrough */ \ + static_assert(true) + +#define TOML_DISABLE_SPAM_WARNINGS \ + __pragma(warning(disable : 4127)) /* conditional expr is constant */ \ + __pragma(warning(disable : 4324)) /* structure was padded due to alignment specifier */ \ + __pragma(warning(disable : 4348)) \ + __pragma(warning(disable : 4464)) /* relative include path contains '..' */ \ + __pragma(warning(disable : 4505)) /* unreferenced local function removed */ \ + __pragma(warning(disable : 4514)) /* unreferenced inline function has been removed */ \ + __pragma(warning(disable : 4582)) /* constructor is not implicitly called */ \ + __pragma(warning(disable : 4619)) /* there is no warning number 'XXXX' */ \ + __pragma( \ + warning(disable : 4623)) /* default constructor was implicitly defined as deleted */ \ + __pragma(warning(disable : 4625)) /* copy constructor was implicitly defined as deleted */ \ + __pragma( \ + warning(disable : 4626)) /* assignment operator was implicitly defined as deleted */ \ + __pragma(warning(disable : 4710)) /* function not inlined */ \ + __pragma(warning(disable : 4711)) /* function selected for automatic expansion */ \ + __pragma(warning(disable : 4820)) /* N bytes padding added */ \ + __pragma(warning(disable : 4946)) /* reinterpret_cast used between related classes */ \ + __pragma(warning(disable : 5026)) /* move constructor was implicitly defined as deleted */ \ + __pragma(warning( \ + disable : 5027)) /* move assignment operator was implicitly defined as deleted */ \ + __pragma(warning( \ + disable : 5039)) /* potentially throwing function passed to 'extern "C"' function */ \ + __pragma(warning(disable : 5045)) /* Compiler will insert Spectre mitigation */ \ + __pragma(warning(disable : 5264)) /* const variable is not used (false-positive) */ \ + __pragma(warning(disable : 26451)) __pragma(warning(disable : 26490)) \ + __pragma(warning(disable : 26495)) __pragma(warning(disable : 26812)) \ + __pragma(warning(disable : 26819)) static_assert(true) + +#define TOML_DISABLE_ARITHMETIC_WARNINGS \ + __pragma(warning(disable : 4365)) /* argument signed/unsigned mismatch */ \ + __pragma(warning(disable : 4738)) /* storing 32-bit float result in memory */ \ + __pragma(warning(disable : 5219)) /* implicit conversion from integral to float */ \ + static_assert(true) + +#define TOML_POP_WARNINGS __pragma(warning(pop)) static_assert(true) + +#define TOML_DISABLE_WARNINGS \ + __pragma(warning(push, 0)) __pragma(warning(disable : 4348)) __pragma(warning(disable : 4668)) \ + __pragma(warning(disable : 5105)) __pragma(warning(disable : 5264)) \ + TOML_DISABLE_CODE_ANALYSIS_WARNINGS; \ + TOML_DISABLE_SWITCH_WARNINGS; \ + TOML_DISABLE_SPAM_WARNINGS; \ + TOML_DISABLE_ARITHMETIC_WARNINGS; \ + static_assert(true) #define TOML_ENABLE_WARNINGS TOML_POP_WARNINGS #elif TOML_ICC -#define TOML_PUSH_WARNINGS \ - __pragma(warning(push)) \ - static_assert(true) +#define TOML_PUSH_WARNINGS __pragma(warning(push)) static_assert(true) -#define TOML_DISABLE_SPAM_WARNINGS \ - __pragma(warning(disable : 82)) /* storage class is not first */ \ - __pragma(warning(disable : 111)) /* statement unreachable (false-positive) */ \ - __pragma(warning(disable : 869)) /* unreferenced parameter */ \ - __pragma(warning(disable : 1011)) /* missing return (false-positive) */ \ - __pragma(warning(disable : 2261)) /* assume expr side-effects discarded */ \ - static_assert(true) +#define TOML_DISABLE_SPAM_WARNINGS \ + __pragma(warning(disable : 82)) /* storage class is not first */ \ + __pragma(warning(disable : 111)) /* statement unreachable (false-positive) */ \ + __pragma(warning(disable : 869)) /* unreferenced parameter */ \ + __pragma(warning(disable : 1011)) /* missing return (false-positive) */ \ + __pragma(warning(disable : 2261)) /* assume expr side-effects discarded */ \ + static_assert(true) -#define TOML_POP_WARNINGS \ - __pragma(warning(pop)) \ - static_assert(true) +#define TOML_POP_WARNINGS __pragma(warning(pop)) static_assert(true) -#define TOML_DISABLE_WARNINGS \ - __pragma(warning(push, 0)) \ - TOML_DISABLE_SPAM_WARNINGS +#define TOML_DISABLE_WARNINGS __pragma(warning(push, 0)) TOML_DISABLE_SPAM_WARNINGS -#define TOML_ENABLE_WARNINGS \ - __pragma(warning(pop)) \ - static_assert(true) +#define TOML_ENABLE_WARNINGS __pragma(warning(pop)) static_assert(true) #elif TOML_GCC -#define TOML_PUSH_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic push) \ - static_assert(true) - -#define TOML_DISABLE_SWITCH_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch-enum") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch-default") \ - static_assert(true) - -#define TOML_DISABLE_ARITHMETIC_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wfloat-equal") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wsign-conversion") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wchar-subscripts") \ - static_assert(true) - -#define TOML_DISABLE_SUGGEST_ATTR_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wsuggest-attribute=const") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wsuggest-attribute=pure") \ - static_assert(true) - -#define TOML_DISABLE_SPAM_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wpadded") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wcast-align") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wcomment") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wtype-limits") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wuseless-cast") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wchar-subscripts") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wsubobject-linkage") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wmissing-field-initializers") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wmaybe-uninitialized") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wnoexcept") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wnull-dereference") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wduplicated-branches") \ - static_assert(true) - -#define TOML_POP_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic pop) \ - static_assert(true) - -#define TOML_DISABLE_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic push) \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wall") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wextra") \ - TOML_PRAGMA_GCC(diagnostic ignored "-Wpedantic") \ - TOML_DISABLE_SWITCH_WARNINGS; \ - TOML_DISABLE_ARITHMETIC_WARNINGS; \ - TOML_DISABLE_SUGGEST_ATTR_WARNINGS; \ - TOML_DISABLE_SPAM_WARNINGS; \ - static_assert(true) - -#define TOML_ENABLE_WARNINGS \ - TOML_PRAGMA_GCC(diagnostic pop) \ - static_assert(true) +#define TOML_PUSH_WARNINGS \ + TOML_PRAGMA_GCC(diagnostic push) \ + static_assert(true) + +#define TOML_DISABLE_SWITCH_WARNINGS \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch-enum") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wswitch-default") \ + static_assert(true) + +#define TOML_DISABLE_ARITHMETIC_WARNINGS \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wfloat-equal") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wsign-conversion") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wchar-subscripts") \ + static_assert(true) + +#define TOML_DISABLE_SUGGEST_ATTR_WARNINGS \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wsuggest-attribute=const") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wsuggest-attribute=pure") \ + static_assert(true) + +#define TOML_DISABLE_SPAM_WARNINGS \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wpadded") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wcast-align") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wcomment") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wtype-limits") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wuseless-cast") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wchar-subscripts") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wsubobject-linkage") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wmissing-field-initializers") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wmaybe-uninitialized") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wnoexcept") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wnull-dereference") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wduplicated-branches") \ + static_assert(true) + +#define TOML_POP_WARNINGS \ + TOML_PRAGMA_GCC(diagnostic pop) \ + static_assert(true) + +#define TOML_DISABLE_WARNINGS \ + TOML_PRAGMA_GCC(diagnostic push) \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wall") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wextra") \ + TOML_PRAGMA_GCC(diagnostic ignored "-Wpedantic") \ + TOML_DISABLE_SWITCH_WARNINGS; \ + TOML_DISABLE_ARITHMETIC_WARNINGS; \ + TOML_DISABLE_SUGGEST_ATTR_WARNINGS; \ + TOML_DISABLE_SPAM_WARNINGS; \ + static_assert(true) + +#define TOML_ENABLE_WARNINGS \ + TOML_PRAGMA_GCC(diagnostic pop) \ + static_assert(true) #endif @@ -877,9 +853,9 @@ #define TOML_SIMPLE_STATIC_ASSERT_MESSAGES 0 #endif -//#==================================================================================================================== -//# USER CONFIGURATION -//#==================================================================================================================== +// #==================================================================================================================== +// # USER CONFIGURATION +// #==================================================================================================================== /// \addtogroup configuration Library Configuration /// \brief Preprocessor macros for configuring library functionality. /// \detail Define these before including toml++ to alter the way it functions. @@ -890,14 +866,14 @@ #ifdef TOML_CONFIG_HEADER #include TOML_CONFIG_HEADER #endif -//# {{ +// # {{ #if TOML_DOXYGEN #define TOML_CONFIG_HEADER #endif /// \def TOML_CONFIG_HEADER /// \brief An additional header to include before any other toml++ header files. /// \detail Not defined by default. -//# }} +// # }} // is the library being built as a shared lib/dll using meson and friends? #ifndef TOML_SHARED_LIB @@ -905,10 +881,11 @@ #endif // header-only mode -#if !defined(TOML_HEADER_ONLY) && defined(TOML_ALL_INLINE) // was TOML_ALL_INLINE pre-2.0 +#if !defined(TOML_HEADER_ONLY) && defined(TOML_ALL_INLINE) // was TOML_ALL_INLINE pre-2.0 #define TOML_HEADER_ONLY TOML_ALL_INLINE #endif -#if !defined(TOML_HEADER_ONLY) || (defined(TOML_HEADER_ONLY) && TOML_HEADER_ONLY) || TOML_INTELLISENSE +#if !defined(TOML_HEADER_ONLY) || (defined(TOML_HEADER_ONLY) && TOML_HEADER_ONLY) || \ + TOML_INTELLISENSE #undef TOML_HEADER_ONLY #define TOML_HEADER_ONLY 1 #endif @@ -943,11 +920,11 @@ /// \detail Not defined by default. Meaningless when #TOML_HEADER_ONLY is enabled. // dll/shared lib function exports (legacy - TOML_API was the old name for this setting) -#if !defined(TOML_EXPORTED_MEMBER_FUNCTION) && !defined(TOML_EXPORTED_STATIC_FUNCTION) \ - && !defined(TOML_EXPORTED_FREE_FUNCTION) && !defined(TOML_EXPORTED_CLASS) && defined(TOML_API) +#if !defined(TOML_EXPORTED_MEMBER_FUNCTION) && !defined(TOML_EXPORTED_STATIC_FUNCTION) && \ + !defined(TOML_EXPORTED_FREE_FUNCTION) && !defined(TOML_EXPORTED_CLASS) && defined(TOML_API) #define TOML_EXPORTED_MEMBER_FUNCTION TOML_API #define TOML_EXPORTED_STATIC_FUNCTION TOML_API -#define TOML_EXPORTED_FREE_FUNCTION TOML_API +#define TOML_EXPORTED_FREE_FUNCTION TOML_API #endif // dll/shared lib exports @@ -959,20 +936,20 @@ #undef TOML_EXPORTED_FREE_FUNCTION #if TOML_WINDOWS #if TOML_IMPLEMENTATION -#define TOML_EXPORTED_CLASS __declspec(dllexport) +#define TOML_EXPORTED_CLASS __declspec(dllexport) #define TOML_EXPORTED_FREE_FUNCTION __declspec(dllexport) #else -#define TOML_EXPORTED_CLASS __declspec(dllimport) +#define TOML_EXPORTED_CLASS __declspec(dllimport) #define TOML_EXPORTED_FREE_FUNCTION __declspec(dllimport) #endif #ifndef TOML_CALLCONV #define TOML_CALLCONV __cdecl #endif #elif defined(__GNUC__) && __GNUC__ >= 4 -#define TOML_EXPORTED_CLASS __attribute__((visibility("default"))) +#define TOML_EXPORTED_CLASS __attribute__((visibility("default"))) #define TOML_EXPORTED_MEMBER_FUNCTION __attribute__((visibility("default"))) #define TOML_EXPORTED_STATIC_FUNCTION __attribute__((visibility("default"))) -#define TOML_EXPORTED_FREE_FUNCTION __attribute__((visibility("default"))) +#define TOML_EXPORTED_FREE_FUNCTION __attribute__((visibility("default"))) #endif #endif #ifndef TOML_EXPORTED_CLASS @@ -1012,11 +989,13 @@ /// into the public API of a DLL on Windows. // experimental language features -#if !defined(TOML_ENABLE_UNRELEASED_FEATURES) && defined(TOML_UNRELEASED_FEATURES) // was TOML_UNRELEASED_FEATURES - // pre-3.0 +#if !defined(TOML_ENABLE_UNRELEASED_FEATURES) && \ + defined(TOML_UNRELEASED_FEATURES) // was TOML_UNRELEASED_FEATURES + // pre-3.0 #define TOML_ENABLE_UNRELEASED_FEATURES TOML_UNRELEASED_FEATURES #endif -#if (defined(TOML_ENABLE_UNRELEASED_FEATURES) && TOML_ENABLE_UNRELEASED_FEATURES) || TOML_INTELLISENSE +#if (defined(TOML_ENABLE_UNRELEASED_FEATURES) && TOML_ENABLE_UNRELEASED_FEATURES) || \ + TOML_INTELLISENSE #undef TOML_ENABLE_UNRELEASED_FEATURES #define TOML_ENABLE_UNRELEASED_FEATURES 1 #endif @@ -1027,13 +1006,15 @@ /// \brief Enables support for unreleased TOML language features not yet part of a /// [numbered version](https://github.com/toml-lang/toml/releases). /// \detail Defaults to `0`. -/// \see [TOML Language Support](https://github.com/marzer/tomlplusplus/blob/master/README.md#toml-language-support) +/// \see [TOML Language +/// Support](https://github.com/marzer/tomlplusplus/blob/master/README.md#toml-language-support) // parser -#if !defined(TOML_ENABLE_PARSER) && defined(TOML_PARSER) // was TOML_PARSER pre-3.0 +#if !defined(TOML_ENABLE_PARSER) && defined(TOML_PARSER) // was TOML_PARSER pre-3.0 #define TOML_ENABLE_PARSER TOML_PARSER #endif -#if !defined(TOML_ENABLE_PARSER) || (defined(TOML_ENABLE_PARSER) && TOML_ENABLE_PARSER) || TOML_INTELLISENSE +#if !defined(TOML_ENABLE_PARSER) || (defined(TOML_ENABLE_PARSER) && TOML_ENABLE_PARSER) || \ + TOML_INTELLISENSE #undef TOML_ENABLE_PARSER #define TOML_ENABLE_PARSER 1 #endif @@ -1044,7 +1025,8 @@ /// to `0` can improve compilation speed and reduce binary size. // formatters -#if !defined(TOML_ENABLE_FORMATTERS) || (defined(TOML_ENABLE_FORMATTERS) && TOML_ENABLE_FORMATTERS) || TOML_INTELLISENSE +#if !defined(TOML_ENABLE_FORMATTERS) || \ + (defined(TOML_ENABLE_FORMATTERS) && TOML_ENABLE_FORMATTERS) || TOML_INTELLISENSE #undef TOML_ENABLE_FORMATTERS #define TOML_ENABLE_FORMATTERS 1 #endif @@ -1059,17 +1041,19 @@ /// - toml::yaml_formatter // SIMD -#if !defined(TOML_ENABLE_SIMD) || (defined(TOML_ENABLE_SIMD) && TOML_ENABLE_SIMD) || TOML_INTELLISENSE +#if !defined(TOML_ENABLE_SIMD) || (defined(TOML_ENABLE_SIMD) && TOML_ENABLE_SIMD) || \ + TOML_INTELLISENSE #undef TOML_ENABLE_SIMD #define TOML_ENABLE_SIMD 1 #endif // windows compat -#if !defined(TOML_ENABLE_WINDOWS_COMPAT) && defined(TOML_WINDOWS_COMPAT) // was TOML_WINDOWS_COMPAT pre-3.0 +#if !defined(TOML_ENABLE_WINDOWS_COMPAT) && \ + defined(TOML_WINDOWS_COMPAT) // was TOML_WINDOWS_COMPAT pre-3.0 #define TOML_ENABLE_WINDOWS_COMPAT TOML_WINDOWS_COMPAT #endif -#if !defined(TOML_ENABLE_WINDOWS_COMPAT) || (defined(TOML_ENABLE_WINDOWS_COMPAT) && TOML_ENABLE_WINDOWS_COMPAT) \ - || TOML_INTELLISENSE +#if !defined(TOML_ENABLE_WINDOWS_COMPAT) || \ + (defined(TOML_ENABLE_WINDOWS_COMPAT) && TOML_ENABLE_WINDOWS_COMPAT) || TOML_INTELLISENSE #undef TOML_ENABLE_WINDOWS_COMPAT #define TOML_ENABLE_WINDOWS_COMPAT 1 #endif @@ -1083,16 +1067,15 @@ #define TOML_INCLUDE_WINDOWS_H 0 #endif /// \def TOML_ENABLE_WINDOWS_COMPAT -/// \brief Enables the use of wide strings (wchar_t, std::wstring) in various places throughout the library -/// when building for Windows. -/// \detail Defaults to `1` when building for Windows, `0` otherwise. Has no effect when building for anything other -/// than Windows. -/// \remark This <strong>does not</strong> change the underlying string type used to represent TOML keys and string -/// values; that will still be std::string. This setting simply enables some narrow <=> wide string -/// conversions when necessary at various interface boundaries. -/// <br><br> -/// If you're building for Windows and you have no need for Windows' "Pretends-to-be-unicode" wide strings, -/// you can safely set this to `0`. +/// \brief Enables the use of wide strings (wchar_t, std::wstring) in various places throughout the +/// library when building for Windows. +/// \detail Defaults to `1` when building for Windows, `0` otherwise. Has no effect when building +/// for anything other than Windows. +/// \remark This <strong>does not</strong> change the underlying string type used to represent TOML +/// keys and string values; that will still be std::string. This setting simply enables some narrow +/// <=> wide string conversions when necessary at various interface boundaries. <br><br> If +/// you're building for Windows and you have no need for Windows' "Pretends-to-be-unicode" wide +/// strings, you can safely set this to `0`. // custom optional #ifdef TOML_OPTIONAL_TYPE @@ -1100,17 +1083,17 @@ #else #define TOML_HAS_CUSTOM_OPTIONAL_TYPE 0 #endif -//# {{ +// # {{ #if TOML_DOXYGEN #define TOML_OPTIONAL_TYPE #endif /// \def TOML_OPTIONAL_TYPE /// \brief Overrides the `optional<T>` type used by the library. /// \detail Not defined by default (use std::optional). -/// \warning The library uses optionals internally in a few places; if you choose to replace the optional type -/// it must be with something that is still API-compatible with std::optional -/// (e.g. [tl::optional](https://github.com/TartanLlama/optional)). -//# }} +/// \warning The library uses optionals internally in a few places; if you choose to replace the +/// optional type it must be with something that is still API-compatible with std::optional (e.g. +/// [tl::optional](https://github.com/TartanLlama/optional)). +// # }} // exceptions (library use) #if TOML_COMPILER_HAS_EXCEPTIONS @@ -1137,14 +1120,15 @@ /// \brief Calling convention to apply to exported free/static functions. /// \detail Not defined by default (let the compiler decide). -//# {{ +// # {{ #if TOML_DOXYGEN #define TOML_SMALL_FLOAT_TYPE #endif /// \def TOML_SMALL_FLOAT_TYPE -/// \brief If your codebase has an additional 'small' float type (e.g. half-precision), this tells toml++ about it. +/// \brief If your codebase has an additional 'small' float type (e.g. half-precision), this tells +/// toml++ about it. /// \detail Not defined by default. -//# }} +// # }} #ifndef TOML_UNDEF_MACROS #define TOML_UNDEF_MACROS 1 @@ -1153,7 +1137,8 @@ #ifndef TOML_MAX_NESTED_VALUES #define TOML_MAX_NESTED_VALUES 256 // this refers to the depth of nested values, e.g. inline tables and arrays. -// 256 is crazy high! if you're hitting this limit with real input, TOML is probably the wrong tool for the job... +// 256 is crazy high! if you're hitting this limit with real input, TOML is probably the wrong tool +// for the job... #endif #ifdef TOML_CHAR_8_STRINGS @@ -1193,28 +1178,29 @@ TOML_ENABLE_WARNINGS; /// \brief Sets the assert function used by the library. /// \detail Defaults to the standard C `assert()`. -//# {{ +// # {{ #if TOML_DOXYGEN #define TOML_SMALL_INT_TYPE #endif /// \def TOML_SMALL_INT_TYPE -/// \brief If your codebase has an additional 'small' integer type (e.g. 24-bits), this tells toml++ about it. +/// \brief If your codebase has an additional 'small' integer type (e.g. 24-bits), this tells toml++ +/// about it. /// \detail Not defined by default. -//# }} +// # }} #ifndef TOML_ENABLE_FLOAT16 #define TOML_ENABLE_FLOAT16 0 #endif -//# {{ +// # {{ /// \def TOML_ENABLE_FLOAT16 /// \brief Enable support for the built-in `_Float16` type. /// \detail Defaults to `0`. -//# }} +// # }} /// @} -//#==================================================================================================================== -//# CHARCONV SUPPORT -//#==================================================================================================================== +// #==================================================================================================================== +// # CHARCONV SUPPORT +// #==================================================================================================================== #if !defined(TOML_FLOAT_CHARCONV) && (TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL)) // not supported by any version of GCC or Clang as of 26/11/2020 @@ -1235,13 +1221,13 @@ TOML_ENABLE_WARNINGS; #if (TOML_INT_CHARCONV || TOML_FLOAT_CHARCONV) && !TOML_HAS_INCLUDE(<charconv>) #undef TOML_INT_CHARCONV #undef TOML_FLOAT_CHARCONV -#define TOML_INT_CHARCONV 0 +#define TOML_INT_CHARCONV 0 #define TOML_FLOAT_CHARCONV 0 #endif -//#===================================================================================================================== -//# SFINAE -//#===================================================================================================================== +// #===================================================================================================================== +// # SFINAE +// #===================================================================================================================== /// \cond #if defined(__cpp_concepts) && __cpp_concepts >= 201907 @@ -1250,41 +1236,41 @@ TOML_ENABLE_WARNINGS; #define TOML_REQUIRES(...) #endif #define TOML_ENABLE_IF(...) , typename std::enable_if<(__VA_ARGS__), int>::type = 0 -#define TOML_CONSTRAINED_TEMPLATE(condition, ...) \ - template <__VA_ARGS__ TOML_ENABLE_IF(condition)> \ - TOML_REQUIRES(condition) +#define TOML_CONSTRAINED_TEMPLATE(condition, ...) \ + template <__VA_ARGS__ TOML_ENABLE_IF(condition)> \ + TOML_REQUIRES(condition) #define TOML_HIDDEN_CONSTRAINT(condition, ...) TOML_CONSTRAINED_TEMPLATE(condition, __VA_ARGS__) /// \endcond -//# {{ +// # {{ #ifndef TOML_CONSTRAINED_TEMPLATE #define TOML_CONSTRAINED_TEMPLATE(condition, ...) template <__VA_ARGS__> #endif #ifndef TOML_HIDDEN_CONSTRAINT #define TOML_HIDDEN_CONSTRAINT(condition, ...) #endif -//# }} +// # }} -//#===================================================================================================================== -//# FLOAT128 -//#===================================================================================================================== +// #===================================================================================================================== +// # FLOAT128 +// #===================================================================================================================== -#if defined(__SIZEOF_FLOAT128__) && defined(__FLT128_MANT_DIG__) && defined(__LDBL_MANT_DIG__) \ - && __FLT128_MANT_DIG__ > __LDBL_MANT_DIG__ +#if defined(__SIZEOF_FLOAT128__) && defined(__FLT128_MANT_DIG__) && defined(__LDBL_MANT_DIG__) && \ + __FLT128_MANT_DIG__ > __LDBL_MANT_DIG__ #define TOML_FLOAT128 __float128 #endif -//#===================================================================================================================== -//# INT128 -//#===================================================================================================================== +// #===================================================================================================================== +// # INT128 +// #===================================================================================================================== #ifdef __SIZEOF_INT128__ -#define TOML_INT128 __int128_t +#define TOML_INT128 __int128_t #define TOML_UINT128 __uint128_t #endif -//#==================================================================================================================== -//# VERSIONS AND NAMESPACES -//#==================================================================================================================== +// #==================================================================================================================== +// # VERSIONS AND NAMESPACES +// #==================================================================================================================== // clang-format off #include "version.hpp" @@ -1349,13 +1335,13 @@ TOML_ENABLE_WARNINGS; #endif // clang-format on -//#==================================================================================================================== -//# ASSERT -//#==================================================================================================================== +// #==================================================================================================================== +// # ASSERT +// #==================================================================================================================== -//#==================================================================================================================== -//# STATIC ASSERT MESSAGE FORMATTING -//#==================================================================================================================== +// #==================================================================================================================== +// # STATIC ASSERT MESSAGE FORMATTING +// #==================================================================================================================== // clang-format off /// \cond diff --git a/vendor/toml++/impl/print_to_stream.hpp b/vendor/toml++/impl/print_to_stream.hpp index b6a4895..60eac4e 100644 --- a/vendor/toml++/impl/print_to_stream.hpp +++ b/vendor/toml++/impl/print_to_stream.hpp @@ -1,128 +1,138 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once -#include "std_string.hpp" #include "forward_declarations.hpp" #include "header_start.hpp" +#include "std_string.hpp" -TOML_IMPL_NAMESPACE_START -{ - // Q: "why does print_to_stream() exist? why not just use ostream::write(), ostream::put() etc?" - // A: - I'm using <charconv> to format numerics. Faster and locale-independent. - // - I can (potentially) avoid forcing users to drag in <sstream> and <iomanip>. - // - Strings in C++. Honestly. +TOML_IMPL_NAMESPACE_START { + // Q: "why does print_to_stream() exist? why not just use ostream::write(), ostream::put() etc?" + // A: - I'm using <charconv> to format numerics. Faster and locale-independent. + // - I can (potentially) avoid forcing users to drag in <sstream> and <iomanip>. + // - Strings in C++. Honestly. - TOML_EXPORTED_FREE_FUNCTION - TOML_ATTR(nonnull) - void TOML_CALLCONV print_to_stream(std::ostream&, const char*, size_t); + TOML_EXPORTED_FREE_FUNCTION + TOML_ATTR(nonnull) + void TOML_CALLCONV print_to_stream(std::ostream&, const char*, size_t); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, std::string_view); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, std::string_view); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const std::string&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const std::string&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, char); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, char); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, signed char, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, signed char, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, signed short, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, signed short, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, signed int, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, signed int, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, signed long, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, signed long, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, signed long long, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, signed long long, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, unsigned char, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, unsigned char, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, unsigned short, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, unsigned short, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, unsigned int, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, unsigned int, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, unsigned long, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, unsigned long, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, unsigned long long, value_flags = {}, size_t min_digits = 0); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, unsigned long long, value_flags = {}, + size_t min_digits = 0); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, float, value_flags = {}, bool relaxed_precision = false); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, float, value_flags = {}, + bool relaxed_precision = false); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, double, value_flags = {}, bool relaxed_precision = false); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, double, value_flags = {}, + bool relaxed_precision = false); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, bool); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, bool); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const toml::date&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const toml::date&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const toml::time&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const toml::time&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const toml::time_offset&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const toml::time_offset&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const toml::date_time&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const toml::date_time&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const source_position&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const source_position&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const source_region&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const source_region&); #if TOML_ENABLE_FORMATTERS - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const array&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const array&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const table&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const table&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const value<std::string>&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const value<std::string>&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const value<int64_t>&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const value<int64_t>&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const value<double>&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const value<double>&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const value<bool>&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const value<bool>&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const value<date>&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const value<date>&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const value<time>&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const value<time>&); - TOML_EXPORTED_FREE_FUNCTION - void TOML_CALLCONV print_to_stream(std::ostream&, const value<date_time>&); + TOML_EXPORTED_FREE_FUNCTION + void TOML_CALLCONV print_to_stream(std::ostream&, const value<date_time>&); #endif - template <typename T, typename U> - inline void print_to_stream_bookended(std::ostream & stream, const T& val, const U& bookend) - { - print_to_stream(stream, bookend); - print_to_stream(stream, val); - print_to_stream(stream, bookend); - } + template <typename T, typename U> + inline void print_to_stream_bookended(std::ostream & stream, const T& val, const U& bookend) { + print_to_stream(stream, bookend); + print_to_stream(stream, val); + print_to_stream(stream, bookend); + } } TOML_IMPL_NAMESPACE_END; diff --git a/vendor/toml++/impl/simd.hpp b/vendor/toml++/impl/simd.hpp index ef66d66..0f9616c 100644 --- a/vendor/toml++/impl/simd.hpp +++ b/vendor/toml++/impl/simd.hpp @@ -1,14 +1,14 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" #if TOML_ENABLE_SIMD -#if defined(__SSE2__) \ - || (defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))) +#if defined(__SSE2__) || (defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_X64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 2))) #define TOML_HAS_SSE2 1 #endif @@ -16,7 +16,7 @@ #define TOML_HAS_SSE4_1 1 #endif -#endif // TOML_ENABLE_SIMD +#endif // TOML_ENABLE_SIMD #ifndef TOML_HAS_SSE2 #define TOML_HAS_SSE2 0 diff --git a/vendor/toml++/impl/source_region.hpp b/vendor/toml++/impl/source_region.hpp index 82a6d4b..e46b013 100644 --- a/vendor/toml++/impl/source_region.hpp +++ b/vendor/toml++/impl/source_region.hpp @@ -1,222 +1,213 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once -#include "std_optional.hpp" -#include "std_string.hpp" #include "forward_declarations.hpp" -#include "print_to_stream.hpp" #include "header_start.hpp" +#include "print_to_stream.hpp" +#include "std_optional.hpp" +#include "std_string.hpp" -TOML_NAMESPACE_START -{ - /// \brief The integer type used to tally line numbers and columns. - using source_index = uint32_t; - - /// \brief A pointer to a shared string resource containing a source path. - using source_path_ptr = std::shared_ptr<const std::string>; - - /// \brief A source document line-and-column pair. - /// - /// \detail \cpp - /// auto table = toml::parse_file("config.toml"sv); - /// std::cout << "The node 'description' was defined at "sv - /// << table.get("description")->source().begin() - /// << "\n"; - /// \ecpp - /// - /// \out - /// The value 'description' was defined at line 7, column 15 - /// \eout - /// - /// \remarks toml++'s parser is unicode-aware insofar as it knows how to handle - /// non-ASCII whitespace and newline characters, but it doesn't give much thought - /// to combining marks, grapheme clusters vs. characters, et cetera. - /// If a TOML document contains lots of codepoints outside of the ASCII range - /// you may find that your source_positions don't match those given by a text editor - /// (typically the line numbers will be accurate but column numbers will be too high). - /// <strong>This is not an error.</strong> I've chosen this behaviour as a deliberate trade-off - /// between parser complexity and correctness. - struct TOML_TRIVIAL_ABI source_position - { - /// \brief The line number. - /// \remarks Valid line numbers start at 1. - source_index line; - - /// \brief The column number. - /// \remarks Valid column numbers start at 1. - source_index column; - - /// \brief Returns true if both line and column numbers are non-zero. - TOML_PURE_GETTER - explicit constexpr operator bool() const noexcept - { - return line > source_index{} // - && column > source_index{}; - } - - /// \brief Equality operator. - TOML_PURE_GETTER - friend constexpr bool operator==(const source_position& lhs, const source_position& rhs) noexcept - { - return lhs.line == rhs.line // - && lhs.column == rhs.column; - } - - /// \brief Inequality operator. - TOML_PURE_INLINE_GETTER - friend constexpr bool operator!=(const source_position& lhs, const source_position& rhs) noexcept - { - return !(lhs == rhs); - } - - private: - /// \cond - - TOML_PURE_GETTER - static constexpr uint64_t pack(const source_position& pos) noexcept - { - return static_cast<uint64_t>(pos.line) << 32 | static_cast<uint64_t>(pos.column); - } - - /// \endcond - - public: - /// \brief Less-than operator. - TOML_PURE_GETTER - friend constexpr bool operator<(const source_position& lhs, const source_position& rhs) noexcept - { - return pack(lhs) < pack(rhs); - } - - /// \brief Less-than-or-equal-to operator. - TOML_PURE_GETTER - friend constexpr bool operator<=(const source_position& lhs, const source_position& rhs) noexcept - { - return pack(lhs) <= pack(rhs); - } - - /// \brief Greater-than operator. - TOML_PURE_GETTER - friend constexpr bool operator>(const source_position& lhs, const source_position& rhs) noexcept - { - return pack(lhs) > pack(rhs); - } - - /// \brief Greater-than-or-equal-to operator. - TOML_PURE_GETTER - friend constexpr bool operator>=(const source_position& lhs, const source_position& rhs) noexcept - { - return pack(lhs) >= pack(rhs); - } - - /// \brief Prints a source_position to a stream. - /// - /// \detail \cpp - /// auto tbl = toml::parse("bar = 42"sv); - /// - /// std::cout << "The value for 'bar' was found on "sv - /// << tbl.get("bar")->source().begin() - /// << "\n"; - /// \ecpp - /// - /// \out - /// The value for 'bar' was found on line 1, column 7 - /// \eout - /// - /// \param lhs The stream. - /// \param rhs The source_position. - /// - /// \returns The input stream. - friend std::ostream& operator<<(std::ostream& lhs, const source_position& rhs) - { - impl::print_to_stream(lhs, rhs); - return lhs; - } - }; - - /// \brief A source document region. - /// - /// \detail \cpp - /// auto tbl = toml::parse_file("config.toml"sv); - /// if (auto server = tbl.get("server")) - /// { - /// std::cout << "begin: "sv << server->source().begin << "\n"; - /// std::cout << "end: "sv << server->source().end << "\n"; - /// std::cout << "path: "sv << *server->source().path << "\n"; - /// } - /// \ecpp - /// - /// \out - /// begin: line 3, column 1 - /// end: line 3, column 22 - /// path: config.toml - /// \eout - /// - /// \remarks toml++'s parser is unicode-aware insofar as it knows how to handle - /// non-ASCII whitespace and newline characters, but it doesn't give much thought - /// to combining marks, grapheme clusters vs. characters, et cetera. - /// If a TOML document contains lots of codepoints outside of the ASCII range - /// you may find that your source_positions don't match those given by a text editor - /// (typically the line numbers will be accurate but column numbers will be too high). - /// <strong>This is not an error.</strong> I've chosen this behaviour as a deliberate trade-off - /// between parser complexity and correctness. - struct source_region - { - /// \brief The beginning of the region (inclusive). - source_position begin; - - /// \brief The end of the region (exclusive). - source_position end; - - /// \brief The path to the corresponding source document. - /// - /// \remarks This will be `nullptr` if no path was provided to toml::parse(). - source_path_ptr path; +TOML_NAMESPACE_START { + /// \brief The integer type used to tally line numbers and columns. + using source_index = uint32_t; + + /// \brief A pointer to a shared string resource containing a source path. + using source_path_ptr = std::shared_ptr<const std::string>; + + /// \brief A source document line-and-column pair. + /// + /// \detail \cpp + /// auto table = toml::parse_file("config.toml"sv); + /// std::cout << "The node 'description' was defined at "sv + /// << table.get("description")->source().begin() + /// << "\n"; + /// \ecpp + /// + /// \out + /// The value 'description' was defined at line 7, column 15 + /// \eout + /// + /// \remarks toml++'s parser is unicode-aware insofar as it knows how to handle + /// non-ASCII whitespace and newline characters, but it doesn't give much thought + /// to combining marks, grapheme clusters vs. characters, et cetera. + /// If a TOML document contains lots of codepoints outside of the ASCII range + /// you may find that your source_positions don't match those given by a text editor + /// (typically the line numbers will be accurate but column numbers will be too high). + /// <strong>This is not an error.</strong> I've chosen this behaviour as a deliberate + /// trade-off between parser complexity and correctness. + struct TOML_TRIVIAL_ABI source_position { + /// \brief The line number. + /// \remarks Valid line numbers start at 1. + source_index line; + + /// \brief The column number. + /// \remarks Valid column numbers start at 1. + source_index column; + + /// \brief Returns true if both line and column numbers are non-zero. + TOML_PURE_GETTER + explicit constexpr operator bool() const noexcept { + return line > source_index{} // + && column > source_index{}; + } + + /// \brief Equality operator. + TOML_PURE_GETTER + friend constexpr bool operator==(const source_position& lhs, + const source_position& rhs) noexcept { + return lhs.line == rhs.line // + && lhs.column == rhs.column; + } + + /// \brief Inequality operator. + TOML_PURE_INLINE_GETTER + friend constexpr bool operator!=(const source_position& lhs, + const source_position& rhs) noexcept { + return !(lhs == rhs); + } + + private: + /// \cond + + TOML_PURE_GETTER + static constexpr uint64_t pack(const source_position& pos) noexcept { + return static_cast<uint64_t>(pos.line) << 32 | static_cast<uint64_t>(pos.column); + } + + /// \endcond + + public: + /// \brief Less-than operator. + TOML_PURE_GETTER + friend constexpr bool operator<(const source_position& lhs, + const source_position& rhs) noexcept { + return pack(lhs) < pack(rhs); + } + + /// \brief Less-than-or-equal-to operator. + TOML_PURE_GETTER + friend constexpr bool operator<=(const source_position& lhs, + const source_position& rhs) noexcept { + return pack(lhs) <= pack(rhs); + } + + /// \brief Greater-than operator. + TOML_PURE_GETTER + friend constexpr bool operator>(const source_position& lhs, + const source_position& rhs) noexcept { + return pack(lhs) > pack(rhs); + } + + /// \brief Greater-than-or-equal-to operator. + TOML_PURE_GETTER + friend constexpr bool operator>=(const source_position& lhs, + const source_position& rhs) noexcept { + return pack(lhs) >= pack(rhs); + } + + /// \brief Prints a source_position to a stream. + /// + /// \detail \cpp + /// auto tbl = toml::parse("bar = 42"sv); + /// + /// std::cout << "The value for 'bar' was found on "sv + /// << tbl.get("bar")->source().begin() + /// << "\n"; + /// \ecpp + /// + /// \out + /// The value for 'bar' was found on line 1, column 7 + /// \eout + /// + /// \param lhs The stream. + /// \param rhs The source_position. + /// + /// \returns The input stream. + friend std::ostream& operator<<(std::ostream& lhs, const source_position& rhs) { + impl::print_to_stream(lhs, rhs); + return lhs; + } + }; + + /// \brief A source document region. + /// + /// \detail \cpp + /// auto tbl = toml::parse_file("config.toml"sv); + /// if (auto server = tbl.get("server")) + /// { + /// std::cout << "begin: "sv << server->source().begin << "\n"; + /// std::cout << "end: "sv << server->source().end << "\n"; + /// std::cout << "path: "sv << *server->source().path << "\n"; + /// } + /// \ecpp + /// + /// \out + /// begin: line 3, column 1 + /// end: line 3, column 22 + /// path: config.toml + /// \eout + /// + /// \remarks toml++'s parser is unicode-aware insofar as it knows how to handle + /// non-ASCII whitespace and newline characters, but it doesn't give much thought + /// to combining marks, grapheme clusters vs. characters, et cetera. + /// If a TOML document contains lots of codepoints outside of the ASCII range + /// you may find that your source_positions don't match those given by a text editor + /// (typically the line numbers will be accurate but column numbers will be too high). + /// <strong>This is not an error.</strong> I've chosen this behaviour as a deliberate + /// trade-off between parser complexity and correctness. + struct source_region { + /// \brief The beginning of the region (inclusive). + source_position begin; + + /// \brief The end of the region (exclusive). + source_position end; + + /// \brief The path to the corresponding source document. + /// + /// \remarks This will be `nullptr` if no path was provided to toml::parse(). + source_path_ptr path; #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief The path to the corresponding source document as a wide-string. - /// - /// \availability This function is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \remarks This will return an empty optional if no path was provided to toml::parse(). - TOML_NODISCARD - optional<std::wstring> wide_path() const - { - if (!path || path->empty()) - return {}; - return { impl::widen(*path) }; - } + /// \brief The path to the corresponding source document as a wide-string. + /// + /// \availability This function is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \remarks This will return an empty optional if no path was provided to toml::parse(). + TOML_NODISCARD + optional<std::wstring> wide_path() const { + if (!path || path->empty()) return {}; + return {impl::widen(*path)}; + } #endif - /// \brief Prints a source_region to a stream. - /// - /// \detail \cpp - /// auto tbl = toml::parse("bar = 42", "config.toml"); - /// - /// std::cout << "The value for 'bar' was found on "sv - /// << tbl.get("bar")->source() - /// << "\n"; - /// \ecpp - /// - /// \out - /// The value for 'bar' was found on line 1, column 7 of 'config.toml' - /// \eout - /// - /// \param lhs The stream. - /// \param rhs The source_position. - /// - /// \returns The input stream. - friend std::ostream& operator<<(std::ostream& lhs, const source_region& rhs) - { - impl::print_to_stream(lhs, rhs); - return lhs; - } - }; + /// \brief Prints a source_region to a stream. + /// + /// \detail \cpp + /// auto tbl = toml::parse("bar = 42", "config.toml"); + /// + /// std::cout << "The value for 'bar' was found on "sv + /// << tbl.get("bar")->source() + /// << "\n"; + /// \ecpp + /// + /// \out + /// The value for 'bar' was found on line 1, column 7 of 'config.toml' + /// \eout + /// + /// \param lhs The stream. + /// \param rhs The source_position. + /// + /// \returns The input stream. + friend std::ostream& operator<<(std::ostream& lhs, const source_region& rhs) { + impl::print_to_stream(lhs, rhs); + return lhs; + } + }; } TOML_NAMESPACE_END; diff --git a/vendor/toml++/impl/std_except.hpp b/vendor/toml++/impl/std_except.hpp index 9ea1479..fe63d6c 100644 --- a/vendor/toml++/impl/std_except.hpp +++ b/vendor/toml++/impl/std_except.hpp @@ -1,7 +1,7 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" diff --git a/vendor/toml++/impl/std_initializer_list.hpp b/vendor/toml++/impl/std_initializer_list.hpp index e1ba61d..00f7ba0 100644 --- a/vendor/toml++/impl/std_initializer_list.hpp +++ b/vendor/toml++/impl/std_initializer_list.hpp @@ -1,7 +1,7 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" diff --git a/vendor/toml++/impl/std_map.hpp b/vendor/toml++/impl/std_map.hpp index 8f97330..64305aa 100644 --- a/vendor/toml++/impl/std_map.hpp +++ b/vendor/toml++/impl/std_map.hpp @@ -1,11 +1,11 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" TOML_DISABLE_WARNINGS; -#include <map> #include <iterator> +#include <map> TOML_ENABLE_WARNINGS; diff --git a/vendor/toml++/impl/std_new.hpp b/vendor/toml++/impl/std_new.hpp index c896a71..dd54bad 100644 --- a/vendor/toml++/impl/std_new.hpp +++ b/vendor/toml++/impl/std_new.hpp @@ -1,7 +1,7 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" @@ -9,7 +9,8 @@ TOML_DISABLE_WARNINGS; #include <new> TOML_ENABLE_WARNINGS; -#if (!defined(__apple_build_version__) && TOML_CLANG >= 8) || TOML_GCC >= 7 || TOML_ICC >= 1910 || TOML_MSVC >= 1914 +#if (!defined(__apple_build_version__) && TOML_CLANG >= 8) || TOML_GCC >= 7 || TOML_ICC >= 1910 || \ + TOML_MSVC >= 1914 #define TOML_LAUNDER(x) __builtin_launder(x) #elif defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 #define TOML_LAUNDER(x) std::launder(x) diff --git a/vendor/toml++/impl/std_optional.hpp b/vendor/toml++/impl/std_optional.hpp index 6760388..6e988b5 100644 --- a/vendor/toml++/impl/std_optional.hpp +++ b/vendor/toml++/impl/std_optional.hpp @@ -1,7 +1,7 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" @@ -11,21 +11,20 @@ TOML_DISABLE_WARNINGS; #endif TOML_ENABLE_WARNINGS; -TOML_NAMESPACE_START -{ +TOML_NAMESPACE_START { #if TOML_HAS_CUSTOM_OPTIONAL_TYPE - template <typename T> - using optional = TOML_OPTIONAL_TYPE<T>; + template <typename T> + using optional = TOML_OPTIONAL_TYPE<T>; #else - /// \brief The 'optional' type used throughout the library. - /// - /// \remarks By default this will be an alias for std::optional, but you can change the optional type - /// used by the library by defining #TOML_OPTIONAL_TYPE. - template <typename T> - using optional = std::optional<T>; + /// \brief The 'optional' type used throughout the library. + /// + /// \remarks By default this will be an alias for std::optional, but you can change the optional + /// type used by the library by defining #TOML_OPTIONAL_TYPE. + template <typename T> + using optional = std::optional<T>; #endif } diff --git a/vendor/toml++/impl/std_string.hpp b/vendor/toml++/impl/std_string.hpp index b75afaf..5230661 100644 --- a/vendor/toml++/impl/std_string.hpp +++ b/vendor/toml++/impl/std_string.hpp @@ -1,18 +1,17 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" TOML_DISABLE_WARNINGS; -#include <string_view> #include <string> +#include <string_view> TOML_ENABLE_WARNINGS; -#if TOML_DOXYGEN \ - || (defined(__cpp_char8_t) && __cpp_char8_t >= 201811 && defined(__cpp_lib_char8_t) \ - && __cpp_lib_char8_t >= 201907) +#if TOML_DOXYGEN || (defined(__cpp_char8_t) && __cpp_char8_t >= 201811 && \ + defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201907) #define TOML_HAS_CHAR8 1 #else #define TOML_HAS_CHAR8 0 @@ -20,34 +19,33 @@ TOML_ENABLE_WARNINGS; /// \cond -namespace toml // non-abi namespace; this is not an error +namespace toml // non-abi namespace; this is not an error { - using namespace std::string_literals; - using namespace std::string_view_literals; -} +using namespace std::string_literals; +using namespace std::string_view_literals; +} // namespace toml #if TOML_ENABLE_WINDOWS_COMPAT -TOML_IMPL_NAMESPACE_START -{ - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - std::string narrow(std::wstring_view); +TOML_IMPL_NAMESPACE_START { + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + std::string narrow(std::wstring_view); - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - std::wstring widen(std::string_view); + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + std::wstring widen(std::string_view); #if TOML_HAS_CHAR8 - TOML_NODISCARD - TOML_EXPORTED_FREE_FUNCTION - std::wstring widen(std::u8string_view); + TOML_NODISCARD + TOML_EXPORTED_FREE_FUNCTION + std::wstring widen(std::u8string_view); #endif } TOML_IMPL_NAMESPACE_END; -#endif // TOML_ENABLE_WINDOWS_COMPAT +#endif // TOML_ENABLE_WINDOWS_COMPAT /// \endcond diff --git a/vendor/toml++/impl/std_utility.hpp b/vendor/toml++/impl/std_utility.hpp index aacb1d5..02c836f 100644 --- a/vendor/toml++/impl/std_utility.hpp +++ b/vendor/toml++/impl/std_utility.hpp @@ -1,7 +1,7 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" diff --git a/vendor/toml++/impl/std_variant.hpp b/vendor/toml++/impl/std_variant.hpp index 14bf1b4..14534eb 100644 --- a/vendor/toml++/impl/std_variant.hpp +++ b/vendor/toml++/impl/std_variant.hpp @@ -1,7 +1,7 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" diff --git a/vendor/toml++/impl/std_vector.hpp b/vendor/toml++/impl/std_vector.hpp index e0cbac4..c1a1218 100644 --- a/vendor/toml++/impl/std_vector.hpp +++ b/vendor/toml++/impl/std_vector.hpp @@ -1,11 +1,11 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" TOML_DISABLE_WARNINGS; -#include <vector> #include <iterator> +#include <vector> TOML_ENABLE_WARNINGS; diff --git a/vendor/toml++/impl/table.hpp b/vendor/toml++/impl/table.hpp index edb7316..a49b16b 100644 --- a/vendor/toml++/impl/table.hpp +++ b/vendor/toml++/impl/table.hpp @@ -1,1995 +1,1726 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once -#include "forward_declarations.hpp" -#include "std_map.hpp" -#include "std_initializer_list.hpp" #include "array.hpp" +#include "forward_declarations.hpp" +#include "header_start.hpp" +#include "key.hpp" #include "make_node.hpp" #include "node_view.hpp" -#include "key.hpp" -#include "header_start.hpp" +#include "std_initializer_list.hpp" +#include "std_map.hpp" /// \cond -TOML_IMPL_NAMESPACE_START -{ - template <bool IsConst> - struct table_proxy_pair - { - using value_type = std::conditional_t<IsConst, const node, node>; - - const toml::key& first; - value_type& second; - }; - - template <bool IsConst> - class table_iterator - { - private: - template <bool> - friend class table_iterator; - - using proxy_type = table_proxy_pair<IsConst>; - using mutable_map_iterator = std::map<toml::key, node_ptr, std::less<>>::iterator; - using const_map_iterator = std::map<toml::key, node_ptr, std::less<>>::const_iterator; - using map_iterator = std::conditional_t<IsConst, const_map_iterator, mutable_map_iterator>; - - 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<void*>(proxy_)) proxy_type{ iter_->first, *iter_->second.get() }; - proxy_instantiated_ = true; - return p; - } - else - return TOML_LAUNDER(reinterpret_cast<proxy_type*>(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<false>& 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<IsConst>; - using reference = value_type&; - using pointer = value_type*; - using difference_type = typename std::iterator_traits<map_iterator>::difference_type; - using iterator_category = typename std::iterator_traits<map_iterator>::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 <typename K, typename V> - TOML_NODISCARD_CTOR - table_init_pair(K&& k, V&& v, value_flags flags = preserve_source_value_flags) // - : key{ static_cast<K&&>(k) }, - value{ make_node(static_cast<V&&>(v), flags) } - {} - }; +TOML_IMPL_NAMESPACE_START { + template <bool IsConst> + struct table_proxy_pair { + using value_type = std::conditional_t<IsConst, const node, node>; + + const toml::key& first; + value_type& second; + }; + + template <bool IsConst> + class table_iterator { + private: + template <bool> + friend class table_iterator; + + using proxy_type = table_proxy_pair<IsConst>; + using mutable_map_iterator = std::map<toml::key, node_ptr, std::less<>>::iterator; + using const_map_iterator = std::map<toml::key, node_ptr, std::less<>>::const_iterator; + using map_iterator = std::conditional_t<IsConst, const_map_iterator, mutable_map_iterator>; + + 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<void*>(proxy_)) proxy_type{iter_->first, *iter_->second.get()}; + proxy_instantiated_ = true; + return p; + } else + return TOML_LAUNDER(reinterpret_cast<proxy_type*>(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<false>& 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<IsConst>; + using reference = value_type&; + using pointer = value_type*; + using difference_type = typename std::iterator_traits<map_iterator>::difference_type; + using iterator_category = typename std::iterator_traits<map_iterator>::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 <typename K, typename V> + TOML_NODISCARD_CTOR table_init_pair(K&& k, V&& v, + value_flags flags = preserve_source_value_flags) // + : key{static_cast<K&&>(k)}, value{make_node(static_cast<V&&>(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<false>); - - /// \brief A BidirectionalIterator for iterating over const key-value pairs in a toml::table. - using const_table_iterator = POXY_IMPLEMENTATION_DETAIL(impl::table_iterator<true>); - - /// \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<toml::key, impl::node_ptr, std::less<>>; - using map_pair = std::pair<const toml::key, impl::node_ptr>; - 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<impl::table_init_pair> 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 <typename ElemType = void> - TOML_PURE_GETTER - bool is_homogeneous() const noexcept - { - using type = impl::remove_cvref<impl::unwrap_node<ElemType>>; - static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>, - "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<type>); - } - /// \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<std::string>* as_string() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<int64_t>* as_integer() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<double>* as_floating_point() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<bool>* as_boolean() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<date>* as_date() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<time>* as_time() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - toml::value<date_time>* as_date_time() noexcept final - { - return nullptr; - } - - /// \brief Returns a const-qualified pointer to the table. - TOML_CONST_INLINE_GETTER - const table* as_table() const noexcept final - { - return this; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const array* as_array() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<std::string>* as_string() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<int64_t>* as_integer() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<double>* as_floating_point() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<bool>* as_boolean() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<date>* as_date() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<time>* as_time() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const toml::value<date_time>* as_date_time() const noexcept final - { - return nullptr; - } - - /// @} - - /// \name Metadata - /// @{ - - /// \brief Returns true if this table is an inline table. - /// - /// \remarks Runtime-constructed tables (i.e. those not created during - /// parsing) are not inline by default. - TOML_PURE_INLINE_GETTER - bool is_inline() const noexcept - { - return inline_; - } - - /// \brief Sets whether this table is a TOML inline table. - /// - /// \detail \godbolt{an9xdj} - /// - /// \cpp - /// auto tbl = toml::table{ - /// { "a", 1 }, - /// { "b", 2 }, - /// { "c", 3 }, - /// { "d", toml::table{ { "e", 4 } } } - /// }; - /// std::cout << "is inline? "sv << tbl.is_inline() << "\n"; - /// std::cout << tbl << "\n\n"; - /// - /// tbl.is_inline(!tbl.is_inline()); - /// std::cout << "is inline? "sv << tbl.is_inline() << "\n"; - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// is inline? false - /// a = 1 - /// b = 2 - /// c = 3 - /// - /// [d] - /// e = 4 - /// - /// - /// is inline? true - /// { a = 1, b = 2, c = 3, d = { e = 4 } } - /// \eout - /// - /// \remarks A table being 'inline' is only relevent during printing; - /// it has no effect on the general functionality of the table - /// object. - /// - /// \param val The new value for 'inline'. - void is_inline(bool val) noexcept - { - inline_ = val; - } - - /// @} - - /// \name Value retrieval - /// @{ - - /// \brief Gets the node at a specific key. - /// - /// \detail \cpp - /// auto tbl = toml::table{ - /// { "a", 42, }, - /// { "b", "is the meaning of life, apparently." } - /// }; - /// std::cout << R"(node ["a"] exists: )"sv << !!arr.get("a") << "\n"; - /// std::cout << R"(node ["b"] exists: )"sv << !!arr.get("b") << "\n"; - /// std::cout << R"(node ["c"] exists: )"sv << !!arr.get("c") << "\n"; - /// if (auto val = arr.get("a")) - /// std::cout << R"(node ["a"] was an )"sv << val->type() << "\n"; - /// \ecpp - /// - /// \out - /// node ["a"] exists: true - /// node ["b"] exists: true - /// node ["c"] exists: false - /// node ["a"] was an integer - /// \eout - /// - /// \param key The node's key. - /// - /// \returns A pointer to the node at the specified key, or nullptr. - TOML_PURE_GETTER - TOML_EXPORTED_MEMBER_FUNCTION - node* get(std::string_view key) noexcept; - - /// \brief Gets the node at a specific key (const overload). - /// - /// \param key The node's key. - /// - /// \returns A pointer to the node at the specified key, or nullptr. - TOML_PURE_INLINE_GETTER - const node* get(std::string_view key) const noexcept - { - return const_cast<table&>(*this).get(key); - } +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<false>); + + /// \brief A BidirectionalIterator for iterating over const key-value pairs in a toml::table. + using const_table_iterator = POXY_IMPLEMENTATION_DETAIL(impl::table_iterator<true>); + + /// \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<toml::key, impl::node_ptr, std::less<>>; + using map_pair = std::pair<const toml::key, impl::node_ptr>; + 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<impl::table_init_pair> 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 <typename ElemType = void> + TOML_PURE_GETTER bool is_homogeneous() const noexcept { + using type = impl::remove_cvref<impl::unwrap_node<ElemType>>; + static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>, + "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<type>); + } + /// \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<std::string>* as_string() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<int64_t>* as_integer() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<double>* as_floating_point() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<bool>* as_boolean() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<date>* as_date() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<time>* as_time() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + toml::value<date_time>* as_date_time() noexcept final { return nullptr; } + + /// \brief Returns a const-qualified pointer to the table. + TOML_CONST_INLINE_GETTER + const table* as_table() const noexcept final { return this; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const array* as_array() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<std::string>* as_string() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<int64_t>* as_integer() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<double>* as_floating_point() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<bool>* as_boolean() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<date>* as_date() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<time>* as_time() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const toml::value<date_time>* as_date_time() const noexcept final { return nullptr; } + + /// @} + + /// \name Metadata + /// @{ + + /// \brief Returns true if this table is an inline table. + /// + /// \remarks Runtime-constructed tables (i.e. those not created during + /// parsing) are not inline by default. + TOML_PURE_INLINE_GETTER + bool is_inline() const noexcept { return inline_; } + + /// \brief Sets whether this table is a TOML inline table. + /// + /// \detail \godbolt{an9xdj} + /// + /// \cpp + /// auto tbl = toml::table{ + /// { "a", 1 }, + /// { "b", 2 }, + /// { "c", 3 }, + /// { "d", toml::table{ { "e", 4 } } } + /// }; + /// std::cout << "is inline? "sv << tbl.is_inline() << "\n"; + /// std::cout << tbl << "\n\n"; + /// + /// tbl.is_inline(!tbl.is_inline()); + /// std::cout << "is inline? "sv << tbl.is_inline() << "\n"; + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// is inline? false + /// a = 1 + /// b = 2 + /// c = 3 + /// + /// [d] + /// e = 4 + /// + /// + /// is inline? true + /// { a = 1, b = 2, c = 3, d = { e = 4 } } + /// \eout + /// + /// \remarks A table being 'inline' is only relevent during printing; + /// it has no effect on the general functionality of the table + /// object. + /// + /// \param val The new value for 'inline'. + void is_inline(bool val) noexcept { inline_ = val; } + + /// @} + + /// \name Value retrieval + /// @{ + + /// \brief Gets the node at a specific key. + /// + /// \detail \cpp + /// auto tbl = toml::table{ + /// { "a", 42, }, + /// { "b", "is the meaning of life, apparently." } + /// }; + /// std::cout << R"(node ["a"] exists: )"sv << !!arr.get("a") << "\n"; + /// std::cout << R"(node ["b"] exists: )"sv << !!arr.get("b") << "\n"; + /// std::cout << R"(node ["c"] exists: )"sv << !!arr.get("c") << "\n"; + /// if (auto val = arr.get("a")) + /// std::cout << R"(node ["a"] was an )"sv << val->type() << "\n"; + /// \ecpp + /// + /// \out + /// node ["a"] exists: true + /// node ["b"] exists: true + /// node ["c"] exists: false + /// node ["a"] was an integer + /// \eout + /// + /// \param key The node's key. + /// + /// \returns A pointer to the node at the specified key, or nullptr. + TOML_PURE_GETTER + TOML_EXPORTED_MEMBER_FUNCTION + node* get(std::string_view key) noexcept; + + /// \brief Gets the node at a specific key (const overload). + /// + /// \param key The node's key. + /// + /// \returns A pointer to the node at the specified key, or nullptr. + TOML_PURE_INLINE_GETTER + const node* get(std::string_view key) const noexcept { + return const_cast<table&>(*this).get(key); + } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Gets the node at a specific key. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key The node's key. - /// - /// \returns A pointer to the node at the specified key, or nullptr. - TOML_NODISCARD - node* get(std::wstring_view key) - { - if (empty()) - return nullptr; - - return get(impl::narrow(key)); - } - - /// \brief Gets the node at a specific key (const overload). - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key The node's key. - /// - /// \returns A pointer to the node at the specified key, or nullptr. - TOML_NODISCARD - const node* get(std::wstring_view key) const - { - return const_cast<table&>(*this).get(key); - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// \brief Gets the node at a specific key if it is a particular type. - /// - /// \detail \cpp - /// auto tbl = toml::table{ - /// { "a", 42, }, - /// { "b", "is the meaning of life, apparently." } - /// }; - /// if (auto val = arr.get_as<int64_t>("a")) - /// std::cout << R"(node ["a"] was an integer with value )"sv << **val << "\n"; - /// \ecpp - /// - /// \out - /// node ["a"] was an integer with value 42 - /// \eout - /// - /// \tparam T One of the TOML node or value types. - /// \param key The node's key. - /// - /// \returns A pointer to the node at the specified key if it was of the given type, or nullptr. - template <typename T> - TOML_PURE_GETTER - impl::wrap_node<T>* get_as(std::string_view key) noexcept - { - const auto n = this->get(key); - return n ? n->template as<T>() : nullptr; - } - - /// \brief Gets the node at a specific key if it is a particular type (const overload). - /// - /// \tparam T One of the TOML node or value types. - /// \param key The node's key. - /// - /// \returns A pointer to the node at the specified key if it was of the given type, or nullptr. - template <typename T> - TOML_PURE_GETTER - const impl::wrap_node<T>* get_as(std::string_view key) const noexcept - { - return const_cast<table&>(*this).template get_as<T>(key); - } + /// \brief Gets the node at a specific key. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key The node's key. + /// + /// \returns A pointer to the node at the specified key, or nullptr. + TOML_NODISCARD + node* get(std::wstring_view key) { + if (empty()) return nullptr; + + return get(impl::narrow(key)); + } + + /// \brief Gets the node at a specific key (const overload). + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key The node's key. + /// + /// \returns A pointer to the node at the specified key, or nullptr. + TOML_NODISCARD + const node* get(std::wstring_view key) const { return const_cast<table&>(*this).get(key); } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// \brief Gets the node at a specific key if it is a particular type. + /// + /// \detail \cpp + /// auto tbl = toml::table{ + /// { "a", 42, }, + /// { "b", "is the meaning of life, apparently." } + /// }; + /// if (auto val = arr.get_as<int64_t>("a")) + /// std::cout << R"(node ["a"] was an integer with value )"sv << **val << "\n"; + /// \ecpp + /// + /// \out + /// node ["a"] was an integer with value 42 + /// \eout + /// + /// \tparam T One of the TOML node or value types. + /// \param key The node's key. + /// + /// \returns A pointer to the node at the specified key if it was of the given type, or + /// nullptr. + template <typename T> + TOML_PURE_GETTER impl::wrap_node<T>* get_as(std::string_view key) noexcept { + const auto n = this->get(key); + return n ? n->template as<T>() : nullptr; + } + + /// \brief Gets the node at a specific key if it is a particular type (const overload). + /// + /// \tparam T One of the TOML node or value types. + /// \param key The node's key. + /// + /// \returns A pointer to the node at the specified key if it was of the given type, or + /// nullptr. + template <typename T> + TOML_PURE_GETTER const impl::wrap_node<T>* get_as(std::string_view key) const noexcept { + return const_cast<table&>(*this).template get_as<T>(key); + } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Gets the node at a specific key if it is a particular type. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \tparam T One of the TOML node or value types. - /// \param key The node's key. - /// - /// \returns A pointer to the node at the specified key if it was of the given type, or nullptr. - template <typename T> - TOML_NODISCARD - impl::wrap_node<T>* get_as(std::wstring_view key) - { - if (empty()) - return nullptr; - - return get_as<T>(impl::narrow(key)); - } - - /// \brief Gets the node at a specific key if it is a particular type (const overload). - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \tparam T One of the TOML node or value types. - /// \param key The node's key. - /// - /// \returns A pointer to the node at the specified key if it was of the given type, or nullptr. - template <typename T> - TOML_NODISCARD - const impl::wrap_node<T>* get_as(std::wstring_view key) const - { - return const_cast<table&>(*this).template get_as<T>(key); - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if none existed. - TOML_NODISCARD - TOML_EXPORTED_MEMBER_FUNCTION - node& at(std::string_view key); - - /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if none existed. - TOML_NODISCARD - const node& at(std::string_view key) const - { - return const_cast<table&>(*this).at(key); - } + /// \brief Gets the node at a specific key if it is a particular type. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \tparam T One of the TOML node or value types. + /// \param key The node's key. + /// + /// \returns A pointer to the node at the specified key if it was of the given type, or + /// nullptr. + template <typename T> + TOML_NODISCARD impl::wrap_node<T>* get_as(std::wstring_view key) { + if (empty()) return nullptr; + + return get_as<T>(impl::narrow(key)); + } + + /// \brief Gets the node at a specific key if it is a particular type (const overload). + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \tparam T One of the TOML node or value types. + /// \param key The node's key. + /// + /// \returns A pointer to the node at the specified key if it was of the given type, or + /// nullptr. + template <typename T> + TOML_NODISCARD const impl::wrap_node<T>* get_as(std::wstring_view key) const { + return const_cast<table&>(*this).template get_as<T>(key); + } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if + /// none existed. + TOML_NODISCARD + TOML_EXPORTED_MEMBER_FUNCTION + node& at(std::string_view key); + + /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if + /// none existed. + TOML_NODISCARD + const node& at(std::string_view key) const { return const_cast<table&>(*this).at(key); } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if none existed. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - node& at(std::wstring_view key) - { - return at(impl::narrow(key)); - } - - /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if none existed. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - const node& at(std::wstring_view key) const - { - return const_cast<table&>(*this).at(key); - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// @} - - /// \name Iteration - /// @{ - - /// \brief A BidirectionalIterator for iterating over key-value pairs in a toml::table. - using iterator = toml::table_iterator; - - /// \brief A BidirectionalIterator for iterating over const key-value pairs in a toml::table. - using const_iterator = toml::const_table_iterator; - - /// \brief Returns an iterator to the first key-value pair. - TOML_PURE_INLINE_GETTER - iterator begin() noexcept - { - return iterator{ map_.begin() }; - } - - /// \brief Returns an iterator to the first key-value pair. - TOML_PURE_INLINE_GETTER - const_iterator begin() const noexcept - { - return const_iterator{ map_.cbegin() }; - } - - /// \brief Returns an iterator to the first key-value pair. - TOML_PURE_INLINE_GETTER - const_iterator cbegin() const noexcept - { - return const_iterator{ map_.cbegin() }; - } - - /// \brief Returns an iterator to one-past-the-last key-value pair. - TOML_PURE_INLINE_GETTER - iterator end() noexcept - { - return iterator{ map_.end() }; - } - - /// \brief Returns an iterator to one-past-the-last key-value pair. - TOML_PURE_INLINE_GETTER - const_iterator end() const noexcept - { - return const_iterator{ map_.cend() }; - } - - /// \brief Returns an iterator to one-past-the-last key-value pair. - TOML_PURE_INLINE_GETTER - const_iterator cend() const noexcept - { - return const_iterator{ map_.cend() }; - } - - private: - /// \cond - - template <typename T, typename Table> - using for_each_value_ref = impl::copy_cvref<impl::wrap_node<impl::remove_cvref<impl::unwrap_node<T>>>, Table>; - - template <typename Func, typename Table, typename T> - using can_for_each = std::disjunction<std::is_invocable<Func, const key&, for_each_value_ref<T, Table>>, // - std::is_invocable<Func, for_each_value_ref<T, Table>>>; - - template <typename Func, typename Table, typename T> - using can_for_each_nothrow = std::conditional_t< - // first form - std::is_invocable_v<Func, const key&, for_each_value_ref<T, Table>>, - std::is_nothrow_invocable<Func, const key&, for_each_value_ref<T, Table>>, - std::conditional_t< - // second form - std::is_invocable_v<Func, for_each_value_ref<T, Table>>, - std::is_nothrow_invocable<Func, for_each_value_ref<T, Table>>, - std::false_type>>; - - template <typename Func, typename Table> - using can_for_each_any = std::disjunction<can_for_each<Func, Table, table>, - can_for_each<Func, Table, array>, - can_for_each<Func, Table, std::string>, - can_for_each<Func, Table, int64_t>, - can_for_each<Func, Table, double>, - can_for_each<Func, Table, bool>, - can_for_each<Func, Table, date>, - can_for_each<Func, Table, time>, - can_for_each<Func, Table, date_time>>; - - template <typename Func, typename Table, typename T> - using for_each_is_nothrow_one = std::disjunction<std::negation<can_for_each<Func, Table, T>>, // - can_for_each_nothrow<Func, Table, T>>; - - template <typename Func, typename Table> - using for_each_is_nothrow = std::conjunction<for_each_is_nothrow_one<Func, Table, table>, - for_each_is_nothrow_one<Func, Table, array>, - for_each_is_nothrow_one<Func, Table, std::string>, - for_each_is_nothrow_one<Func, Table, int64_t>, - for_each_is_nothrow_one<Func, Table, double>, - for_each_is_nothrow_one<Func, Table, bool>, - for_each_is_nothrow_one<Func, Table, date>, - for_each_is_nothrow_one<Func, Table, time>, - for_each_is_nothrow_one<Func, Table, date_time>>; - - template <typename Func, typename Table> - static void do_for_each(Func&& visitor, Table&& tbl) // - noexcept(for_each_is_nothrow<Func&&, Table&&>::value) - { - static_assert(can_for_each_any<Func&&, Table&&>::value, - "TOML table for_each visitors must be invocable for at least one of the toml::node " - "specializations:" TOML_SA_NODE_TYPE_LIST); - - using kvp_type = impl::copy_cv<map_pair, std::remove_reference_t<Table>>; - - for (kvp_type& kvp : tbl.map_) - { - using node_ref = impl::copy_cvref<toml::node, Table&&>; - static_assert(std::is_reference_v<node_ref>); + /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if + /// none existed. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + node& at(std::wstring_view key) { return at(impl::narrow(key)); } + + /// \brief Gets a reference to the element at a specific key, throwing `std::out_of_range` if + /// none existed. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + const node& at(std::wstring_view key) const { return const_cast<table&>(*this).at(key); } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// @} + + /// \name Iteration + /// @{ + + /// \brief A BidirectionalIterator for iterating over key-value pairs in a toml::table. + using iterator = toml::table_iterator; + + /// \brief A BidirectionalIterator for iterating over const key-value pairs in a toml::table. + using const_iterator = toml::const_table_iterator; + + /// \brief Returns an iterator to the first key-value pair. + TOML_PURE_INLINE_GETTER + iterator begin() noexcept { return iterator{map_.begin()}; } + + /// \brief Returns an iterator to the first key-value pair. + TOML_PURE_INLINE_GETTER + const_iterator begin() const noexcept { return const_iterator{map_.cbegin()}; } + + /// \brief Returns an iterator to the first key-value pair. + TOML_PURE_INLINE_GETTER + const_iterator cbegin() const noexcept { return const_iterator{map_.cbegin()}; } + + /// \brief Returns an iterator to one-past-the-last key-value pair. + TOML_PURE_INLINE_GETTER + iterator end() noexcept { return iterator{map_.end()}; } + + /// \brief Returns an iterator to one-past-the-last key-value pair. + TOML_PURE_INLINE_GETTER + const_iterator end() const noexcept { return const_iterator{map_.cend()}; } + + /// \brief Returns an iterator to one-past-the-last key-value pair. + TOML_PURE_INLINE_GETTER + const_iterator cend() const noexcept { return const_iterator{map_.cend()}; } + + private: + /// \cond + + template <typename T, typename Table> + using for_each_value_ref = + impl::copy_cvref<impl::wrap_node<impl::remove_cvref<impl::unwrap_node<T>>>, Table>; + + template <typename Func, typename Table, typename T> + using can_for_each = + std::disjunction<std::is_invocable<Func, const key&, for_each_value_ref<T, Table>>, // + std::is_invocable<Func, for_each_value_ref<T, Table>>>; + + template <typename Func, typename Table, typename T> + using can_for_each_nothrow = std::conditional_t< + // first form + std::is_invocable_v<Func, const key&, for_each_value_ref<T, Table>>, + std::is_nothrow_invocable<Func, const key&, for_each_value_ref<T, Table>>, + std::conditional_t< + // second form + std::is_invocable_v<Func, for_each_value_ref<T, Table>>, + std::is_nothrow_invocable<Func, for_each_value_ref<T, Table>>, std::false_type>>; + + template <typename Func, typename Table> + using can_for_each_any = + std::disjunction<can_for_each<Func, Table, table>, can_for_each<Func, Table, array>, + can_for_each<Func, Table, std::string>, can_for_each<Func, Table, int64_t>, + can_for_each<Func, Table, double>, can_for_each<Func, Table, bool>, + can_for_each<Func, Table, date>, can_for_each<Func, Table, time>, + can_for_each<Func, Table, date_time>>; + + template <typename Func, typename Table, typename T> + using for_each_is_nothrow_one = + std::disjunction<std::negation<can_for_each<Func, Table, T>>, // + can_for_each_nothrow<Func, Table, T>>; + + template <typename Func, typename Table> + using for_each_is_nothrow = std::conjunction< + for_each_is_nothrow_one<Func, Table, table>, for_each_is_nothrow_one<Func, Table, array>, + for_each_is_nothrow_one<Func, Table, std::string>, + for_each_is_nothrow_one<Func, Table, int64_t>, for_each_is_nothrow_one<Func, Table, double>, + for_each_is_nothrow_one<Func, Table, bool>, for_each_is_nothrow_one<Func, Table, date>, + for_each_is_nothrow_one<Func, Table, time>, + for_each_is_nothrow_one<Func, Table, date_time>>; + + template <typename Func, typename Table> + static void do_for_each(Func&& visitor, Table&& tbl) // + noexcept(for_each_is_nothrow<Func&&, Table&&>::value) { + static_assert( + can_for_each_any<Func&&, Table&&>::value, + "TOML table for_each visitors must be invocable for at least one of the toml::node " + "specializations:" TOML_SA_NODE_TYPE_LIST); + + using kvp_type = impl::copy_cv<map_pair, std::remove_reference_t<Table>>; + + for (kvp_type& kvp : tbl.map_) { + using node_ref = impl::copy_cvref<toml::node, Table&&>; + static_assert(std::is_reference_v<node_ref>); #if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN #ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED - static_assert(impl::always_false<Func, Table, kvp_type, node_ref>, // - TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE); + static_assert(impl::always_false<Func, Table, kvp_type, node_ref>, // + TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE); #endif - static_cast<node_ref>(*kvp.second) - .visit( - [&]([[maybe_unused]] auto&& v) // - noexcept(for_each_is_nothrow_one<Func&&, Table&&, decltype(v)>::value) - { - using value_ref = for_each_value_ref<decltype(v), Table&&>; - static_assert(std::is_reference_v<value_ref>); - - // func(key, val) - if constexpr (std::is_invocable_v<Func&&, const key&, value_ref>) - { - static_cast<Func&&>(visitor)(static_cast<const key&>(kvp.first), - static_cast<value_ref>(v)); - } - - // func(val) - else if constexpr (std::is_invocable_v<Func&&, value_ref>) - { - static_cast<Func&&>(visitor)(static_cast<value_ref>(v)); - } - }); + static_cast<node_ref>(*kvp.second) + .visit([&]([[maybe_unused]] auto&& v) // + noexcept(for_each_is_nothrow_one<Func&&, Table&&, decltype(v)>::value) { + using value_ref = for_each_value_ref<decltype(v), Table&&>; + static_assert(std::is_reference_v<value_ref>); + + // func(key, val) + if constexpr (std::is_invocable_v<Func&&, const key&, value_ref>) { + static_cast<Func&&>(visitor)(static_cast<const key&>(kvp.first), + static_cast<value_ref>(v)); + } + + // func(val) + else if constexpr (std::is_invocable_v<Func&&, value_ref>) { + static_cast<Func&&>(visitor)(static_cast<value_ref>(v)); + } + }); #else - const auto keep_going = - static_cast<node_ref>(*kvp.second) - .visit( - [&]([[maybe_unused]] auto&& v) // - noexcept(for_each_is_nothrow_one<Func&&, Table&&, decltype(v)>::value) - { - using value_ref = for_each_value_ref<decltype(v), Table&&>; - static_assert(std::is_reference_v<value_ref>); - - // func(key, val) - if constexpr (std::is_invocable_v<Func&&, const key&, value_ref>) - { - using return_type = decltype(static_cast<Func&&>( - visitor)(static_cast<const key&>(kvp.first), static_cast<value_ref>(v))); - - if constexpr (impl::is_constructible_or_convertible<bool, return_type>) - { - return static_cast<bool>(static_cast<Func&&>( - visitor)(static_cast<const key&>(kvp.first), static_cast<value_ref>(v))); - } - else - { - static_cast<Func&&>(visitor)(static_cast<const key&>(kvp.first), - static_cast<value_ref>(v)); - return true; - } - } - - // func(val) - else if constexpr (std::is_invocable_v<Func&&, value_ref>) - { - using return_type = - decltype(static_cast<Func&&>(visitor)(static_cast<value_ref>(v))); - - if constexpr (impl::is_constructible_or_convertible<bool, return_type>) - { - return static_cast<bool>( - static_cast<Func&&>(visitor)(static_cast<value_ref>(v))); - } - else - { - static_cast<Func&&>(visitor)(static_cast<value_ref>(v)); - return true; - } - } - - // visitor not compatible with this particular type - else - return true; - }); - - if (!keep_going) - return; + const auto keep_going = + static_cast<node_ref>(*kvp.second) + .visit([&]([[maybe_unused]] auto&& v) // + noexcept(for_each_is_nothrow_one<Func&&, Table&&, decltype(v)>::value) { + using value_ref = for_each_value_ref<decltype(v), Table&&>; + static_assert(std::is_reference_v<value_ref>); + + // func(key, val) + if constexpr (std::is_invocable_v<Func&&, const key&, value_ref>) { + using return_type = decltype(static_cast<Func&&>(visitor)( + static_cast<const key&>(kvp.first), static_cast<value_ref>(v))); + + if constexpr (impl::is_constructible_or_convertible<bool, return_type>) { + return static_cast<bool>(static_cast<Func&&>(visitor)( + static_cast<const key&>(kvp.first), static_cast<value_ref>(v))); + } else { + static_cast<Func&&>(visitor)(static_cast<const key&>(kvp.first), + static_cast<value_ref>(v)); + return true; + } + } + + // func(val) + else if constexpr (std::is_invocable_v<Func&&, value_ref>) { + using return_type = + decltype(static_cast<Func&&>(visitor)(static_cast<value_ref>(v))); + + if constexpr (impl::is_constructible_or_convertible<bool, return_type>) { + return static_cast<bool>( + static_cast<Func&&>(visitor)(static_cast<value_ref>(v))); + } else { + static_cast<Func&&>(visitor)(static_cast<value_ref>(v)); + return true; + } + } + + // visitor not compatible with this particular type + else + return true; + }); + + if (!keep_going) return; #endif - } - } - - /// \endcond - - public: - /// \brief Invokes a visitor on each key-value pair in the table. - /// - /// \tparam Func A callable type invocable with one of the following signatures: - /// <ul> - /// <li> `func(key, val)` - /// <li> `func(val)` - /// </ul> - /// Where: - /// <ul> - /// <li> `key` will recieve a const reference to a toml::key - /// <li> `val` will recieve the value as it's concrete type with cvref-qualifications matching the table - /// </ul> - /// Visitors returning `bool` (or something convertible to `bool`) will cause iteration to - /// stop if they return `false`. - /// - /// \param visitor The visitor object. - /// - /// \returns A reference to the table. - /// - /// \details \cpp - /// toml::table tbl{ - /// { "0", 0 }, - /// { "1", 1 }, - /// { "2", 2 }, - /// { "3", 3.0 }, - /// { "4", "four" }, - /// { "5", "five" }, - /// { "6", 6 } - /// }; - /// - /// // select only the integers using a strongly-typed visitor - /// tbl.for_each([](toml::value<int64_t>& val) - /// { - /// std::cout << val << ", "; - /// }); - /// std::cout << "\n"; - /// - /// // select all the numeric values using a generic visitor + is_number<> metafunction - /// tbl.for_each([](auto&& val) - /// { - /// if constexpr (toml::is_number<decltype(val)>) - /// std::cout << val << ", "; - /// }); - /// std::cout << "\n"; - /// - /// // select all the numeric values until we encounter something non-numeric - /// tbl.for_each([](auto&& val) - /// { - /// if constexpr (toml::is_number<decltype(val)>) - /// { - /// std::cout << val << ", "; - /// return true; // "keep going" - /// } - /// else - /// return false; // "stop!" - /// - /// }); - /// std::cout << "\n\n"; - /// - /// // visitors may also recieve the key - /// tbl.for_each([](const toml::key& key, auto&& val) - /// { - /// std::cout << key << ": " << val << "\n"; - /// }); - /// - /// \ecpp - /// \out - /// 0, 1, 2, 6, - /// 0, 1, 2, 3.0, 6, - /// 0, 1, 2, 3.0, - /// - /// 0: 0 - /// 1: 1 - /// 2: 2 - /// 3: 3.0 - /// 4: 'four' - /// 5: 'five' - /// 6: 6 - /// \eout - /// - /// \see node::visit() - template <typename Func> - table& for_each(Func&& visitor) & // - noexcept(for_each_is_nothrow<Func&&, table&>::value) - { - do_for_each(static_cast<Func&&>(visitor), *this); - return *this; - } - - /// \brief Invokes a visitor on each key-value pair in the table (rvalue overload). - template <typename Func> - table&& for_each(Func&& visitor) && // - noexcept(for_each_is_nothrow<Func&&, table&&>::value) - { - do_for_each(static_cast<Func&&>(visitor), static_cast<table&&>(*this)); - return static_cast<table&&>(*this); - } - - /// \brief Invokes a visitor on each key-value pair in the table (const lvalue overload). - template <typename Func> - const table& for_each(Func&& visitor) const& // - noexcept(for_each_is_nothrow<Func&&, const table&>::value) - { - do_for_each(static_cast<Func&&>(visitor), *this); - return *this; - } - - /// \brief Invokes a visitor on each key-value pair in the table (const rvalue overload). - template <typename Func> - const table&& for_each(Func&& visitor) const&& // - noexcept(for_each_is_nothrow<Func&&, const table&&>::value) - { - do_for_each(static_cast<Func&&>(visitor), static_cast<const table&&>(*this)); - return static_cast<const table&&>(*this); - } - - /// @} - - /// \name Size and Capacity - /// @{ - - /// \brief Returns true if the table is empty. - TOML_PURE_INLINE_GETTER - bool empty() const noexcept - { - return map_.empty(); - } - - /// \brief Returns the number of key-value pairs in the table. - TOML_PURE_INLINE_GETTER - size_t size() const noexcept - { - return map_.size(); - } - - /// @} - - /// \name Searching - /// @{ - - private: - /// \cond - - TOML_PURE_GETTER - TOML_EXPORTED_MEMBER_FUNCTION - map_iterator get_lower_bound(std::string_view) noexcept; - - /// \endcond - - public: - /// \brief Returns an iterator to the first key-value pair with key that is _not less_ than the given key. - /// - /// \returns An iterator to the first matching key-value pair, or #end(). - TOML_PURE_GETTER - iterator lower_bound(std::string_view key) noexcept - { - return iterator{ get_lower_bound(key) }; - } - - /// \brief Returns a const iterator to the first key-value pair with key that is _not less_ than the given key. - /// - /// \returns An iterator to the first matching key-value pair, or #end(). - TOML_PURE_GETTER - const_iterator lower_bound(std::string_view key) const noexcept - { - return const_iterator{ const_cast<table&>(*this).get_lower_bound(key) }; - } + } + } + + /// \endcond + + public: + /// \brief Invokes a visitor on each key-value pair in the table. + /// + /// \tparam Func A callable type invocable with one of the following signatures: + /// <ul> + /// <li> `func(key, val)` + /// <li> `func(val)` + /// </ul> + /// Where: + /// <ul> + /// <li> `key` will recieve a const reference to a toml::key + /// <li> `val` will recieve the value as it's concrete type with cvref-qualifications + ///matching the table + /// </ul> + /// Visitors returning `bool` (or something convertible to `bool`) will cause iteration + ///to stop if they return `false`. + /// + /// \param visitor The visitor object. + /// + /// \returns A reference to the table. + /// + /// \details \cpp + /// toml::table tbl{ + /// { "0", 0 }, + /// { "1", 1 }, + /// { "2", 2 }, + /// { "3", 3.0 }, + /// { "4", "four" }, + /// { "5", "five" }, + /// { "6", 6 } + /// }; + /// + /// // select only the integers using a strongly-typed visitor + /// tbl.for_each([](toml::value<int64_t>& val) + /// { + /// std::cout << val << ", "; + /// }); + /// std::cout << "\n"; + /// + /// // select all the numeric values using a generic visitor + is_number<> metafunction + /// tbl.for_each([](auto&& val) + /// { + /// if constexpr (toml::is_number<decltype(val)>) + /// std::cout << val << ", "; + /// }); + /// std::cout << "\n"; + /// + /// // select all the numeric values until we encounter something non-numeric + /// tbl.for_each([](auto&& val) + /// { + /// if constexpr (toml::is_number<decltype(val)>) + /// { + /// std::cout << val << ", "; + /// return true; // "keep going" + /// } + /// else + /// return false; // "stop!" + /// + /// }); + /// std::cout << "\n\n"; + /// + /// // visitors may also recieve the key + /// tbl.for_each([](const toml::key& key, auto&& val) + /// { + /// std::cout << key << ": " << val << "\n"; + /// }); + /// + /// \ecpp + /// \out + /// 0, 1, 2, 6, + /// 0, 1, 2, 3.0, 6, + /// 0, 1, 2, 3.0, + /// + /// 0: 0 + /// 1: 1 + /// 2: 2 + /// 3: 3.0 + /// 4: 'four' + /// 5: 'five' + /// 6: 6 + /// \eout + /// + /// \see node::visit() + template <typename Func> + table& for_each(Func&& visitor) & // + noexcept(for_each_is_nothrow<Func&&, table&>::value) { + do_for_each(static_cast<Func&&>(visitor), *this); + return *this; + } + + /// \brief Invokes a visitor on each key-value pair in the table (rvalue overload). + template <typename Func> + table&& for_each(Func&& visitor) && // + noexcept(for_each_is_nothrow<Func&&, table&&>::value) { + do_for_each(static_cast<Func&&>(visitor), static_cast<table&&>(*this)); + return static_cast<table&&>(*this); + } + + /// \brief Invokes a visitor on each key-value pair in the table (const lvalue overload). + template <typename Func> + const table& for_each(Func&& visitor) const& // + noexcept(for_each_is_nothrow<Func&&, const table&>::value) { + do_for_each(static_cast<Func&&>(visitor), *this); + return *this; + } + + /// \brief Invokes a visitor on each key-value pair in the table (const rvalue overload). + template <typename Func> + const table&& for_each(Func&& visitor) const&& // + noexcept(for_each_is_nothrow<Func&&, const table&&>::value) { + do_for_each(static_cast<Func&&>(visitor), static_cast<const table&&>(*this)); + return static_cast<const table&&>(*this); + } + + /// @} + + /// \name Size and Capacity + /// @{ + + /// \brief Returns true if the table is empty. + TOML_PURE_INLINE_GETTER + bool empty() const noexcept { return map_.empty(); } + + /// \brief Returns the number of key-value pairs in the table. + TOML_PURE_INLINE_GETTER + size_t size() const noexcept { return map_.size(); } + + /// @} + + /// \name Searching + /// @{ + + private: + /// \cond + + TOML_PURE_GETTER + TOML_EXPORTED_MEMBER_FUNCTION + map_iterator get_lower_bound(std::string_view) noexcept; + + /// \endcond + + public: + /// \brief Returns an iterator to the first key-value pair with key that is _not less_ than the + /// given key. + /// + /// \returns An iterator to the first matching key-value pair, or #end(). + TOML_PURE_GETTER + iterator lower_bound(std::string_view key) noexcept { return iterator{get_lower_bound(key)}; } + + /// \brief Returns a const iterator to the first key-value pair with key that is _not less_ than + /// the given key. + /// + /// \returns An iterator to the first matching key-value pair, or #end(). + TOML_PURE_GETTER + const_iterator lower_bound(std::string_view key) const noexcept { + return const_iterator{const_cast<table&>(*this).get_lower_bound(key)}; + } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Returns an iterator to the first key-value pair with key that is _not less_ than the given key. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \returns An iterator to the first matching key-value pair, or #end(). - TOML_NODISCARD - iterator lower_bound(std::wstring_view key) - { - if (empty()) - return end(); - - return lower_bound(impl::narrow(key)); - } - - /// \brief Returns a const iterator to the first key-value pair with key that is _not less_ than the given key. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \returns An iterator to the first matching key-value pair, or #end(). - TOML_NODISCARD - const_iterator lower_bound(std::wstring_view key) const - { - if (empty()) - return end(); - - return lower_bound(impl::narrow(key)); - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// \brief Gets an iterator to the node at a specific key. - /// - /// \param key The node's key. - /// - /// \returns An iterator to the node at the specified key, or end(). - TOML_PURE_GETTER - TOML_EXPORTED_MEMBER_FUNCTION - iterator find(std::string_view key) noexcept; - - /// \brief Gets an iterator to the node at a specific key (const overload) - /// - /// \param key The node's key. - /// - /// \returns A const iterator to the node at the specified key, or cend(). - TOML_PURE_GETTER - TOML_EXPORTED_MEMBER_FUNCTION - const_iterator find(std::string_view key) const noexcept; - - /// \brief Returns true if the table contains a node at the given key. - TOML_PURE_GETTER - bool contains(std::string_view key) const noexcept - { - return get(key) != nullptr; - } + /// \brief Returns an iterator to the first key-value pair with key that is _not less_ than the + /// given key. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \returns An iterator to the first matching key-value pair, or #end(). + TOML_NODISCARD + iterator lower_bound(std::wstring_view key) { + if (empty()) return end(); + + return lower_bound(impl::narrow(key)); + } + + /// \brief Returns a const iterator to the first key-value pair with key that is _not less_ than + /// the given key. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \returns An iterator to the first matching key-value pair, or #end(). + TOML_NODISCARD + const_iterator lower_bound(std::wstring_view key) const { + if (empty()) return end(); + + return lower_bound(impl::narrow(key)); + } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// \brief Gets an iterator to the node at a specific key. + /// + /// \param key The node's key. + /// + /// \returns An iterator to the node at the specified key, or end(). + TOML_PURE_GETTER + TOML_EXPORTED_MEMBER_FUNCTION + iterator find(std::string_view key) noexcept; + + /// \brief Gets an iterator to the node at a specific key (const overload) + /// + /// \param key The node's key. + /// + /// \returns A const iterator to the node at the specified key, or cend(). + TOML_PURE_GETTER + TOML_EXPORTED_MEMBER_FUNCTION + const_iterator find(std::string_view key) const noexcept; + + /// \brief Returns true if the table contains a node at the given key. + TOML_PURE_GETTER + bool contains(std::string_view key) const noexcept { return get(key) != nullptr; } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Gets an iterator to the node at a specific key. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key The node's key. - /// - /// \returns An iterator to the node at the specified key, or end(). - TOML_NODISCARD - iterator find(std::wstring_view key) - { - if (empty()) - return end(); - - return find(impl::narrow(key)); - } - - /// \brief Gets an iterator to the node at a specific key (const overload). - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key The node's key. - /// - /// \returns A const iterator to the node at the specified key, or cend(). - TOML_NODISCARD - const_iterator find(std::wstring_view key) const - { - return find(impl::narrow(key)); - } - - /// \brief Returns true if the table contains a node at the given key. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - TOML_NODISCARD - bool contains(std::wstring_view key) const - { - return contains(impl::narrow(key)); - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// @} - - /// \name Erasure - /// @{ - - private: - /// \cond - - TOML_EXPORTED_MEMBER_FUNCTION - map_iterator erase(const_map_iterator) noexcept; - - TOML_EXPORTED_MEMBER_FUNCTION - map_iterator erase(const_map_iterator, const_map_iterator) noexcept; - - /// \endcond - - public: - /// \brief Removes the specified key-value pair from the table. - /// - /// \detail \cpp - /// auto tbl = toml::table{ - /// { "a", 1 }, - /// { "b", 2 }, - /// { "c", 3 } - /// }; - /// std::cout << tbl << "\n"; - /// - /// tbl.erase(tbl.begin() + 1); - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// { a = 1, b = 2, c = 3 } - /// { a = 1, c = 3 } - /// \eout - /// - /// \param pos Iterator to the key-value pair being erased. - /// - /// \returns Iterator to the first key-value pair immediately following the removed key-value pair. - iterator erase(iterator pos) noexcept - { - return iterator{ erase(const_map_iterator{ pos }) }; - } - - /// \brief Removes the specified key-value pair from the table (const iterator overload). - /// - /// \detail \cpp - /// auto tbl = toml::table{ - /// { "a", 1 }, - /// { "b", 2 }, - /// { "c", 3 } - /// }; - /// std::cout << tbl << "\n"; - /// - /// tbl.erase(tbl.cbegin() + 1); - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// { a = 1, b = 2, c = 3 } - /// { a = 1, c = 3 } - /// \eout - /// - /// \param pos Iterator to the key-value pair being erased. - /// - /// \returns Iterator to the first key-value pair immediately following the removed key-value pair. - iterator erase(const_iterator pos) noexcept - { - return iterator{ erase(const_map_iterator{ pos }) }; - } - - /// \brief Removes the key-value pairs in the range [first, last) from the table. - /// - /// \detail \cpp - /// auto tbl = toml::table{ - /// { "a", 1 }, - /// { "b", "bad" }, - /// { "c", "karma" }, - /// { "d", 2 } - /// }; - /// std::cout << tbl << "\n"; - /// - /// tbl.erase(tbl.cbegin() + 1, tbl.cbegin() + 3); - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// { a = 1, b = "bad", c = "karma", d = 2 } - /// { a = 1, d = 2 } - /// \eout - /// - /// \param begin Iterator to the first key-value pair being erased. - /// \param end Iterator to the one-past-the-last key-value pair being erased. - /// - /// \returns Iterator to the first key-value pair immediately following the last removed key-value pair. - iterator erase(const_iterator begin, const_iterator end) noexcept - { - return iterator{ erase(const_map_iterator{ begin }, const_map_iterator{ end }) }; - } - - /// \brief Removes the value with the given key from the table. - /// - /// \detail \cpp - /// auto tbl = toml::table{ - /// { "a", 1 }, - /// { "b", 2 }, - /// { "c", 3 } - /// }; - /// std::cout << tbl << "\n"; - /// - /// std::cout << tbl.erase("b") << "\n"; - /// std::cout << tbl.erase("not an existing key") << "\n"; - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// { a = 1, b = 2, c = 3 } - /// true - /// false - /// { a = 1, c = 3 } - /// \eout - /// - /// \param key Key to erase. - /// - /// \returns Number of elements removed (0 or 1). - TOML_EXPORTED_MEMBER_FUNCTION - size_t erase(std::string_view key) noexcept; + /// \brief Gets an iterator to the node at a specific key. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key The node's key. + /// + /// \returns An iterator to the node at the specified key, or end(). + TOML_NODISCARD + iterator find(std::wstring_view key) { + if (empty()) return end(); + + return find(impl::narrow(key)); + } + + /// \brief Gets an iterator to the node at a specific key (const overload). + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key The node's key. + /// + /// \returns A const iterator to the node at the specified key, or cend(). + TOML_NODISCARD + const_iterator find(std::wstring_view key) const { return find(impl::narrow(key)); } + + /// \brief Returns true if the table contains a node at the given key. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + TOML_NODISCARD + bool contains(std::wstring_view key) const { return contains(impl::narrow(key)); } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// @} + + /// \name Erasure + /// @{ + + private: + /// \cond + + TOML_EXPORTED_MEMBER_FUNCTION + map_iterator erase(const_map_iterator) noexcept; + + TOML_EXPORTED_MEMBER_FUNCTION + map_iterator erase(const_map_iterator, const_map_iterator) noexcept; + + /// \endcond + + public: + /// \brief Removes the specified key-value pair from the table. + /// + /// \detail \cpp + /// auto tbl = toml::table{ + /// { "a", 1 }, + /// { "b", 2 }, + /// { "c", 3 } + /// }; + /// std::cout << tbl << "\n"; + /// + /// tbl.erase(tbl.begin() + 1); + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// { a = 1, b = 2, c = 3 } + /// { a = 1, c = 3 } + /// \eout + /// + /// \param pos Iterator to the key-value pair being erased. + /// + /// \returns Iterator to the first key-value pair immediately following the removed key-value + /// pair. + iterator erase(iterator pos) noexcept { return iterator{erase(const_map_iterator{pos})}; } + + /// \brief Removes the specified key-value pair from the table (const iterator overload). + /// + /// \detail \cpp + /// auto tbl = toml::table{ + /// { "a", 1 }, + /// { "b", 2 }, + /// { "c", 3 } + /// }; + /// std::cout << tbl << "\n"; + /// + /// tbl.erase(tbl.cbegin() + 1); + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// { a = 1, b = 2, c = 3 } + /// { a = 1, c = 3 } + /// \eout + /// + /// \param pos Iterator to the key-value pair being erased. + /// + /// \returns Iterator to the first key-value pair immediately following the removed key-value + /// pair. + iterator erase(const_iterator pos) noexcept { return iterator{erase(const_map_iterator{pos})}; } + + /// \brief Removes the key-value pairs in the range [first, last) from the table. + /// + /// \detail \cpp + /// auto tbl = toml::table{ + /// { "a", 1 }, + /// { "b", "bad" }, + /// { "c", "karma" }, + /// { "d", 2 } + /// }; + /// std::cout << tbl << "\n"; + /// + /// tbl.erase(tbl.cbegin() + 1, tbl.cbegin() + 3); + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// { a = 1, b = "bad", c = "karma", d = 2 } + /// { a = 1, d = 2 } + /// \eout + /// + /// \param begin Iterator to the first key-value pair being erased. + /// \param end Iterator to the one-past-the-last key-value pair being erased. + /// + /// \returns Iterator to the first key-value pair immediately following the last removed + /// key-value pair. + iterator erase(const_iterator begin, const_iterator end) noexcept { + return iterator{erase(const_map_iterator{begin}, const_map_iterator{end})}; + } + + /// \brief Removes the value with the given key from the table. + /// + /// \detail \cpp + /// auto tbl = toml::table{ + /// { "a", 1 }, + /// { "b", 2 }, + /// { "c", 3 } + /// }; + /// std::cout << tbl << "\n"; + /// + /// std::cout << tbl.erase("b") << "\n"; + /// std::cout << tbl.erase("not an existing key") << "\n"; + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// { a = 1, b = 2, c = 3 } + /// true + /// false + /// { a = 1, c = 3 } + /// \eout + /// + /// \param key Key to erase. + /// + /// \returns Number of elements removed (0 or 1). + TOML_EXPORTED_MEMBER_FUNCTION + size_t erase(std::string_view key) noexcept; #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Removes the value with the given key from the table. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key Key to erase. - /// - /// \returns Number of elements removed (0 or 1). - size_t erase(std::wstring_view key) - { - if (empty()) - return false; - - return erase(impl::narrow(key)); - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// \brief Removes empty child arrays and tables. - /// - /// \detail \cpp - /// - /// auto tbl = toml::table{ { "a", 1 }, { "b", toml::array{ } }, { "c", toml::array{ toml::table{}, toml::array{} } } }; - /// std::cout << arr << "\n"; - /// - /// arr.prune(); - /// std::cout << arr << "\n"; - /// \ecpp - /// - /// \out - /// { a = 1, b = [], c = [ {}, [] ] } - /// { a = 1 } - /// \eout - /// - /// \param recursive Should child arrays and tables themselves be pruned? - /// - /// \returns A reference to the table. - TOML_EXPORTED_MEMBER_FUNCTION - table& prune(bool recursive = true) & noexcept; - - /// \brief Removes empty child arrays and tables (rvalue overload). - /// - /// \param recursive Should child arrays and tables themselves be pruned? - /// - /// \returns An rvalue reference to the table. - table&& prune(bool recursive = true) && noexcept - { - return static_cast<toml::table&&>(this->prune(recursive)); - } - - /// \brief Removes all key-value pairs from the table. - TOML_EXPORTED_MEMBER_FUNCTION - void clear() noexcept; - - /// @} - - /// \name Insertion and Emplacement - /// @{ - - private: - /// \cond - - TOML_EXPORTED_MEMBER_FUNCTION - map_iterator insert_with_hint(const_iterator, key&&, impl::node_ptr&&); - - /// \endcond - - public: - /// \brief Emplaces a new value at a specific key if one did not already exist. - /// - /// \tparam ValueType toml::table, toml::array, or any native TOML value type. - /// \tparam KeyType A toml::key or any compatible string type. - /// \tparam ValueArgs Value constructor argument types. - /// \param hint Iterator to the position before which the new element will be emplaced. - /// \param key The key at which to emplace the new value. - /// \param args Arguments to forward to the value's constructor. - /// - /// \returns An iterator to the emplacement position (or the position of the value that prevented emplacement) - /// - /// \note This function has exactly the same semantics as [std::map::emplace_hint()](https://en.cppreference.com/w/cpp/container/map/emplace_hint). - TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>), - typename ValueType = void, - typename KeyType, - typename... ValueArgs) - iterator emplace_hint(const_iterator hint, KeyType&& key, ValueArgs&&... args) - { - static_assert(!impl::is_wide_string<KeyType> || TOML_ENABLE_WINDOWS_COMPAT, - "Emplacement using wide-character keys is only supported on Windows with " - "TOML_ENABLE_WINDOWS_COMPAT enabled."); - - using raw_value_type = impl::remove_cvref<ValueType>; - using value_type = std:: - conditional_t<std::is_void_v<raw_value_type>, impl::emplaced_type_of<ValueArgs&&...>, raw_value_type>; - - if constexpr (impl::is_wide_string<KeyType>) - { + /// \brief Removes the value with the given key from the table. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key Key to erase. + /// + /// \returns Number of elements removed (0 or 1). + size_t erase(std::wstring_view key) { + if (empty()) return false; + + return erase(impl::narrow(key)); + } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// \brief Removes empty child arrays and tables. + /// + /// \detail \cpp + /// + /// auto tbl = toml::table{ { "a", 1 }, { "b", toml::array{ } }, { "c", toml::array{ + /// toml::table{}, toml::array{} } } }; std::cout << arr << "\n"; + /// + /// arr.prune(); + /// std::cout << arr << "\n"; + /// \ecpp + /// + /// \out + /// { a = 1, b = [], c = [ {}, [] ] } + /// { a = 1 } + /// \eout + /// + /// \param recursive Should child arrays and tables themselves be pruned? + /// + /// \returns A reference to the table. + TOML_EXPORTED_MEMBER_FUNCTION + table& prune(bool recursive = true) & noexcept; + + /// \brief Removes empty child arrays and tables (rvalue overload). + /// + /// \param recursive Should child arrays and tables themselves be pruned? + /// + /// \returns An rvalue reference to the table. + table&& prune(bool recursive = true) && noexcept { + return static_cast<toml::table&&>(this->prune(recursive)); + } + + /// \brief Removes all key-value pairs from the table. + TOML_EXPORTED_MEMBER_FUNCTION + void clear() noexcept; + + /// @} + + /// \name Insertion and Emplacement + /// @{ + + private: + /// \cond + + TOML_EXPORTED_MEMBER_FUNCTION + map_iterator insert_with_hint(const_iterator, key&&, impl::node_ptr&&); + + /// \endcond + + public: + /// \brief Emplaces a new value at a specific key if one did not already exist. + /// + /// \tparam ValueType toml::table, toml::array, or any native TOML value type. + /// \tparam KeyType A toml::key or any compatible string type. + /// \tparam ValueArgs Value constructor argument types. + /// \param hint Iterator to the position before which the new element will be emplaced. + /// \param key The key at which to emplace the new value. + /// \param args Arguments to forward to the value's constructor. + /// + /// \returns An iterator to the emplacement position (or the position of the value that + /// prevented emplacement) + /// + /// \note This function has exactly the same semantics as + /// [std::map::emplace_hint()](https://en.cppreference.com/w/cpp/container/map/emplace_hint). + TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>), + typename ValueType = void, typename KeyType, typename... ValueArgs) + iterator emplace_hint(const_iterator hint, KeyType&& key, ValueArgs&&... args) { + static_assert(!impl::is_wide_string<KeyType> || TOML_ENABLE_WINDOWS_COMPAT, + "Emplacement using wide-character keys is only supported on Windows with " + "TOML_ENABLE_WINDOWS_COMPAT enabled."); + + using raw_value_type = impl::remove_cvref<ValueType>; + using value_type = std::conditional_t<std::is_void_v<raw_value_type>, + impl::emplaced_type_of<ValueArgs&&...>, raw_value_type>; + + if constexpr (impl::is_wide_string<KeyType>) { #if TOML_ENABLE_WINDOWS_COMPAT - return emplace_hint<value_type>(hint, - impl::narrow(static_cast<KeyType&&>(key)), - static_cast<ValueArgs&&>(args)...); + return emplace_hint<value_type>(hint, impl::narrow(static_cast<KeyType&&>(key)), + static_cast<ValueArgs&&>(args)...); #else - static_assert(impl::always_false<KeyType>, "Evaluated unreachable branch!"); + static_assert(impl::always_false<KeyType>, "Evaluated unreachable branch!"); #endif - } - else - { - static constexpr auto moving_node_ptr = std::is_same_v<value_type, impl::node_ptr> // - && sizeof...(ValueArgs) == 1u // - && impl::first_is_same<impl::node_ptr&&, ValueArgs&&...>; - using unwrapped_type = impl::remove_cvref<impl::unwrap_node<value_type>>; - - static_assert(moving_node_ptr // - || impl::is_native<unwrapped_type> // - || impl::is_one_of<unwrapped_type, table, array>, // - "ValueType argument of table::emplace_hint() must be one " - "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - map_iterator ipos = insert_with_hint(hint, toml::key{ static_cast<KeyType&&>(key) }, nullptr); - - // if second is nullptr then we successully claimed the key and inserted the empty sentinel, - // so now we have to construct the actual value - if (!ipos->second) - { - if constexpr (moving_node_ptr) - ipos->second = std::move(static_cast<ValueArgs&&>(args)...); - else - { + } else { + static constexpr auto moving_node_ptr = + std::is_same_v<value_type, impl::node_ptr> // + && sizeof...(ValueArgs) == 1u // + && impl::first_is_same<impl::node_ptr&&, ValueArgs&&...>; + using unwrapped_type = impl::remove_cvref<impl::unwrap_node<value_type>>; + + static_assert(moving_node_ptr // + || impl::is_native<unwrapped_type> // + || impl::is_one_of<unwrapped_type, table, array>, // + "ValueType argument of table::emplace_hint() must be one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + map_iterator ipos = insert_with_hint(hint, toml::key{static_cast<KeyType&&>(key)}, nullptr); + + // if second is nullptr then we successully claimed the key and inserted the empty sentinel, + // so now we have to construct the actual value + if (!ipos->second) { + if constexpr (moving_node_ptr) + ipos->second = std::move(static_cast<ValueArgs&&>(args)...); + else { #if TOML_COMPILER_HAS_EXCEPTIONS - try - { + try { #endif - ipos->second.reset( - new impl::wrap_node<unwrapped_type>{ static_cast<ValueArgs&&>(args)... }); + ipos->second.reset( + new impl::wrap_node<unwrapped_type>{static_cast<ValueArgs&&>(args)...}); #if TOML_COMPILER_HAS_EXCEPTIONS - } - catch (...) - { - erase(const_map_iterator{ ipos }); // strong exception guarantee - throw; - } + } catch (...) { + erase(const_map_iterator{ipos}); // strong exception guarantee + throw; + } #endif - } - } - return iterator{ ipos }; - } - } - - /// \brief Inserts a new value at a specific key if one did not already exist. - /// - /// \detail \godbolt{bMnW5r} - /// - /// \cpp - /// auto tbl = toml::table{ - /// { "a", 1 }, - /// { "b", 2 }, - /// { "c", 3 } - /// }; - /// std::cout << tbl << "\n"; - /// - /// for (auto k : { "a", "d" }) - /// { - /// auto result = tbl.insert(k, 42); - /// std::cout << "inserted with key '"sv << k << "': "sv << result.second << "\n"; - /// } - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// a = 1 - /// b = 2 - /// c = 3 - /// - /// inserted with key 'a': false - /// inserted with key 'd': true - /// a = 1 - /// b = 2 - /// c = 3 - /// d = 42 - /// \eout - /// - /// \tparam KeyType A toml::key or any compatible string type. - /// \tparam ValueType toml::node, toml::node_view, toml::table, toml::array, or a native TOML value type - /// (or a type promotable to one). - /// \param key The key at which to insert the new value. - /// \param val The new value to insert. - /// \param flags Value flags to apply to new values. - /// - /// \returns \conditional_return{Valid input} - /// <ul> - /// <li>An iterator to the insertion position (or the position of the value that prevented insertion) - /// <li>A boolean indicating if the insertion was successful. - /// </ul> - /// \conditional_return{Input is a null toml::node_view} - /// `{ end(), false }` - /// - /// \attention The return value will always be `{ end(), false }` if the input value was an - /// null toml::node_view, because no insertion can take place. This is the only circumstance - /// in which this can occur. - TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>), - typename KeyType, - typename ValueType) - std::pair<iterator, bool> insert(KeyType&& key, - ValueType&& val, - value_flags flags = preserve_source_value_flags) - { - static_assert(!impl::is_wide_string<KeyType> || TOML_ENABLE_WINDOWS_COMPAT, - "Insertion using wide-character keys is only supported on Windows with " - "TOML_ENABLE_WINDOWS_COMPAT enabled."); - - if constexpr (is_node_view<ValueType>) - { - if (!val) - return { end(), false }; - } - - if constexpr (impl::is_wide_string<KeyType>) - { + } + } + return iterator{ipos}; + } + } + + /// \brief Inserts a new value at a specific key if one did not already exist. + /// + /// \detail \godbolt{bMnW5r} + /// + /// \cpp + /// auto tbl = toml::table{ + /// { "a", 1 }, + /// { "b", 2 }, + /// { "c", 3 } + /// }; + /// std::cout << tbl << "\n"; + /// + /// for (auto k : { "a", "d" }) + /// { + /// auto result = tbl.insert(k, 42); + /// std::cout << "inserted with key '"sv << k << "': "sv << result.second << "\n"; + /// } + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// a = 1 + /// b = 2 + /// c = 3 + /// + /// inserted with key 'a': false + /// inserted with key 'd': true + /// a = 1 + /// b = 2 + /// c = 3 + /// d = 42 + /// \eout + /// + /// \tparam KeyType A toml::key or any compatible string type. + /// \tparam ValueType toml::node, toml::node_view, toml::table, toml::array, or a native TOML + /// value type (or a type promotable to one). + /// \param key The key at which to insert the new value. + /// \param val The new value to insert. + /// \param flags Value flags to apply to new values. + /// + /// \returns \conditional_return{Valid input} + /// <ul> + /// <li>An iterator to the insertion position (or the position of the value that + /// prevented insertion) <li>A boolean indicating if the insertion was successful. + /// </ul> + /// \conditional_return{Input is a null toml::node_view} + /// `{ end(), false }` + /// + /// \attention The return value will always be `{ end(), false }` if the input value was an + /// null toml::node_view, because no insertion can take place. This is the only + /// circumstance in which this can occur. + TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>), + typename KeyType, typename ValueType) + std::pair<iterator, bool> insert(KeyType&& key, ValueType&& val, + value_flags flags = preserve_source_value_flags) { + static_assert(!impl::is_wide_string<KeyType> || TOML_ENABLE_WINDOWS_COMPAT, + "Insertion using wide-character keys is only supported on Windows with " + "TOML_ENABLE_WINDOWS_COMPAT enabled."); + + if constexpr (is_node_view<ValueType>) { + if (!val) return {end(), false}; + } + + if constexpr (impl::is_wide_string<KeyType>) { #if TOML_ENABLE_WINDOWS_COMPAT - return insert(impl::narrow(static_cast<KeyType&&>(key)), static_cast<ValueType&&>(val), flags); + return insert(impl::narrow(static_cast<KeyType&&>(key)), static_cast<ValueType&&>(val), + flags); #else - static_assert(impl::always_false<KeyType>, "Evaluated unreachable branch!"); + static_assert(impl::always_false<KeyType>, "Evaluated unreachable branch!"); #endif - } - else - { - const auto key_view = std::string_view{ key }; - map_iterator ipos = get_lower_bound(key_view); - if (ipos == map_.end() || ipos->first != key_view) - { - ipos = insert_with_hint(const_iterator{ ipos }, - toml::key{ static_cast<KeyType&&>(key) }, - impl::make_node(static_cast<ValueType&&>(val), flags)); - return { iterator{ ipos }, true }; - } - return { iterator{ ipos }, false }; - } - } - - /// \brief Inserts a series of key-value pairs into the table. - /// - /// \detail \godbolt{bzYcce} - /// - /// \cpp - /// auto tbl = toml::table{ - /// { "a", 1 }, - /// { "b", 2 }, - /// { "c", 3 } - /// }; - /// std::cout << tbl << "\n"; - /// - /// auto kvps = std::array<std::pair<std::string, int>, 2>{{ - /// { "d", 42 }, - /// { "a", 43 } // won't be inserted, 'a' already exists - /// }}; - /// tbl.insert(kvps.begin(), kvps.end()); - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// a = 1 - /// b = 2 - /// c = 3 - /// - /// a = 1 - /// b = 2 - /// c = 3 - /// d = 42 - /// \eout - /// - /// \tparam Iter An InputIterator to a collection of key-value pairs. - /// \param begin An iterator to the first value in the input collection. - /// \param end An iterator to one-past-the-last value in the input collection. - /// \param flags Value flags to apply to new values. - /// - /// \remarks This function is morally equivalent to calling `insert(key, value)` for each - /// key-value pair covered by the iterator range, so any values with keys already found in the - /// table will not be replaced. - TOML_CONSTRAINED_TEMPLATE((!is_key_or_convertible<Iter> && !impl::is_wide_string<Iter>), typename Iter) - void insert(Iter begin, Iter end, value_flags flags = preserve_source_value_flags) - { - if (begin == end) - return; - for (auto it = begin; it != end; it++) - { - if constexpr (std::is_rvalue_reference_v<decltype(*it)>) - insert(std::move((*it).first), std::move((*it).second), flags); - else - insert((*it).first, (*it).second, flags); - } - } - - /// \brief Inserts or assigns a value at a specific key. - /// - /// \detail \godbolt{ddK563} - /// - /// \cpp - /// auto tbl = toml::table{ - /// { "a", 1 }, - /// { "b", 2 }, - /// { "c", 3 } - /// }; - /// std::cout << tbl << "\n"; - /// - /// for (auto k : { "a", "d" }) - /// { - /// auto result = tbl.insert_or_assign(k, 42); - /// std::cout << "value at key '"sv << k - /// << "' was "sv << (result.second ? "inserted"sv : "assigned"sv) << "\n"; - /// } - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// a = 1 - /// b = 2 - /// c = 3 - /// - /// value at key 'a' was assigned - /// value at key 'd' was inserted - /// a = 42 - /// b = 2 - /// c = 3 - /// d = 42 - /// \eout - /// - /// \tparam KeyType A toml::key or any compatible string type. - /// \tparam ValueType toml::node, toml::node_view, toml::table, toml::array, or a native TOML value type - /// (or a type promotable to one). - /// \param key The key at which to insert or assign the value. - /// \param val The value to insert/assign. - /// \param flags Value flags to apply to new values. - /// - /// \returns \conditional_return{Valid input} - /// <ul> - /// <li>An iterator to the value's position - /// <li>`true` if the value was inserted, `false` if it was assigned. - /// </ul> - /// \conditional_return{Input is a null toml::node_view} - /// `{ end(), false }` - /// - /// \attention The return value will always be `{ end(), false }` if the input value was - /// a null toml::node_view, because no insertion or assignment can take place. - /// This is the only circumstance in which this can occur. - TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>), - typename KeyType, - typename ValueType) - std::pair<iterator, bool> insert_or_assign(KeyType&& key, - ValueType&& val, - value_flags flags = preserve_source_value_flags) - { - static_assert(!impl::is_wide_string<KeyType> || TOML_ENABLE_WINDOWS_COMPAT, - "Insertion using wide-character keys is only supported on Windows with " - "TOML_ENABLE_WINDOWS_COMPAT enabled."); - - if constexpr (is_node_view<ValueType>) - { - if (!val) - return { end(), false }; - } - - if constexpr (impl::is_wide_string<KeyType>) - { + } else { + const auto key_view = std::string_view{key}; + map_iterator ipos = get_lower_bound(key_view); + if (ipos == map_.end() || ipos->first != key_view) { + ipos = insert_with_hint(const_iterator{ipos}, toml::key{static_cast<KeyType&&>(key)}, + impl::make_node(static_cast<ValueType&&>(val), flags)); + return {iterator{ipos}, true}; + } + return {iterator{ipos}, false}; + } + } + + /// \brief Inserts a series of key-value pairs into the table. + /// + /// \detail \godbolt{bzYcce} + /// + /// \cpp + /// auto tbl = toml::table{ + /// { "a", 1 }, + /// { "b", 2 }, + /// { "c", 3 } + /// }; + /// std::cout << tbl << "\n"; + /// + /// auto kvps = std::array<std::pair<std::string, int>, 2>{{ + /// { "d", 42 }, + /// { "a", 43 } // won't be inserted, 'a' already exists + /// }}; + /// tbl.insert(kvps.begin(), kvps.end()); + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// a = 1 + /// b = 2 + /// c = 3 + /// + /// a = 1 + /// b = 2 + /// c = 3 + /// d = 42 + /// \eout + /// + /// \tparam Iter An InputIterator to a collection of key-value pairs. + /// \param begin An iterator to the first value in the input collection. + /// \param end An iterator to one-past-the-last value in the input collection. + /// \param flags Value flags to apply to new values. + /// + /// \remarks This function is morally equivalent to calling `insert(key, value)` for each + /// key-value pair covered by the iterator range, so any values with keys already found in + /// the table will not be replaced. + TOML_CONSTRAINED_TEMPLATE((!is_key_or_convertible<Iter> && !impl::is_wide_string<Iter>), + typename Iter) + void insert(Iter begin, Iter end, value_flags flags = preserve_source_value_flags) { + if (begin == end) return; + for (auto it = begin; it != end; it++) { + if constexpr (std::is_rvalue_reference_v<decltype(*it)>) + insert(std::move((*it).first), std::move((*it).second), flags); + else + insert((*it).first, (*it).second, flags); + } + } + + /// \brief Inserts or assigns a value at a specific key. + /// + /// \detail \godbolt{ddK563} + /// + /// \cpp + /// auto tbl = toml::table{ + /// { "a", 1 }, + /// { "b", 2 }, + /// { "c", 3 } + /// }; + /// std::cout << tbl << "\n"; + /// + /// for (auto k : { "a", "d" }) + /// { + /// auto result = tbl.insert_or_assign(k, 42); + /// std::cout << "value at key '"sv << k + /// << "' was "sv << (result.second ? "inserted"sv : "assigned"sv) << "\n"; + /// } + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// a = 1 + /// b = 2 + /// c = 3 + /// + /// value at key 'a' was assigned + /// value at key 'd' was inserted + /// a = 42 + /// b = 2 + /// c = 3 + /// d = 42 + /// \eout + /// + /// \tparam KeyType A toml::key or any compatible string type. + /// \tparam ValueType toml::node, toml::node_view, toml::table, toml::array, or a native TOML + /// value type (or a type promotable to one). + /// \param key The key at which to insert or assign the value. + /// \param val The value to insert/assign. + /// \param flags Value flags to apply to new values. + /// + /// \returns \conditional_return{Valid input} + /// <ul> + /// <li>An iterator to the value's position + /// <li>`true` if the value was inserted, `false` if it was assigned. + /// </ul> + /// \conditional_return{Input is a null toml::node_view} + /// `{ end(), false }` + /// + /// \attention The return value will always be `{ end(), false }` if the input value was + /// a null toml::node_view, because no insertion or assignment can take place. + /// This is the only circumstance in which this can occur. + TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>), + typename KeyType, typename ValueType) + std::pair<iterator, bool> insert_or_assign(KeyType&& key, ValueType&& val, + value_flags flags = preserve_source_value_flags) { + static_assert(!impl::is_wide_string<KeyType> || TOML_ENABLE_WINDOWS_COMPAT, + "Insertion using wide-character keys is only supported on Windows with " + "TOML_ENABLE_WINDOWS_COMPAT enabled."); + + if constexpr (is_node_view<ValueType>) { + if (!val) return {end(), false}; + } + + if constexpr (impl::is_wide_string<KeyType>) { #if TOML_ENABLE_WINDOWS_COMPAT - return insert_or_assign(impl::narrow(static_cast<KeyType&&>(key)), - static_cast<ValueType&&>(val), - flags); + return insert_or_assign(impl::narrow(static_cast<KeyType&&>(key)), + static_cast<ValueType&&>(val), flags); #else - static_assert(impl::always_false<KeyType>, "Evaluated unreachable branch!"); + static_assert(impl::always_false<KeyType>, "Evaluated unreachable branch!"); #endif - } - else - { - const auto key_view = std::string_view{ key }; - map_iterator ipos = get_lower_bound(key_view); - if (ipos == map_.end() || ipos->first != key_view) - { - ipos = insert_with_hint(const_iterator{ ipos }, - toml::key{ static_cast<KeyType&&>(key) }, - impl::make_node(static_cast<ValueType&&>(val), flags)); - return { iterator{ ipos }, true }; - } - else - { - (*ipos).second = impl::make_node(static_cast<ValueType&&>(val), flags); - return { iterator{ ipos }, false }; - } - } - } - - /// \brief Emplaces a new value at a specific key if one did not already exist. - /// - /// \detail \cpp - /// auto tbl = toml::table{ - /// { "a", 1 }, - /// { "b", 2 }, - /// { "c", 3 } - /// }; - /// std::cout << tbl << "\n"; - /// - /// for (auto k : { "a", "d" }) - /// { - /// // add a string using std::string's substring constructor - /// auto result = tbl.emplace<std::string>(k, "this is not a drill"sv, 14, 5); - /// std::cout << "emplaced with key '"sv << k << "': "sv << result.second << "\n"; - /// } - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// { a = 1, b = 2, c = 3 } - /// emplaced with key 'a': false - /// emplaced with key 'd': true - /// { a = 1, b = 2, c = 3, d = "drill" } - /// \eout - /// - /// \tparam ValueType toml::table, toml::array, or any native TOML value type. - /// \tparam KeyType A toml::key or any compatible string type. - /// \tparam ValueArgs Value constructor argument types. - /// \param key The key at which to emplace the new value. - /// \param args Arguments to forward to the value's constructor. - /// - /// \returns A std::pair containing: <br> - /// - An iterator to the emplacement position (or the position of the value that prevented emplacement) - /// - A boolean indicating if the emplacement was successful. - /// - /// \remark There is no difference between insert() and emplace() for trivial value types (floats, ints, bools). - TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>), - typename ValueType = void, - typename KeyType, - typename... ValueArgs) - std::pair<iterator, bool> emplace(KeyType&& key, ValueArgs&&... args) - { - static_assert(!impl::is_wide_string<KeyType> || TOML_ENABLE_WINDOWS_COMPAT, - "Emplacement using wide-character keys is only supported on Windows with " - "TOML_ENABLE_WINDOWS_COMPAT enabled."); - - using raw_value_type = impl::remove_cvref<ValueType>; - using value_type = std:: - conditional_t<std::is_void_v<raw_value_type>, impl::emplaced_type_of<ValueArgs&&...>, raw_value_type>; - - if constexpr (impl::is_wide_string<KeyType>) - { + } else { + const auto key_view = std::string_view{key}; + map_iterator ipos = get_lower_bound(key_view); + if (ipos == map_.end() || ipos->first != key_view) { + ipos = insert_with_hint(const_iterator{ipos}, toml::key{static_cast<KeyType&&>(key)}, + impl::make_node(static_cast<ValueType&&>(val), flags)); + return {iterator{ipos}, true}; + } else { + (*ipos).second = impl::make_node(static_cast<ValueType&&>(val), flags); + return {iterator{ipos}, false}; + } + } + } + + /// \brief Emplaces a new value at a specific key if one did not already exist. + /// + /// \detail \cpp + /// auto tbl = toml::table{ + /// { "a", 1 }, + /// { "b", 2 }, + /// { "c", 3 } + /// }; + /// std::cout << tbl << "\n"; + /// + /// for (auto k : { "a", "d" }) + /// { + /// // add a string using std::string's substring constructor + /// auto result = tbl.emplace<std::string>(k, "this is not a drill"sv, 14, 5); + /// std::cout << "emplaced with key '"sv << k << "': "sv << result.second << "\n"; + /// } + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// { a = 1, b = 2, c = 3 } + /// emplaced with key 'a': false + /// emplaced with key 'd': true + /// { a = 1, b = 2, c = 3, d = "drill" } + /// \eout + /// + /// \tparam ValueType toml::table, toml::array, or any native TOML value type. + /// \tparam KeyType A toml::key or any compatible string type. + /// \tparam ValueArgs Value constructor argument types. + /// \param key The key at which to emplace the new value. + /// \param args Arguments to forward to the value's constructor. + /// + /// \returns A std::pair containing: <br> + /// - An iterator to the emplacement position (or the position of the value that prevented + /// emplacement) + /// - A boolean indicating if the emplacement was successful. + /// + /// \remark There is no difference between insert() and emplace() for trivial value types + /// (floats, ints, bools). + TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>), + typename ValueType = void, typename KeyType, typename... ValueArgs) + std::pair<iterator, bool> emplace(KeyType&& key, ValueArgs&&... args) { + static_assert(!impl::is_wide_string<KeyType> || TOML_ENABLE_WINDOWS_COMPAT, + "Emplacement using wide-character keys is only supported on Windows with " + "TOML_ENABLE_WINDOWS_COMPAT enabled."); + + using raw_value_type = impl::remove_cvref<ValueType>; + using value_type = std::conditional_t<std::is_void_v<raw_value_type>, + impl::emplaced_type_of<ValueArgs&&...>, raw_value_type>; + + if constexpr (impl::is_wide_string<KeyType>) { #if TOML_ENABLE_WINDOWS_COMPAT - return emplace<value_type>(impl::narrow(static_cast<KeyType&&>(key)), - static_cast<ValueArgs&&>(args)...); + return emplace<value_type>(impl::narrow(static_cast<KeyType&&>(key)), + static_cast<ValueArgs&&>(args)...); #else - static_assert(impl::always_false<KeyType>, "Evaluated unreachable branch!"); + static_assert(impl::always_false<KeyType>, "Evaluated unreachable branch!"); #endif - } - else - { - using unwrapped_type = impl::remove_cvref<impl::unwrap_node<value_type>>; - static_assert((impl::is_native<unwrapped_type> || impl::is_one_of<unwrapped_type, table, array>), - "ValueType argument of table::emplace() must be one " - "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - const auto key_view = std::string_view{ key }; - auto ipos = get_lower_bound(key_view); - if (ipos == map_.end() || ipos->first != key_view) - { - ipos = insert_with_hint( - const_iterator{ ipos }, - toml::key{ static_cast<KeyType&&>(key) }, - impl::node_ptr{ new impl::wrap_node<unwrapped_type>{ static_cast<ValueArgs&&>(args)... } }); - return { iterator{ ipos }, true }; - } - return { iterator{ ipos }, false }; - } - } - - /// @} - - /// \name Node views - /// @{ - - /// \cond - using node::operator[]; // inherit operator[toml::path] - /// \endcond - - /// \brief Gets a node_view for the selected value. - /// - /// \param key The key used for the lookup. - /// - /// \returns A view of the value at the given key if one existed, or an empty node view. - /// - /// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it - /// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it. - /// <strong>This is not an error.</strong> - /// - /// \see toml::node_view - TOML_NODISCARD - node_view<node> operator[](std::string_view key) noexcept - { - return node_view<node>{ get(key) }; - } - - /// \brief Gets a node_view for the selected value (const overload). - /// - /// \param key The key used for the lookup. - /// - /// \returns A view of the value at the given key if one existed, or an empty node view. - /// - /// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it - /// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it. - /// <strong>This is not an error.</strong> - /// - /// \see toml::node_view - TOML_NODISCARD - node_view<const node> operator[](std::string_view key) const noexcept - { - return node_view<const node>{ get(key) }; - } + } else { + using unwrapped_type = impl::remove_cvref<impl::unwrap_node<value_type>>; + static_assert( + (impl::is_native<unwrapped_type> || impl::is_one_of<unwrapped_type, table, array>), + "ValueType argument of table::emplace() must be one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + const auto key_view = std::string_view{key}; + auto ipos = get_lower_bound(key_view); + if (ipos == map_.end() || ipos->first != key_view) { + ipos = insert_with_hint(const_iterator{ipos}, toml::key{static_cast<KeyType&&>(key)}, + impl::node_ptr{new impl::wrap_node<unwrapped_type>{ + static_cast<ValueArgs&&>(args)...}}); + return {iterator{ipos}, true}; + } + return {iterator{ipos}, false}; + } + } + + /// @} + + /// \name Node views + /// @{ + + /// \cond + using node::operator[]; // inherit operator[toml::path] + /// \endcond + + /// \brief Gets a node_view for the selected value. + /// + /// \param key The key used for the lookup. + /// + /// \returns A view of the value at the given key if one existed, or an empty node view. + /// + /// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it + /// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it. + /// <strong>This is not an error.</strong> + /// + /// \see toml::node_view + TOML_NODISCARD + node_view<node> operator[](std::string_view key) noexcept { return node_view<node>{get(key)}; } + + /// \brief Gets a node_view for the selected value (const overload). + /// + /// \param key The key used for the lookup. + /// + /// \returns A view of the value at the given key if one existed, or an empty node view. + /// + /// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it + /// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it. + /// <strong>This is not an error.</strong> + /// + /// \see toml::node_view + TOML_NODISCARD + node_view<const node> operator[](std::string_view key) const noexcept { + return node_view<const node>{get(key)}; + } #if TOML_ENABLE_WINDOWS_COMPAT - /// \brief Gets a node_view for the selected value. - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key The key used for the lookup. - /// - /// \returns A view of the value at the given key if one existed, or an empty node view. - /// - /// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it - /// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it. - /// <strong>This is not an error.</strong> - /// - /// \see toml::node_view - TOML_NODISCARD - node_view<node> operator[](std::wstring_view key) - { - return node_view<node>{ get(key) }; - } - - /// \brief Gets a node_view for the selected value (const overload). - /// - /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. - /// - /// \param key The key used for the lookup. - /// - /// \returns A view of the value at the given key if one existed, or an empty node view. - /// - /// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it - /// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it. - /// <strong>This is not an error.</strong> - /// - /// \see toml::node_view - TOML_NODISCARD - node_view<const node> operator[](std::wstring_view key) const - { - return node_view<const node>{ get(key) }; - } - -#endif // TOML_ENABLE_WINDOWS_COMPAT - - /// @} - - /// \name Equality - /// @{ - - private: - /// \cond - - TOML_PURE_GETTER - TOML_EXPORTED_STATIC_FUNCTION - static bool TOML_CALLCONV equal(const table&, const table&) noexcept; - - /// \endcond - public: - /// \brief Equality operator. - /// - /// \param lhs The LHS table. - /// \param rhs The RHS table. - /// - /// \returns True if the tables contained the same keys and map. - TOML_NODISCARD - friend bool operator==(const table& lhs, const table& rhs) noexcept - { - return equal(lhs, rhs); - } - - /// \brief Inequality operator. - /// - /// \param lhs The LHS table. - /// \param rhs The RHS table. - /// - /// \returns True if the tables did not contain the same keys and map. - TOML_NODISCARD - friend bool operator!=(const table& lhs, const table& rhs) noexcept - { - return !equal(lhs, rhs); - } - - /// @} + /// \brief Gets a node_view for the selected value. + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key The key used for the lookup. + /// + /// \returns A view of the value at the given key if one existed, or an empty node view. + /// + /// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it + /// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it. + /// <strong>This is not an error.</strong> + /// + /// \see toml::node_view + TOML_NODISCARD + node_view<node> operator[](std::wstring_view key) { return node_view<node>{get(key)}; } + + /// \brief Gets a node_view for the selected value (const overload). + /// + /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. + /// + /// \param key The key used for the lookup. + /// + /// \returns A view of the value at the given key if one existed, or an empty node view. + /// + /// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it + /// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it. + /// <strong>This is not an error.</strong> + /// + /// \see toml::node_view + TOML_NODISCARD + node_view<const node> operator[](std::wstring_view key) const { + return node_view<const node>{get(key)}; + } + +#endif // TOML_ENABLE_WINDOWS_COMPAT + + /// @} + + /// \name Equality + /// @{ + + private: + /// \cond + + TOML_PURE_GETTER + TOML_EXPORTED_STATIC_FUNCTION + static bool TOML_CALLCONV equal(const table&, const table&) noexcept; + + /// \endcond + public: + /// \brief Equality operator. + /// + /// \param lhs The LHS table. + /// \param rhs The RHS table. + /// + /// \returns True if the tables contained the same keys and map. + TOML_NODISCARD + friend bool operator==(const table& lhs, const table& rhs) noexcept { return equal(lhs, rhs); } + + /// \brief Inequality operator. + /// + /// \param lhs The LHS table. + /// \param rhs The RHS table. + /// + /// \returns True if the tables did not contain the same keys and map. + TOML_NODISCARD + friend bool operator!=(const table& lhs, const table& rhs) noexcept { return !equal(lhs, rhs); } + + /// @} #if TOML_ENABLE_FORMATTERS - /// \brief Prints the table out to a stream as formatted TOML. - /// - /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. - friend std::ostream& operator<<(std::ostream& lhs, const table& rhs) - { - impl::print_to_stream(lhs, rhs); - return lhs; - } + /// \brief Prints the table out to a stream as formatted TOML. + /// + /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. + friend std::ostream& operator<<(std::ostream& lhs, const table& rhs) { + impl::print_to_stream(lhs, rhs); + return lhs; + } #endif - }; + }; } TOML_NAMESPACE_END; diff --git a/vendor/toml++/impl/toml_formatter.hpp b/vendor/toml++/impl/toml_formatter.hpp index ffd6325..d307277 100644 --- a/vendor/toml++/impl/toml_formatter.hpp +++ b/vendor/toml++/impl/toml_formatter.hpp @@ -1,153 +1,149 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" #if TOML_ENABLE_FORMATTERS -#include "std_vector.hpp" #include "formatter.hpp" #include "header_start.hpp" +#include "std_vector.hpp" -TOML_NAMESPACE_START -{ - /// \brief A wrapper for printing TOML objects out to a stream as formatted TOML. - /// - /// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled. - /// - /// \remarks You generally don't need to create an instance of this class explicitly; the stream - /// operators of the TOML node types already print themselves out using this formatter. - /// - /// \detail \cpp - /// auto tbl = toml::table{ - /// { "description", "This is some TOML, yo." }, - /// { "fruit", toml::array{ "apple", "orange", "pear" } }, - /// { "numbers", toml::array{ 1, 2, 3, 4, 5 } }, - /// { "table", toml::table{ { "foo", "bar" } } } - /// }; - /// - /// // these two lines are equivalent: - /// std::cout << toml::toml_formatter{ tbl } << "\n"; - /// std::cout << tbl << "\n"; - /// \ecpp - /// - /// \out - /// description = "This is some TOML, yo." - /// fruit = ["apple", "orange", "pear"] - /// numbers = [1, 2, 3, 4, 5] - /// - /// [table] - /// foo = "bar" - /// \eout - class TOML_EXPORTED_CLASS toml_formatter : impl::formatter - { - private: - /// \cond - - using base = impl::formatter; - std::vector<const key*> key_path_; - bool pending_table_separator_ = false; - - TOML_EXPORTED_MEMBER_FUNCTION - void print_pending_table_separator(); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const key&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print_inline(const toml::table&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const toml::array&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const toml::table&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(); - - static constexpr impl::formatter_constants constants = { format_flags::none, // mandatory - format_flags::none, // ignored - "inf"sv, - "-inf"sv, - "nan"sv, - "true"sv, - "false"sv }; - - /// \endcond - - public: - /// \brief The default flags for a toml_formatter. - static constexpr format_flags default_flags = constants.mandatory_flags // - | format_flags::allow_literal_strings // - | format_flags::allow_multi_line_strings // - | format_flags::allow_unicode_strings // - | format_flags::allow_real_tabs_in_strings // - | format_flags::allow_binary_integers // - | format_flags::allow_octal_integers // - | format_flags::allow_hexadecimal_integers // - | format_flags::indentation; - - /// \brief Constructs a TOML formatter and binds it to a TOML object. - /// - /// \param source The source TOML object. - /// \param flags Format option flags. - TOML_NODISCARD_CTOR - explicit toml_formatter(const toml::node& source, format_flags flags = default_flags) noexcept - : base{ &source, nullptr, constants, { flags, " "sv } } - {} +TOML_NAMESPACE_START { + /// \brief A wrapper for printing TOML objects out to a stream as formatted TOML. + /// + /// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled. + /// + /// \remarks You generally don't need to create an instance of this class explicitly; the stream + /// operators of the TOML node types already print themselves out using this formatter. + /// + /// \detail \cpp + /// auto tbl = toml::table{ + /// { "description", "This is some TOML, yo." }, + /// { "fruit", toml::array{ "apple", "orange", "pear" } }, + /// { "numbers", toml::array{ 1, 2, 3, 4, 5 } }, + /// { "table", toml::table{ { "foo", "bar" } } } + /// }; + /// + /// // these two lines are equivalent: + /// std::cout << toml::toml_formatter{ tbl } << "\n"; + /// std::cout << tbl << "\n"; + /// \ecpp + /// + /// \out + /// description = "This is some TOML, yo." + /// fruit = ["apple", "orange", "pear"] + /// numbers = [1, 2, 3, 4, 5] + /// + /// [table] + /// foo = "bar" + /// \eout + class TOML_EXPORTED_CLASS toml_formatter : impl::formatter { + private: + /// \cond + + using base = impl::formatter; + std::vector<const key*> key_path_; + bool pending_table_separator_ = false; + + TOML_EXPORTED_MEMBER_FUNCTION + void print_pending_table_separator(); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const key&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print_inline(const toml::table&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const toml::array&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const toml::table&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(); + + static constexpr impl::formatter_constants constants = {format_flags::none, // mandatory + format_flags::none, // ignored + "inf"sv, + "-inf"sv, + "nan"sv, + "true"sv, + "false"sv}; + + /// \endcond + + public: + /// \brief The default flags for a toml_formatter. + static constexpr format_flags default_flags = constants.mandatory_flags // + | format_flags::allow_literal_strings // + | format_flags::allow_multi_line_strings // + | format_flags::allow_unicode_strings // + | format_flags::allow_real_tabs_in_strings // + | format_flags::allow_binary_integers // + | format_flags::allow_octal_integers // + | format_flags::allow_hexadecimal_integers // + | format_flags::indentation; + + /// \brief Constructs a TOML formatter and binds it to a TOML object. + /// + /// \param source The source TOML object. + /// \param flags Format option flags. + TOML_NODISCARD_CTOR + explicit toml_formatter(const toml::node& source, format_flags flags = default_flags) noexcept + : base{&source, nullptr, constants, {flags, " "sv}} {} #if TOML_DOXYGEN || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS) - /// \brief Constructs a TOML formatter and binds it to a toml::parse_result. - /// - /// \availability This constructor is only available when exceptions are disabled. - /// - /// \attention Formatting a failed parse result will simply dump the error message out as-is. - /// This will not be valid TOML, but at least gives you something to log or show up in diagnostics: - /// \cpp - /// std::cout << toml::toml_formatter{ toml::parse("a = 'b'"sv) } // ok - /// << "\n\n" - /// << toml::toml_formatter{ toml::parse("a = "sv) } // malformed - /// << "\n"; - /// \ecpp - /// \out - /// a = 'b' - /// - /// Error while parsing key-value pair: encountered end-of-file - /// (error occurred at line 1, column 5) - /// \eout - /// Use the library with exceptions if you want to avoid this scenario. - /// - /// \param result The parse result. - /// \param flags Format option flags. - TOML_NODISCARD_CTOR - explicit toml_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept - : base{ nullptr, &result, constants, { flags, " "sv } } - {} + /// \brief Constructs a TOML formatter and binds it to a toml::parse_result. + /// + /// \availability This constructor is only available when exceptions are disabled. + /// + /// \attention Formatting a failed parse result will simply dump the error message out as-is. + /// This will not be valid TOML, but at least gives you something to log or show up in + ///diagnostics: + /// \cpp + /// std::cout << toml::toml_formatter{ toml::parse("a = 'b'"sv) } // ok + /// << "\n\n" + /// << toml::toml_formatter{ toml::parse("a = "sv) } // malformed + /// << "\n"; + /// \ecpp + /// \out + /// a = 'b' + /// + /// Error while parsing key-value pair: encountered end-of-file + /// (error occurred at line 1, column 5) + /// \eout + /// Use the library with exceptions if you want to avoid this scenario. + /// + /// \param result The parse result. + /// \param flags Format option flags. + TOML_NODISCARD_CTOR + explicit toml_formatter(const toml::parse_result& result, + format_flags flags = default_flags) noexcept + : base{nullptr, &result, constants, {flags, " "sv}} {} #endif - /// \brief Prints the bound TOML object out to the stream as formatted TOML. - friend std::ostream& operator<<(std::ostream& lhs, toml_formatter& rhs) - { - rhs.attach(lhs); - rhs.key_path_.clear(); - rhs.print(); - rhs.detach(); - return lhs; - } - - /// \brief Prints the bound TOML object out to the stream as formatted TOML (rvalue overload). - friend std::ostream& operator<<(std::ostream& lhs, toml_formatter&& rhs) - { - return lhs << rhs; // as lvalue - } - }; + /// \brief Prints the bound TOML object out to the stream as formatted TOML. + friend std::ostream& operator<<(std::ostream& lhs, toml_formatter& rhs) { + rhs.attach(lhs); + rhs.key_path_.clear(); + rhs.print(); + rhs.detach(); + return lhs; + } + + /// \brief Prints the bound TOML object out to the stream as formatted TOML (rvalue overload). + friend std::ostream& operator<<(std::ostream& lhs, toml_formatter&& rhs) { + return lhs << rhs; // as lvalue + } + }; } TOML_NAMESPACE_END; #include "header_end.hpp" -#endif // TOML_ENABLE_FORMATTERS +#endif // TOML_ENABLE_FORMATTERS diff --git a/vendor/toml++/impl/unicode.hpp b/vendor/toml++/impl/unicode.hpp index 9bad395..3b399c3 100644 --- a/vendor/toml++/impl/unicode.hpp +++ b/vendor/toml++/impl/unicode.hpp @@ -1,195 +1,164 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once -#include "unicode_autogenerated.hpp" #include "header_start.hpp" +#include "unicode_autogenerated.hpp" /// \cond -TOML_IMPL_NAMESPACE_START -{ - TOML_CONST_GETTER - constexpr bool is_string_delimiter(char32_t c) noexcept - { - return c == U'"' || c == U'\''; - } - - TOML_CONST_GETTER - constexpr bool is_ascii_letter(char32_t c) noexcept - { - return (c >= U'a' && c <= U'z') || (c >= U'A' && c <= U'Z'); - } - - TOML_CONST_GETTER - constexpr bool is_binary_digit(char32_t c) noexcept - { - return c == U'0' || c == U'1'; - } - - TOML_CONST_GETTER - constexpr bool is_octal_digit(char32_t c) noexcept - { - return (c >= U'0' && c <= U'7'); - } - - TOML_CONST_GETTER - constexpr bool is_decimal_digit(char32_t c) noexcept - { - return (c >= U'0' && c <= U'9'); - } - - TOML_CONST_GETTER - constexpr bool is_hexadecimal_digit(char32_t c) noexcept - { - return U'0' <= c && c <= U'f' && (1ull << (static_cast<uint_least64_t>(c) - 0x30u)) & 0x7E0000007E03FFull; - } - - template <typename T> - TOML_CONST_GETTER - constexpr uint_least32_t hex_to_dec(const T c) noexcept - { - if constexpr (std::is_same_v<remove_cvref<T>, uint_least32_t>) - return c >= 0x41u // >= 'A' - ? 10u + (c | 0x20u) - 0x61u // - 'a' - : c - 0x30u // - '0' - ; - else - return hex_to_dec(static_cast<uint_least32_t>(c)); - } - - TOML_CONST_GETTER - constexpr bool is_horizontal_whitespace(char32_t c) noexcept - { - return is_ascii_horizontal_whitespace(c) || is_non_ascii_horizontal_whitespace(c); - } - - TOML_CONST_GETTER - constexpr bool is_vertical_whitespace(char32_t c) noexcept - { - return is_ascii_vertical_whitespace(c) || is_non_ascii_vertical_whitespace(c); - } - - TOML_CONST_GETTER - constexpr bool is_whitespace(char32_t c) noexcept - { - return is_horizontal_whitespace(c) || is_vertical_whitespace(c); - } - - TOML_CONST_GETTER - constexpr bool is_bare_key_character(char32_t c) noexcept - { - return is_ascii_bare_key_character(c) -#if TOML_LANG_UNRELEASED // toml/pull/891 (unicode bare keys) - || is_non_ascii_bare_key_character(c) +TOML_IMPL_NAMESPACE_START { + TOML_CONST_GETTER + constexpr bool is_string_delimiter(char32_t c) noexcept { + return c == U'"' || c == U'\''; + } + + TOML_CONST_GETTER + constexpr bool is_ascii_letter(char32_t c) noexcept { + return (c >= U'a' && c <= U'z') || (c >= U'A' && c <= U'Z'); + } + + TOML_CONST_GETTER + constexpr bool is_binary_digit(char32_t c) noexcept { + return c == U'0' || c == U'1'; + } + + TOML_CONST_GETTER + constexpr bool is_octal_digit(char32_t c) noexcept { + return (c >= U'0' && c <= U'7'); + } + + TOML_CONST_GETTER + constexpr bool is_decimal_digit(char32_t c) noexcept { + return (c >= U'0' && c <= U'9'); + } + + TOML_CONST_GETTER + constexpr bool is_hexadecimal_digit(char32_t c) noexcept { + return U'0' <= c && c <= U'f' && + (1ull << (static_cast<uint_least64_t>(c) - 0x30u)) & 0x7E0000007E03FFull; + } + + template <typename T> + TOML_CONST_GETTER constexpr uint_least32_t hex_to_dec(const T c) noexcept { + if constexpr (std::is_same_v<remove_cvref<T>, uint_least32_t>) + return c >= 0x41u // >= 'A' + ? 10u + (c | 0x20u) - 0x61u // - 'a' + : c - 0x30u // - '0' + ; + else + return hex_to_dec(static_cast<uint_least32_t>(c)); + } + + TOML_CONST_GETTER + constexpr bool is_horizontal_whitespace(char32_t c) noexcept { + return is_ascii_horizontal_whitespace(c) || is_non_ascii_horizontal_whitespace(c); + } + + TOML_CONST_GETTER + constexpr bool is_vertical_whitespace(char32_t c) noexcept { + return is_ascii_vertical_whitespace(c) || is_non_ascii_vertical_whitespace(c); + } + + TOML_CONST_GETTER + constexpr bool is_whitespace(char32_t c) noexcept { + return is_horizontal_whitespace(c) || is_vertical_whitespace(c); + } + + TOML_CONST_GETTER + constexpr bool is_bare_key_character(char32_t c) noexcept { + return is_ascii_bare_key_character(c) +#if TOML_LANG_UNRELEASED // toml/pull/891 (unicode bare keys) + || is_non_ascii_bare_key_character(c) #endif - ; - } - - TOML_CONST_GETTER - constexpr bool is_value_terminator(char32_t c) noexcept - { - return is_whitespace(c) || c == U']' || c == U'}' || c == U',' || c == U'#'; - } - - TOML_CONST_GETTER - constexpr bool is_control_character(char c) noexcept - { - return c <= '\u001F' || c == '\u007F'; - } - - TOML_CONST_GETTER - constexpr bool is_control_character(char32_t c) noexcept - { - return c <= U'\u001F' || c == U'\u007F'; - } - - TOML_CONST_GETTER - constexpr bool is_nontab_control_character(char32_t c) noexcept - { - return c <= U'\u0008' || (c >= U'\u000A' && c <= U'\u001F') || c == U'\u007F'; - } - - TOML_CONST_GETTER - constexpr bool is_unicode_surrogate(char32_t c) noexcept - { - return c >= 0xD800u && c <= 0xDFFF; - } - - struct utf8_decoder - { - // utf8_decoder based on this: https://bjoern.hoehrmann.de/utf-8/decoder/dfa/ - // Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> - - uint_least32_t state{}; - char32_t codepoint{}; - - static constexpr uint8_t state_table[]{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 11, 6, 6, - 6, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - - 0, 12, 24, 36, 60, 96, 84, 12, 12, 12, 48, 72, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 12, - 12, 12, 12, 12, 0, 12, 0, 12, 12, 12, 24, 12, 12, 12, 12, 12, 24, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 24, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 36, 12, - 36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 36, 12, 36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 - }; - - TOML_PURE_INLINE_GETTER - constexpr bool error() const noexcept - { - return state == uint_least32_t{ 12u }; - } - - TOML_PURE_INLINE_GETTER - constexpr bool has_code_point() const noexcept - { - return state == uint_least32_t{}; - } - - TOML_PURE_INLINE_GETTER - constexpr bool needs_more_input() const noexcept - { - return !has_code_point() && !error(); - } - - constexpr void operator()(uint8_t byte) noexcept - { - TOML_ASSERT_ASSUME(!error()); - - const auto type = state_table[byte]; - - codepoint = static_cast<char32_t>(has_code_point() ? (uint_least32_t{ 255u } >> type) & byte - : (byte & uint_least32_t{ 63u }) - | (static_cast<uint_least32_t>(codepoint) << 6)); - - state = state_table[state + uint_least32_t{ 256u } + type]; - } - - TOML_ALWAYS_INLINE - constexpr void operator()(char c) noexcept - { - operator()(static_cast<uint8_t>(c)); - } - - TOML_ALWAYS_INLINE - constexpr void reset() noexcept - { - state = {}; - } - }; - - TOML_PURE_GETTER - TOML_ATTR(nonnull) - bool is_ascii(const char* str, size_t len) noexcept; + ; + } + + TOML_CONST_GETTER + constexpr bool is_value_terminator(char32_t c) noexcept { + return is_whitespace(c) || c == U']' || c == U'}' || c == U',' || c == U'#'; + } + + TOML_CONST_GETTER + constexpr bool is_control_character(char c) noexcept { + return c <= '\u001F' || c == '\u007F'; + } + + TOML_CONST_GETTER + constexpr bool is_control_character(char32_t c) noexcept { + return c <= U'\u001F' || c == U'\u007F'; + } + + TOML_CONST_GETTER + constexpr bool is_nontab_control_character(char32_t c) noexcept { + return c <= U'\u0008' || (c >= U'\u000A' && c <= U'\u001F') || c == U'\u007F'; + } + + TOML_CONST_GETTER + constexpr bool is_unicode_surrogate(char32_t c) noexcept { + return c >= 0xD800u && c <= 0xDFFF; + } + + struct utf8_decoder { + // utf8_decoder based on this: https://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> + + uint_least32_t state{}; + char32_t codepoint{}; + + static constexpr uint8_t state_table[]{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 11, 6, + 6, 6, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + + 0, 12, 24, 36, 60, 96, 84, 12, 12, 12, 48, 72, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 0, 12, 12, 12, 12, 12, 0, 12, 0, 12, 12, 12, 24, 12, 12, 12, 12, 12, 24, + 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, + 12, 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 36, 12, 36, 12, 12, 12, 36, 12, 12, + 12, 12, 12, 36, 12, 36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}; + + TOML_PURE_INLINE_GETTER + constexpr bool error() const noexcept { return state == uint_least32_t{12u}; } + + TOML_PURE_INLINE_GETTER + constexpr bool has_code_point() const noexcept { return state == uint_least32_t{}; } + + TOML_PURE_INLINE_GETTER + constexpr bool needs_more_input() const noexcept { return !has_code_point() && !error(); } + + constexpr void operator()(uint8_t byte) noexcept { + TOML_ASSERT_ASSUME(!error()); + + const auto type = state_table[byte]; + + codepoint = static_cast<char32_t>(has_code_point() + ? (uint_least32_t{255u} >> type) & byte + : (byte & uint_least32_t{63u}) | + (static_cast<uint_least32_t>(codepoint) << 6)); + + state = state_table[state + uint_least32_t{256u} + type]; + } + + TOML_ALWAYS_INLINE + constexpr void operator()(char c) noexcept { operator()(static_cast<uint8_t>(c)); } + + TOML_ALWAYS_INLINE + constexpr void reset() noexcept { state = {}; } + }; + + TOML_PURE_GETTER + TOML_ATTR(nonnull) + bool is_ascii(const char* str, size_t len) noexcept; } TOML_IMPL_NAMESPACE_END; diff --git a/vendor/toml++/impl/unicode_autogenerated.hpp b/vendor/toml++/impl/unicode_autogenerated.hpp index cadd9e7..bbec714 100644 --- a/vendor/toml++/impl/unicode_autogenerated.hpp +++ b/vendor/toml++/impl/unicode_autogenerated.hpp @@ -1,176 +1,167 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once -#include "preprocessor.hpp" #include "header_start.hpp" +#include "preprocessor.hpp" /// \cond #if TOML_GCC && TOML_GCC < 9 #pragma GCC push_options -#pragma GCC optimize("O1") // codegen bugs +#pragma GCC optimize("O1") // codegen bugs #endif -// the functions in this namespace block are automatically generated by a tool - they are not meant to be hand-edited - -TOML_IMPL_NAMESPACE_START -{ - TOML_CONST_GETTER - constexpr bool is_ascii_horizontal_whitespace(char32_t c) noexcept - { - return c == U'\t' || c == U' '; - } - - TOML_CONST_GETTER - constexpr bool is_non_ascii_horizontal_whitespace(char32_t c) noexcept - { - // 20 code units from 8 ranges (spanning a search area of 65120) - - if (c < U'\xA0' || c > U'\uFEFF') - return false; - - const auto child_index_0 = (static_cast<uint_least64_t>(c) - 0xA0ull) / 0x3FAull; - if ((1ull << child_index_0) & 0x7FFFFFFFFFFFF75Eull) - return false; - if (c == U'\xA0' || c == U'\u3000' || c == U'\uFEFF') - return true; - switch (child_index_0) - { - case 0x05: return c == U'\u1680' || c == U'\u180E'; - case 0x07: - return (U'\u2000' <= c && c <= U'\u200B') || (U'\u205F' <= c && c <= U'\u2060') || c == U'\u202F'; - default: TOML_UNREACHABLE; - } - - TOML_UNREACHABLE; - } - - TOML_CONST_GETTER - constexpr bool is_ascii_vertical_whitespace(char32_t c) noexcept - { - return c >= U'\n' && c <= U'\r'; - } - - TOML_CONST_GETTER - constexpr bool is_non_ascii_vertical_whitespace(char32_t c) noexcept - { - return (U'\u2028' <= c && c <= U'\u2029') || c == U'\x85'; - } - - TOML_CONST_GETTER - constexpr bool is_ascii_bare_key_character(char32_t c) noexcept - { -#if TOML_LANG_UNRELEASED // toml/issues/644 ('+' in bare keys) - if TOML_UNLIKELY(c == U'+') - return true; +// the functions in this namespace block are automatically generated by a tool - they are not meant +// to be hand-edited + +TOML_IMPL_NAMESPACE_START { + TOML_CONST_GETTER + constexpr bool is_ascii_horizontal_whitespace(char32_t c) noexcept { + return c == U'\t' || c == U' '; + } + + TOML_CONST_GETTER + constexpr bool is_non_ascii_horizontal_whitespace(char32_t c) noexcept { + // 20 code units from 8 ranges (spanning a search area of 65120) + + if (c < U'\xA0' || c > U'\uFEFF') return false; + + const auto child_index_0 = (static_cast<uint_least64_t>(c) - 0xA0ull) / 0x3FAull; + if ((1ull << child_index_0) & 0x7FFFFFFFFFFFF75Eull) return false; + if (c == U'\xA0' || c == U'\u3000' || c == U'\uFEFF') return true; + switch (child_index_0) { + case 0x05: + return c == U'\u1680' || c == U'\u180E'; + case 0x07: + return (U'\u2000' <= c && c <= U'\u200B') || (U'\u205F' <= c && c <= U'\u2060') || + c == U'\u202F'; + default: + TOML_UNREACHABLE; + } + + TOML_UNREACHABLE; + } + + TOML_CONST_GETTER + constexpr bool is_ascii_vertical_whitespace(char32_t c) noexcept { + return c >= U'\n' && c <= U'\r'; + } + + TOML_CONST_GETTER + constexpr bool is_non_ascii_vertical_whitespace(char32_t c) noexcept { + return (U'\u2028' <= c && c <= U'\u2029') || c == U'\x85'; + } + + TOML_CONST_GETTER + constexpr bool is_ascii_bare_key_character(char32_t c) noexcept { +#if TOML_LANG_UNRELEASED // toml/issues/644 ('+' in bare keys) + if TOML_UNLIKELY (c == U'+') return true; #endif - // 64 code units from 5 ranges (spanning a search area of 78) - - if (c < U'-' || c > U'z') - return false; - - return (((static_cast<uint_least64_t>(c) - 0x2Dull) / 0x40ull) != 0ull) - || ((1ull << (static_cast<uint_least64_t>(c) - 0x2Dull)) & 0xFFF43FFFFFF01FF9ull); - } - -#if TOML_LANG_UNRELEASED // toml/pull/891 (unicode bare keys) - - TOML_CONST_GETTER - constexpr bool is_non_ascii_bare_key_character(char32_t c) noexcept - { - // 971732 code units from 16 ranges (spanning a search area of 982862) - - if (c < U'\xB2' || c > U'\U000EFFFF') - return false; - - const auto child_index_0 = (static_cast<uint_least64_t>(c) - 0xB2ull) / 0x3BFEull; - if ((1ull << child_index_0) & 0xFFFFFFFFFFFFFFE6ull) - return true; - switch (child_index_0) - { - case 0x00: // [0] 00B2 - 3CAF - { - // 12710 code units from 13 ranges (spanning a search area of 15358) - - TOML_ASSUME(c >= U'\xB2' && c <= U'\u3CAF'); - - constexpr uint_least64_t bitmask_table_1[] = { - 0xFFFFFFDFFFFFDC83u, 0xFFFFFFFFFFFFFFDFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFEFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0x000000000C003FFFu, 0xC000000000006000u, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x000000003FFFFFFFu, - 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, - 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, - 0x0000000000000000u, 0x0000000000000000u, 0xFFFFC00000000000u, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0x0000000000003FFFu, 0x0000000000000000u, 0x0000000000000000u, - 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, - 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, - 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, - 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, - 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, - 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, - 0x0000000000000000u, 0xFFFFFFFFFFFFC000u, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0x3FFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFF8000u, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, - 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x3FFFFFFFFFFFFFFFu, - }; - return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xB2ull) / 0x40ull] - & (0x1ull << ((static_cast<uint_least64_t>(c) - 0xB2ull) % 0x40ull)); - } - case 0x03: return c <= U'\uD7FF'; - case 0x04: - return (U'\uF900' <= c && c <= U'\uFDCF') || (U'\uFDF0' <= c && c <= U'\uFFFD') || U'\U00010000' <= c; - default: TOML_UNREACHABLE; - } - - TOML_UNREACHABLE; - } - -#endif // TOML_LANG_UNRELEASED + // 64 code units from 5 ranges (spanning a search area of 78) + + if (c < U'-' || c > U'z') return false; + + return (((static_cast<uint_least64_t>(c) - 0x2Dull) / 0x40ull) != 0ull) || + ((1ull << (static_cast<uint_least64_t>(c) - 0x2Dull)) & 0xFFF43FFFFFF01FF9ull); + } + +#if TOML_LANG_UNRELEASED // toml/pull/891 (unicode bare keys) + + TOML_CONST_GETTER + constexpr bool is_non_ascii_bare_key_character(char32_t c) noexcept { + // 971732 code units from 16 ranges (spanning a search area of 982862) + + if (c < U'\xB2' || c > U'\U000EFFFF') return false; + + const auto child_index_0 = (static_cast<uint_least64_t>(c) - 0xB2ull) / 0x3BFEull; + if ((1ull << child_index_0) & 0xFFFFFFFFFFFFFFE6ull) return true; + switch (child_index_0) { + case 0x00: // [0] 00B2 - 3CAF + { + // 12710 code units from 13 ranges (spanning a search area of 15358) + + TOML_ASSUME(c >= U'\xB2' && c <= U'\u3CAF'); + + constexpr uint_least64_t bitmask_table_1[] = { + 0xFFFFFFDFFFFFDC83u, 0xFFFFFFFFFFFFFFDFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFEFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0x000000000C003FFFu, 0xC000000000006000u, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x000000003FFFFFFFu, + 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, + 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, + 0x0000000000000000u, 0x0000000000000000u, 0xFFFFC00000000000u, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0x0000000000003FFFu, 0x0000000000000000u, 0x0000000000000000u, + 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, + 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, + 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, + 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, + 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, + 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, 0x0000000000000000u, + 0x0000000000000000u, 0xFFFFFFFFFFFFC000u, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0x3FFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFF8000u, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, + 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFFu, 0x3FFFFFFFFFFFFFFFu, + }; + return bitmask_table_1[(static_cast<uint_least64_t>(c) - 0xB2ull) / 0x40ull] & + (0x1ull << ((static_cast<uint_least64_t>(c) - 0xB2ull) % 0x40ull)); + } + case 0x03: + return c <= U'\uD7FF'; + case 0x04: + return (U'\uF900' <= c && c <= U'\uFDCF') || (U'\uFDF0' <= c && c <= U'\uFFFD') || + U'\U00010000' <= c; + default: + TOML_UNREACHABLE; + } + + TOML_UNREACHABLE; + } + +#endif // TOML_LANG_UNRELEASED } TOML_IMPL_NAMESPACE_END; diff --git a/vendor/toml++/impl/value.hpp b/vendor/toml++/impl/value.hpp index 6fb35dc..964e90d 100644 --- a/vendor/toml++/impl/value.hpp +++ b/vendor/toml++/impl/value.hpp @@ -1,14 +1,14 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "date_time.hpp" +#include "header_start.hpp" #include "node.hpp" #include "print_to_stream.hpp" #include "std_utility.hpp" -#include "header_start.hpp" TOML_DISABLE_ARITHMETIC_WARNINGS; /// \cond @@ -74,1136 +74,892 @@ TOML_DISABLE_ARITHMETIC_WARNINGS; /// \endcond /// \cond -TOML_IMPL_NAMESPACE_START -{ - template <typename T, typename...> - struct native_value_maker - { - template <typename... Args> - TOML_NODISCARD - static T make(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args&&...>) - { - if constexpr (std::is_aggregate_v<T>) - return T{ static_cast<Args&&>(args)... }; - else - return T(static_cast<Args&&>(args)...); - } - }; - - template <typename T> - struct native_value_maker<T, T> - { - template <typename U> - TOML_NODISCARD - TOML_ALWAYS_INLINE - static U&& make(U&& val) noexcept - { - return static_cast<U&&>(val); - } - }; +TOML_IMPL_NAMESPACE_START { + template <typename T, typename...> + struct native_value_maker { + template <typename... Args> + TOML_NODISCARD static T make(Args&&... args) noexcept( + std::is_nothrow_constructible_v<T, Args&&...>) { + if constexpr (std::is_aggregate_v<T>) + return T{static_cast<Args&&>(args)...}; + else + return T(static_cast<Args&&>(args)...); + } + }; + + template <typename T> + struct native_value_maker<T, T> { + template <typename U> + TOML_NODISCARD TOML_ALWAYS_INLINE static U&& make(U&& val) noexcept { + return static_cast<U&&>(val); + } + }; #if TOML_HAS_CHAR8 || TOML_ENABLE_WINDOWS_COMPAT - struct string_maker - { - template <typename T> - TOML_NODISCARD - static std::string make(T&& arg) - { - using arg_type = std::decay_t<T>; + struct string_maker { + template <typename T> + TOML_NODISCARD static std::string make(T&& arg) { + using arg_type = std::decay_t<T>; #if TOML_HAS_CHAR8 - if constexpr (is_one_of<arg_type, char8_t*, const char8_t*>) - { - return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg))); - } - if constexpr (is_one_of<arg_type, std::u8string, std::u8string_view>) - { - return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg.data())), - arg.length()); - } + if constexpr (is_one_of<arg_type, char8_t*, const char8_t*>) { + return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg))); + } + if constexpr (is_one_of<arg_type, std::u8string, std::u8string_view>) { + return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg.data())), + arg.length()); + } #endif #if TOML_ENABLE_WINDOWS_COMPAT - if constexpr (is_wide_string<arg_type>) - { - return narrow(static_cast<T&&>(arg)); - } + if constexpr (is_wide_string<arg_type>) { + return narrow(static_cast<T&&>(arg)); + } #endif - } - }; + } + }; #if TOML_HAS_CHAR8 - template <> - struct native_value_maker<std::string, char8_t*> : string_maker - {}; - template <> - struct native_value_maker<std::string, const char8_t*> : string_maker - {}; - template <> - struct native_value_maker<std::string, std::u8string> : string_maker - {}; - template <> - struct native_value_maker<std::string, std::u8string_view> : string_maker - {}; -#endif // TOML_HAS_CHAR8 + template <> + struct native_value_maker<std::string, char8_t*> : string_maker {}; + template <> + struct native_value_maker<std::string, const char8_t*> : string_maker {}; + template <> + struct native_value_maker<std::string, std::u8string> : string_maker {}; + template <> + struct native_value_maker<std::string, std::u8string_view> : string_maker {}; +#endif // TOML_HAS_CHAR8 #if TOML_ENABLE_WINDOWS_COMPAT - template <> - struct native_value_maker<std::string, wchar_t*> : string_maker - {}; - template <> - struct native_value_maker<std::string, const wchar_t*> : string_maker - {}; - template <> - struct native_value_maker<std::string, std::wstring> : string_maker - {}; - template <> - struct native_value_maker<std::string, std::wstring_view> : string_maker - {}; -#endif // TOML_ENABLE_WINDOWS_COMPAT - -#endif // TOML_HAS_CHAR8 || TOML_ENABLE_WINDOWS_COMPAT - - template <typename T> - TOML_CONST_GETTER - inline optional<T> node_integer_cast(int64_t val) noexcept - { - static_assert(node_type_of<T> == node_type::integer); - static_assert(!is_cvref<T>); - - using traits = value_traits<T>; - if constexpr (!traits::is_signed) - { - if constexpr ((sizeof(T) * CHAR_BIT) < 63) // 63 bits == int64_max - { - using common_t = decltype(int64_t{} + T{}); - if (val < int64_t{} || static_cast<common_t>(val) > static_cast<common_t>(traits::max)) - return {}; - } - else - { - if (val < int64_t{}) - return {}; - } - } - else - { - if (val < traits::min || val > traits::max) - return {}; - } - return { static_cast<T>(val) }; - } - - template <typename...> - struct value_variadic_ctor_allowed : std::true_type - {}; - - template <typename T, typename... Args> - struct value_variadic_ctor_allowed<value<T>, value<T>, Args...> : std::false_type - {}; + template <> + struct native_value_maker<std::string, wchar_t*> : string_maker {}; + template <> + struct native_value_maker<std::string, const wchar_t*> : string_maker {}; + template <> + struct native_value_maker<std::string, std::wstring> : string_maker {}; + template <> + struct native_value_maker<std::string, std::wstring_view> : string_maker {}; +#endif // TOML_ENABLE_WINDOWS_COMPAT + +#endif // TOML_HAS_CHAR8 || TOML_ENABLE_WINDOWS_COMPAT + + template <typename T> + TOML_CONST_GETTER inline optional<T> node_integer_cast(int64_t val) noexcept { + static_assert(node_type_of<T> == node_type::integer); + static_assert(!is_cvref<T>); + + using traits = value_traits<T>; + if constexpr (!traits::is_signed) { + if constexpr ((sizeof(T) * CHAR_BIT) < 63) // 63 bits == int64_max + { + using common_t = decltype(int64_t{} + T{}); + if (val < int64_t{} || static_cast<common_t>(val) > static_cast<common_t>(traits::max)) + return {}; + } else { + if (val < int64_t{}) return {}; + } + } else { + if (val < traits::min || val > traits::max) return {}; + } + return {static_cast<T>(val)}; + } + + template <typename...> + struct value_variadic_ctor_allowed : std::true_type {}; + + template <typename T, typename... Args> + struct value_variadic_ctor_allowed<value<T>, value<T>, Args...> : std::false_type {}; } TOML_IMPL_NAMESPACE_END; /// \endcond -TOML_NAMESPACE_START -{ - /// \brief A TOML value. - /// - /// \tparam ValueType The value's native TOML data type. Can be one of: - /// - std::string - /// - toml::date - /// - toml::time - /// - toml::date_time - /// - int64_t - /// - double - /// - bool - template <typename ValueType> - class value : public node - { - static_assert(impl::is_native<ValueType> && !impl::is_cvref<ValueType>, - "A toml::value<> must model one of the native TOML value types:" TOML_SA_NATIVE_VALUE_TYPE_LIST); - - private: - /// \cond - - friend class TOML_PARSER_TYPENAME; - - template <typename T, typename U> - TOML_CONST_INLINE_GETTER - static auto as_value([[maybe_unused]] U* ptr) noexcept - { - if constexpr (std::is_same_v<value_type, T>) - return ptr; - else - return nullptr; - } - - ValueType val_; - value_flags flags_ = value_flags::none; - - /// \endcond - - public: - /// \brief The value's underlying data type. - using value_type = ValueType; - - /// \brief A type alias for 'value arguments'. - /// \details This differs according to the value's type argument: - /// - ints, floats, booleans: `value_type` - /// - strings: `string_view` - /// - everything else: `const value_type&` - using value_arg = POXY_IMPLEMENTATION_DETAIL( - std::conditional_t< - std::is_same_v<value_type, std::string>, - std::string_view, - std::conditional_t<impl::is_one_of<value_type, double, int64_t, bool>, value_type, const value_type&>>); - - /// \brief Constructs a toml value. - /// - /// \tparam Args Constructor argument types. - /// \param args Arguments to forward to the internal value's constructor. - TOML_HIDDEN_CONSTRAINT( - (impl::value_variadic_ctor_allowed<value<ValueType>, impl::remove_cvref<Args>...>::value), - typename... Args) - TOML_NODISCARD_CTOR - explicit value(Args&&... args) noexcept(noexcept(value_type( - impl::native_value_maker<value_type, std::decay_t<Args>...>::make(static_cast<Args&&>(args)...)))) - : val_(impl::native_value_maker<value_type, std::decay_t<Args>...>::make(static_cast<Args&&>(args)...)) - { +TOML_NAMESPACE_START { + /// \brief A TOML value. + /// + /// \tparam ValueType The value's native TOML data type. Can be one of: + /// - std::string + /// - toml::date + /// - toml::time + /// - toml::date_time + /// - int64_t + /// - double + /// - bool + template <typename ValueType> + class value : public node { + static_assert(impl::is_native<ValueType> && !impl::is_cvref<ValueType>, + "A toml::value<> must model one of the native TOML value " + "types:" TOML_SA_NATIVE_VALUE_TYPE_LIST); + + private: + /// \cond + + friend class TOML_PARSER_TYPENAME; + + template <typename T, typename U> + TOML_CONST_INLINE_GETTER static auto as_value([[maybe_unused]] U* ptr) noexcept { + if constexpr (std::is_same_v<value_type, T>) + return ptr; + else + return nullptr; + } + + ValueType val_; + value_flags flags_ = value_flags::none; + + /// \endcond + + public: + /// \brief The value's underlying data type. + using value_type = ValueType; + + /// \brief A type alias for 'value arguments'. + /// \details This differs according to the value's type argument: + /// - ints, floats, booleans: `value_type` + /// - strings: `string_view` + /// - everything else: `const value_type&` + using value_arg = POXY_IMPLEMENTATION_DETAIL( + std::conditional_t<std::is_same_v<value_type, std::string>, std::string_view, + std::conditional_t<impl::is_one_of<value_type, double, int64_t, bool>, + value_type, const value_type&>>); + + /// \brief Constructs a toml value. + /// + /// \tparam Args Constructor argument types. + /// \param args Arguments to forward to the internal value's constructor. + TOML_HIDDEN_CONSTRAINT( + (impl::value_variadic_ctor_allowed<value<ValueType>, impl::remove_cvref<Args>...>::value), + typename... Args) + TOML_NODISCARD_CTOR + explicit value(Args&&... args) noexcept( + noexcept(value_type(impl::native_value_maker<value_type, std::decay_t<Args>...>::make( + static_cast<Args&&>(args)...)))) + : val_(impl::native_value_maker<value_type, std::decay_t<Args>...>::make( + static_cast<Args&&>(args)...)) { #if TOML_LIFETIME_HOOKS - TOML_VALUE_CREATED; + TOML_VALUE_CREATED; #endif - } - - /// \brief Copy constructor. - TOML_NODISCARD_CTOR - value(const value& other) noexcept // - : node(other), - val_{ other.val_ }, - flags_{ other.flags_ } - { + } + + /// \brief Copy constructor. + TOML_NODISCARD_CTOR + value(const value& other) noexcept // + : node(other), val_{other.val_}, flags_{other.flags_} { #if TOML_LIFETIME_HOOKS - TOML_VALUE_CREATED; + TOML_VALUE_CREATED; #endif - } - - /// \brief Copy constructor with flags override. - TOML_NODISCARD_CTOR - value(const value& other, value_flags flags) noexcept // - : node(other), - val_{ other.val_ }, - flags_{ flags == preserve_source_value_flags ? other.flags_ : flags } - { + } + + /// \brief Copy constructor with flags override. + TOML_NODISCARD_CTOR + value(const value& other, value_flags flags) noexcept // + : node(other), + val_{other.val_}, + flags_{flags == preserve_source_value_flags ? other.flags_ : flags} { #if TOML_LIFETIME_HOOKS - TOML_VALUE_CREATED; + TOML_VALUE_CREATED; #endif - } - - /// \brief Move constructor. - TOML_NODISCARD_CTOR - value(value&& other) noexcept // - : node(std::move(other)), - val_{ std::move(other.val_) }, - flags_{ std::exchange(other.flags_, value_flags{}) } - { + } + + /// \brief Move constructor. + TOML_NODISCARD_CTOR + value(value&& other) noexcept // + : node(std::move(other)), + val_{std::move(other.val_)}, + flags_{std::exchange(other.flags_, value_flags{})} { #if TOML_LIFETIME_HOOKS - TOML_VALUE_CREATED; + TOML_VALUE_CREATED; #endif - } - - /// \brief Move constructor with flags override. - TOML_NODISCARD_CTOR - value(value&& other, value_flags flags) noexcept // - : node(std::move(other)), - val_{ std::move(other.val_) }, - flags_{ flags == preserve_source_value_flags ? other.flags_ : flags } - { + } + + /// \brief Move constructor with flags override. + TOML_NODISCARD_CTOR + value(value&& other, value_flags flags) noexcept // + : node(std::move(other)), + val_{std::move(other.val_)}, + flags_{flags == preserve_source_value_flags ? other.flags_ : flags} { #if TOML_LIFETIME_HOOKS - TOML_VALUE_CREATED; + TOML_VALUE_CREATED; #endif - other.flags_ = {}; - } - - /// \brief Copy-assignment operator. - value& operator=(const value& rhs) noexcept - { - node::operator=(rhs); - val_ = rhs.val_; - flags_ = rhs.flags_; - return *this; - } - - /// \brief Move-assignment operator. - value& operator=(value&& rhs) noexcept - { - if (&rhs != this) - { - node::operator=(std::move(rhs)); - val_ = std::move(rhs.val_); - flags_ = std::exchange(rhs.flags_, value_flags{}); - } - return *this; - } + other.flags_ = {}; + } + + /// \brief Copy-assignment operator. + value& operator=(const value& rhs) noexcept { + node::operator=(rhs); + val_ = rhs.val_; + flags_ = rhs.flags_; + return *this; + } + + /// \brief Move-assignment operator. + value& operator=(value&& rhs) noexcept { + if (&rhs != this) { + node::operator=(std::move(rhs)); + val_ = std::move(rhs.val_); + flags_ = std::exchange(rhs.flags_, value_flags{}); + } + return *this; + } #if TOML_LIFETIME_HOOKS - ~value() noexcept - { - TOML_VALUE_DESTROYED; - } + ~value() noexcept { TOML_VALUE_DESTROYED; } #endif - /// \name Type checks - /// @{ - - /// \brief Returns the value's node type identifier. - /// - /// \returns One of: - /// - node_type::string - /// - node_type::integer - /// - node_type::floating_point - /// - node_type::boolean - /// - node_type::date - /// - node_type::time - /// - node_type::date_time - TOML_CONST_INLINE_GETTER - node_type type() const noexcept final - { - return impl::node_type_of<value_type>; - } - - TOML_PURE_GETTER - bool is_homogeneous(node_type ntype) const noexcept final - { - return ntype == node_type::none || ntype == impl::node_type_of<value_type>; - } - - TOML_PURE_GETTER - bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final - { - if (ntype != node_type::none && ntype != impl::node_type_of<value_type>) - { - first_nonmatch = this; - return false; - } - return true; - } - - TOML_PURE_GETTER - bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final - { - if (ntype != node_type::none && ntype != impl::node_type_of<value_type>) - { - first_nonmatch = this; - return false; - } - return true; - } - - /// \cond - template <typename ElemType = void> - TOML_PURE_GETTER - bool is_homogeneous() const noexcept - { - using type = impl::remove_cvref<impl::unwrap_node<ElemType>>; - static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>, - "The template type argument of value::is_homogeneous() must be void or one " - "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); - - if constexpr (std::is_void_v<type>) - return true; - else - return impl::node_type_of<type> == impl::node_type_of<value_type>; - } - /// \endcond - - /// \brief Returns `false`. - TOML_CONST_INLINE_GETTER - bool is_table() const noexcept final - { - return false; - } - - /// \brief Returns `false`. - TOML_CONST_INLINE_GETTER - bool is_array() const noexcept final - { - return false; - } - - /// \brief Returns `false`. - TOML_CONST_INLINE_GETTER - bool is_array_of_tables() const noexcept final - { - return false; - } - - /// \brief Returns `true`. - TOML_CONST_INLINE_GETTER - bool is_value() const noexcept final - { - return true; - } - - /// \brief Returns `true` if the #value_type is std::string. - TOML_CONST_INLINE_GETTER - bool is_string() const noexcept final - { - return std::is_same_v<value_type, std::string>; - } - - /// \brief Returns `true` if the #value_type is int64_t. - TOML_CONST_INLINE_GETTER - bool is_integer() const noexcept final - { - return std::is_same_v<value_type, int64_t>; - } - - /// \brief Returns `true` if the #value_type is `double`. - TOML_CONST_INLINE_GETTER - bool is_floating_point() const noexcept final - { - return std::is_same_v<value_type, double>; - } - - /// \brief Returns `true` if the #value_type is int64_t or `double`. - TOML_CONST_INLINE_GETTER - bool is_number() const noexcept final - { - return impl::is_one_of<value_type, int64_t, double>; - } - - /// \brief Returns `true` if the #value_type is `bool`. - TOML_CONST_INLINE_GETTER - bool is_boolean() const noexcept final - { - return std::is_same_v<value_type, bool>; - } - - /// \brief Returns `true` if the #value_type is toml::date. - TOML_CONST_INLINE_GETTER - bool is_date() const noexcept final - { - return std::is_same_v<value_type, date>; - } - - /// \brief Returns `true` if the #value_type is toml::time. - TOML_CONST_INLINE_GETTER - bool is_time() const noexcept final - { - return std::is_same_v<value_type, time>; - } - - /// \brief Returns `true` if the #value_type is toml_date_time. - TOML_CONST_INLINE_GETTER - bool is_date_time() const noexcept final - { - return std::is_same_v<value_type, date_time>; - } - - /// @} - - /// \name Type casts - /// @{ - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - table* as_table() noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - array* as_array() noexcept final - { - return nullptr; - } - - /// \brief Returns a pointer to the value if it is a value<std::string>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - value<std::string>* as_string() noexcept final - { - return as_value<std::string>(this); - } - - /// \brief Returns a pointer to the value if it is a value<int64_t>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - value<int64_t>* as_integer() noexcept final - { - return as_value<int64_t>(this); - } - - /// \brief Returns a pointer to the value if it is a value<double>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - value<double>* as_floating_point() noexcept final - { - return as_value<double>(this); - } - - /// \brief Returns a pointer to the value if it is a value<bool>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - value<bool>* as_boolean() noexcept final - { - return as_value<bool>(this); - } - - /// \brief Returns a pointer to the value if it is a value<date>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - value<date>* as_date() noexcept final - { - return as_value<date>(this); - } - - /// \brief Returns a pointer to the value if it is a value<time>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - value<time>* as_time() noexcept final - { - return as_value<time>(this); - } - - /// \brief Returns a pointer to the value if it is a value<date_time>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - value<date_time>* as_date_time() noexcept final - { - return as_value<date_time>(this); - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const table* as_table() const noexcept final - { - return nullptr; - } - - /// \brief Returns `nullptr`. - TOML_CONST_INLINE_GETTER - const array* as_array() const noexcept final - { - return nullptr; - } - - /// \brief Returns a const-qualified pointer to the value if it is a value<std::string>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - const value<std::string>* as_string() const noexcept final - { - return as_value<std::string>(this); - } - - /// \brief Returns a const-qualified pointer to the value if it is a value<int64_t>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - const value<int64_t>* as_integer() const noexcept final - { - return as_value<int64_t>(this); - } - - /// \brief Returns a const-qualified pointer to the value if it is a value<double>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - const value<double>* as_floating_point() const noexcept final - { - return as_value<double>(this); - } - - /// \brief Returns a const-qualified pointer to the value if it is a value<bool>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - const value<bool>* as_boolean() const noexcept final - { - return as_value<bool>(this); - } - - /// \brief Returns a const-qualified pointer to the value if it is a value<date>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - const value<date>* as_date() const noexcept final - { - return as_value<date>(this); - } - - /// \brief Returns a const-qualified pointer to the value if it is a value<time>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - const value<time>* as_time() const noexcept final - { - return as_value<time>(this); - } - - /// \brief Returns a const-qualified pointer to the value if it is a value<date_time>, otherwise `nullptr`. - TOML_CONST_INLINE_GETTER - const value<date_time>* as_date_time() const noexcept final - { - return as_value<date_time>(this); - } - - /// @} - - /// \name Value retrieval - /// @{ - - /// \brief Returns a reference to the underlying value. - TOML_PURE_INLINE_GETTER - value_type& get() & noexcept - { - return val_; - } - - /// \brief Returns a reference to the underlying value (rvalue overload). - TOML_PURE_INLINE_GETTER - value_type&& get() && noexcept - { - return static_cast<value_type&&>(val_); - } - - /// \brief Returns a reference to the underlying value (const overload). - TOML_PURE_INLINE_GETTER - const value_type& get() const& noexcept - { - return val_; - } - - /// \brief Returns a reference to the underlying value (const rvalue overload). - TOML_PURE_INLINE_GETTER - const value_type&& get() const&& noexcept - { - return static_cast<const value_type&&>(val_); - } - - /// \brief Returns a reference to the underlying value. - TOML_PURE_INLINE_GETTER - value_type& operator*() & noexcept - { - return val_; - } - - /// \brief Returns a reference to the underlying value (rvalue overload). - TOML_PURE_INLINE_GETTER - value_type&& operator*() && noexcept - { - return static_cast<value_type&&>(val_); - } - - /// \brief Returns a reference to the underlying value (const overload). - TOML_PURE_INLINE_GETTER - const value_type& operator*() const& noexcept - { - return val_; - } - - /// \brief Returns a reference to the underlying value (const rvalue overload). - TOML_PURE_INLINE_GETTER - const value_type&& operator*() const&& noexcept - { - return static_cast<const value_type&&>(val_); - } - - /// \brief Returns a reference to the underlying value. - TOML_PURE_INLINE_GETTER - explicit operator value_type&() & noexcept - { - return val_; - } - - /// \brief Returns a reference to the underlying value (rvalue overload). - TOML_PURE_INLINE_GETTER - explicit operator value_type&&() && noexcept - { - return static_cast<value_type&&>(val_); - } - - /// \brief Returns a reference to the underlying value (const overload). - TOML_PURE_INLINE_GETTER - explicit operator const value_type&() const& noexcept - { - return val_; - } - - /// \brief Returns a reference to the underlying value (const rvalue overload). - TOML_PURE_INLINE_GETTER - explicit operator const value_type&&() && noexcept - { - return static_cast<const value_type&&>(val_); - } - - /// \brief Returns a pointer to the underlying value. - /// - /// \availability This operator is only available when #value_type is a class/struct. - TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type) - TOML_PURE_INLINE_GETTER - value_type* operator->() noexcept - { - return &val_; - } - - /// \brief Returns a pointer to the underlying value (const overload). - /// - /// \availability This operator is only available when #value_type is a class/struct. - TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type) - TOML_PURE_INLINE_GETTER - const value_type* operator->() const noexcept - { - return &val_; - } - - /// @} - - /// \name Metadata - /// @{ - - /// \brief Returns the metadata flags associated with this value. - TOML_NODISCARD - value_flags flags() const noexcept - { - return flags_; - } - - /// \brief Sets the metadata flags associated with this value. - /// \returns A reference to the value object. - value& flags(value_flags new_flags) noexcept - { - flags_ = new_flags; - return *this; - } - - /// @} - - /// \brief Value-assignment operator. - value& operator=(value_arg rhs) noexcept - { - if constexpr (std::is_same_v<value_type, std::string>) - val_.assign(rhs); - else - val_ = rhs; - return *this; - } - - TOML_CONSTRAINED_TEMPLATE((std::is_same_v<T, std::string>), typename T = value_type) - value& operator=(std::string&& rhs) noexcept - { - val_ = std::move(rhs); - return *this; - } - - /// \name Equality and Comparison - /// @{ - - /// \brief Value equality operator. - TOML_PURE_GETTER - friend bool operator==(const value& lhs, value_arg rhs) noexcept - { - if constexpr (std::is_same_v<value_type, double>) - { - const auto lhs_nan = impl::fpclassify(lhs.val_) == impl::fp_class::nan; - const auto rhs_nan = impl::fpclassify(rhs) == impl::fp_class::nan; - if (lhs_nan != rhs_nan) - return false; - if (lhs_nan) - return true; - } - return lhs.val_ == rhs; - } - TOML_ASYMMETRICAL_EQUALITY_OPS(const value&, value_arg, ); - - /// \brief Value less-than operator. - TOML_PURE_GETTER - friend bool operator<(const value& lhs, value_arg rhs) noexcept - { - return lhs.val_ < rhs; - } - - /// \brief Value less-than operator. - TOML_PURE_GETTER - friend bool operator<(value_arg lhs, const value& rhs) noexcept - { - return lhs < rhs.val_; - } - - /// \brief Value less-than-or-equal-to operator. - TOML_PURE_GETTER - friend bool operator<=(const value& lhs, value_arg rhs) noexcept - { - return lhs.val_ <= rhs; - } - - /// \brief Value less-than-or-equal-to operator. - TOML_PURE_GETTER - friend bool operator<=(value_arg lhs, const value& rhs) noexcept - { - return lhs <= rhs.val_; - } - - /// \brief Value greater-than operator. - TOML_PURE_GETTER - friend bool operator>(const value& lhs, value_arg rhs) noexcept - { - return lhs.val_ > rhs; - } - - /// \brief Value greater-than operator. - TOML_PURE_GETTER - friend bool operator>(value_arg lhs, const value& rhs) noexcept - { - return lhs > rhs.val_; - } - - /// \brief Value greater-than-or-equal-to operator. - TOML_PURE_GETTER - friend bool operator>=(const value& lhs, value_arg rhs) noexcept - { - return lhs.val_ >= rhs; - } - - /// \brief Value greater-than-or-equal-to operator. - TOML_PURE_GETTER - friend bool operator>=(value_arg lhs, const value& rhs) noexcept - { - return lhs >= rhs.val_; - } - - /// \brief Equality operator. - /// - /// \param lhs The LHS value. - /// \param rhs The RHS value. - /// - /// \returns True if the values were of the same type and contained the same value. - template <typename T> - TOML_PURE_GETTER - friend bool operator==(const value& lhs, const value<T>& rhs) noexcept - { - if constexpr (std::is_same_v<value_type, T>) - return lhs == rhs.val_; // calls asymmetrical value-equality operator defined above - else - return false; - } - - /// \brief Inequality operator. - /// - /// \param lhs The LHS value. - /// \param rhs The RHS value. - /// - /// \returns True if the values were not of the same type, or did not contain the same value. - template <typename T> - TOML_PURE_INLINE_GETTER - friend bool operator!=(const value& lhs, const value<T>& rhs) noexcept - { - return !(lhs == rhs); - } - - /// \brief Less-than operator. - /// - /// \param lhs The LHS toml::value. - /// \param rhs The RHS toml::value. - /// - /// \returns \conditional_return{Same value types} - /// `lhs.get() < rhs.get()` - /// \conditional_return{Different value types} - /// `lhs.type() < rhs.type()` - template <typename T> - TOML_PURE_GETTER - friend bool operator<(const value& lhs, const value<T>& rhs) noexcept - { - if constexpr (std::is_same_v<value_type, T>) - return lhs.val_ < rhs.val_; - else - return impl::node_type_of<value_type> < impl::node_type_of<T>; - } - - /// \brief Less-than-or-equal-to operator. - /// - /// \param lhs The LHS toml::value. - /// \param rhs The RHS toml::value. - /// - /// \returns \conditional_return{Same value types} - /// `lhs.get() <= rhs.get()` - /// \conditional_return{Different value types} - /// `lhs.type() <= rhs.type()` - template <typename T> - TOML_PURE_GETTER - friend bool operator<=(const value& lhs, const value<T>& rhs) noexcept - { - if constexpr (std::is_same_v<value_type, T>) - return lhs.val_ <= rhs.val_; - else - return impl::node_type_of<value_type> <= impl::node_type_of<T>; - } - - /// \brief Greater-than operator. - /// - /// \param lhs The LHS toml::value. - /// \param rhs The RHS toml::value. - /// - /// \returns \conditional_return{Same value types} - /// `lhs.get() > rhs.get()` - /// \conditional_return{Different value types} - /// `lhs.type() > rhs.type()` - template <typename T> - TOML_PURE_GETTER - friend bool operator>(const value& lhs, const value<T>& rhs) noexcept - { - if constexpr (std::is_same_v<value_type, T>) - return lhs.val_ > rhs.val_; - else - return impl::node_type_of<value_type> > impl::node_type_of<T>; - } - - /// \brief Greater-than-or-equal-to operator. - /// - /// \param lhs The LHS toml::value. - /// \param rhs The RHS toml::value. - /// - /// \returns \conditional_return{Same value types} - /// `lhs.get() >= rhs.get()` - /// \conditional_return{Different value types} - /// `lhs.type() >= rhs.type()` - template <typename T> - TOML_PURE_GETTER - friend bool operator>=(const value& lhs, const value<T>& rhs) noexcept - { - if constexpr (std::is_same_v<value_type, T>) - return lhs.val_ >= rhs.val_; - else - return impl::node_type_of<value_type> >= impl::node_type_of<T>; - } - - /// @} + /// \name Type checks + /// @{ + + /// \brief Returns the value's node type identifier. + /// + /// \returns One of: + /// - node_type::string + /// - node_type::integer + /// - node_type::floating_point + /// - node_type::boolean + /// - node_type::date + /// - node_type::time + /// - node_type::date_time + TOML_CONST_INLINE_GETTER + node_type type() const noexcept final { return impl::node_type_of<value_type>; } + + TOML_PURE_GETTER + bool is_homogeneous(node_type ntype) const noexcept final { + return ntype == node_type::none || ntype == impl::node_type_of<value_type>; + } + + TOML_PURE_GETTER + bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final { + if (ntype != node_type::none && ntype != impl::node_type_of<value_type>) { + first_nonmatch = this; + return false; + } + return true; + } + + TOML_PURE_GETTER + bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final { + if (ntype != node_type::none && ntype != impl::node_type_of<value_type>) { + first_nonmatch = this; + return false; + } + return true; + } + + /// \cond + template <typename ElemType = void> + TOML_PURE_GETTER bool is_homogeneous() const noexcept { + using type = impl::remove_cvref<impl::unwrap_node<ElemType>>; + static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>, + "The template type argument of value::is_homogeneous() must be void or one " + "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); + + if constexpr (std::is_void_v<type>) + return true; + else + return impl::node_type_of<type> == impl::node_type_of<value_type>; + } + /// \endcond + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_table() const noexcept final { return false; } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_array() const noexcept final { return false; } + + /// \brief Returns `false`. + TOML_CONST_INLINE_GETTER + bool is_array_of_tables() const noexcept final { return false; } + + /// \brief Returns `true`. + TOML_CONST_INLINE_GETTER + bool is_value() const noexcept final { return true; } + + /// \brief Returns `true` if the #value_type is std::string. + TOML_CONST_INLINE_GETTER + bool is_string() const noexcept final { return std::is_same_v<value_type, std::string>; } + + /// \brief Returns `true` if the #value_type is int64_t. + TOML_CONST_INLINE_GETTER + bool is_integer() const noexcept final { return std::is_same_v<value_type, int64_t>; } + + /// \brief Returns `true` if the #value_type is `double`. + TOML_CONST_INLINE_GETTER + bool is_floating_point() const noexcept final { return std::is_same_v<value_type, double>; } + + /// \brief Returns `true` if the #value_type is int64_t or `double`. + TOML_CONST_INLINE_GETTER + bool is_number() const noexcept final { return impl::is_one_of<value_type, int64_t, double>; } + + /// \brief Returns `true` if the #value_type is `bool`. + TOML_CONST_INLINE_GETTER + bool is_boolean() const noexcept final { return std::is_same_v<value_type, bool>; } + + /// \brief Returns `true` if the #value_type is toml::date. + TOML_CONST_INLINE_GETTER + bool is_date() const noexcept final { return std::is_same_v<value_type, date>; } + + /// \brief Returns `true` if the #value_type is toml::time. + TOML_CONST_INLINE_GETTER + bool is_time() const noexcept final { return std::is_same_v<value_type, time>; } + + /// \brief Returns `true` if the #value_type is toml_date_time. + TOML_CONST_INLINE_GETTER + bool is_date_time() const noexcept final { return std::is_same_v<value_type, date_time>; } + + /// @} + + /// \name Type casts + /// @{ + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + table* as_table() noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + array* as_array() noexcept final { return nullptr; } + + /// \brief Returns a pointer to the value if it is a value<std::string>, otherwise `nullptr`. + TOML_CONST_INLINE_GETTER + value<std::string>* as_string() noexcept final { return as_value<std::string>(this); } + + /// \brief Returns a pointer to the value if it is a value<int64_t>, otherwise `nullptr`. + TOML_CONST_INLINE_GETTER + value<int64_t>* as_integer() noexcept final { return as_value<int64_t>(this); } + + /// \brief Returns a pointer to the value if it is a value<double>, otherwise `nullptr`. + TOML_CONST_INLINE_GETTER + value<double>* as_floating_point() noexcept final { return as_value<double>(this); } + + /// \brief Returns a pointer to the value if it is a value<bool>, otherwise `nullptr`. + TOML_CONST_INLINE_GETTER + value<bool>* as_boolean() noexcept final { return as_value<bool>(this); } + + /// \brief Returns a pointer to the value if it is a value<date>, otherwise `nullptr`. + TOML_CONST_INLINE_GETTER + value<date>* as_date() noexcept final { return as_value<date>(this); } + + /// \brief Returns a pointer to the value if it is a value<time>, otherwise `nullptr`. + TOML_CONST_INLINE_GETTER + value<time>* as_time() noexcept final { return as_value<time>(this); } + + /// \brief Returns a pointer to the value if it is a value<date_time>, otherwise `nullptr`. + TOML_CONST_INLINE_GETTER + value<date_time>* as_date_time() noexcept final { return as_value<date_time>(this); } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const table* as_table() const noexcept final { return nullptr; } + + /// \brief Returns `nullptr`. + TOML_CONST_INLINE_GETTER + const array* as_array() const noexcept final { return nullptr; } + + /// \brief Returns a const-qualified pointer to the value if it is a value<std::string>, + /// otherwise `nullptr`. + TOML_CONST_INLINE_GETTER + const value<std::string>* as_string() const noexcept final { + return as_value<std::string>(this); + } + + /// \brief Returns a const-qualified pointer to the value if it is a value<int64_t>, otherwise + /// `nullptr`. + TOML_CONST_INLINE_GETTER + const value<int64_t>* as_integer() const noexcept final { return as_value<int64_t>(this); } + + /// \brief Returns a const-qualified pointer to the value if it is a value<double>, otherwise + /// `nullptr`. + TOML_CONST_INLINE_GETTER + const value<double>* as_floating_point() const noexcept final { return as_value<double>(this); } + + /// \brief Returns a const-qualified pointer to the value if it is a value<bool>, otherwise + /// `nullptr`. + TOML_CONST_INLINE_GETTER + const value<bool>* as_boolean() const noexcept final { return as_value<bool>(this); } + + /// \brief Returns a const-qualified pointer to the value if it is a value<date>, otherwise + /// `nullptr`. + TOML_CONST_INLINE_GETTER + const value<date>* as_date() const noexcept final { return as_value<date>(this); } + + /// \brief Returns a const-qualified pointer to the value if it is a value<time>, otherwise + /// `nullptr`. + TOML_CONST_INLINE_GETTER + const value<time>* as_time() const noexcept final { return as_value<time>(this); } + + /// \brief Returns a const-qualified pointer to the value if it is a value<date_time>, otherwise + /// `nullptr`. + TOML_CONST_INLINE_GETTER + const value<date_time>* as_date_time() const noexcept final { + return as_value<date_time>(this); + } + + /// @} + + /// \name Value retrieval + /// @{ + + /// \brief Returns a reference to the underlying value. + TOML_PURE_INLINE_GETTER + value_type& get() & noexcept { return val_; } + + /// \brief Returns a reference to the underlying value (rvalue overload). + TOML_PURE_INLINE_GETTER + value_type&& get() && noexcept { return static_cast<value_type&&>(val_); } + + /// \brief Returns a reference to the underlying value (const overload). + TOML_PURE_INLINE_GETTER + const value_type& get() const& noexcept { return val_; } + + /// \brief Returns a reference to the underlying value (const rvalue overload). + TOML_PURE_INLINE_GETTER + const value_type&& get() const&& noexcept { return static_cast<const value_type&&>(val_); } + + /// \brief Returns a reference to the underlying value. + TOML_PURE_INLINE_GETTER + value_type& operator*() & noexcept { return val_; } + + /// \brief Returns a reference to the underlying value (rvalue overload). + TOML_PURE_INLINE_GETTER + value_type&& operator*() && noexcept { return static_cast<value_type&&>(val_); } + + /// \brief Returns a reference to the underlying value (const overload). + TOML_PURE_INLINE_GETTER + const value_type& operator*() const& noexcept { return val_; } + + /// \brief Returns a reference to the underlying value (const rvalue overload). + TOML_PURE_INLINE_GETTER + const value_type&& operator*() const&& noexcept { + return static_cast<const value_type&&>(val_); + } + + /// \brief Returns a reference to the underlying value. + TOML_PURE_INLINE_GETTER + explicit operator value_type&() & noexcept { return val_; } + + /// \brief Returns a reference to the underlying value (rvalue overload). + TOML_PURE_INLINE_GETTER + explicit operator value_type&&() && noexcept { return static_cast<value_type&&>(val_); } + + /// \brief Returns a reference to the underlying value (const overload). + TOML_PURE_INLINE_GETTER + explicit operator const value_type&() const& noexcept { return val_; } + + /// \brief Returns a reference to the underlying value (const rvalue overload). + TOML_PURE_INLINE_GETTER + explicit operator const value_type&&() && noexcept { + return static_cast<const value_type&&>(val_); + } + + /// \brief Returns a pointer to the underlying value. + /// + /// \availability This operator is only available when #value_type is a class/struct. + TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type) + TOML_PURE_INLINE_GETTER + value_type* operator->() noexcept { return &val_; } + + /// \brief Returns a pointer to the underlying value (const overload). + /// + /// \availability This operator is only available when #value_type is a class/struct. + TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type) + TOML_PURE_INLINE_GETTER + const value_type* operator->() const noexcept { return &val_; } + + /// @} + + /// \name Metadata + /// @{ + + /// \brief Returns the metadata flags associated with this value. + TOML_NODISCARD + value_flags flags() const noexcept { return flags_; } + + /// \brief Sets the metadata flags associated with this value. + /// \returns A reference to the value object. + value& flags(value_flags new_flags) noexcept { + flags_ = new_flags; + return *this; + } + + /// @} + + /// \brief Value-assignment operator. + value& operator=(value_arg rhs) noexcept { + if constexpr (std::is_same_v<value_type, std::string>) + val_.assign(rhs); + else + val_ = rhs; + return *this; + } + + TOML_CONSTRAINED_TEMPLATE((std::is_same_v<T, std::string>), typename T = value_type) + value& operator=(std::string&& rhs) noexcept { + val_ = std::move(rhs); + return *this; + } + + /// \name Equality and Comparison + /// @{ + + /// \brief Value equality operator. + TOML_PURE_GETTER + friend bool operator==(const value& lhs, value_arg rhs) noexcept { + if constexpr (std::is_same_v<value_type, double>) { + const auto lhs_nan = impl::fpclassify(lhs.val_) == impl::fp_class::nan; + const auto rhs_nan = impl::fpclassify(rhs) == impl::fp_class::nan; + if (lhs_nan != rhs_nan) return false; + if (lhs_nan) return true; + } + return lhs.val_ == rhs; + } + TOML_ASYMMETRICAL_EQUALITY_OPS(const value&, value_arg, ); + + /// \brief Value less-than operator. + TOML_PURE_GETTER + friend bool operator<(const value& lhs, value_arg rhs) noexcept { return lhs.val_ < rhs; } + + /// \brief Value less-than operator. + TOML_PURE_GETTER + friend bool operator<(value_arg lhs, const value& rhs) noexcept { return lhs < rhs.val_; } + + /// \brief Value less-than-or-equal-to operator. + TOML_PURE_GETTER + friend bool operator<=(const value& lhs, value_arg rhs) noexcept { return lhs.val_ <= rhs; } + + /// \brief Value less-than-or-equal-to operator. + TOML_PURE_GETTER + friend bool operator<=(value_arg lhs, const value& rhs) noexcept { return lhs <= rhs.val_; } + + /// \brief Value greater-than operator. + TOML_PURE_GETTER + friend bool operator>(const value& lhs, value_arg rhs) noexcept { return lhs.val_ > rhs; } + + /// \brief Value greater-than operator. + TOML_PURE_GETTER + friend bool operator>(value_arg lhs, const value& rhs) noexcept { return lhs > rhs.val_; } + + /// \brief Value greater-than-or-equal-to operator. + TOML_PURE_GETTER + friend bool operator>=(const value& lhs, value_arg rhs) noexcept { return lhs.val_ >= rhs; } + + /// \brief Value greater-than-or-equal-to operator. + TOML_PURE_GETTER + friend bool operator>=(value_arg lhs, const value& rhs) noexcept { return lhs >= rhs.val_; } + + /// \brief Equality operator. + /// + /// \param lhs The LHS value. + /// \param rhs The RHS value. + /// + /// \returns True if the values were of the same type and contained the same value. + template <typename T> + TOML_PURE_GETTER friend bool operator==(const value& lhs, const value<T>& rhs) noexcept { + if constexpr (std::is_same_v<value_type, T>) + return lhs == rhs.val_; // calls asymmetrical value-equality operator defined above + else + return false; + } + + /// \brief Inequality operator. + /// + /// \param lhs The LHS value. + /// \param rhs The RHS value. + /// + /// \returns True if the values were not of the same type, or did not contain the same value. + template <typename T> + TOML_PURE_INLINE_GETTER friend bool operator!=(const value& lhs, const value<T>& rhs) noexcept { + return !(lhs == rhs); + } + + /// \brief Less-than operator. + /// + /// \param lhs The LHS toml::value. + /// \param rhs The RHS toml::value. + /// + /// \returns \conditional_return{Same value types} + /// `lhs.get() < rhs.get()` + /// \conditional_return{Different value types} + /// `lhs.type() < rhs.type()` + template <typename T> + TOML_PURE_GETTER friend bool operator<(const value& lhs, const value<T>& rhs) noexcept { + if constexpr (std::is_same_v<value_type, T>) + return lhs.val_ < rhs.val_; + else + return impl::node_type_of<value_type> < impl::node_type_of<T>; + } + + /// \brief Less-than-or-equal-to operator. + /// + /// \param lhs The LHS toml::value. + /// \param rhs The RHS toml::value. + /// + /// \returns \conditional_return{Same value types} + /// `lhs.get() <= rhs.get()` + /// \conditional_return{Different value types} + /// `lhs.type() <= rhs.type()` + template <typename T> + TOML_PURE_GETTER friend bool operator<=(const value& lhs, const value<T>& rhs) noexcept { + if constexpr (std::is_same_v<value_type, T>) + return lhs.val_ <= rhs.val_; + else + return impl::node_type_of<value_type> <= impl::node_type_of<T>; + } + + /// \brief Greater-than operator. + /// + /// \param lhs The LHS toml::value. + /// \param rhs The RHS toml::value. + /// + /// \returns \conditional_return{Same value types} + /// `lhs.get() > rhs.get()` + /// \conditional_return{Different value types} + /// `lhs.type() > rhs.type()` + template <typename T> + TOML_PURE_GETTER friend bool operator>(const value& lhs, const value<T>& rhs) noexcept { + if constexpr (std::is_same_v<value_type, T>) + return lhs.val_ > rhs.val_; + else + return impl::node_type_of<value_type> > impl::node_type_of<T>; + } + + /// \brief Greater-than-or-equal-to operator. + /// + /// \param lhs The LHS toml::value. + /// \param rhs The RHS toml::value. + /// + /// \returns \conditional_return{Same value types} + /// `lhs.get() >= rhs.get()` + /// \conditional_return{Different value types} + /// `lhs.type() >= rhs.type()` + template <typename T> + TOML_PURE_GETTER friend bool operator>=(const value& lhs, const value<T>& rhs) noexcept { + if constexpr (std::is_same_v<value_type, T>) + return lhs.val_ >= rhs.val_; + else + return impl::node_type_of<value_type> >= impl::node_type_of<T>; + } + + /// @} #if TOML_ENABLE_FORMATTERS - /// \brief Prints the value out to a stream as formatted TOML. - /// - /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. - friend std::ostream& operator<<(std::ostream& lhs, const value& rhs) - { - impl::print_to_stream(lhs, rhs); - return lhs; - } + /// \brief Prints the value out to a stream as formatted TOML. + /// + /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled. + friend std::ostream& operator<<(std::ostream& lhs, const value& rhs) { + impl::print_to_stream(lhs, rhs); + return lhs; + } #endif - }; - - /// \cond - - template <typename T> - value(T) -> value<impl::native_type_of<impl::remove_cvref<T>>>; - template <typename T> - value(T, value_flags) -> value<impl::native_type_of<impl::remove_cvref<T>>>; - - template <typename T> - TOML_NODISCARD - inline decltype(auto) node::get_value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>) - { - using namespace impl; - - static_assert(node_type_of<T> != node_type::none); - static_assert(node_type_of<T> != node_type::table); - static_assert(node_type_of<T> != node_type::array); - static_assert(is_native<T> || can_represent_native<T>); - static_assert(!is_cvref<T>); - TOML_ASSERT(this->type() == node_type_of<T>); - - if constexpr (node_type_of<T> == node_type::string) - { - const auto& str = *ref_cast<std::string>(); - if constexpr (std::is_same_v<T, std::string>) - return str; - else if constexpr (std::is_same_v<T, std::string_view>) - return T{ str }; - else if constexpr (std::is_same_v<T, const char*>) - return str.c_str(); - - else if constexpr (std::is_same_v<T, std::wstring>) - { + }; + + /// \cond + + template <typename T> + value(T) -> value<impl::native_type_of<impl::remove_cvref<T>>>; + template <typename T> + value(T, value_flags) -> value<impl::native_type_of<impl::remove_cvref<T>>>; + + template <typename T> + TOML_NODISCARD inline decltype(auto) node::get_value_exact() + const noexcept(impl::value_retrieval_is_nothrow<T>) { + using namespace impl; + + static_assert(node_type_of<T> != node_type::none); + static_assert(node_type_of<T> != node_type::table); + static_assert(node_type_of<T> != node_type::array); + static_assert(is_native<T> || can_represent_native<T>); + static_assert(!is_cvref<T>); + TOML_ASSERT(this->type() == node_type_of<T>); + + if constexpr (node_type_of<T> == node_type::string) { + const auto& str = *ref_cast<std::string>(); + if constexpr (std::is_same_v<T, std::string>) + return str; + else if constexpr (std::is_same_v<T, std::string_view>) + return T{str}; + else if constexpr (std::is_same_v<T, const char*>) + return str.c_str(); + + else if constexpr (std::is_same_v<T, std::wstring>) { #if TOML_ENABLE_WINDOWS_COMPAT - return widen(str); + return widen(str); #else - static_assert(always_false<T>, "Evaluated unreachable branch!"); + static_assert(always_false<T>, "Evaluated unreachable branch!"); #endif - } + } #if TOML_HAS_CHAR8 - // char -> char8_t (potentially unsafe - the feature is 'experimental'!) - else if constexpr (is_one_of<T, std::u8string, std::u8string_view>) - return T(reinterpret_cast<const char8_t*>(str.c_str()), str.length()); - else if constexpr (std::is_same_v<T, const char8_t*>) - return reinterpret_cast<const char8_t*>(str.c_str()); - else - static_assert(always_false<T>, "Evaluated unreachable branch!"); + // char -> char8_t (potentially unsafe - the feature is 'experimental'!) + else if constexpr (is_one_of<T, std::u8string, std::u8string_view>) + return T(reinterpret_cast<const char8_t*>(str.c_str()), str.length()); + else if constexpr (std::is_same_v<T, const char8_t*>) + return reinterpret_cast<const char8_t*>(str.c_str()); + else + static_assert(always_false<T>, "Evaluated unreachable branch!"); #endif - } - else - return static_cast<T>(*ref_cast<native_type_of<T>>()); - } - - template <typename T> - TOML_NODISCARD - inline optional<T> node::value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>) - { - using namespace impl; - - static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, - "Retrieving values as wide-character strings with node::value_exact() is only " - "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); - - static_assert((is_native<T> || can_represent_native<T>)&&!is_cvref<T>, - TOML_SA_VALUE_EXACT_FUNC_MESSAGE("return type of node::value_exact()")); - - // prevent additional compiler error spam when the static_assert fails by gating behind if constexpr - if constexpr ((is_native<T> || can_represent_native<T>)&&!is_cvref<T>) - { - if (type() == node_type_of<T>) - return { this->get_value_exact<T>() }; - else - return {}; - } - } - - template <typename T> - TOML_NODISCARD - inline optional<T> node::value() const noexcept(impl::value_retrieval_is_nothrow<T>) - { - using namespace impl; - - static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, - "Retrieving values as wide-character strings with node::value() is only " - "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); - static_assert((is_native<T> || can_represent_native<T> || can_partially_represent_native<T>)&&!is_cvref<T>, - TOML_SA_VALUE_FUNC_MESSAGE("return type of node::value()")); - - // when asking for strings, dates, times and date_times there's no 'fuzzy' conversion - // semantics to be mindful of so the exact retrieval is enough. - if constexpr (is_natively_one_of<T, std::string, time, date, date_time>) - { - if (type() == node_type_of<T>) - return { this->get_value_exact<T>() }; - else - return {}; - } - - // everything else requires a bit of logicking. - else - { - switch (type()) - { - // int -> * - case node_type::integer: - { - // int -> int - if constexpr (is_natively_one_of<T, int64_t>) - { - if constexpr (is_native<T> || can_represent_native<T>) - return static_cast<T>(*ref_cast<int64_t>()); - else - return node_integer_cast<T>(*ref_cast<int64_t>()); - } - - // int -> float - else if constexpr (is_natively_one_of<T, double>) - { - const int64_t val = *ref_cast<int64_t>(); - if constexpr (std::numeric_limits<T>::digits < 64) - { - constexpr auto largest_whole_float = (int64_t{ 1 } << std::numeric_limits<T>::digits); - if (val < -largest_whole_float || val > largest_whole_float) - return {}; - } - return static_cast<T>(val); - } - - // int -> bool - else if constexpr (is_natively_one_of<T, bool>) - return static_cast<bool>(*ref_cast<int64_t>()); - - // int -> anything else - else - return {}; - } - - // float -> * - case node_type::floating_point: - { - // float -> float - if constexpr (is_natively_one_of<T, double>) - { - if constexpr (is_native<T> || can_represent_native<T>) - return { static_cast<T>(*ref_cast<double>()) }; - else - { - const double val = *ref_cast<double>(); - if (impl::fpclassify(val) == fp_class::ok - && (val < (std::numeric_limits<T>::lowest)() || val > (std::numeric_limits<T>::max)())) - return {}; - return { static_cast<T>(val) }; - } - } - - // float -> int - else if constexpr (is_natively_one_of<T, int64_t>) - { - const double val = *ref_cast<double>(); - if (impl::fpclassify(val) == fp_class::ok - && static_cast<double>(static_cast<int64_t>(val)) == val) - return node_integer_cast<T>(static_cast<int64_t>(val)); - else - return {}; - } - - // float -> anything else - else - return {}; - } - - // bool -> * - case node_type::boolean: - { - // bool -> bool - if constexpr (is_natively_one_of<T, bool>) - return { *ref_cast<bool>() }; - - // bool -> int - else if constexpr (is_natively_one_of<T, int64_t>) - return { static_cast<T>(*ref_cast<bool>()) }; - - // bool -> anything else - else - return {}; - } - } - - // non-values, or 'exact' types covered above - return {}; - } - } - - template <typename T> - TOML_NODISCARD - inline auto node::value_or(T && default_value) const noexcept(impl::value_retrieval_is_nothrow<T>) - { - using namespace impl; - - static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, - "Retrieving values as wide-character strings with node::value_or() is only " - "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); - - if constexpr (is_wide_string<T>) - { + } else + return static_cast<T>(*ref_cast<native_type_of<T>>()); + } + + template <typename T> + TOML_NODISCARD inline optional<T> node::value_exact() + const noexcept(impl::value_retrieval_is_nothrow<T>) { + using namespace impl; + + static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, + "Retrieving values as wide-character strings with node::value_exact() is only " + "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); + + static_assert((is_native<T> || can_represent_native<T>) && !is_cvref<T>, + TOML_SA_VALUE_EXACT_FUNC_MESSAGE("return type of node::value_exact()")); + + // prevent additional compiler error spam when the static_assert fails by gating behind if + // constexpr + if constexpr ((is_native<T> || can_represent_native<T>) && !is_cvref<T>) { + if (type() == node_type_of<T>) + return {this->get_value_exact<T>()}; + else + return {}; + } + } + + template <typename T> + TOML_NODISCARD inline optional<T> node::value() + const noexcept(impl::value_retrieval_is_nothrow<T>) { + using namespace impl; + + static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, + "Retrieving values as wide-character strings with node::value() is only " + "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); + static_assert((is_native<T> || can_represent_native<T> || can_partially_represent_native<T>) && + !is_cvref<T>, + TOML_SA_VALUE_FUNC_MESSAGE("return type of node::value()")); + + // when asking for strings, dates, times and date_times there's no 'fuzzy' conversion + // semantics to be mindful of so the exact retrieval is enough. + if constexpr (is_natively_one_of<T, std::string, time, date, date_time>) { + if (type() == node_type_of<T>) + return {this->get_value_exact<T>()}; + else + return {}; + } + + // everything else requires a bit of logicking. + else { + switch (type()) { + // int -> * + case node_type::integer: { + // int -> int + if constexpr (is_natively_one_of<T, int64_t>) { + if constexpr (is_native<T> || can_represent_native<T>) + return static_cast<T>(*ref_cast<int64_t>()); + else + return node_integer_cast<T>(*ref_cast<int64_t>()); + } + + // int -> float + else if constexpr (is_natively_one_of<T, double>) { + const int64_t val = *ref_cast<int64_t>(); + if constexpr (std::numeric_limits<T>::digits < 64) { + constexpr auto largest_whole_float = (int64_t{1} << std::numeric_limits<T>::digits); + if (val < -largest_whole_float || val > largest_whole_float) return {}; + } + return static_cast<T>(val); + } + + // int -> bool + else if constexpr (is_natively_one_of<T, bool>) + return static_cast<bool>(*ref_cast<int64_t>()); + + // int -> anything else + else + return {}; + } + + // float -> * + case node_type::floating_point: { + // float -> float + if constexpr (is_natively_one_of<T, double>) { + if constexpr (is_native<T> || can_represent_native<T>) + return {static_cast<T>(*ref_cast<double>())}; + else { + const double val = *ref_cast<double>(); + if (impl::fpclassify(val) == fp_class::ok && + (val < (std::numeric_limits<T>::lowest)() || + val > (std::numeric_limits<T>::max)())) + return {}; + return {static_cast<T>(val)}; + } + } + + // float -> int + else if constexpr (is_natively_one_of<T, int64_t>) { + const double val = *ref_cast<double>(); + if (impl::fpclassify(val) == fp_class::ok && + static_cast<double>(static_cast<int64_t>(val)) == val) + return node_integer_cast<T>(static_cast<int64_t>(val)); + else + return {}; + } + + // float -> anything else + else + return {}; + } + + // bool -> * + case node_type::boolean: { + // bool -> bool + if constexpr (is_natively_one_of<T, bool>) return {*ref_cast<bool>()}; + + // bool -> int + else if constexpr (is_natively_one_of<T, int64_t>) + return {static_cast<T>(*ref_cast<bool>())}; + + // bool -> anything else + else + return {}; + } + } + + // non-values, or 'exact' types covered above + return {}; + } + } + + template <typename T> + TOML_NODISCARD inline auto node::value_or(T && default_value) + const noexcept(impl::value_retrieval_is_nothrow<T>) { + using namespace impl; + + static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT, + "Retrieving values as wide-character strings with node::value_or() is only " + "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled."); + + if constexpr (is_wide_string<T>) { #if TOML_ENABLE_WINDOWS_COMPAT - if (type() == node_type::string) - return widen(*ref_cast<std::string>()); - return std::wstring{ static_cast<T&&>(default_value) }; + if (type() == node_type::string) return widen(*ref_cast<std::string>()); + return std::wstring{static_cast<T&&>(default_value)}; #else - static_assert(always_false<T>, "Evaluated unreachable branch!"); + static_assert(always_false<T>, "Evaluated unreachable branch!"); #endif - } - else - { - using value_type = - std::conditional_t<std::is_pointer_v<std::decay_t<T>>, - std::add_pointer_t<std::add_const_t<std::remove_pointer_t<std::decay_t<T>>>>, - std::decay_t<T>>; - using traits = value_traits<value_type>; + } else { + using value_type = std::conditional_t< + std::is_pointer_v<std::decay_t<T>>, + std::add_pointer_t<std::add_const_t<std::remove_pointer_t<std::decay_t<T>>>>, + std::decay_t<T>>; + using traits = value_traits<value_type>; - // clang-format off + // clang-format off static_assert( traits::is_native || traits::can_represent_native || traits::can_partially_represent_native, @@ -1243,27 +999,25 @@ TOML_NAMESPACE_START TOML_SA_LIST_END ); - // clang-format on - - // prevent additional compiler error spam when the static_assert fails by gating behind if constexpr - if constexpr (traits::is_native || traits::can_represent_native || traits::can_partially_represent_native) - { - if constexpr (traits::is_native) - { - if (type() == node_type_of<value_type>) - return *ref_cast<typename traits::native_type>(); - } - if (auto val = this->value<value_type>()) - return *val; - if constexpr (std::is_pointer_v<value_type>) - return value_type{ default_value }; - else - return static_cast<T&&>(default_value); - } - } - } - - /// \endcond + // clang-format on + + // prevent additional compiler error spam when the static_assert fails by gating behind if + // constexpr + if constexpr (traits::is_native || traits::can_represent_native || + traits::can_partially_represent_native) { + if constexpr (traits::is_native) { + if (type() == node_type_of<value_type>) return *ref_cast<typename traits::native_type>(); + } + if (auto val = this->value<value_type>()) return *val; + if constexpr (std::is_pointer_v<value_type>) + return value_type{default_value}; + else + return static_cast<T&&>(default_value); + } + } + } + + /// \endcond } TOML_NAMESPACE_END; diff --git a/vendor/toml++/impl/version.hpp b/vendor/toml++/impl/version.hpp index 626691f..63a49be 100644 --- a/vendor/toml++/impl/version.hpp +++ b/vendor/toml++/impl/version.hpp @@ -1,7 +1,7 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #define TOML_LIB_MAJOR 3 diff --git a/vendor/toml++/impl/yaml_formatter.hpp b/vendor/toml++/impl/yaml_formatter.hpp index 1a3d24f..8d57156 100644 --- a/vendor/toml++/impl/yaml_formatter.hpp +++ b/vendor/toml++/impl/yaml_formatter.hpp @@ -1,7 +1,7 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" @@ -10,130 +10,125 @@ #include "formatter.hpp" #include "header_start.hpp" -TOML_NAMESPACE_START -{ - /// \brief A wrapper for printing TOML objects out to a stream as formatted YAML. - /// - /// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled. - /// - /// \detail \cpp - /// auto some_toml = toml::parse(R"( - /// [fruit] - /// apple.color = "red" - /// apple.taste.sweet = true - /// - /// [fruit.apple.texture] - /// smooth = true - /// )"sv); - /// std::cout << toml::yaml_formatter{ some_toml } << "\n"; - /// \ecpp - /// - /// \out - /// fruit: - /// apple: - /// color: red - /// taste: - /// sweet: true - /// texture: - /// smooth: true - /// \eout - class TOML_EXPORTED_CLASS yaml_formatter : impl::formatter - { - private: - /// \cond - - using base = impl::formatter; - - TOML_EXPORTED_MEMBER_FUNCTION - void print_yaml_string(const value<std::string>&); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const toml::table&, bool = false); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(const toml::array&, bool = false); - - TOML_EXPORTED_MEMBER_FUNCTION - void print(); - - static constexpr impl::formatter_constants constants = { - // - format_flags::quote_dates_and_times | format_flags::indentation, // mandatory - format_flags::allow_multi_line_strings, // ignored - ".inf"sv, - "-.inf"sv, - ".NAN"sv, - "true"sv, - "false"sv - }; - - /// \endcond - - public: - /// \brief The default flags for a yaml_formatter. - static constexpr format_flags default_flags = constants.mandatory_flags // - | format_flags::allow_literal_strings // - | format_flags::allow_unicode_strings // - | format_flags::allow_octal_integers // - | format_flags::allow_hexadecimal_integers; - - /// \brief Constructs a YAML formatter and binds it to a TOML object. - /// - /// \param source The source TOML object. - /// \param flags Format option flags. - TOML_NODISCARD_CTOR - explicit yaml_formatter(const toml::node& source, format_flags flags = default_flags) noexcept - : base{ &source, nullptr, constants, { flags, " "sv } } - {} +TOML_NAMESPACE_START { + /// \brief A wrapper for printing TOML objects out to a stream as formatted YAML. + /// + /// \availability This class is only available when #TOML_ENABLE_FORMATTERS is enabled. + /// + /// \detail \cpp + /// auto some_toml = toml::parse(R"( + /// [fruit] + /// apple.color = "red" + /// apple.taste.sweet = true + /// + /// [fruit.apple.texture] + /// smooth = true + /// )"sv); + /// std::cout << toml::yaml_formatter{ some_toml } << "\n"; + /// \ecpp + /// + /// \out + /// fruit: + /// apple: + /// color: red + /// taste: + /// sweet: true + /// texture: + /// smooth: true + /// \eout + class TOML_EXPORTED_CLASS yaml_formatter : impl::formatter { + private: + /// \cond + + using base = impl::formatter; + + TOML_EXPORTED_MEMBER_FUNCTION + void print_yaml_string(const value<std::string>&); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const toml::table&, bool = false); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(const toml::array&, bool = false); + + TOML_EXPORTED_MEMBER_FUNCTION + void print(); + + static constexpr impl::formatter_constants constants = { + // + format_flags::quote_dates_and_times | format_flags::indentation, // mandatory + format_flags::allow_multi_line_strings, // ignored + ".inf"sv, + "-.inf"sv, + ".NAN"sv, + "true"sv, + "false"sv}; + + /// \endcond + + public: + /// \brief The default flags for a yaml_formatter. + static constexpr format_flags default_flags = constants.mandatory_flags // + | format_flags::allow_literal_strings // + | format_flags::allow_unicode_strings // + | format_flags::allow_octal_integers // + | format_flags::allow_hexadecimal_integers; + + /// \brief Constructs a YAML formatter and binds it to a TOML object. + /// + /// \param source The source TOML object. + /// \param flags Format option flags. + TOML_NODISCARD_CTOR + explicit yaml_formatter(const toml::node& source, format_flags flags = default_flags) noexcept + : base{&source, nullptr, constants, {flags, " "sv}} {} #if TOML_DOXYGEN || (TOML_ENABLE_PARSER && !TOML_EXCEPTIONS) - /// \brief Constructs a YAML formatter and binds it to a toml::parse_result. - /// - /// \availability This constructor is only available when exceptions are disabled. - /// - /// \attention Formatting a failed parse result will simply dump the error message out as-is. - /// This will not be valid YAML, but at least gives you something to log or show up in diagnostics: - /// \cpp - /// std::cout << toml::yaml_formatter{ toml::parse("a = 'b'"sv) } // ok - /// << "\n\n" - /// << toml::yaml_formatter{ toml::parse("a = "sv) } // malformed - /// << "\n"; - /// \ecpp - /// \out - /// a: b - /// - /// Error while parsing key-value pair: encountered end-of-file - /// (error occurred at line 1, column 5) - /// \eout - /// Use the library with exceptions if you want to avoid this scenario. - /// - /// \param result The parse result. - /// \param flags Format option flags. - TOML_NODISCARD_CTOR - explicit yaml_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept - : base{ nullptr, &result, constants, { flags, " "sv } } - {} + /// \brief Constructs a YAML formatter and binds it to a toml::parse_result. + /// + /// \availability This constructor is only available when exceptions are disabled. + /// + /// \attention Formatting a failed parse result will simply dump the error message out as-is. + /// This will not be valid YAML, but at least gives you something to log or show up in + ///diagnostics: + /// \cpp + /// std::cout << toml::yaml_formatter{ toml::parse("a = 'b'"sv) } // ok + /// << "\n\n" + /// << toml::yaml_formatter{ toml::parse("a = "sv) } // malformed + /// << "\n"; + /// \ecpp + /// \out + /// a: b + /// + /// Error while parsing key-value pair: encountered end-of-file + /// (error occurred at line 1, column 5) + /// \eout + /// Use the library with exceptions if you want to avoid this scenario. + /// + /// \param result The parse result. + /// \param flags Format option flags. + TOML_NODISCARD_CTOR + explicit yaml_formatter(const toml::parse_result& result, + format_flags flags = default_flags) noexcept + : base{nullptr, &result, constants, {flags, " "sv}} {} #endif - /// \brief Prints the bound TOML object out to the stream as YAML. - friend std::ostream& TOML_CALLCONV operator<<(std::ostream& lhs, yaml_formatter& rhs) - { - rhs.attach(lhs); - rhs.print(); - rhs.detach(); - return lhs; - } - - /// \brief Prints the bound TOML object out to the stream as YAML (rvalue overload). - friend std::ostream& TOML_CALLCONV operator<<(std::ostream& lhs, yaml_formatter&& rhs) - { - return lhs << rhs; // as lvalue - } - }; + /// \brief Prints the bound TOML object out to the stream as YAML. + friend std::ostream& TOML_CALLCONV operator<<(std::ostream& lhs, yaml_formatter& rhs) { + rhs.attach(lhs); + rhs.print(); + rhs.detach(); + return lhs; + } + + /// \brief Prints the bound TOML object out to the stream as YAML (rvalue overload). + friend std::ostream& TOML_CALLCONV operator<<(std::ostream& lhs, yaml_formatter&& rhs) { + return lhs << rhs; // as lvalue + } + }; } TOML_NAMESPACE_END; #include "header_end.hpp" -#endif // TOML_ENABLE_FORMATTERS +#endif // TOML_ENABLE_FORMATTERS diff --git a/vendor/toml++/toml.hpp b/vendor/toml++/toml.hpp index 7783f24..a25cef5 100644 --- a/vendor/toml++/toml.hpp +++ b/vendor/toml++/toml.hpp @@ -1,12 +1,12 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #ifndef TOMLPLUSPLUS_HPP #define TOMLPLUSPLUS_HPP -#define INCLUDE_TOMLPLUSPLUS_H // old guard name used pre-v3 -#define TOMLPLUSPLUS_H // guard name used in the legacy toml.h +#define INCLUDE_TOMLPLUSPLUS_H // old guard name used pre-v3 +#define TOMLPLUSPLUS_H // guard name used in the legacy toml.h #include "impl/preprocessor.hpp" @@ -17,9 +17,9 @@ TOML_DISABLE_SUGGEST_ATTR_WARNINGS; // misc warning false-positives #if TOML_MSVC -#pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch +#pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch #if TOML_SHARED_LIB -#pragma warning(disable : 4251) // dll exports for std lib types +#pragma warning(disable : 4251) // dll exports for std lib types #endif #elif TOML_CLANG TOML_PRAGMA_CLANG(diagnostic ignored "-Wheader-hygiene") @@ -31,49 +31,49 @@ TOML_PRAGMA_CLANG(diagnostic ignored "-Wreserved-identifier") #endif #endif -#include "impl/std_new.hpp" -#include "impl/std_string.hpp" -#include "impl/std_optional.hpp" -#include "impl/forward_declarations.hpp" -#include "impl/print_to_stream.hpp" -#include "impl/source_region.hpp" -#include "impl/date_time.hpp" +#include "impl/array.hpp" #include "impl/at_path.hpp" -#include "impl/path.hpp" +#include "impl/date_time.hpp" +#include "impl/formatter.hpp" +#include "impl/forward_declarations.hpp" +#include "impl/json_formatter.hpp" +#include "impl/key.hpp" +#include "impl/make_node.hpp" #include "impl/node.hpp" #include "impl/node_view.hpp" -#include "impl/value.hpp" -#include "impl/make_node.hpp" -#include "impl/array.hpp" -#include "impl/key.hpp" -#include "impl/table.hpp" -#include "impl/unicode_autogenerated.hpp" -#include "impl/unicode.hpp" #include "impl/parse_error.hpp" #include "impl/parse_result.hpp" #include "impl/parser.hpp" -#include "impl/formatter.hpp" +#include "impl/path.hpp" +#include "impl/print_to_stream.hpp" +#include "impl/source_region.hpp" +#include "impl/std_new.hpp" +#include "impl/std_optional.hpp" +#include "impl/std_string.hpp" +#include "impl/table.hpp" #include "impl/toml_formatter.hpp" -#include "impl/json_formatter.hpp" +#include "impl/unicode.hpp" +#include "impl/unicode_autogenerated.hpp" +#include "impl/value.hpp" #include "impl/yaml_formatter.hpp" #if TOML_IMPLEMENTATION -#include "impl/std_string.inl" -#include "impl/print_to_stream.inl" -#include "impl/node.inl" +#include "impl/array.inl" #include "impl/at_path.inl" +#include "impl/formatter.inl" +#include "impl/json_formatter.inl" +#include "impl/node.inl" +#include "impl/parser.inl" #include "impl/path.inl" -#include "impl/array.inl" +#include "impl/print_to_stream.inl" +#include "impl/std_string.inl" #include "impl/table.inl" -#include "impl/unicode.inl" -#include "impl/parser.inl" -#include "impl/formatter.inl" #include "impl/toml_formatter.inl" -#include "impl/json_formatter.inl" +#include "impl/unicode.inl" #include "impl/yaml_formatter.inl" -#endif // TOML_IMPLEMENTATION +#endif // TOML_IMPLEMENTATION TOML_POP_WARNINGS; @@ -228,4 +228,4 @@ TOML_POP_WARNINGS; #undef TOML_WINDOWS #endif -#endif // TOMLPLUSPLUS_HPP +#endif // TOMLPLUSPLUS_HPP |
