NeBuild dev
Loading...
Searching...
No Matches
node.hpp
Go to the documentation of this file.
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"
9#include "source_region.hpp"
10#include "header_start.hpp"
11
13{
19 {
20 private:
22
23 friend class TOML_PARSER_TYPENAME;
24 source_region source_{};
25
26 template <typename T>
28 decltype(auto) get_value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>);
29
30 template <typename T, typename N>
31 using ref_type_ = std::conditional_t< //
32 std::is_reference_v<T>, //
33 impl::copy_ref<impl::copy_cv<impl::unwrap_node<T>, std::remove_reference_t<N>>, T>, //
34 impl::copy_cvref<impl::unwrap_node<T>, N> //
35 >;
36
37 template <typename T, typename N>
38 using ref_type = std::conditional_t< //
39 std::is_reference_v<N>, //
40 ref_type_<T, N>, //
41 ref_type_<T, std::add_lvalue_reference_t<N>> //
42 >;
43
44 template <typename T, typename N>
46 static ref_type<T, N&&> do_ref(N&& n) noexcept
47 {
48 using unwrapped_type = impl::unwrap_node<T>;
49 static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
50 "The template type argument of node::ref() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
51
53 n.template is<unwrapped_type>()
54 && "template type argument provided to toml::node::ref() didn't match the node's actual type");
55
56 using node_ref = std::remove_volatile_t<std::remove_reference_t<N>>&;
57 using val_type = std::remove_volatile_t<unwrapped_type>;
58 using out_ref = ref_type<T, N&&>;
59 static_assert(std::is_reference_v<out_ref>);
60
61 if constexpr (toml::is_value<unwrapped_type>)
62 return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>().get());
63 else
64 return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>());
65 }
66
67 protected:
69 node() noexcept;
70
72 node(const node&) noexcept;
73
75 node(node&&) noexcept;
76
78 node& operator=(const node&) noexcept;
79
81 node& operator=(node&&) noexcept;
82
83 template <typename T, typename N>
84 using ref_cast_type_ = std::conditional_t< //
85 std::is_reference_v<T>, //
86 impl::copy_ref<impl::copy_cv<impl::wrap_node<T>, std::remove_reference_t<N>>, T>, //
87 impl::copy_cvref<impl::wrap_node<T>, N> //
88 >;
89
90 template <typename T, typename N>
91 using ref_cast_type = std::conditional_t< //
92 std::is_reference_v<N>, //
93 ref_cast_type_<T, N>, //
94 ref_cast_type_<T, std::add_lvalue_reference_t<N>> //
95 >;
96
97 template <typename T>
99 ref_cast_type<T, node&> ref_cast() & noexcept
100 {
101 using out_ref = ref_cast_type<T, node&>;
102 using out_type = std::remove_reference_t<out_ref>;
103 return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
104 }
105
106 template <typename T>
108 ref_cast_type<T, node&&> ref_cast() && noexcept
109 {
110 using out_ref = ref_cast_type<T, node&&>;
111 using out_type = std::remove_reference_t<out_ref>;
112 return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
113 }
114
115 template <typename T>
117 ref_cast_type<T, const node&> ref_cast() const& noexcept
118 {
119 using out_ref = ref_cast_type<T, const node&>;
120 using out_type = std::remove_reference_t<out_ref>;
121 return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
122 }
123
124 template <typename T>
126 ref_cast_type<T, const node&&> ref_cast() const&& noexcept
127 {
128 using out_ref = ref_cast_type<T, const node&&>;
129 using out_type = std::remove_reference_t<out_ref>;
130 return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
131 }
132
134
135 public:
137 virtual ~node() noexcept;
138
141
174 virtual bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept = 0;
175
178 virtual bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept = 0;
179
207 virtual bool is_homogeneous(node_type ntype) const noexcept = 0;
208
235 template <typename ElemType = void>
237 bool is_homogeneous() const noexcept
238 {
239 using type = impl::remove_cvref<impl::unwrap_node<ElemType>>;
240 static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>,
241 "The template type argument of node::is_homogeneous() must be void or one "
242 "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
243
244 return is_homogeneous(impl::node_type_of<type>);
245 }
246
249 virtual node_type type() const noexcept = 0;
250
253 virtual bool is_table() const noexcept = 0;
254
257 virtual bool is_array() const noexcept = 0;
258
261 virtual bool is_array_of_tables() const noexcept = 0;
262
265 virtual bool is_value() const noexcept = 0;
266
269 virtual bool is_string() const noexcept = 0;
270
273 virtual bool is_integer() const noexcept = 0;
274
277 virtual bool is_floating_point() const noexcept = 0;
278
281 virtual bool is_number() const noexcept = 0;
282
285 virtual bool is_boolean() const noexcept = 0;
286
289 virtual bool is_date() const noexcept = 0;
290
293 virtual bool is_time() const noexcept = 0;
294
297 virtual bool is_date_time() const noexcept = 0;
298
304 template <typename T>
306 bool is() const noexcept
307 {
308 using type = impl::remove_cvref<impl::unwrap_node<T>>;
309 static_assert(toml::is_value<type> || toml::is_container<type>,
310 "The template type argument of node::is() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
311
312 if constexpr (std::is_same_v<type, table>)
313 return is_table();
314 else if constexpr (std::is_same_v<type, array>)
315 return is_array();
316 else if constexpr (std::is_same_v<type, std::string>)
317 return is_string();
318 else if constexpr (std::is_same_v<type, int64_t>)
319 return is_integer();
320 else if constexpr (std::is_same_v<type, double>)
321 return is_floating_point();
322 else if constexpr (std::is_same_v<type, bool>)
323 return is_boolean();
324 else if constexpr (std::is_same_v<type, date>)
325 return is_date();
326 else if constexpr (std::is_same_v<type, time>)
327 return is_time();
328 else if constexpr (std::is_same_v<type, date_time>)
329 return is_date_time();
330 }
331
333
336
339 virtual table* as_table() noexcept = 0;
340
343 virtual array* as_array() noexcept = 0;
344
347 virtual toml::value<std::string>* as_string() noexcept = 0;
348
351 virtual toml::value<int64_t>* as_integer() noexcept = 0;
352
355 virtual toml::value<double>* as_floating_point() noexcept = 0;
356
359 virtual toml::value<bool>* as_boolean() noexcept = 0;
360
363 virtual toml::value<date>* as_date() noexcept = 0;
364
367 virtual toml::value<time>* as_time() noexcept = 0;
368
371 virtual toml::value<date_time>* as_date_time() noexcept = 0;
372
375 virtual const table* as_table() const noexcept = 0;
376
379 virtual const array* as_array() const noexcept = 0;
380
383 virtual const toml::value<std::string>* as_string() const noexcept = 0;
384
387 virtual const toml::value<int64_t>* as_integer() const noexcept = 0;
388
391 virtual const toml::value<double>* as_floating_point() const noexcept = 0;
392
395 virtual const toml::value<bool>* as_boolean() const noexcept = 0;
396
399 virtual const toml::value<date>* as_date() const noexcept = 0;
400
403 virtual const toml::value<time>* as_time() const noexcept = 0;
404
407 virtual const toml::value<date_time>* as_date_time() const noexcept = 0;
408
429 template <typename T>
431 impl::wrap_node<T>* as() noexcept
432 {
433 using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
434 static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
435 "The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
436
437 if constexpr (std::is_same_v<unwrapped_type, table>)
438 return as_table();
439 else if constexpr (std::is_same_v<unwrapped_type, array>)
440 return as_array();
441 else if constexpr (std::is_same_v<unwrapped_type, std::string>)
442 return as_string();
443 else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
444 return as_integer();
445 else if constexpr (std::is_same_v<unwrapped_type, double>)
446 return as_floating_point();
447 else if constexpr (std::is_same_v<unwrapped_type, bool>)
448 return as_boolean();
449 else if constexpr (std::is_same_v<unwrapped_type, date>)
450 return as_date();
451 else if constexpr (std::is_same_v<unwrapped_type, time>)
452 return as_time();
453 else if constexpr (std::is_same_v<unwrapped_type, date_time>)
454 return as_date_time();
455 }
456
458 template <typename T>
460 const impl::wrap_node<T>* as() const noexcept
461 {
462 using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
463 static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
464 "The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
465
466 if constexpr (std::is_same_v<unwrapped_type, table>)
467 return as_table();
468 else if constexpr (std::is_same_v<unwrapped_type, array>)
469 return as_array();
470 else if constexpr (std::is_same_v<unwrapped_type, std::string>)
471 return as_string();
472 else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
473 return as_integer();
474 else if constexpr (std::is_same_v<unwrapped_type, double>)
475 return as_floating_point();
476 else if constexpr (std::is_same_v<unwrapped_type, bool>)
477 return as_boolean();
478 else if constexpr (std::is_same_v<unwrapped_type, date>)
479 return as_date();
480 else if constexpr (std::is_same_v<unwrapped_type, time>)
481 return as_time();
482 else if constexpr (std::is_same_v<unwrapped_type, date_time>)
483 return as_date_time();
484 }
485
487
490
503 template <typename T>
505 optional<T> value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>);
506
633 template <typename T>
635 optional<T> value() const noexcept(impl::value_retrieval_is_nothrow<T>);
636
654 template <typename T>
656 auto value_or(T&& default_value) const noexcept(impl::value_retrieval_is_nothrow<T>);
657
686 template <typename T>
688 decltype(auto) ref() & noexcept
689 {
690 return do_ref<T>(*this);
691 }
692
694 template <typename T>
696 decltype(auto) ref() && noexcept
697 {
698 return do_ref<T>(std::move(*this));
699 }
700
702 template <typename T>
704 decltype(auto) ref() const& noexcept
705 {
706 return do_ref<T>(*this);
707 }
708
710 template <typename T>
712 decltype(auto) ref() const&& noexcept
713 {
714 return do_ref<T>(std::move(*this));
715 }
716
718
721
724 const source_region& source() const noexcept
725 {
726 return source_;
727 }
728
730
731 private:
733
734 template <typename Func, typename Node, typename T>
735 static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<T, Node>>;
736
737 template <typename Func, typename Node, typename T>
738 static constexpr bool can_visit_nothrow = std::is_nothrow_invocable_v<Func, ref_cast_type<T, Node>>;
739
740 template <typename Func, typename Node>
741 static constexpr bool can_visit_any = can_visit<Func, Node, table> //
742 || can_visit<Func, Node, array> //
743 || can_visit<Func, Node, std::string> //
744 || can_visit<Func, Node, int64_t> //
745 || can_visit<Func, Node, double> //
746 || can_visit<Func, Node, bool> //
747 || can_visit<Func, Node, date> //
748 || can_visit<Func, Node, time> //
749 || can_visit<Func, Node, date_time>;
750
751 // clang-format off
752
753 template <typename Func, typename Node>
754 static constexpr bool can_visit_all = can_visit<Func, Node, table> //
755 && can_visit<Func, Node, array> //
756 && can_visit<Func, Node, std::string> //
757 && can_visit<Func, Node, int64_t> //
758 && can_visit<Func, Node, double> //
759 && can_visit<Func, Node, bool> //
760 && can_visit<Func, Node, date> //
761 && can_visit<Func, Node, time> //
762 && can_visit<Func, Node, date_time>;
763
764 template <typename Func, typename Node, typename T>
765 static constexpr bool visit_is_nothrow_one = !can_visit<Func, Node, T> || can_visit_nothrow<Func, Node, T>;
766
767 template <typename Func, typename Node>
768 static constexpr bool visit_is_nothrow = visit_is_nothrow_one<Func, Node, table> //
769 && visit_is_nothrow_one<Func, Node, array> //
770 && visit_is_nothrow_one<Func, Node, std::string> //
771 && visit_is_nothrow_one<Func, Node, int64_t> //
772 && visit_is_nothrow_one<Func, Node, double> //
773 && visit_is_nothrow_one<Func, Node, bool> //
774 && visit_is_nothrow_one<Func, Node, date> //
775 && visit_is_nothrow_one<Func, Node, time> //
776 && visit_is_nothrow_one<Func, Node, date_time>;
777
778 // clang-format on
779
780 template <typename Func, typename Node, typename T, bool = can_visit<Func, Node, T>>
781 struct visit_return_type_
782 {
783 using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<T, Node>>()));
784 };
785 template <typename Func, typename Node, typename T>
786 struct visit_return_type_<Func, Node, T, false>
787 {
788 using type = void;
789 };
790
791 template <typename Func, typename Node, typename T>
792 using visit_return_type = typename visit_return_type_<Func, Node, T>::type;
793
794 template <typename A, typename B>
795 using nonvoid = std::conditional_t<std::is_void_v<A>, B, A>;
796
797 template <typename Func, typename Node>
798 static decltype(auto) do_visit(Func&& visitor, Node&& n) noexcept(visit_is_nothrow<Func&&, Node&&>)
799 {
800 static_assert(can_visit_any<Func&&, Node&&>,
801 "TOML node visitors must be invocable for at least one of the toml::node "
802 "specializations:" TOML_SA_NODE_TYPE_LIST);
803
804 switch (n.type())
805 {
806 case node_type::table:
807 if constexpr (can_visit<Func&&, Node&&, table>)
808 return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<table>());
809 break;
810
811 case node_type::array:
812 if constexpr (can_visit<Func&&, Node&&, array>)
813 return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<array>());
814 break;
815
816 case node_type::string:
817 if constexpr (can_visit<Func&&, Node&&, std::string>)
818 return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<std::string>());
819 break;
820
821 case node_type::integer:
822 if constexpr (can_visit<Func&&, Node&&, int64_t>)
823 return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<int64_t>());
824 break;
825
826 case node_type::floating_point:
827 if constexpr (can_visit<Func&&, Node&&, double>)
828 return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<double>());
829 break;
830
831 case node_type::boolean:
832 if constexpr (can_visit<Func&&, Node&&, bool>)
833 return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<bool>());
834 break;
835
836 case node_type::date:
837 if constexpr (can_visit<Func&&, Node&&, date>)
838 return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<date>());
839 break;
840
841 case node_type::time:
842 if constexpr (can_visit<Func&&, Node&&, time>)
843 return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<time>());
844 break;
845
846 case node_type::date_time:
847 if constexpr (can_visit<Func&&, Node&&, date_time>)
848 return static_cast<Func&&>(visitor)(static_cast<Node&&>(n).template ref_cast<date_time>());
849 break;
850
851 case node_type::none: TOML_UNREACHABLE;
852 default: TOML_UNREACHABLE;
853 }
854
855 if constexpr (!can_visit_all<Func&&, Node&&>)
856 {
857 // clang-format off
858
859 using return_type =
860 nonvoid<visit_return_type<Func&&, Node&&, table>,
861 nonvoid<visit_return_type<Func&&, Node&&, array>,
862 nonvoid<visit_return_type<Func&&, Node&&, std::string>,
863 nonvoid<visit_return_type<Func&&, Node&&, int64_t>,
864 nonvoid<visit_return_type<Func&&, Node&&, double>,
865 nonvoid<visit_return_type<Func&&, Node&&, bool>,
866 nonvoid<visit_return_type<Func&&, Node&&, date>,
867 nonvoid<visit_return_type<Func&&, Node&&, time>,
868 visit_return_type<Func&&, Node&&, date_time>
869 >>>>>>>>;
870
871 // clang-format on
872
873 if constexpr (!std::is_void_v<return_type>)
874 {
875 static_assert(std::is_default_constructible_v<return_type>,
876 "Non-exhaustive visitors must return a default-constructible type, or void");
877 return return_type{};
878 }
879 }
880 }
881
883
884 public:
887
919 template <typename Func>
920 decltype(auto) visit(Func&& visitor) & noexcept(visit_is_nothrow<Func&&, node&>)
921 {
922 return do_visit(static_cast<Func&&>(visitor), *this);
923 }
924
926 template <typename Func>
927 decltype(auto) visit(Func&& visitor) && noexcept(visit_is_nothrow<Func&&, node&&>)
928 {
929 return do_visit(static_cast<Func&&>(visitor), static_cast<node&&>(*this));
930 }
931
933 template <typename Func>
934 decltype(auto) visit(Func&& visitor) const& noexcept(visit_is_nothrow<Func&&, const node&>)
935 {
936 return do_visit(static_cast<Func&&>(visitor), *this);
937 }
938
940 template <typename Func>
941 decltype(auto) visit(Func&& visitor) const&& noexcept(visit_is_nothrow<Func&&, const node&&>)
942 {
943 return do_visit(static_cast<Func&&>(visitor), static_cast<const node&&>(*this));
944 }
945
947
950
953 explicit operator node_view<node>() noexcept;
954
957 explicit operator node_view<const node>() const noexcept;
958
998 node_view<node> at_path(std::string_view path) noexcept;
999
1005 node_view<const node> at_path(std::string_view path) const noexcept;
1006
1047 node_view<node> at_path(const toml::path& path) noexcept;
1048
1054 node_view<const node> at_path(const toml::path& path) const noexcept;
1055
1056#if TOML_ENABLE_WINDOWS_COMPAT
1057
1065 node_view<node> at_path(std::wstring_view path);
1066
1074 node_view<const node> at_path(std::wstring_view path) const;
1075
1076#endif // TOML_ENABLE_WINDOWS_COMPAT
1077
1087 node_view<node> operator[](const toml::path& path) noexcept;
1088
1098 node_view<const node> operator[](const toml::path& path) const noexcept;
1099
1101 };
1102}
1104
1107{
1110 bool TOML_CALLCONV node_deep_equality(const node*, const node*) noexcept;
1111}
1114
1115#include "header_end.hpp"
TOML_NODISCARD TOML_EXPORTED_FREE_FUNCTION node_view< const node > TOML_CALLCONV at_path(const node &root, std::string_view path) noexcept
Returns a const view of the node matching a fully-qualified "TOML path".
A TOML array.
Definition array.hpp:285
A TOML path.
Definition path.hpp:239
A TOML table.
Definition table.hpp:220
constexpr bool is_number
Metafunction for determining if a type satisfies either toml::is_integer or toml::is_floating_point.
Definition forward_declarations.hpp:986
constexpr bool is_boolean
Metafunction for determining if a type is, or is a reference to, a bool or toml::value<bool>.
Definition forward_declarations.hpp:990
constexpr bool is_floating_point
Metafunction for determining if a type is, or is a reference to, a double or toml::value<double>.
Definition forward_declarations.hpp:980
constexpr bool is_date
Metafunction for determining if a type is, or is a reference to, a toml::date or toml::value<date>.
Definition forward_declarations.hpp:996
constexpr bool is_string
Metafunction for determining if a type is, or is a reference to, a std::string or toml::value<std::st...
Definition forward_declarations.hpp:968
constexpr bool is_array
Metafunction for determining if a type is, or is a reference to, a toml::array.
Definition forward_declarations.hpp:960
constexpr bool is_date_time
Metafunction for determining if a type is, or is a reference to, a toml::date_time or toml::value<dat...
Definition forward_declarations.hpp:1008
constexpr bool is_integer
Metafunction for determining if a type is, or is a reference to, a int64_t or toml::value<int64_t>.
Definition forward_declarations.hpp:974
constexpr bool is_time
Metafunction for determining if a type is, or is a reference to, a toml::time or toml::value<time>.
Definition forward_declarations.hpp:1002
constexpr bool is_value
Metafunction for determining if a type is, or is a reference to, any of the toml value types....
Definition forward_declarations.hpp:1018
#define TOML_CALLCONV
Calling convention to apply to exported free/static functions. \detail Not defined by default (let th...
Definition preprocessor.hpp:1134
#define TOML_EXPORTED_CLASS
An 'export' annotation to add to classes. \detail Not defined by default.
Definition preprocessor.hpp:979
#define TOML_ASSERT_ASSUME(expr)
Definition preprocessor.hpp:1190
#define TOML_EXPORTED_FREE_FUNCTION
An 'export' annotation to add to free functions. \detail Not defined by default.
Definition preprocessor.hpp:988
#define TOML_EXPORTED_MEMBER_FUNCTION
An 'export' annotation to add to non-static class member functions. \detail Not defined by default.
Definition preprocessor.hpp:982
TOML_NAMESPACE_START
Definition node.hpp:13
TOML_NAMESPACE_END
Definition node.hpp:1103
#define TOML_UNREACHABLE
Definition preprocessor.hpp:515
#define TOML_NODISCARD
Definition preprocessor.hpp:439
#define TOML_PURE_GETTER
Definition preprocessor.hpp:474
#define TOML_PURE_INLINE_GETTER
Definition preprocessor.hpp:479
#define TOML_IMPL_NAMESPACE_END
Definition preprocessor.hpp:1334
#define TOML_IMPL_NAMESPACE_START
Definition preprocessor.hpp:1333
#define TOML_ABSTRACT_INTERFACE
Definition preprocessor.hpp:423
A source document region.
Definition source_region.hpp:167