/src/tomlplusplus/include/toml++/impl/node.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | //# This file is a part of toml++ and is subject to the the terms of the MIT license. |
2 | | //# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> |
3 | | //# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. |
4 | | // SPDX-License-Identifier: MIT |
5 | | #pragma once |
6 | | |
7 | | #include "std_utility.hpp" |
8 | | #include "forward_declarations.hpp" |
9 | | #include "source_region.hpp" |
10 | | #include "header_start.hpp" |
11 | | |
12 | | // workaround for this: https://github.com/marzer/tomlplusplus/issues/220 |
13 | | #if TOML_NVCC |
14 | | #define TOML_NVCC_WORKAROUND \ |
15 | | { \ |
16 | | return {}; \ |
17 | | } |
18 | | #else |
19 | | #define TOML_NVCC_WORKAROUND = 0 |
20 | | #endif |
21 | | |
22 | | TOML_NAMESPACE_START |
23 | | { |
24 | | /// \brief A TOML node. |
25 | | /// |
26 | | /// \detail A parsed TOML document forms a tree made up of tables, arrays and values. |
27 | | /// This type is the base of each of those, providing a lot of the polymorphic plumbing. |
28 | | class TOML_ABSTRACT_INTERFACE TOML_EXPORTED_CLASS node |
29 | | { |
30 | | private: |
31 | | /// \cond |
32 | | |
33 | | friend class TOML_PARSER_TYPENAME; |
34 | | source_region source_{}; |
35 | | |
36 | | template <typename T> |
37 | | TOML_NODISCARD |
38 | | decltype(auto) get_value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>); |
39 | | |
40 | | template <typename T, typename N> |
41 | | using ref_type_ = std::conditional_t< // |
42 | | std::is_reference_v<T>, // |
43 | | impl::copy_ref<impl::copy_cv<impl::unwrap_node<T>, std::remove_reference_t<N>>, T>, // |
44 | | impl::copy_cvref<impl::unwrap_node<T>, N> // |
45 | | >; |
46 | | |
47 | | template <typename T, typename N> |
48 | | using ref_type = std::conditional_t< // |
49 | | std::is_reference_v<N>, // |
50 | | ref_type_<T, N>, // |
51 | | ref_type_<T, std::add_lvalue_reference_t<N>> // |
52 | | >; |
53 | | |
54 | | template <typename T, typename N> |
55 | | TOML_PURE_GETTER |
56 | | static ref_type<T, N&&> do_ref(N&& n) noexcept |
57 | | { |
58 | | using unwrapped_type = impl::unwrap_node<T>; |
59 | | static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>, |
60 | | "The template type argument of node::ref() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); |
61 | | |
62 | | TOML_ASSERT_ASSUME( |
63 | | n.template is<unwrapped_type>() |
64 | | && "template type argument provided to toml::node::ref() didn't match the node's actual type"); |
65 | | |
66 | | using node_ref = std::remove_volatile_t<std::remove_reference_t<N>>&; |
67 | | using val_type = std::remove_volatile_t<unwrapped_type>; |
68 | | using out_ref = ref_type<T, N&&>; |
69 | | static_assert(std::is_reference_v<out_ref>); |
70 | | |
71 | | if constexpr (toml::is_value<unwrapped_type>) |
72 | | return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>().get()); |
73 | | else |
74 | | return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>()); |
75 | | } |
76 | | |
77 | | protected: |
78 | | TOML_EXPORTED_MEMBER_FUNCTION |
79 | | node() noexcept; |
80 | | |
81 | | TOML_EXPORTED_MEMBER_FUNCTION |
82 | | node(const node&) noexcept; |
83 | | |
84 | | TOML_EXPORTED_MEMBER_FUNCTION |
85 | | node(node&&) noexcept; |
86 | | |
87 | | TOML_EXPORTED_MEMBER_FUNCTION |
88 | | node& operator=(const node&) noexcept; |
89 | | |
90 | | TOML_EXPORTED_MEMBER_FUNCTION |
91 | | node& operator=(node&&) noexcept; |
92 | | |
93 | | template <typename T, typename N> |
94 | | using ref_cast_type_ = std::conditional_t< // |
95 | | std::is_reference_v<T>, // |
96 | | impl::copy_ref<impl::copy_cv<impl::wrap_node<T>, std::remove_reference_t<N>>, T>, // |
97 | | impl::copy_cvref<impl::wrap_node<T>, N> // |
98 | | >; |
99 | | |
100 | | template <typename T, typename N> |
101 | | using ref_cast_type = std::conditional_t< // |
102 | | std::is_reference_v<N>, // |
103 | | ref_cast_type_<T, N>, // |
104 | | ref_cast_type_<T, std::add_lvalue_reference_t<N>> // |
105 | | >; |
106 | | |
107 | | template <typename T> |
108 | | TOML_PURE_INLINE_GETTER |
109 | | ref_cast_type<T, node&> ref_cast() & noexcept |
110 | 1.76M | { |
111 | 1.76M | using out_ref = ref_cast_type<T, node&>; |
112 | 1.76M | using out_type = std::remove_reference_t<out_ref>; |
113 | 1.76M | return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); |
114 | 1.76M | } _ZNR4toml2v34node8ref_castINS0_5tableEEENSt3__111conditionalILb1ENS5_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS7_8copy_cv_INS7_12node_wrapperIu20__remove_reference_tIS6_EE4typeES1_E4typeES6_E4typeENS8_INS8_INS9_Iu20__remove_reference_tISD_ES1_E4typeESD_E4typeERS1_E4typeEE4typeESR_E4typeEv Line | Count | Source | 110 | 1.50M | { | 111 | 1.50M | using out_ref = ref_cast_type<T, node&>; | 112 | 1.50M | using out_type = std::remove_reference_t<out_ref>; | 113 | 1.50M | return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); | 114 | 1.50M | } |
_ZNR4toml2v34node8ref_castINS0_5arrayEEENSt3__111conditionalILb1ENS5_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS7_8copy_cv_INS7_12node_wrapperIu20__remove_reference_tIS6_EE4typeES1_E4typeES6_E4typeENS8_INS8_INS9_Iu20__remove_reference_tISD_ES1_E4typeESD_E4typeERS1_E4typeEE4typeESR_E4typeEv Line | Count | Source | 110 | 258k | { | 111 | 258k | using out_ref = ref_cast_type<T, node&>; | 112 | 258k | using out_type = std::remove_reference_t<out_ref>; | 113 | 258k | return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); | 114 | 258k | } |
_ZNR4toml2v34node8ref_castIlEENSt3__111conditionalILb1ENS4_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS6_8copy_cv_INS6_12node_wrapperIu20__remove_reference_tIS5_EE4typeES1_E4typeES5_E4typeENS7_INS7_INS8_Iu20__remove_reference_tISC_ES1_E4typeESC_E4typeERS1_E4typeEE4typeESQ_E4typeEv Line | Count | Source | 110 | 4.18k | { | 111 | 4.18k | using out_ref = ref_cast_type<T, node&>; | 112 | 4.18k | using out_type = std::remove_reference_t<out_ref>; | 113 | 4.18k | return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); | 114 | 4.18k | } |
Unexecuted instantiation: _ZNR4toml2v34node8ref_castINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEENS3_11conditionalILb1ENSA_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INSC_8copy_cv_INSC_12node_wrapperIu20__remove_reference_tISB_EE4typeES1_E4typeESB_E4typeENSD_INSD_INSE_Iu20__remove_reference_tISI_ES1_E4typeESI_E4typeERS1_E4typeEE4typeESW_E4typeEv Unexecuted instantiation: _ZNR4toml2v34node8ref_castIdEENSt3__111conditionalILb1ENS4_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS6_8copy_cv_INS6_12node_wrapperIu20__remove_reference_tIS5_EE4typeES1_E4typeES5_E4typeENS7_INS7_INS8_Iu20__remove_reference_tISC_ES1_E4typeESC_E4typeERS1_E4typeEE4typeESQ_E4typeEv Unexecuted instantiation: _ZNR4toml2v34node8ref_castIbEENSt3__111conditionalILb1ENS4_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS6_8copy_cv_INS6_12node_wrapperIu20__remove_reference_tIS5_EE4typeES1_E4typeES5_E4typeENS7_INS7_INS8_Iu20__remove_reference_tISC_ES1_E4typeESC_E4typeERS1_E4typeEE4typeESQ_E4typeEv Unexecuted instantiation: _ZNR4toml2v34node8ref_castINS0_4dateEEENSt3__111conditionalILb1ENS5_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS7_8copy_cv_INS7_12node_wrapperIu20__remove_reference_tIS6_EE4typeES1_E4typeES6_E4typeENS8_INS8_INS9_Iu20__remove_reference_tISD_ES1_E4typeESD_E4typeERS1_E4typeEE4typeESR_E4typeEv Unexecuted instantiation: _ZNR4toml2v34node8ref_castINS0_4timeEEENSt3__111conditionalILb1ENS5_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS7_8copy_cv_INS7_12node_wrapperIu20__remove_reference_tIS6_EE4typeES1_E4typeES6_E4typeENS8_INS8_INS9_Iu20__remove_reference_tISD_ES1_E4typeESD_E4typeERS1_E4typeEE4typeESR_E4typeEv Unexecuted instantiation: _ZNR4toml2v34node8ref_castINS0_6stdopt9date_timeEEENSt3__111conditionalILb1ENS6_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS8_8copy_cv_INS8_12node_wrapperIu20__remove_reference_tIS7_EE4typeES1_E4typeES7_E4typeENS9_INS9_INSA_Iu20__remove_reference_tISE_ES1_E4typeESE_E4typeERS1_E4typeEE4typeESS_E4typeEv |
115 | | |
116 | | template <typename T> |
117 | | TOML_PURE_INLINE_GETTER |
118 | | ref_cast_type<T, node&&> ref_cast() && noexcept |
119 | | { |
120 | | using out_ref = ref_cast_type<T, node&&>; |
121 | | using out_type = std::remove_reference_t<out_ref>; |
122 | | return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); |
123 | | } |
124 | | |
125 | | template <typename T> |
126 | | TOML_PURE_INLINE_GETTER |
127 | | ref_cast_type<T, const node&> ref_cast() const& noexcept |
128 | 0 | { |
129 | 0 | using out_ref = ref_cast_type<T, const node&>; |
130 | 0 | using out_type = std::remove_reference_t<out_ref>; |
131 | 0 | return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); |
132 | 0 | } Unexecuted instantiation: _ZNKR4toml2v34node8ref_castINS0_5tableEEENSt3__111conditionalILb1ENS5_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS7_8copy_cv_INS7_12node_wrapperIu20__remove_reference_tIS6_EE4typeEKS1_E4typeES6_E4typeENS8_INS8_INS9_Iu20__remove_reference_tISD_ESE_E4typeESD_E4typeERSE_E4typeEE4typeESS_E4typeEv Unexecuted instantiation: _ZNKR4toml2v34node8ref_castINS0_5arrayEEENSt3__111conditionalILb1ENS5_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS7_8copy_cv_INS7_12node_wrapperIu20__remove_reference_tIS6_EE4typeEKS1_E4typeES6_E4typeENS8_INS8_INS9_Iu20__remove_reference_tISD_ESE_E4typeESD_E4typeERSE_E4typeEE4typeESS_E4typeEv Unexecuted instantiation: _ZNKR4toml2v34node8ref_castINSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEENS3_11conditionalILb1ENSA_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INSC_8copy_cv_INSC_12node_wrapperIu20__remove_reference_tISB_EE4typeEKS1_E4typeESB_E4typeENSD_INSD_INSE_Iu20__remove_reference_tISI_ESJ_E4typeESI_E4typeERSJ_E4typeEE4typeESX_E4typeEv Unexecuted instantiation: _ZNKR4toml2v34node8ref_castIlEENSt3__111conditionalILb1ENS4_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS6_8copy_cv_INS6_12node_wrapperIu20__remove_reference_tIS5_EE4typeEKS1_E4typeES5_E4typeENS7_INS7_INS8_Iu20__remove_reference_tISC_ESD_E4typeESC_E4typeERSD_E4typeEE4typeESR_E4typeEv Unexecuted instantiation: _ZNKR4toml2v34node8ref_castIdEENSt3__111conditionalILb1ENS4_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS6_8copy_cv_INS6_12node_wrapperIu20__remove_reference_tIS5_EE4typeEKS1_E4typeES5_E4typeENS7_INS7_INS8_Iu20__remove_reference_tISC_ESD_E4typeESC_E4typeERSD_E4typeEE4typeESR_E4typeEv Unexecuted instantiation: _ZNKR4toml2v34node8ref_castIbEENSt3__111conditionalILb1ENS4_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS6_8copy_cv_INS6_12node_wrapperIu20__remove_reference_tIS5_EE4typeEKS1_E4typeES5_E4typeENS7_INS7_INS8_Iu20__remove_reference_tISC_ESD_E4typeESC_E4typeERSD_E4typeEE4typeESR_E4typeEv Unexecuted instantiation: _ZNKR4toml2v34node8ref_castINS0_4dateEEENSt3__111conditionalILb1ENS5_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS7_8copy_cv_INS7_12node_wrapperIu20__remove_reference_tIS6_EE4typeEKS1_E4typeES6_E4typeENS8_INS8_INS9_Iu20__remove_reference_tISD_ESE_E4typeESD_E4typeERSE_E4typeEE4typeESS_E4typeEv Unexecuted instantiation: _ZNKR4toml2v34node8ref_castINS0_4timeEEENSt3__111conditionalILb1ENS5_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS7_8copy_cv_INS7_12node_wrapperIu20__remove_reference_tIS6_EE4typeEKS1_E4typeES6_E4typeENS8_INS8_INS9_Iu20__remove_reference_tISD_ESE_E4typeESD_E4typeERSE_E4typeEE4typeESS_E4typeEv Unexecuted instantiation: _ZNKR4toml2v34node8ref_castINS0_6stdopt9date_timeEEENSt3__111conditionalILb1ENS6_IXsr3stdE14is_reference_vIT_EENS0_4impl9copy_ref_INS8_8copy_cv_INS8_12node_wrapperIu20__remove_reference_tIS7_EE4typeEKS1_E4typeES7_E4typeENS9_INS9_INSA_Iu20__remove_reference_tISE_ESF_E4typeESE_E4typeERSF_E4typeEE4typeEST_E4typeEv |
133 | | |
134 | | template <typename T> |
135 | | TOML_PURE_INLINE_GETTER |
136 | | ref_cast_type<T, const node&&> ref_cast() const&& noexcept |
137 | | { |
138 | | using out_ref = ref_cast_type<T, const node&&>; |
139 | | using out_type = std::remove_reference_t<out_ref>; |
140 | | return static_cast<out_ref>(*reinterpret_cast<out_type*>(this)); |
141 | | } |
142 | | |
143 | | /// \endcond |
144 | | |
145 | | public: |
146 | | TOML_EXPORTED_MEMBER_FUNCTION |
147 | | virtual ~node() noexcept; |
148 | | |
149 | | /// \name Type checks |
150 | | /// @{ |
151 | | |
152 | | /// \brief Checks if a node contains values/elements of only one type. |
153 | | /// |
154 | | /// \detail \cpp |
155 | | /// auto cfg = toml::parse("arr = [ 1, 2, 3, 4.0 ]"); |
156 | | /// toml::array& arr = *cfg["arr"].as_array(); |
157 | | /// |
158 | | /// toml::node* nonmatch{}; |
159 | | /// if (arr.is_homogeneous(toml::node_type::integer, nonmatch)) |
160 | | /// std::cout << "array was homogeneous"sv << "\n"; |
161 | | /// else |
162 | | /// std::cout << "array was not homogeneous!\n" |
163 | | /// << "first non-match was a "sv << nonmatch->type() << " at " << nonmatch->source() << "\n"; |
164 | | /// \ecpp |
165 | | /// |
166 | | /// \out |
167 | | /// array was not homogeneous! |
168 | | /// first non-match was a floating-point at line 1, column 18 |
169 | | /// \eout |
170 | | /// |
171 | | /// \param ntype A TOML node type. <br> |
172 | | /// \conditional_return{toml::node_type::none} |
173 | | /// "is every element the same type?" |
174 | | /// \conditional_return{Anything else} |
175 | | /// "is every element one of these?" |
176 | | /// |
177 | | /// \param first_nonmatch Reference to a pointer in which the address of the first non-matching element |
178 | | /// will be stored if the return value is false. |
179 | | /// |
180 | | /// \returns True if the node was homogeneous. |
181 | | /// |
182 | | /// \remarks Always returns `false` for empty tables and arrays. |
183 | | TOML_NODISCARD |
184 | | virtual bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept = 0; |
185 | | |
186 | | /// \brief Checks if a node contains values/elements of only one type (const overload). |
187 | | TOML_NODISCARD |
188 | | virtual bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept = 0; |
189 | | |
190 | | /// \brief Checks if the node contains values/elements of only one type. |
191 | | /// |
192 | | /// \detail \cpp |
193 | | /// auto arr = toml::array{ 1, 2, 3 }; |
194 | | /// std::cout << "homogenous: "sv << arr.is_homogeneous(toml::node_type::none) << "\n"; |
195 | | /// std::cout << "all floats: "sv << arr.is_homogeneous(toml::node_type::floating_point) << "\n"; |
196 | | /// std::cout << "all arrays: "sv << arr.is_homogeneous(toml::node_type::array) << "\n"; |
197 | | /// std::cout << "all ints: "sv << arr.is_homogeneous(toml::node_type::integer) << "\n"; |
198 | | /// \ecpp |
199 | | /// |
200 | | /// \out |
201 | | /// homogeneous: true |
202 | | /// all floats: false |
203 | | /// all arrays: false |
204 | | /// all ints: true |
205 | | /// \eout |
206 | | /// |
207 | | /// \param ntype A TOML node type. <br> |
208 | | /// \conditional_return{toml::node_type::none} |
209 | | /// "is every element the same type?" |
210 | | /// \conditional_return{Anything else} |
211 | | /// "is every element one of these?" |
212 | | /// |
213 | | /// \returns True if the node was homogeneous. |
214 | | /// |
215 | | /// \remarks Always returns `false` for empty tables and arrays. |
216 | | TOML_PURE_GETTER |
217 | | virtual bool is_homogeneous(node_type ntype) const noexcept = 0; |
218 | | |
219 | | /// \brief Checks if the node contains values/elements of only one type. |
220 | | /// |
221 | | /// \detail \cpp |
222 | | /// auto arr = toml::array{ 1, 2, 3 }; |
223 | | /// std::cout << "homogenous: "sv << arr.is_homogeneous() << "\n"; |
224 | | /// std::cout << "all doubles: "sv << arr.is_homogeneous<double>() << "\n"; |
225 | | /// std::cout << "all arrays: "sv << arr.is_homogeneous<toml::array>() << "\n"; |
226 | | /// std::cout << "all integers: "sv << arr.is_homogeneous<int64_t>() << "\n"; |
227 | | /// \ecpp |
228 | | /// |
229 | | /// \out |
230 | | /// homogeneous: true |
231 | | /// all floats: false |
232 | | /// all arrays: false |
233 | | /// all ints: true |
234 | | /// \eout |
235 | | /// |
236 | | /// \tparam ElemType A TOML node or value type. <br> |
237 | | /// \conditional_return{Left as `void`} |
238 | | /// "is every element the same type?" <br> |
239 | | /// \conditional_return{Explicitly specified} |
240 | | /// "is every element a T?" |
241 | | /// |
242 | | /// \returns True if the node was homogeneous. |
243 | | /// |
244 | | /// \remarks Always returns `false` for empty tables and arrays. |
245 | | template <typename ElemType = void> |
246 | | TOML_PURE_GETTER |
247 | | bool is_homogeneous() const noexcept |
248 | | { |
249 | | using type = impl::remove_cvref<impl::unwrap_node<ElemType>>; |
250 | | static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>, |
251 | | "The template type argument of node::is_homogeneous() must be void or one " |
252 | | "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); |
253 | | |
254 | | return is_homogeneous(impl::node_type_of<type>); |
255 | | } |
256 | | |
257 | | /// \brief Returns the node's type identifier. |
258 | | TOML_PURE_GETTER |
259 | | virtual node_type type() const noexcept TOML_NVCC_WORKAROUND; |
260 | | |
261 | | /// \brief Returns true if this node is a table. |
262 | | TOML_PURE_GETTER |
263 | | virtual bool is_table() const noexcept TOML_NVCC_WORKAROUND; |
264 | | |
265 | | /// \brief Returns true if this node is an array. |
266 | | TOML_PURE_GETTER |
267 | | virtual bool is_array() const noexcept = 0; |
268 | | |
269 | | /// \brief Returns true if this node is an array containing only tables. |
270 | | TOML_PURE_GETTER |
271 | | virtual bool is_array_of_tables() const noexcept TOML_NVCC_WORKAROUND; |
272 | | |
273 | | /// \brief Returns true if this node is a value. |
274 | | TOML_PURE_GETTER |
275 | | virtual bool is_value() const noexcept = 0; |
276 | | |
277 | | /// \brief Returns true if this node is a string value. |
278 | | TOML_PURE_GETTER |
279 | | virtual bool is_string() const noexcept = 0; |
280 | | |
281 | | /// \brief Returns true if this node is an integer value. |
282 | | TOML_PURE_GETTER |
283 | | virtual bool is_integer() const noexcept = 0; |
284 | | |
285 | | /// \brief Returns true if this node is an floating-point value. |
286 | | TOML_PURE_GETTER |
287 | | virtual bool is_floating_point() const noexcept = 0; |
288 | | |
289 | | /// \brief Returns true if this node is an integer or floating-point value. |
290 | | TOML_PURE_GETTER |
291 | | virtual bool is_number() const noexcept = 0; |
292 | | |
293 | | /// \brief Returns true if this node is a boolean value. |
294 | | TOML_PURE_GETTER |
295 | | virtual bool is_boolean() const noexcept = 0; |
296 | | |
297 | | /// \brief Returns true if this node is a local date value. |
298 | | TOML_PURE_GETTER |
299 | | virtual bool is_date() const noexcept = 0; |
300 | | |
301 | | /// \brief Returns true if this node is a local time value. |
302 | | TOML_PURE_GETTER |
303 | | virtual bool is_time() const noexcept = 0; |
304 | | |
305 | | /// \brief Returns true if this node is a date-time value. |
306 | | TOML_PURE_GETTER |
307 | | virtual bool is_date_time() const noexcept = 0; |
308 | | |
309 | | /// \brief Checks if a node is a specific type. |
310 | | /// |
311 | | /// \tparam T A TOML node or value type. |
312 | | /// |
313 | | /// \returns Returns true if this node is an instance of the specified type. |
314 | | template <typename T> |
315 | | TOML_PURE_INLINE_GETTER |
316 | | bool is() const noexcept |
317 | | { |
318 | | using type = impl::remove_cvref<impl::unwrap_node<T>>; |
319 | | static_assert(toml::is_value<type> || toml::is_container<type>, |
320 | | "The template type argument of node::is() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); |
321 | | |
322 | | if constexpr (std::is_same_v<type, table>) |
323 | | return is_table(); |
324 | | else if constexpr (std::is_same_v<type, array>) |
325 | | return is_array(); |
326 | | else if constexpr (std::is_same_v<type, std::string>) |
327 | | return is_string(); |
328 | | else if constexpr (std::is_same_v<type, int64_t>) |
329 | | return is_integer(); |
330 | | else if constexpr (std::is_same_v<type, double>) |
331 | | return is_floating_point(); |
332 | | else if constexpr (std::is_same_v<type, bool>) |
333 | | return is_boolean(); |
334 | | else if constexpr (std::is_same_v<type, date>) |
335 | | return is_date(); |
336 | | else if constexpr (std::is_same_v<type, time>) |
337 | | return is_time(); |
338 | | else if constexpr (std::is_same_v<type, date_time>) |
339 | | return is_date_time(); |
340 | | |
341 | | TOML_UNREACHABLE; |
342 | | } |
343 | | |
344 | | /// @} |
345 | | |
346 | | /// \name Type casts |
347 | | /// @{ |
348 | | |
349 | | /// \brief Returns a pointer to the node as a toml::table, if it is one. |
350 | | TOML_PURE_GETTER |
351 | | virtual table* as_table() noexcept = 0; |
352 | | |
353 | | /// \brief Returns a pointer to the node as a toml::array, if it is one. |
354 | | TOML_PURE_GETTER |
355 | | virtual array* as_array() noexcept = 0; |
356 | | |
357 | | /// \brief Returns a pointer to the node as a toml::value<std::string>, if it is one. |
358 | | TOML_PURE_GETTER |
359 | | virtual toml::value<std::string>* as_string() noexcept = 0; |
360 | | |
361 | | /// \brief Returns a pointer to the node as a toml::value<int64_t>, if it is one. |
362 | | TOML_PURE_GETTER |
363 | | virtual toml::value<int64_t>* as_integer() noexcept = 0; |
364 | | |
365 | | /// \brief Returns a pointer to the node as a toml::value<double>, if it is one. |
366 | | TOML_PURE_GETTER |
367 | | virtual toml::value<double>* as_floating_point() noexcept = 0; |
368 | | |
369 | | /// \brief Returns a pointer to the node as a toml::value<bool>, if it is one. |
370 | | TOML_PURE_GETTER |
371 | | virtual toml::value<bool>* as_boolean() noexcept = 0; |
372 | | |
373 | | /// \brief Returns a pointer to the node as a toml::value<toml::date>, if it is one. |
374 | | TOML_PURE_GETTER |
375 | | virtual toml::value<date>* as_date() noexcept = 0; |
376 | | |
377 | | /// \brief Returns a pointer to the node as a toml::value<toml::time>, if it is one. |
378 | | TOML_PURE_GETTER |
379 | | virtual toml::value<time>* as_time() noexcept = 0; |
380 | | |
381 | | /// \brief Returns a pointer to the node as a toml::value<toml::date_time>, if it is one. |
382 | | TOML_PURE_GETTER |
383 | | virtual toml::value<date_time>* as_date_time() noexcept = 0; |
384 | | |
385 | | /// \brief Returns a const-qualified pointer to the node as a toml::table, if it is one. |
386 | | TOML_PURE_GETTER |
387 | | virtual const table* as_table() const noexcept = 0; |
388 | | |
389 | | /// \brief Returns a const-qualified pointer to the node as a toml::array, if it is one. |
390 | | TOML_PURE_GETTER |
391 | | virtual const array* as_array() const noexcept = 0; |
392 | | |
393 | | /// \brief Returns a const-qualified pointer to the node as a toml::value<std::string>, if it is one. |
394 | | TOML_PURE_GETTER |
395 | | virtual const toml::value<std::string>* as_string() const noexcept = 0; |
396 | | |
397 | | /// \brief Returns a const-qualified pointer to the node as a toml::value<int64_t>, if it is one. |
398 | | TOML_PURE_GETTER |
399 | | virtual const toml::value<int64_t>* as_integer() const noexcept = 0; |
400 | | |
401 | | /// \brief Returns a const-qualified pointer to the node as a toml::value<double>, if it is one. |
402 | | TOML_PURE_GETTER |
403 | | virtual const toml::value<double>* as_floating_point() const noexcept = 0; |
404 | | |
405 | | /// \brief Returns a const-qualified pointer to the node as a toml::value<bool>, if it is one. |
406 | | TOML_PURE_GETTER |
407 | | virtual const toml::value<bool>* as_boolean() const noexcept = 0; |
408 | | |
409 | | /// \brief Returns a const-qualified pointer to the node as a toml::value<toml::date>, if it is one. |
410 | | TOML_PURE_GETTER |
411 | | virtual const toml::value<date>* as_date() const noexcept = 0; |
412 | | |
413 | | /// \brief Returns a const-qualified pointer to the node as a toml::value<toml::time>, if it is one. |
414 | | TOML_PURE_GETTER |
415 | | virtual const toml::value<time>* as_time() const noexcept = 0; |
416 | | |
417 | | /// \brief Returns a const-qualified pointer to the node as a toml::value<toml::date_time>, if it is one. |
418 | | TOML_PURE_GETTER |
419 | | virtual const toml::value<date_time>* as_date_time() const noexcept = 0; |
420 | | |
421 | | /// \brief Gets a pointer to the node as a more specific node type. |
422 | | /// |
423 | | /// \details \cpp |
424 | | /// |
425 | | /// toml::value<int64_t>* int_value = node->as<int64_t>(); |
426 | | /// toml::table* tbl = node->as<toml::table>(); |
427 | | /// if (int_value) |
428 | | /// std::cout << "Node is a value<int64_t>\n"; |
429 | | /// else if (tbl) |
430 | | /// std::cout << "Node is a table\n"; |
431 | | /// |
432 | | /// // fully-qualified value node types also work (useful for template code): |
433 | | /// toml::value<int64_t>* int_value2 = node->as<toml::value<int64_t>>(); |
434 | | /// if (int_value2) |
435 | | /// std::cout << "Node is a value<int64_t>\n"; |
436 | | /// \ecpp |
437 | | /// |
438 | | /// \tparam T The node type or TOML value type to cast to. |
439 | | /// |
440 | | /// \returns A pointer to the node as the given type, or nullptr if it was a different type. |
441 | | template <typename T> |
442 | | TOML_PURE_INLINE_GETTER |
443 | | impl::wrap_node<T>* as() noexcept |
444 | 0 | { |
445 | 0 | using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>; |
446 | 0 | static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>, |
447 | 0 | "The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); |
448 | 0 |
|
449 | 0 | if constexpr (std::is_same_v<unwrapped_type, table>) |
450 | 0 | return as_table(); |
451 | 0 | else if constexpr (std::is_same_v<unwrapped_type, array>) |
452 | 0 | return as_array(); |
453 | 0 | else if constexpr (std::is_same_v<unwrapped_type, std::string>) |
454 | 0 | return as_string(); |
455 | 0 | else if constexpr (std::is_same_v<unwrapped_type, int64_t>) |
456 | 0 | return as_integer(); |
457 | 0 | else if constexpr (std::is_same_v<unwrapped_type, double>) |
458 | 0 | return as_floating_point(); |
459 | 0 | else if constexpr (std::is_same_v<unwrapped_type, bool>) |
460 | 0 | return as_boolean(); |
461 | 0 | else if constexpr (std::is_same_v<unwrapped_type, date>) |
462 | 0 | return as_date(); |
463 | 0 | else if constexpr (std::is_same_v<unwrapped_type, time>) |
464 | 0 | return as_time(); |
465 | 0 | else if constexpr (std::is_same_v<unwrapped_type, date_time>) |
466 | 0 | return as_date_time(); |
467 | 0 |
|
468 | 0 | TOML_UNREACHABLE; |
469 | 0 | } Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::table>::type* toml::v3::node::as<toml::v3::table>() Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::array>::type* toml::v3::node::as<toml::v3::array>() |
470 | | |
471 | | /// \brief Gets a pointer to the node as a more specific node type (const overload). |
472 | | template <typename T> |
473 | | TOML_PURE_INLINE_GETTER |
474 | | const impl::wrap_node<T>* as() const noexcept |
475 | 0 | { |
476 | 0 | using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>; |
477 | 0 | static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>, |
478 | 0 | "The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); |
479 | 0 |
|
480 | 0 | if constexpr (std::is_same_v<unwrapped_type, table>) |
481 | 0 | return as_table(); |
482 | 0 | else if constexpr (std::is_same_v<unwrapped_type, array>) |
483 | 0 | return as_array(); |
484 | 0 | else if constexpr (std::is_same_v<unwrapped_type, std::string>) |
485 | 0 | return as_string(); |
486 | 0 | else if constexpr (std::is_same_v<unwrapped_type, int64_t>) |
487 | 0 | return as_integer(); |
488 | 0 | else if constexpr (std::is_same_v<unwrapped_type, double>) |
489 | 0 | return as_floating_point(); |
490 | 0 | else if constexpr (std::is_same_v<unwrapped_type, bool>) |
491 | 0 | return as_boolean(); |
492 | 0 | else if constexpr (std::is_same_v<unwrapped_type, date>) |
493 | 0 | return as_date(); |
494 | 0 | else if constexpr (std::is_same_v<unwrapped_type, time>) |
495 | 0 | return as_time(); |
496 | 0 | else if constexpr (std::is_same_v<unwrapped_type, date_time>) |
497 | 0 | return as_date_time(); |
498 | 0 |
|
499 | 0 | TOML_UNREACHABLE; |
500 | 0 | } Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::table>::type const* toml::v3::node::as<toml::v3::table>() const Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::array>::type const* toml::v3::node::as<toml::v3::array>() const Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::type const* toml::v3::node::as<toml::v3::value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >() const Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::value<long> >::type const* toml::v3::node::as<toml::v3::value<long> >() const Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::value<double> >::type const* toml::v3::node::as<toml::v3::value<double> >() const Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::value<bool> >::type const* toml::v3::node::as<toml::v3::value<bool> >() const Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::value<toml::v3::date> >::type const* toml::v3::node::as<toml::v3::value<toml::v3::date> >() const Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::value<toml::v3::time> >::type const* toml::v3::node::as<toml::v3::value<toml::v3::time> >() const Unexecuted instantiation: toml::v3::impl::node_wrapper<__remove_reference_t, toml::v3::value<toml::v3::stdopt::date_time> >::type const* toml::v3::node::as<toml::v3::value<toml::v3::stdopt::date_time> >() const |
501 | | |
502 | | /// @} |
503 | | |
504 | | /// \name Value retrieval |
505 | | /// @{ |
506 | | |
507 | | /// \brief Gets the value contained by this node. |
508 | | /// |
509 | | /// \detail This function has 'exact' retrieval semantics; the only return value types allowed are the |
510 | | /// TOML native value types, or types that can losslessly represent a native value type (e.g. |
511 | | /// std::wstring on Windows). |
512 | | /// |
513 | | /// \tparam T One of the native TOML value types, or a type capable of losslessly representing one. |
514 | | /// |
515 | | /// \returns The underlying value if the node was a value of the |
516 | | /// matching type (or losslessly convertible to it), or an empty optional. |
517 | | /// |
518 | | /// \see node::value() |
519 | | template <typename T> |
520 | | TOML_NODISCARD |
521 | | optional<T> value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>); |
522 | | |
523 | | /// \brief Gets the value contained by this node. |
524 | | /// |
525 | | /// \detail This function has 'permissive' retrieval semantics; some value types are allowed |
526 | | /// to convert to others (e.g. retrieving a boolean as an integer), and the specified return value |
527 | | /// type can be any type where a reasonable conversion from a native TOML value exists |
528 | | /// (e.g. std::wstring on Windows). If the source value cannot be represented by |
529 | | /// the destination type, an empty optional is returned. |
530 | | /// |
531 | | /// \godbolt{zzG81K} |
532 | | /// |
533 | | /// \cpp |
534 | | /// auto tbl = toml::parse(R"( |
535 | | /// int = -10 |
536 | | /// flt = 25.0 |
537 | | /// pi = 3.14159 |
538 | | /// bool = false |
539 | | /// huge = 9223372036854775807 |
540 | | /// str = "foo" |
541 | | /// )"sv); |
542 | | /// |
543 | | /// const auto print_value_with_typename = |
544 | | /// [&](std::string_view key, std::string_view type_name, auto* dummy) |
545 | | /// { |
546 | | /// std::cout << "- " << std::setw(18) << std::left << type_name; |
547 | | /// using type = std::remove_pointer_t<decltype(dummy)>; |
548 | | /// if (auto val = tbl.get(key)->value<type>(); val) |
549 | | /// std::cout << *val << "\n"; |
550 | | /// else |
551 | | /// std::cout << "n/a\n"; |
552 | | /// }; |
553 | | /// |
554 | | /// #define print_value(key, T) print_value_with_typename(key, #T, (T*)nullptr) |
555 | | /// |
556 | | /// for (auto key : { "int", "flt", "pi", "bool", "huge", "str" }) |
557 | | /// { |
558 | | /// std::cout << tbl[key].type() << " value '" << key << "' as:\n"; |
559 | | /// print_value(key, bool); |
560 | | /// print_value(key, int); |
561 | | /// print_value(key, unsigned int); |
562 | | /// print_value(key, long long); |
563 | | /// print_value(key, float); |
564 | | /// print_value(key, double); |
565 | | /// print_value(key, std::string); |
566 | | /// print_value(key, std::string_view); |
567 | | /// print_value(key, const char*); |
568 | | /// std::cout << "\n"; |
569 | | /// } |
570 | | /// \ecpp |
571 | | /// |
572 | | /// \out |
573 | | /// integer value 'int' as: |
574 | | /// - bool true |
575 | | /// - int -10 |
576 | | /// - unsigned int n/a |
577 | | /// - long long -10 |
578 | | /// - float -10 |
579 | | /// - double -10 |
580 | | /// - std::string n/a |
581 | | /// - std::string_view n/a |
582 | | /// - const char* n/a |
583 | | /// |
584 | | /// floating-point value 'flt' as: |
585 | | /// - bool n/a |
586 | | /// - int 25 |
587 | | /// - unsigned int 25 |
588 | | /// - long long 25 |
589 | | /// - float 25 |
590 | | /// - double 25 |
591 | | /// - std::string n/a |
592 | | /// - std::string_view n/a |
593 | | /// - const char* n/a |
594 | | /// |
595 | | /// floating-point value 'pi' as: |
596 | | /// - bool n/a |
597 | | /// - int n/a |
598 | | /// - unsigned int n/a |
599 | | /// - long long n/a |
600 | | /// - float 3.14159 |
601 | | /// - double 3.14159 |
602 | | /// - std::string n/a |
603 | | /// - std::string_view n/a |
604 | | /// - const char* n/a |
605 | | /// |
606 | | /// boolean value 'bool' as: |
607 | | /// - bool false |
608 | | /// - int 0 |
609 | | /// - unsigned int 0 |
610 | | /// - long long 0 |
611 | | /// - float n/a |
612 | | /// - double n/a |
613 | | /// - std::string n/a |
614 | | /// - std::string_view n/a |
615 | | /// - const char* n/a |
616 | | /// |
617 | | /// integer value 'huge' as: |
618 | | /// - bool true |
619 | | /// - int n/a |
620 | | /// - unsigned int n/a |
621 | | /// - long long 9223372036854775807 |
622 | | /// - float n/a |
623 | | /// - double n/a |
624 | | /// - std::string n/a |
625 | | /// - std::string_view n/a |
626 | | /// - const char* n/a |
627 | | /// |
628 | | /// string value 'str' as: |
629 | | /// - bool n/a |
630 | | /// - int n/a |
631 | | /// - unsigned int n/a |
632 | | /// - long long n/a |
633 | | /// - float n/a |
634 | | /// - double n/a |
635 | | /// - std::string foo |
636 | | /// - std::string_view foo |
637 | | /// - const char* foo |
638 | | /// \eout |
639 | | /// |
640 | | /// \tparam T One of the native TOML value types, or a type capable of converting to one. |
641 | | /// |
642 | | /// \returns The underlying value if the node was a value of the matching type (or convertible to it) |
643 | | /// and within the range of the output type, or an empty optional. |
644 | | /// |
645 | | /// \note If you want strict value retrieval semantics that do not allow for any type conversions, |
646 | | /// use node::value_exact() instead. |
647 | | /// |
648 | | /// \see node::value_exact() |
649 | | template <typename T> |
650 | | TOML_NODISCARD |
651 | | optional<T> value() const noexcept(impl::value_retrieval_is_nothrow<T>); |
652 | | |
653 | | /// \brief Gets the raw value contained by this node, or a default. |
654 | | /// |
655 | | /// \tparam T Default value type. Must be one of the native TOML value types, |
656 | | /// or convertible to it. |
657 | | /// \param default_value The default value to return if the node wasn't a value, wasn't the |
658 | | /// correct type, or no conversion was possible. |
659 | | /// |
660 | | /// \returns The underlying value if the node was a value of the matching type (or convertible to it) |
661 | | /// and within the range of the output type, or the provided default. |
662 | | /// |
663 | | /// \note This function has the same permissive retrieval semantics as node::value(). If you want strict |
664 | | /// value retrieval semantics that do not allow for any type conversions, use node::value_exact() |
665 | | /// instead. |
666 | | /// |
667 | | /// \see |
668 | | /// - node::value() |
669 | | /// - node::value_exact() |
670 | | template <typename T> |
671 | | TOML_NODISCARD |
672 | | auto value_or(T&& default_value) const noexcept(impl::value_retrieval_is_nothrow<T>); |
673 | | |
674 | | /// \brief Gets a raw reference to a node's underlying data. |
675 | | /// |
676 | | /// \warning This function is dangerous if used carelessly and **WILL** break your code if the |
677 | | /// chosen value type doesn't match the node's actual type. In debug builds an assertion |
678 | | /// will fire when invalid accesses are attempted: \cpp |
679 | | /// |
680 | | /// auto tbl = toml::parse(R"( |
681 | | /// min = 32 |
682 | | /// max = 45 |
683 | | /// )"sv); |
684 | | /// |
685 | | /// int64_t& min_ref = tbl.at("min").ref<int64_t>(); // matching type |
686 | | /// double& max_ref = tbl.at("max").ref<double>(); // mismatched type, hits assert() |
687 | | /// \ecpp |
688 | | /// |
689 | | /// \note Specifying explicit ref qualifiers acts as an explicit ref-category cast, |
690 | | /// whereas specifying explicit cv-ref qualifiers merges them with whatever |
691 | | /// the cv qualification of the node is (to ensure cv-correctness is propagated), e.g.: |
692 | | /// | node | T | return type | |
693 | | /// |-------------|------------------------|------------------------------| |
694 | | /// | node& | std::string | std::string& | |
695 | | /// | node& | std::string&& | std::string&& | |
696 | | /// | const node& | volatile std::string | const volatile std::string& | |
697 | | /// | const node& | volatile std::string&& | const volatile std::string&& | |
698 | | /// |
699 | | /// \tparam T toml::table, toml::array, or one of the TOML value types. |
700 | | /// |
701 | | /// \returns A reference to the underlying data. |
702 | | template <typename T> |
703 | | TOML_PURE_GETTER |
704 | | decltype(auto) ref() & noexcept |
705 | | { |
706 | | return do_ref<T>(*this); |
707 | | } |
708 | | |
709 | | /// \brief Gets a raw reference to a node's underlying data (rvalue overload). |
710 | | template <typename T> |
711 | | TOML_PURE_GETTER |
712 | | decltype(auto) ref() && noexcept |
713 | | { |
714 | | return do_ref<T>(std::move(*this)); |
715 | | } |
716 | | |
717 | | /// \brief Gets a raw reference to a node's underlying data (const lvalue overload). |
718 | | template <typename T> |
719 | | TOML_PURE_GETTER |
720 | | decltype(auto) ref() const& noexcept |
721 | | { |
722 | | return do_ref<T>(*this); |
723 | | } |
724 | | |
725 | | /// \brief Gets a raw reference to a node's underlying data (const rvalue overload). |
726 | | template <typename T> |
727 | | TOML_PURE_GETTER |
728 | | decltype(auto) ref() const&& noexcept |
729 | | { |
730 | | return do_ref<T>(std::move(*this)); |
731 | | } |
732 | | |
733 | | /// @} |
734 | | |
735 | | /// \name Metadata |
736 | | /// @{ |
737 | | |
738 | | /// \brief Returns the source region responsible for generating this node during parsing. |
739 | | TOML_PURE_INLINE_GETTER |
740 | | const source_region& source() const noexcept |
741 | 778k | { |
742 | 778k | return source_; |
743 | 778k | } |
744 | | |
745 | | /// @} |
746 | | |
747 | | private: |
748 | | /// \cond |
749 | | |
750 | | template <typename Func, typename Node, typename T> |
751 | | static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<T, Node>>; |
752 | | |
753 | | template <typename Func, typename Node, typename T> |
754 | | static constexpr bool can_visit_nothrow = std::is_nothrow_invocable_v<Func, ref_cast_type<T, Node>>; |
755 | | |
756 | | template <typename Func, typename Node> |
757 | | static constexpr bool can_visit_any = can_visit<Func, Node, table> // |
758 | | || can_visit<Func, Node, array> // |
759 | | || can_visit<Func, Node, std::string> // |
760 | | || can_visit<Func, Node, int64_t> // |
761 | | || can_visit<Func, Node, double> // |
762 | | || can_visit<Func, Node, bool> // |
763 | | || can_visit<Func, Node, date> // |
764 | | || can_visit<Func, Node, time> // |
765 | | || can_visit<Func, Node, date_time>; |
766 | | |
767 | | // clang-format off |
768 | | |
769 | | template <typename Func, typename Node> |
770 | | static constexpr bool can_visit_all = can_visit<Func, Node, table> // |
771 | | && can_visit<Func, Node, array> // |
772 | | && can_visit<Func, Node, std::string> // |
773 | | && can_visit<Func, Node, int64_t> // |
774 | | && can_visit<Func, Node, double> // |
775 | | && can_visit<Func, Node, bool> // |
776 | | && can_visit<Func, Node, date> // |
777 | | && can_visit<Func, Node, time> // |
778 | | && can_visit<Func, Node, date_time>; |
779 | | |
780 | | template <typename Func, typename Node, typename T> |
781 | | static constexpr bool visit_is_nothrow_one = !can_visit<Func, Node, T> || can_visit_nothrow<Func, Node, T>; |
782 | | |
783 | | template <typename Func, typename Node> |
784 | | static constexpr bool visit_is_nothrow = visit_is_nothrow_one<Func, Node, table> // |
785 | | && visit_is_nothrow_one<Func, Node, array> // |
786 | | && visit_is_nothrow_one<Func, Node, std::string> // |
787 | | && visit_is_nothrow_one<Func, Node, int64_t> // |
788 | | && visit_is_nothrow_one<Func, Node, double> // |
789 | | && visit_is_nothrow_one<Func, Node, bool> // |
790 | | && visit_is_nothrow_one<Func, Node, date> // |
791 | | && visit_is_nothrow_one<Func, Node, time> // |
792 | | && visit_is_nothrow_one<Func, Node, date_time>; |
793 | | |
794 | | // clang-format on |
795 | | |
796 | | template <typename Func, typename Node, typename T, bool = can_visit<Func, Node, T>> |
797 | | struct visit_return_type_ |
798 | | { |
799 | | using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<T, Node>>())); |
800 | | }; |
801 | | template <typename Func, typename Node, typename T> |
802 | | struct visit_return_type_<Func, Node, T, false> |
803 | | { |
804 | | using type = void; |
805 | | }; |
806 | | |
807 | | template <typename Func, typename Node, typename T> |
808 | | using visit_return_type = typename visit_return_type_<Func, Node, T>::type; |
809 | | |
810 | | template <typename A, typename B> |
811 | | using nonvoid = std::conditional_t<std::is_void_v<A>, B, A>; |
812 | | |
813 | | template <typename Func, typename Node> |
814 | | static decltype(auto) do_visit(Func&& visitor, Node&& n) noexcept(visit_is_nothrow<Func&&, Node&&>) |
815 | 0 | { |
816 | 0 | static_assert(can_visit_any<Func&&, Node&&>, |
817 | 0 | "TOML node visitors must be invocable for at least one of the toml::node " |
818 | 0 | "specializations:" TOML_SA_NODE_TYPE_LIST); |
819 | 0 |
|
820 | 0 | switch (n.type()) |
821 | 0 | { |
822 | 0 | case node_type::table: |
823 | 0 | if constexpr (can_visit<Func&&, Node&&, table>) |
824 | 0 | return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<table>()); |
825 | 0 | break; |
826 | 0 |
|
827 | 0 | case node_type::array: |
828 | 0 | if constexpr (can_visit<Func&&, Node&&, array>) |
829 | 0 | return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<array>()); |
830 | 0 | break; |
831 | 0 |
|
832 | 0 | case node_type::string: |
833 | 0 | if constexpr (can_visit<Func&&, Node&&, std::string>) |
834 | 0 | return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<std::string>()); |
835 | 0 | break; |
836 | 0 |
|
837 | 0 | case node_type::integer: |
838 | 0 | if constexpr (can_visit<Func&&, Node&&, int64_t>) |
839 | 0 | return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<int64_t>()); |
840 | 0 | break; |
841 | 0 |
|
842 | 0 | case node_type::floating_point: |
843 | 0 | if constexpr (can_visit<Func&&, Node&&, double>) |
844 | 0 | return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<double>()); |
845 | 0 | break; |
846 | 0 |
|
847 | 0 | case node_type::boolean: |
848 | 0 | if constexpr (can_visit<Func&&, Node&&, bool>) |
849 | 0 | return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<bool>()); |
850 | 0 | break; |
851 | 0 |
|
852 | 0 | case node_type::date: |
853 | 0 | if constexpr (can_visit<Func&&, Node&&, date>) |
854 | 0 | return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<date>()); |
855 | 0 | break; |
856 | 0 |
|
857 | 0 | case node_type::time: |
858 | 0 | if constexpr (can_visit<Func&&, Node&&, time>) |
859 | 0 | return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<time>()); |
860 | 0 | break; |
861 | 0 |
|
862 | 0 | case node_type::date_time: |
863 | 0 | if constexpr (can_visit<Func&&, Node&&, date_time>) |
864 | 0 | return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<date_time>()); |
865 | 0 | break; |
866 | 0 |
|
867 | 0 | case node_type::none: TOML_UNREACHABLE; |
868 | 0 | default: TOML_UNREACHABLE; |
869 | 0 | } |
870 | 0 |
|
871 | 0 | if constexpr (!can_visit_all<Func&&, Node&&>) |
872 | 0 | { |
873 | 0 | // clang-format off |
874 | 0 |
|
875 | 0 | using return_type = |
876 | 0 | nonvoid<visit_return_type<Func&&, Node&&, table>, |
877 | 0 | nonvoid<visit_return_type<Func&&, Node&&, array>, |
878 | 0 | nonvoid<visit_return_type<Func&&, Node&&, std::string>, |
879 | 0 | nonvoid<visit_return_type<Func&&, Node&&, int64_t>, |
880 | 0 | nonvoid<visit_return_type<Func&&, Node&&, double>, |
881 | 0 | nonvoid<visit_return_type<Func&&, Node&&, bool>, |
882 | 0 | nonvoid<visit_return_type<Func&&, Node&&, date>, |
883 | 0 | nonvoid<visit_return_type<Func&&, Node&&, time>, |
884 | 0 | visit_return_type<Func&&, Node&&, date_time> |
885 | 0 | >>>>>>>>; |
886 | 0 |
|
887 | 0 | // clang-format on |
888 | 0 |
|
889 | 0 | if constexpr (!std::is_void_v<return_type>) |
890 | 0 | { |
891 | 0 | static_assert(std::is_default_constructible_v<return_type>, |
892 | 0 | "Non-exhaustive visitors must return a default-constructible type, or void"); |
893 | 0 | return return_type{}; |
894 | 0 | } |
895 | 0 | } |
896 | 0 | } Unexecuted instantiation: decltype(auto) toml::v3::node::do_visit<toml::v3::impl::node_deep_equality(toml::v3::node const*, toml::v3::node const*)::{lambda(auto:1&)#1}, toml::v3::node const&>(toml::v3::impl::node_deep_equality(toml::v3::node const*, toml::v3::node const*)::{lambda(auto:1&)#1}&&, toml::v3::node const&) Unexecuted instantiation: decltype(auto) toml::v3::node::do_visit<toml::v3::array::equal(toml::v3::array const&, toml::v3::array const&)::{lambda(auto:1 const&)#1}, toml::v3::node&>(toml::v3::array::equal(toml::v3::array const&, toml::v3::array const&)::{lambda(auto:1 const&)#1}&&, toml::v3::node&) Unexecuted instantiation: decltype(auto) toml::v3::node::do_visit<toml::v3::table::equal(toml::v3::table const&, toml::v3::table const&)::{lambda(auto:1 const&)#1}, toml::v3::node&>(toml::v3::table::equal(toml::v3::table const&, toml::v3::table const&)::{lambda(auto:1 const&)#1}&&, toml::v3::node&) Unexecuted instantiation: decltype(auto) toml::v3::node::do_visit<toml::v3::impl::make_node_impl<toml::v3::node const&>(toml::v3::node const&, toml::v3::value_flags)::{lambda(auto:1&&)#1}, toml::v3::node const&>(toml::v3::node const&, toml::v3::node const&) Unexecuted instantiation: decltype(auto) toml::v3::node::do_visit<toml::v3::impl::make_node_impl<toml::v3::node&>(toml::v3::node&, toml::v3::value_flags)::{lambda(auto:1&&)#1}, toml::v3::node&>(toml::v3::node&, toml::v3::node&) |
897 | | |
898 | | /// \endcond |
899 | | |
900 | | public: |
901 | | /// \name Visitation |
902 | | /// @{ |
903 | | |
904 | | /// \brief Invokes a visitor on the node based on the node's concrete type. |
905 | | /// |
906 | | /// \details Visitation is useful when you expect |
907 | | /// a node to be one of a set number of types and need |
908 | | /// to handle these types differently. Using `visit()` allows |
909 | | /// you to eliminate some of the casting/conversion boilerplate: \cpp |
910 | | /// |
911 | | /// node.visit([](auto&& n) |
912 | | /// { |
913 | | /// if constexpr (toml::is_string<decltype(n)>) |
914 | | /// do_something_with_a_string(*n)); //n is a toml::value<std::string> |
915 | | /// else if constexpr (toml::is_integer<decltype(n)>) |
916 | | /// do_something_with_an_int(*n); //n is a toml::value<int64_t> |
917 | | /// }); |
918 | | /// \ecpp |
919 | | /// |
920 | | /// Visitor functions need not be generic; specifying a concrete node type as the input argument type |
921 | | /// effectively acts a 'filter', only invoking the visitor if the concrete type is compatible. |
922 | | /// Thus the example above can be re-written as: \cpp |
923 | | /// node.visit([](toml::value<std::string>& s) { do_something_with_a_string(*s)); }); |
924 | | /// node.visit([](toml::value<int64_t>& i) { do_something_with_an_int(*i)); }); |
925 | | /// \ecpp |
926 | | /// |
927 | | /// \tparam Func A callable type invocable with one or more of the toml++ node types. |
928 | | /// |
929 | | /// \param visitor The visitor object. |
930 | | /// |
931 | | /// \returns The return value of the visitor. |
932 | | /// Can be void. Non-exhaustive visitors must return a default-constructible type. |
933 | | /// |
934 | | /// \see https://en.wikipedia.org/wiki/Visitor_pattern |
935 | | template <typename Func> |
936 | | decltype(auto) visit(Func&& visitor) & noexcept(visit_is_nothrow<Func&&, node&>) |
937 | 0 | { |
938 | 0 | return do_visit(static_cast<Func&&>(visitor), *this); |
939 | 0 | } Unexecuted instantiation: decltype(auto) toml::v3::node::visit<toml::v3::array::equal(toml::v3::array const&, toml::v3::array const&)::{lambda(auto:1 const&)#1}>(toml::v3::array::equal(toml::v3::array const&, toml::v3::array const&)::{lambda(auto:1 const&)#1}&&) & Unexecuted instantiation: decltype(auto) toml::v3::node::visit<toml::v3::table::equal(toml::v3::table const&, toml::v3::table const&)::{lambda(auto:1 const&)#1}>(toml::v3::table::equal(toml::v3::table const&, toml::v3::table const&)::{lambda(auto:1 const&)#1}&&) & Unexecuted instantiation: decltype(auto) toml::v3::node::visit<toml::v3::impl::make_node_impl<toml::v3::node&>(toml::v3::node&, toml::v3::value_flags)::{lambda(auto:1&&)#1}>(toml::v3::node&) & |
940 | | |
941 | | /// \brief Invokes a visitor on the node based on the node's concrete type (rvalue overload). |
942 | | template <typename Func> |
943 | | decltype(auto) visit(Func&& visitor) && noexcept(visit_is_nothrow<Func&&, node&&>) |
944 | | { |
945 | | return do_visit(static_cast<Func&&>(visitor), static_cast<node&&>(*this)); |
946 | | } |
947 | | |
948 | | /// \brief Invokes a visitor on the node based on the node's concrete type (const lvalue overload). |
949 | | template <typename Func> |
950 | | decltype(auto) visit(Func&& visitor) const& noexcept(visit_is_nothrow<Func&&, const node&>) |
951 | 0 | { |
952 | 0 | return do_visit(static_cast<Func&&>(visitor), *this); |
953 | 0 | } Unexecuted instantiation: decltype(auto) toml::v3::node::visit<toml::v3::impl::node_deep_equality(toml::v3::node const*, toml::v3::node const*)::{lambda(auto:1&)#1}>(toml::v3::impl::node_deep_equality(toml::v3::node const*, toml::v3::node const*)::{lambda(auto:1&)#1}&&) const & Unexecuted instantiation: decltype(auto) toml::v3::node::visit<toml::v3::impl::make_node_impl<toml::v3::node const&>(toml::v3::node const&, toml::v3::value_flags)::{lambda(auto:1&&)#1}>(toml::v3::node const&) const & |
954 | | |
955 | | /// \brief Invokes a visitor on the node based on the node's concrete type (const rvalue overload). |
956 | | template <typename Func> |
957 | | decltype(auto) visit(Func&& visitor) const&& noexcept(visit_is_nothrow<Func&&, const node&&>) |
958 | | { |
959 | | return do_visit(static_cast<Func&&>(visitor), static_cast<const node&&>(*this)); |
960 | | } |
961 | | |
962 | | /// @} |
963 | | |
964 | | /// \name Node views |
965 | | /// @{ |
966 | | |
967 | | /// \brief Creates a node_view pointing to this node. |
968 | | TOML_NODISCARD |
969 | | explicit operator node_view<node>() noexcept; |
970 | | |
971 | | /// \brief Creates a node_view pointing to this node (const overload). |
972 | | TOML_NODISCARD |
973 | | explicit operator node_view<const node>() const noexcept; |
974 | | |
975 | | /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". |
976 | | /// |
977 | | /// \detail \cpp |
978 | | /// auto config = toml::parse(R"( |
979 | | /// |
980 | | /// [foo] |
981 | | /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] |
982 | | /// |
983 | | /// )"sv); |
984 | | /// |
985 | | /// std::cout << config.at_path("foo.bar[2]") << "\n"; |
986 | | /// std::cout << config.at_path("foo.bar[3][0]") << "\n"; |
987 | | /// std::cout << config.at_path("foo.bar[4].kek") << "\n"; |
988 | | /// \ecpp |
989 | | /// |
990 | | /// \out |
991 | | /// 2 |
992 | | /// 3 |
993 | | /// 4 |
994 | | /// \eout |
995 | | /// |
996 | | /// |
997 | | /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: |
998 | | /// \cpp |
999 | | /// config.at_path( "foo.bar") // same as node_view{ config }["foo"]["bar"] |
1000 | | /// config.at_path( "foo. bar") // same as node_view{ config }["foo"][" bar"] |
1001 | | /// config.at_path( "foo..bar") // same as node_view{ config }["foo"][""]["bar"] |
1002 | | /// config.at_path( ".foo.bar") // same as node_view{ config }[""]["foo"]["bar"] |
1003 | | /// \ecpp |
1004 | | /// <br> |
1005 | | /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted strings. |
1006 | | /// This function makes no allowance for this, instead treating all period characters as sub-table delimiters. |
1007 | | /// If you have periods in your table keys, first consider: |
1008 | | /// 1. Not doing that |
1009 | | /// 2. Using node_view::operator[] instead. |
1010 | | /// |
1011 | | /// \param path The "TOML path" to traverse. |
1012 | | TOML_NODISCARD |
1013 | | TOML_EXPORTED_MEMBER_FUNCTION |
1014 | | node_view<node> at_path(std::string_view path) noexcept; |
1015 | | |
1016 | | /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". |
1017 | | /// |
1018 | | /// \see #at_path(std::string_view) |
1019 | | TOML_NODISCARD |
1020 | | TOML_EXPORTED_MEMBER_FUNCTION |
1021 | | node_view<const node> at_path(std::string_view path) const noexcept; |
1022 | | |
1023 | | /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". |
1024 | | /// |
1025 | | /// \detail \cpp |
1026 | | /// auto config = toml::parse(R"( |
1027 | | /// |
1028 | | /// [foo] |
1029 | | /// bar = [ 0, 1, 2, [ 3 ], { kek = 4 } ] |
1030 | | /// |
1031 | | /// )"sv); |
1032 | | /// |
1033 | | /// toml::path path1("foo.bar[2]"); |
1034 | | /// toml::path path2("foo.bar[4].kek"); |
1035 | | /// std::cout << config.at_path(path1) << "\n"; |
1036 | | /// std::cout << config.at_path(path1.parent_path()) << "\n"; |
1037 | | /// std::cout << config.at_path(path2) << "\n"; |
1038 | | /// std::cout << config.at_path(path2.parent_path()) << "\n"; |
1039 | | /// \ecpp |
1040 | | /// |
1041 | | /// \out |
1042 | | /// 2 |
1043 | | /// [ 0, 1, 2, [ 3 ], { kek = 4 } ] |
1044 | | /// 4 |
1045 | | /// { kek = 4 } |
1046 | | /// \eout |
1047 | | /// |
1048 | | /// |
1049 | | /// \note Keys in paths are interpreted literally, so whitespace (or lack thereof) matters: |
1050 | | /// \cpp |
1051 | | /// config.at_path(toml::path("foo.bar")) // same as node_view{ config }["foo"]["bar"] |
1052 | | /// config.at_path(toml::path("foo. bar")) // same as node_view{ config }["foo"][" bar"] |
1053 | | /// config.at_path(toml::path("foo..bar")) // same as node_view{ config }["foo"][""]["bar"] |
1054 | | /// config.at_path(toml::path(".foo.bar")) // same as node_view{ config }[""]["foo"]["bar"] |
1055 | | /// \ecpp |
1056 | | /// <br> |
1057 | | /// Additionally, TOML allows '.' (period) characters to appear in keys if they are quoted strings. |
1058 | | /// This function makes no allowance for this, instead treating all period characters as sub-table delimiters. |
1059 | | /// |
1060 | | /// \param path The "TOML path" to traverse. |
1061 | | TOML_NODISCARD |
1062 | | TOML_EXPORTED_MEMBER_FUNCTION |
1063 | | node_view<node> at_path(const toml::path& path) noexcept; |
1064 | | |
1065 | | /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". |
1066 | | /// |
1067 | | /// \see #at_path(const toml::path&) |
1068 | | TOML_NODISCARD |
1069 | | TOML_EXPORTED_MEMBER_FUNCTION |
1070 | | node_view<const node> at_path(const toml::path& path) const noexcept; |
1071 | | |
1072 | | #if TOML_ENABLE_WINDOWS_COMPAT |
1073 | | |
1074 | | /// \brief Returns a view of the subnode matching a fully-qualified "TOML path". |
1075 | | /// |
1076 | | /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. |
1077 | | /// |
1078 | | /// \see #at_path(std::string_view) |
1079 | | TOML_NODISCARD |
1080 | | TOML_EXPORTED_MEMBER_FUNCTION |
1081 | | node_view<node> at_path(std::wstring_view path); |
1082 | | |
1083 | | /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". |
1084 | | /// |
1085 | | /// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled. |
1086 | | /// |
1087 | | /// \see #at_path(std::string_view) |
1088 | | TOML_NODISCARD |
1089 | | TOML_EXPORTED_MEMBER_FUNCTION |
1090 | | node_view<const node> at_path(std::wstring_view path) const; |
1091 | | |
1092 | | #endif // TOML_ENABLE_WINDOWS_COMPAT |
1093 | | |
1094 | | /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". |
1095 | | /// |
1096 | | /// \param path The "TOML path" to the desired child. |
1097 | | /// |
1098 | | /// \returns A view of the child node at the given path if one existed, or an empty node view. |
1099 | | /// |
1100 | | /// \see toml::node_view |
1101 | | TOML_NODISCARD |
1102 | | TOML_EXPORTED_MEMBER_FUNCTION |
1103 | | node_view<node> operator[](const toml::path& path) noexcept; |
1104 | | |
1105 | | /// \brief Returns a const view of the subnode matching a fully-qualified "TOML path". |
1106 | | /// |
1107 | | /// \param path The "TOML path" to the desired child. |
1108 | | /// |
1109 | | /// \returns A view of the child node at the given path if one existed, or an empty node view. |
1110 | | /// |
1111 | | /// \see toml::node_view |
1112 | | TOML_NODISCARD |
1113 | | TOML_EXPORTED_MEMBER_FUNCTION |
1114 | | node_view<const node> operator[](const toml::path& path) const noexcept; |
1115 | | |
1116 | | /// @} |
1117 | | }; |
1118 | | } |
1119 | | TOML_NAMESPACE_END; |
1120 | | |
1121 | | /// \cond |
1122 | | TOML_IMPL_NAMESPACE_START |
1123 | | { |
1124 | | TOML_PURE_GETTER |
1125 | | TOML_EXPORTED_FREE_FUNCTION |
1126 | | bool TOML_CALLCONV node_deep_equality(const node*, const node*) noexcept; |
1127 | | } |
1128 | | TOML_IMPL_NAMESPACE_END; |
1129 | | /// \endcond |
1130 | | |
1131 | | #undef TOML_NVCC_WORKAROUND |
1132 | | #include "header_end.hpp" |