NeBuild dev
Loading...
Searching...
No Matches
array.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"
8#include "std_vector.hpp"
10#include "value.hpp"
11#include "make_node.hpp"
12#include "header_start.hpp"
13
14#ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN
15#if TOML_GCC && TOML_GCC <= 7
16#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN 1
17#else
18#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN 0
19#endif
20#endif
21
22#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN && !defined(TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED)
23#define TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE \
24 "If you're seeing this error it's because you're using one of toml++'s for_each() functions on a compiler with " \
25 "known bugs in that area (e.g. GCC 7). On these compilers returning a bool (or bool-convertible) value from the " \
26 "for_each() callable causes spurious compilation failures, while returning nothing (void) works fine. " \
27 "If you believe this message is incorrect for your compiler, you can try your luck by #defining " \
28 "TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN as 0 and recompiling - if it works, great! Let me know at " \
29 "https://github.com/marzer/tomlplusplus/issues. Alternatively, if you don't have any need for early-exiting from " \
30 "for_each(), you can suppress this error by #defining TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED " \
31 "and moving on with your life."
32#endif
33
36{
37 template <bool IsConst>
38 class TOML_TRIVIAL_ABI array_iterator
39 {
40 private:
41 template <bool>
42 friend class array_iterator;
43
44 using mutable_vector_iterator = std::vector<node_ptr>::iterator;
45 using const_vector_iterator = std::vector<node_ptr>::const_iterator;
46 using vector_iterator = std::conditional_t<IsConst, const_vector_iterator, mutable_vector_iterator>;
47
48 mutable vector_iterator iter_;
49
50 public:
51 using value_type = std::conditional_t<IsConst, const node, node>;
52 using reference = value_type&;
53 using pointer = value_type*;
54 using difference_type = ptrdiff_t;
55 using iterator_category = typename std::iterator_traits<vector_iterator>::iterator_category;
56
58 array_iterator() noexcept = default;
59
61 explicit array_iterator(mutable_vector_iterator iter) noexcept //
62 : iter_{ iter }
63 {}
64
65 TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst)
67 explicit array_iterator(const_vector_iterator iter) noexcept //
68 : iter_{ iter }
69 {}
70
71 TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst)
73 array_iterator(const array_iterator<false>& other) noexcept //
74 : iter_{ other.iter_ }
75 {}
76
78 array_iterator(const array_iterator&) noexcept = default;
79
80 array_iterator& operator=(const array_iterator&) noexcept = default;
81
82 array_iterator& operator++() noexcept // ++pre
83 {
84 ++iter_;
85 return *this;
86 }
87
88 array_iterator operator++(int) noexcept // post++
89 {
90 array_iterator out{ iter_ };
91 ++iter_;
92 return out;
93 }
94
95 array_iterator& operator--() noexcept // --pre
96 {
97 --iter_;
98 return *this;
99 }
100
101 array_iterator operator--(int) noexcept // post--
102 {
103 array_iterator out{ iter_ };
104 --iter_;
105 return out;
106 }
107
109 reference operator*() const noexcept
110 {
111 return *iter_->get();
112 }
113
115 pointer operator->() const noexcept
116 {
117 return iter_->get();
118 }
119
121 explicit operator const vector_iterator&() const noexcept
122 {
123 return iter_;
124 }
125
126 TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst)
128 explicit operator const const_vector_iterator() const noexcept
129 {
130 return iter_;
131 }
132
133 array_iterator& operator+=(ptrdiff_t rhs) noexcept
134 {
135 iter_ += rhs;
136 return *this;
137 }
138
139 array_iterator& operator-=(ptrdiff_t rhs) noexcept
140 {
141 iter_ -= rhs;
142 return *this;
143 }
144
146 friend array_iterator operator+(const array_iterator& lhs, ptrdiff_t rhs) noexcept
147 {
148 return array_iterator{ lhs.iter_ + rhs };
149 }
150
152 friend array_iterator operator+(ptrdiff_t lhs, const array_iterator& rhs) noexcept
153 {
154 return array_iterator{ rhs.iter_ + lhs };
155 }
156
158 friend array_iterator operator-(const array_iterator& lhs, ptrdiff_t rhs) noexcept
159 {
160 return array_iterator{ lhs.iter_ - rhs };
161 }
162
164 friend ptrdiff_t operator-(const array_iterator& lhs, const array_iterator& rhs) noexcept
165 {
166 return lhs.iter_ - rhs.iter_;
167 }
168
170 friend bool operator==(const array_iterator& lhs, const array_iterator& rhs) noexcept
171 {
172 return lhs.iter_ == rhs.iter_;
173 }
174
176 friend bool operator!=(const array_iterator& lhs, const array_iterator& rhs) noexcept
177 {
178 return lhs.iter_ != rhs.iter_;
179 }
180
182 friend bool operator<(const array_iterator& lhs, const array_iterator& rhs) noexcept
183 {
184 return lhs.iter_ < rhs.iter_;
185 }
186
188 friend bool operator<=(const array_iterator& lhs, const array_iterator& rhs) noexcept
189 {
190 return lhs.iter_ <= rhs.iter_;
191 }
192
194 friend bool operator>(const array_iterator& lhs, const array_iterator& rhs) noexcept
195 {
196 return lhs.iter_ > rhs.iter_;
197 }
198
200 friend bool operator>=(const array_iterator& lhs, const array_iterator& rhs) noexcept
201 {
202 return lhs.iter_ >= rhs.iter_;
203 }
204
206 reference operator[](ptrdiff_t idx) const noexcept
207 {
208 return *(iter_ + idx)->get();
209 }
210 };
211
212 struct array_init_elem
213 {
214 mutable node_ptr value;
215
216 template <typename T>
218 array_init_elem(T&& val, value_flags flags = preserve_source_value_flags) //
219 : value{ make_node(static_cast<T&&>(val), flags) }
220 {}
221 };
222}
225
227{
229 using array_iterator = POXY_IMPLEMENTATION_DETAIL(impl::array_iterator<false>);
230
232 using const_array_iterator = POXY_IMPLEMENTATION_DETAIL(impl::array_iterator<true>);
233
284 class TOML_EXPORTED_CLASS array : public node
285 {
286 private:
288
289 using vector_type = std::vector<impl::node_ptr>;
290 using vector_iterator = typename vector_type::iterator;
291 using const_vector_iterator = typename vector_type::const_iterator;
292 vector_type elems_;
293
296 array(const impl::array_init_elem*, const impl::array_init_elem*);
297
299 array(std::false_type, std::initializer_list<impl::array_init_elem> elems) //
300 : array{ elems.begin(), elems.end() }
301 {}
302
304 void preinsertion_resize(size_t idx, size_t count);
305
307 void insert_at_back(impl::node_ptr&&);
308
310 vector_iterator insert_at(const_vector_iterator, impl::node_ptr&&);
311
312 template <typename T>
313 void emplace_back_if_not_empty_view(T&& val, value_flags flags)
314 {
315 if constexpr (is_node_view<T>)
316 {
317 if (!val)
318 return;
319 }
320 insert_at_back(impl::make_node(static_cast<T&&>(val), flags));
321 }
322
325 size_t total_leaf_count() const noexcept;
326
328 void flatten_child(array&& child, size_t& dest_index) noexcept;
329
331
332 public:
333 using value_type = node;
334 using size_type = size_t;
335 using difference_type = ptrdiff_t;
336 using reference = node&;
337 using const_reference = const node&;
338
342 array() noexcept;
343
345 ~array() noexcept;
346
350 array(const array&);
351
355 array(array&& other) noexcept;
356
389 TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0 || !std::is_same_v<impl::remove_cvref<ElemType>, array>),
390 typename ElemType,
391 typename... ElemTypes)
393 explicit array(ElemType&& val, ElemTypes&&... vals)
394 : array{ std::false_type{},
395 std::initializer_list<impl::array_init_elem>{ static_cast<ElemType&&>(val),
396 static_cast<ElemTypes&&>(vals)... } }
397 {}
398
401 array& operator=(const array&);
402
405 array& operator=(array&& rhs) noexcept;
406
409
412 node_type type() const noexcept final
413 {
414 return node_type::array;
415 }
416
419 bool is_homogeneous(node_type ntype) const noexcept final;
420
423 bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final;
424
427 bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final;
428
430 template <typename ElemType = void>
432 bool is_homogeneous() const noexcept
433 {
434 using type = impl::remove_cvref<impl::unwrap_node<ElemType>>;
435 static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>,
436 "The template type argument of array::is_homogeneous() must be void or one "
437 "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
438
439 return is_homogeneous(impl::node_type_of<type>);
440 }
442
445 bool is_table() const noexcept final
446 {
447 return false;
448 }
449
452 bool is_array() const noexcept final
453 {
454 return true;
455 }
456
459 bool is_array_of_tables() const noexcept final
460 {
461 return is_homogeneous(node_type::table);
462 }
463
466 bool is_value() const noexcept final
467 {
468 return false;
469 }
470
473 bool is_string() const noexcept final
474 {
475 return false;
476 }
477
480 bool is_integer() const noexcept final
481 {
482 return false;
483 }
484
487 bool is_floating_point() const noexcept final
488 {
489 return false;
490 }
491
494 bool is_number() const noexcept final
495 {
496 return false;
497 }
498
501 bool is_boolean() const noexcept final
502 {
503 return false;
504 }
505
508 bool is_date() const noexcept final
509 {
510 return false;
511 }
512
515 bool is_time() const noexcept final
516 {
517 return false;
518 }
519
522 bool is_date_time() const noexcept final
523 {
524 return false;
525 }
526
528
531
534 table* as_table() noexcept final
535 {
536 return nullptr;
537 }
538
541 array* as_array() noexcept final
542 {
543 return this;
544 }
545
548 toml::value<std::string>* as_string() noexcept final
549 {
550 return nullptr;
551 }
552
555 toml::value<int64_t>* as_integer() noexcept final
556 {
557 return nullptr;
558 }
559
562 toml::value<double>* as_floating_point() noexcept final
563 {
564 return nullptr;
565 }
566
569 toml::value<bool>* as_boolean() noexcept final
570 {
571 return nullptr;
572 }
573
576 toml::value<date>* as_date() noexcept final
577 {
578 return nullptr;
579 }
580
583 toml::value<time>* as_time() noexcept final
584 {
585 return nullptr;
586 }
587
590 toml::value<date_time>* as_date_time() noexcept final
591 {
592 return nullptr;
593 }
594
597 const table* as_table() const noexcept final
598 {
599 return nullptr;
600 }
601
604 const array* as_array() const noexcept final
605 {
606 return this;
607 }
608
611 const toml::value<std::string>* as_string() const noexcept final
612 {
613 return nullptr;
614 }
615
618 const toml::value<int64_t>* as_integer() const noexcept final
619 {
620 return nullptr;
621 }
622
625 const toml::value<double>* as_floating_point() const noexcept final
626 {
627 return nullptr;
628 }
629
632 const toml::value<bool>* as_boolean() const noexcept final
633 {
634 return nullptr;
635 }
636
639 const toml::value<date>* as_date() const noexcept final
640 {
641 return nullptr;
642 }
643
646 const toml::value<time>* as_time() const noexcept final
647 {
648 return nullptr;
649 }
650
653 const toml::value<date_time>* as_date_time() const noexcept final
654 {
655 return nullptr;
656 }
657
659
662
685 node* get(size_t index) noexcept
686 {
687 return index < elems_.size() ? elems_[index].get() : nullptr;
688 }
689
696 const node* get(size_t index) const noexcept
697 {
698 return const_cast<array&>(*this).get(index);
699 }
700
717 template <typename ElemType>
719 impl::wrap_node<ElemType>* get_as(size_t index) noexcept
720 {
721 if (auto val = get(index))
722 return val->template as<ElemType>();
723 return nullptr;
724 }
725
732 template <typename ElemType>
734 const impl::wrap_node<ElemType>* get_as(size_t index) const noexcept
735 {
736 return const_cast<array&>(*this).template get_as<ElemType>(index);
737 }
738
740 using node::operator[]; // inherit operator[toml::path]
742
745 node& operator[](size_t index) noexcept
746 {
747 return *elems_[index];
748 }
749
752 const node& operator[](size_t index) const noexcept
753 {
754 return *elems_[index];
755 }
756
760 node& at(size_t index);
761
764 const node& at(size_t index) const
765 {
766 return const_cast<array&>(*this).at(index);
767 }
768
771 node& front() noexcept
772 {
773 return *elems_.front();
774 }
775
778 const node& front() const noexcept
779 {
780 return *elems_.front();
781 }
782
785 node& back() noexcept
786 {
787 return *elems_.back();
788 }
789
792 const node& back() const noexcept
793 {
794 return *elems_.back();
795 }
796
798
801
803 using iterator = array_iterator;
804
807
810 iterator begin() noexcept
811 {
812 return iterator{ elems_.begin() };
813 }
814
817 const_iterator begin() const noexcept
818 {
819 return const_iterator{ elems_.cbegin() };
820 }
821
824 const_iterator cbegin() const noexcept
825 {
826 return const_iterator{ elems_.cbegin() };
827 }
828
831 iterator end() noexcept
832 {
833 return iterator{ elems_.end() };
834 }
835
838 const_iterator end() const noexcept
839 {
840 return const_iterator{ elems_.cend() };
841 }
842
845 const_iterator cend() const noexcept
846 {
847 return const_iterator{ elems_.cend() };
848 }
849
850 private:
852
853 template <typename T, typename Array>
854 using for_each_elem_ref = impl::copy_cvref<impl::wrap_node<impl::remove_cvref<impl::unwrap_node<T>>>, Array>;
855
856 template <typename Func, typename Array, typename T>
857 using can_for_each = std::disjunction<std::is_invocable<Func, for_each_elem_ref<T, Array>, size_t>,
858 std::is_invocable<Func, size_t, for_each_elem_ref<T, Array>>,
859 std::is_invocable<Func, for_each_elem_ref<T, Array>>>;
860
861 template <typename Func, typename Array, typename T>
862 using can_for_each_nothrow = std::conditional_t<
863 // first form
864 std::is_invocable_v<Func, for_each_elem_ref<T, Array>, size_t>,
865 std::is_nothrow_invocable<Func, for_each_elem_ref<T, Array>, size_t>,
866 std::conditional_t<
867 // second form
868 std::is_invocable_v<Func, size_t, for_each_elem_ref<T, Array>>,
869 std::is_nothrow_invocable<Func, size_t, for_each_elem_ref<T, Array>>,
870 std::conditional_t<
871 // third form
872 std::is_invocable_v<Func, for_each_elem_ref<T, Array>>,
873 std::is_nothrow_invocable<Func, for_each_elem_ref<T, Array>>,
874 std::false_type>>>;
875
876 template <typename Func, typename Array>
877 using can_for_each_any = std::disjunction<can_for_each<Func, Array, table>,
878 can_for_each<Func, Array, array>,
879 can_for_each<Func, Array, std::string>,
880 can_for_each<Func, Array, int64_t>,
881 can_for_each<Func, Array, double>,
882 can_for_each<Func, Array, bool>,
883 can_for_each<Func, Array, date>,
884 can_for_each<Func, Array, time>,
885 can_for_each<Func, Array, date_time>>;
886
887 template <typename Func, typename Array, typename T>
888 using for_each_is_nothrow_one = std::disjunction<std::negation<can_for_each<Func, Array, T>>, //
889 can_for_each_nothrow<Func, Array, T>>;
890
891 template <typename Func, typename Array>
892 using for_each_is_nothrow = std::conjunction<for_each_is_nothrow_one<Func, Array, table>,
893 for_each_is_nothrow_one<Func, Array, array>,
894 for_each_is_nothrow_one<Func, Array, std::string>,
895 for_each_is_nothrow_one<Func, Array, int64_t>,
896 for_each_is_nothrow_one<Func, Array, double>,
897 for_each_is_nothrow_one<Func, Array, bool>,
898 for_each_is_nothrow_one<Func, Array, date>,
899 for_each_is_nothrow_one<Func, Array, time>,
900 for_each_is_nothrow_one<Func, Array, date_time>>;
901
902 template <typename Func, typename Array>
903 static void do_for_each(Func&& visitor, Array&& arr) //
904 noexcept(for_each_is_nothrow<Func&&, Array&&>::value)
905 {
906 static_assert(can_for_each_any<Func&&, Array&&>::value,
907 "TOML array for_each visitors must be invocable for at least one of the toml::node "
908 "specializations:" TOML_SA_NODE_TYPE_LIST);
909
910 for (size_t i = 0; i < arr.size(); i++)
911 {
912 using node_ref = impl::copy_cvref<toml::node, Array&&>;
913 static_assert(std::is_reference_v<node_ref>);
914
915#if TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN
916
917#ifndef TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_ACKNOWLEDGED
918 static_assert(impl::always_false<Func, Array, node_ref>, //
919 TOML_RETURN_BOOL_FROM_FOR_EACH_BROKEN_MESSAGE);
920#endif
921
922 static_cast<node_ref>(static_cast<Array&&>(arr)[i])
923 .visit(
924 [&]([[maybe_unused]] auto&& elem) //
925 noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>::value)
926 {
927 using elem_ref = for_each_elem_ref<decltype(elem), Array&&>;
928 static_assert(std::is_reference_v<elem_ref>);
929
930 // func(elem, i)
931 if constexpr (std::is_invocable_v<Func&&, elem_ref, size_t>)
932 {
933 static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i);
934 }
935
936 // func(i, elem)
937 else if constexpr (std::is_invocable_v<Func&&, size_t, elem_ref>)
938 {
939 static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem));
940 }
941
942 // func(elem)
943 else if constexpr (std::is_invocable_v<Func&&, elem_ref>)
944 {
945 static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem));
946 }
947 });
948
949#else
950 const auto keep_going =
951 static_cast<node_ref>(static_cast<Array&&>(arr)[i])
952 .visit(
953 [&]([[maybe_unused]] auto&& elem) //
954 noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>::value)
955 {
956 using elem_ref = for_each_elem_ref<decltype(elem), Array&&>;
957 static_assert(std::is_reference_v<elem_ref>);
958
959 // func(elem, i)
960 if constexpr (std::is_invocable_v<Func&&, elem_ref, size_t>)
961 {
962 using return_type =
963 decltype(static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i));
964
965 if constexpr (impl::is_constructible_or_convertible<bool, return_type>)
966 {
967 return static_cast<bool>(
968 static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i));
969 }
970 else
971 {
972 static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem), i);
973 return true;
974 }
975 }
976
977 // func(i, elem)
978 else if constexpr (std::is_invocable_v<Func&&, size_t, elem_ref>)
979 {
980 using return_type =
981 decltype(static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem)));
982
983 if constexpr (impl::is_constructible_or_convertible<bool, return_type>)
984 {
985 return static_cast<bool>(
986 static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem)));
987 }
988 else
989 {
990 static_cast<Func&&>(visitor)(i, static_cast<elem_ref>(elem));
991 return true;
992 }
993 }
994
995 // func(elem)
996 else if constexpr (std::is_invocable_v<Func&&, elem_ref>)
997 {
998 using return_type =
999 decltype(static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem)));
1000
1001 if constexpr (impl::is_constructible_or_convertible<bool, return_type>)
1002 {
1003 return static_cast<bool>(
1004 static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem)));
1005 }
1006 else
1007 {
1008 static_cast<Func&&>(visitor)(static_cast<elem_ref>(elem));
1009 return true;
1010 }
1011 }
1012
1013 // visitor not compatible with this particular type
1014 else
1015 return true;
1016 });
1017
1018 if (!keep_going)
1019 return;
1020#endif
1021 }
1022 }
1023
1025
1026 public:
1087 template <typename Func>
1088 array& for_each(Func&& visitor) & //
1089 noexcept(for_each_is_nothrow<Func&&, array&>::value)
1090 {
1091 do_for_each(static_cast<Func&&>(visitor), *this);
1092 return *this;
1093 }
1094
1096 template <typename Func>
1097 array&& for_each(Func&& visitor) && //
1098 noexcept(for_each_is_nothrow<Func&&, array&&>::value)
1099 {
1100 do_for_each(static_cast<Func&&>(visitor), static_cast<array&&>(*this));
1101 return static_cast<array&&>(*this);
1102 }
1103
1105 template <typename Func>
1106 const array& for_each(Func&& visitor) const& //
1107 noexcept(for_each_is_nothrow<Func&&, const array&>::value)
1108 {
1109 do_for_each(static_cast<Func&&>(visitor), *this);
1110 return *this;
1111 }
1112
1114 template <typename Func>
1115 const array&& for_each(Func&& visitor) const&& //
1116 noexcept(for_each_is_nothrow<Func&&, const array&&>::value)
1117 {
1118 do_for_each(static_cast<Func&&>(visitor), static_cast<const array&&>(*this));
1119 return static_cast<const array&&>(*this);
1120 }
1121
1123
1126
1129 bool empty() const noexcept
1130 {
1131 return elems_.empty();
1132 }
1133
1136 size_t size() const noexcept
1137 {
1138 return elems_.size();
1139 }
1140
1143 size_t max_size() const noexcept
1144 {
1145 return elems_.max_size();
1146 }
1147
1150 size_t capacity() const noexcept
1151 {
1152 return elems_.capacity();
1153 }
1154
1157 void reserve(size_t new_capacity);
1158
1162
1186 void truncate(size_t new_size);
1187
1215 template <typename ElemType>
1216 void resize(size_t new_size,
1217 ElemType&& default_init_val,
1218 value_flags default_init_flags = preserve_source_value_flags)
1219 {
1220 static_assert(!is_node_view<ElemType>,
1221 "The default element type argument to toml::array::resize may not be toml::node_view.");
1222
1223 if (!new_size)
1224 clear();
1225 else if (new_size > elems_.size())
1226 insert(cend(), new_size - elems_.size(), static_cast<ElemType&&>(default_init_val), default_init_flags);
1227 else
1228 truncate(new_size);
1229 }
1230
1232
1235
1256
1278
1300
1303 {
1304 return static_cast<toml::array&&>(this->flatten());
1305 }
1306
1327 array& prune(bool recursive = true) & noexcept;
1328
1334 array&& prune(bool recursive = true) && noexcept
1335 {
1336 return static_cast<toml::array&&>(this->prune(recursive));
1337 }
1338
1341 void pop_back() noexcept;
1342
1345 void clear() noexcept;
1346
1348
1351
1378 template <typename ElemType>
1380 {
1381 if constexpr (is_node_view<ElemType>)
1382 {
1383 if (!val)
1384 return end();
1385 }
1386 return iterator{ insert_at(const_vector_iterator{ pos },
1387 impl::make_node(static_cast<ElemType&&>(val), flags)) };
1388 }
1389
1427 template <typename ElemType>
1429 size_t count,
1430 ElemType&& val,
1432 {
1433 if constexpr (is_node_view<ElemType>)
1434 {
1435 if (!val)
1436 return end();
1437 }
1438 switch (count)
1439 {
1440 case 0: return iterator{ elems_.begin() + (const_vector_iterator{ pos } - elems_.cbegin()) };
1441 case 1: return insert(pos, static_cast<ElemType&&>(val), flags);
1442 default:
1443 {
1444 const auto start_idx = static_cast<size_t>(const_vector_iterator{ pos } - elems_.cbegin());
1445 preinsertion_resize(start_idx, count);
1446 size_t i = start_idx;
1447 for (size_t e = start_idx + count - 1u; i < e; i++)
1448 elems_[i] = impl::make_node(val, flags);
1449
1450 //# potentially move the initial value into the last element
1451 elems_[i] = impl::make_node(static_cast<ElemType&&>(val), flags);
1452 return iterator{ elems_.begin() + static_cast<ptrdiff_t>(start_idx) };
1453 }
1454 }
1455 }
1456
1471 template <typename Iter>
1473 {
1474 const auto distance = std::distance(first, last);
1475 if (distance <= 0)
1476 return iterator{ elems_.begin() + (const_vector_iterator{ pos } - elems_.cbegin()) };
1477 else
1478 {
1479 auto count = distance;
1480 using deref_type = decltype(*first);
1481 if constexpr (is_node_view<deref_type>)
1482 {
1483 for (auto it = first; it != last; it++)
1484 if (!(*it))
1485 count--;
1486 if (!count)
1487 return iterator{ elems_.begin() + (const_vector_iterator{ pos } - elems_.cbegin()) };
1488 }
1489 const auto start_idx = static_cast<size_t>(const_vector_iterator{ pos } - elems_.cbegin());
1490 preinsertion_resize(start_idx, static_cast<size_t>(count));
1491 size_t i = start_idx;
1492 for (auto it = first; it != last; it++)
1493 {
1494 if constexpr (is_node_view<deref_type>)
1495 {
1496 if (!(*it))
1497 continue;
1498 }
1499 if constexpr (std::is_rvalue_reference_v<deref_type>)
1500 elems_[i++] = impl::make_node(std::move(*it), flags);
1501 else
1502 elems_[i++] = impl::make_node(*it, flags);
1503 }
1504 return iterator{ elems_.begin() + static_cast<ptrdiff_t>(start_idx) };
1505 }
1506 }
1507
1522 template <typename ElemType>
1524 std::initializer_list<ElemType> ilist,
1526 {
1527 return insert(pos, ilist.begin(), ilist.end(), flags);
1528 }
1529
1553 template <typename ElemType = void, typename... Args>
1554 iterator emplace(const_iterator pos, Args&&... args)
1555 {
1556 using raw_elem_type = impl::remove_cvref<ElemType>;
1557 using elem_type = std::conditional_t<std::is_void_v<raw_elem_type>, //
1558 impl::emplaced_type_of<Args&&...>,
1559 raw_elem_type>;
1560
1561 using type = impl::remove_cvref<impl::unwrap_node<elem_type>>;
1562 static_assert(impl::is_native<type> || impl::is_one_of<type, table, array>,
1563 "Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
1564
1565 return iterator{ insert_at(const_vector_iterator{ pos },
1566 impl::node_ptr{ new impl::wrap_node<type>{ static_cast<Args&&>(args)... } }) };
1567 }
1568
1596 template <typename ElemType>
1598 {
1599 TOML_ASSERT(pos >= cbegin() && pos < cend());
1600
1601 if constexpr (is_node_view<ElemType>)
1602 {
1603 if (!val)
1604 return end();
1605 }
1606
1607 const auto it = elems_.begin() + (const_vector_iterator{ pos } - elems_.cbegin());
1608 *it = impl::make_node(static_cast<ElemType&&>(val), flags);
1609 return iterator{ it };
1610 }
1611
1632 template <typename ElemType>
1634 {
1635 emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), flags);
1636 }
1637
1658 template <typename ElemType = void, typename... Args>
1659 decltype(auto) emplace_back(Args&&... args)
1660 {
1661 using raw_elem_type = impl::remove_cvref<ElemType>;
1662 using elem_type = std::conditional_t<std::is_void_v<raw_elem_type>, //
1663 impl::emplaced_type_of<Args&&...>,
1664 raw_elem_type>;
1665
1666 static constexpr auto moving_node_ptr = std::is_same_v<elem_type, impl::node_ptr> //
1667 && sizeof...(Args) == 1u //
1668 && impl::first_is_same<impl::node_ptr&&, Args&&...>;
1669
1670 using unwrapped_type = impl::remove_cvref<impl::unwrap_node<elem_type>>;
1671
1672 static_assert(
1673 moving_node_ptr //
1674 || impl::is_native<unwrapped_type> //
1675 || impl::is_one_of<unwrapped_type, table, array>, //
1676 "ElemType argument of array::emplace_back() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
1677
1678 if constexpr (moving_node_ptr)
1679 {
1680 insert_at_back(static_cast<Args&&>(args)...);
1681 return *elems_.back();
1682 }
1683 else
1684 {
1685 auto ptr = new impl::wrap_node<unwrapped_type>{ static_cast<Args&&>(args)... };
1686 insert_at_back(impl::node_ptr{ ptr });
1687 return *ptr;
1688 }
1689 }
1690
1692
1693 private:
1695
1698 static bool TOML_CALLCONV equal(const array&, const array&) noexcept;
1699
1700 template <typename T>
1702 static bool equal_to_container(const array& lhs, const T& rhs) noexcept
1703 {
1704 using element_type = std::remove_const_t<typename T::value_type>;
1705 static_assert(impl::is_losslessly_convertible_to_native<element_type>,
1706 "Container element type must be losslessly convertible one of the native TOML value types");
1707
1708 if (lhs.size() != rhs.size())
1709 return false;
1710 if (rhs.size() == 0u)
1711 return true;
1712
1713 size_t i{};
1714 for (auto& list_elem : rhs)
1715 {
1716 const auto elem = lhs.get_as<impl::native_type_of<element_type>>(i++);
1717 if (!elem || *elem != list_elem)
1718 return false;
1719 }
1720
1721 return true;
1722 }
1723
1725
1726 public:
1729
1737 friend bool operator==(const array& lhs, const array& rhs) noexcept
1738 {
1739 return equal(lhs, rhs);
1740 }
1741
1749 friend bool operator!=(const array& lhs, const array& rhs) noexcept
1750 {
1751 return !equal(lhs, rhs);
1752 }
1753
1755 template <typename T>
1757 friend bool operator==(const array& lhs, const std::initializer_list<T>& rhs) noexcept
1758 {
1759 return equal_to_container(lhs, rhs);
1760 }
1761 TOML_ASYMMETRICAL_EQUALITY_OPS(const array&, const std::initializer_list<T>&, template <typename T>);
1762
1764 template <typename T>
1766 friend bool operator==(const array& lhs, const std::vector<T>& rhs) noexcept
1767 {
1768 return equal_to_container(lhs, rhs);
1769 }
1770 TOML_ASYMMETRICAL_EQUALITY_OPS(const array&, const std::vector<T>&, template <typename T>);
1771
1773
1774#if TOML_ENABLE_FORMATTERS
1775
1779 friend std::ostream& operator<<(std::ostream& lhs, const array& rhs)
1780 {
1781 impl::print_to_stream(lhs, rhs);
1782 return lhs;
1783 }
1784
1785#endif
1786 };
1787}
1789
1790#include "header_end.hpp"
TOML_NAMESPACE_START
Definition array.hpp:227
POXY_IMPLEMENTATION_DETAIL(impl::array_iterator< true >) const_array_iterator
A RandomAccessIterator for iterating over const elements in a toml::array.
Definition array.hpp:232
TOML_NAMESPACE_END
Definition array.hpp:1788
A TOML array.
Definition array.hpp:285
TOML_NODISCARD iterator begin() noexcept
Returns an iterator to the first element.
Definition array.hpp:810
TOML_CONST_INLINE_GETTER table * as_table() noexcept final
Returns nullptr.
Definition array.hpp:534
TOML_PURE_INLINE_GETTER node * get(size_t index) noexcept
Gets a pointer to the element at a specific index.
Definition array.hpp:685
const node & const_reference
Definition array.hpp:337
TOML_EXPORTED_MEMBER_FUNCTION void reserve(size_t new_capacity)
Reserves internal storage capacity up to a pre-determined number of elements.
TOML_NODISCARD friend bool operator==(const array &lhs, const std::initializer_list< T > &rhs) noexcept
Initializer list equality operator.
Definition array.hpp:1757
TOML_CONST_INLINE_GETTER bool is_boolean() const noexcept final
Returns false.
Definition array.hpp:501
TOML_CONST_INLINE_GETTER bool is_array() const noexcept final
Returns true.
Definition array.hpp:452
TOML_CONST_INLINE_GETTER bool is_date_time() const noexcept final
Returns false.
Definition array.hpp:522
TOML_NODISCARD friend bool operator==(const array &lhs, const std::vector< T > &rhs) noexcept
Vector equality operator.
Definition array.hpp:1766
TOML_EXPORTED_MEMBER_FUNCTION array & operator=(array &&rhs) noexcept
Move-assignment operator.
TOML_CONST_INLINE_GETTER toml::value< double > * as_floating_point() noexcept final
Returns nullptr.
Definition array.hpp:562
TOML_CONST_INLINE_GETTER const toml::value< bool > * as_boolean() const noexcept final
Returns nullptr.
Definition array.hpp:632
TOML_NODISCARD iterator end() noexcept
Returns an iterator to one-past-the-last element.
Definition array.hpp:831
const array & for_each(Func &&visitor) const &noexcept(for_each_is_nothrow< Func &&, const array & >::value)
Invokes a visitor on each element in the array (const lvalue overload).
Definition array.hpp:1106
TOML_CONST_INLINE_GETTER bool is_string() const noexcept final
Returns false.
Definition array.hpp:473
TOML_NODISCARD const_iterator cbegin() const noexcept
Returns an iterator to the first element.
Definition array.hpp:824
TOML_CONST_INLINE_GETTER toml::value< std::string > * as_string() noexcept final
Returns nullptr.
Definition array.hpp:548
TOML_PURE_GETTER TOML_EXPORTED_MEMBER_FUNCTION bool is_homogeneous(node_type ntype, const node *&first_nonmatch) const noexcept final
TOML_NODISCARD node & back() noexcept
Returns a reference to the last element in the array.
Definition array.hpp:785
array && prune(bool recursive=true) &&noexcept
Removes empty child arrays and tables (rvalue overload).
Definition array.hpp:1334
TOML_NODISCARD size_t capacity() const noexcept
Returns the current max number of elements that may be held in the array's internal storage.
Definition array.hpp:1150
iterator insert(const_iterator pos, size_t count, ElemType &&val, value_flags flags=preserve_source_value_flags)
Repeatedly inserts a new element starting at a specific position in the array.
Definition array.hpp:1428
TOML_NODISCARD friend bool operator!=(const array &lhs, const array &rhs) noexcept
Inequality operator.
Definition array.hpp:1749
TOML_CONST_INLINE_GETTER bool is_floating_point() const noexcept final
Returns false.
Definition array.hpp:487
TOML_CONST_INLINE_GETTER toml::value< bool > * as_boolean() noexcept final
Returns nullptr.
Definition array.hpp:569
TOML_PURE_INLINE_GETTER const node * get(size_t index) const noexcept
Gets a pointer to the element at a specific index (const overload).
Definition array.hpp:696
TOML_EXPORTED_MEMBER_FUNCTION iterator erase(const_iterator pos) noexcept
Removes the specified element from the array.
TOML_ASYMMETRICAL_EQUALITY_OPS(const array &, const std::vector< T > &, template< typename T >)
node & reference
Definition array.hpp:336
array && for_each(Func &&visitor) &&noexcept(for_each_is_nothrow< Func &&, array && >::value)
Invokes a visitor on each element in the array (rvalue overload).
Definition array.hpp:1097
decltype(auto) emplace_back(Args &&... args)
Emplaces a new element at the end of the array.
Definition array.hpp:1659
TOML_ASYMMETRICAL_EQUALITY_OPS(const array &, const std::initializer_list< T > &, template< typename T >)
TOML_NODISCARD const node & operator[](size_t index) const noexcept
Gets a reference to the element at a specific index.
Definition array.hpp:752
TOML_NODISCARD const_iterator cend() const noexcept
Returns an iterator to one-past-the-last element.
Definition array.hpp:845
TOML_EXPORTED_MEMBER_FUNCTION void pop_back() noexcept
Removes the last element from the array.
TOML_CONST_INLINE_GETTER const toml::value< time > * as_time() const noexcept final
Returns nullptr.
Definition array.hpp:646
TOML_CONST_INLINE_GETTER bool is_time() const noexcept final
Returns false.
Definition array.hpp:515
TOML_NODISCARD TOML_EXPORTED_MEMBER_FUNCTION node & at(size_t index)
Gets a reference to the element at a specific index, throwing std::out_of_range if none existed.
TOML_CONST_INLINE_GETTER const toml::value< date_time > * as_date_time() const noexcept final
Returns nullptr.
Definition array.hpp:653
TOML_CONST_INLINE_GETTER bool is_integer() const noexcept final
Returns false.
Definition array.hpp:480
TOML_EXPORTED_MEMBER_FUNCTION array & prune(bool recursive=true) &noexcept
Removes empty child arrays and tables.
array && flatten() &&
Flattens this array, recursively hoisting the contents of child arrays up into itself (rvalue overloa...
Definition array.hpp:1302
TOML_CONST_INLINE_GETTER toml::value< int64_t > * as_integer() noexcept final
Returns nullptr.
Definition array.hpp:555
TOML_PURE_GETTER bool is_array_of_tables() const noexcept final
Returns true if the array contains only tables.
Definition array.hpp:459
TOML_NODISCARD const_iterator begin() const noexcept
Returns an iterator to the first element.
Definition array.hpp:817
TOML_NODISCARD const_iterator end() const noexcept
Returns an iterator to one-past-the-last element.
Definition array.hpp:838
TOML_CONST_INLINE_GETTER const array * as_array() const noexcept final
Returns a const-qualified pointer to the array.
Definition array.hpp:604
iterator insert(const_iterator pos, std::initializer_list< ElemType > ilist, value_flags flags=preserve_source_value_flags)
Inserts a range of elements into the array at a specific position.
Definition array.hpp:1523
const array && for_each(Func &&visitor) const &&noexcept(for_each_is_nothrow< Func &&, const array && >::value)
Invokes a visitor on each element in the array (const rvalue overload).
Definition array.hpp:1115
TOML_EXPORTED_MEMBER_FUNCTION iterator erase(const_iterator first, const_iterator last) noexcept
Removes the elements in the range [first, last) from the array.
TOML_EXPORTED_MEMBER_FUNCTION void truncate(size_t new_size)
Shrinks the array to the given size.
TOML_NODISCARD friend bool operator==(const array &lhs, const array &rhs) noexcept
Equality operator.
Definition array.hpp:1737
TOML_CONST_INLINE_GETTER toml::value< date_time > * as_date_time() noexcept final
Returns nullptr.
Definition array.hpp:590
TOML_CONST_INLINE_GETTER node_type type() const noexcept final
Returns #toml::node_type::array.
Definition array.hpp:412
TOML_CONST_INLINE_GETTER const table * as_table() const noexcept final
Returns nullptr.
Definition array.hpp:597
array & for_each(Func &&visitor) &noexcept(for_each_is_nothrow< Func &&, array & >::value)
Invokes a visitor on each element in the array.
Definition array.hpp:1088
TOML_CONST_INLINE_GETTER bool is_value() const noexcept final
Returns false.
Definition array.hpp:466
TOML_NODISCARD node & operator[](size_t index) noexcept
Gets a reference to the element at a specific index.
Definition array.hpp:745
TOML_NODISCARD bool empty() const noexcept
Returns true if the array is empty.
Definition array.hpp:1129
TOML_NODISCARD size_t max_size() const noexcept
Returns the maximum number of elements that can be stored in an array on the current platform.
Definition array.hpp:1143
size_t size_type
Definition array.hpp:334
TOML_CONST_INLINE_GETTER const toml::value< double > * as_floating_point() const noexcept final
Returns nullptr.
Definition array.hpp:625
TOML_CONST_INLINE_GETTER const toml::value< int64_t > * as_integer() const noexcept final
Returns nullptr.
Definition array.hpp:618
TOML_PURE_GETTER TOML_EXPORTED_MEMBER_FUNCTION bool is_homogeneous(node_type ntype) const noexcept final
TOML_CONST_INLINE_GETTER const toml::value< std::string > * as_string() const noexcept final
Returns nullptr.
Definition array.hpp:611
TOML_CONST_INLINE_GETTER toml::value< time > * as_time() noexcept final
Returns nullptr.
Definition array.hpp:583
ptrdiff_t difference_type
Definition array.hpp:335
TOML_NODISCARD const node & at(size_t index) const
Gets a reference to the element at a specific index, throwing std::out_of_range if none existed.
Definition array.hpp:764
void resize(size_t new_size, ElemType &&default_init_val, value_flags default_init_flags=preserve_source_value_flags)
Resizes the array.
Definition array.hpp:1216
TOML_NODISCARD node & front() noexcept
Returns a reference to the first element in the array.
Definition array.hpp:771
TOML_EXPORTED_MEMBER_FUNCTION array & flatten() &
Flattens this array, recursively hoisting the contents of child arrays up into itself.
iterator replace(const_iterator pos, ElemType &&val, value_flags flags=preserve_source_value_flags)
Replaces the element at a specific position in the array with a different value.
Definition array.hpp:1597
TOML_CONST_INLINE_GETTER const toml::value< date > * as_date() const noexcept final
Returns nullptr.
Definition array.hpp:639
TOML_CONST_INLINE_GETTER toml::value< date > * as_date() noexcept final
Returns nullptr.
Definition array.hpp:576
friend std::ostream & operator<<(std::ostream &lhs, const array &rhs)
Prints the array out to a stream as formatted TOML.
Definition array.hpp:1779
array_iterator iterator
A RandomAccessIterator for iterating over elements in a toml::array.
Definition array.hpp:803
TOML_CONST_INLINE_GETTER bool is_number() const noexcept final
Returns false.
Definition array.hpp:494
TOML_PURE_GETTER TOML_EXPORTED_MEMBER_FUNCTION bool is_homogeneous(node_type ntype, node *&first_nonmatch) noexcept final
const_array_iterator const_iterator
A RandomAccessIterator for iterating over const elements in a toml::array.
Definition array.hpp:806
iterator emplace(const_iterator pos, Args &&... args)
Emplaces a new element at a specific position in the array.
Definition array.hpp:1554
iterator insert(const_iterator pos, Iter first, Iter last, value_flags flags=preserve_source_value_flags)
Inserts a range of elements into the array at a specific position.
Definition array.hpp:1472
TOML_CONST_INLINE_GETTER array * as_array() noexcept final
Returns a pointer to the array.
Definition array.hpp:541
TOML_NODISCARD impl::wrap_node< ElemType > * get_as(size_t index) noexcept
Gets a pointer to the element at a specific index if it is a particular type.
Definition array.hpp:719
TOML_EXPORTED_MEMBER_FUNCTION void shrink_to_fit()
Requests the removal of any unused internal storage capacity.
TOML_NODISCARD_CTOR TOML_EXPORTED_MEMBER_FUNCTION array() noexcept
Default constructor.
TOML_NODISCARD const node & front() const noexcept
Returns a reference to the first element in the array.
Definition array.hpp:778
TOML_NODISCARD const node & back() const noexcept
Returns a reference to the last element in the array.
Definition array.hpp:792
TOML_NODISCARD size_t size() const noexcept
Returns the number of elements in the array.
Definition array.hpp:1136
node value_type
Definition array.hpp:333
TOML_CONST_INLINE_GETTER bool is_table() const noexcept final
Returns false.
Definition array.hpp:445
TOML_NODISCARD const impl::wrap_node< ElemType > * get_as(size_t index) const noexcept
Gets a pointer to the element at a specific index if it is a particular type (const overload).
Definition array.hpp:734
TOML_CONST_INLINE_GETTER bool is_date() const noexcept final
Returns false.
Definition array.hpp:508
void push_back(ElemType &&val, value_flags flags=preserve_source_value_flags)
Appends a new element to the end of the array.
Definition array.hpp:1633
A TOML table.
Definition table.hpp:220
enum TOML_OPEN_FLAGS_ENUM value_flags
Metadata associated with TOML values.
Definition forward_declarations.hpp:272
constexpr value_flags preserve_source_value_flags
Special #toml::value_flags constant used for array + table insert functions to specify that any value...
Definition forward_declarations.hpp:290
#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_EXPORTED_STATIC_FUNCTION
An 'export' annotation to add to static class member functions. \detail Not defined by default.
Definition preprocessor.hpp:985
#define TOML_ASSERT(expr)
Sets the assert function used by the library. \detail Defaults to the standard C assert().
Definition preprocessor.hpp:1185
#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
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.h:14737
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.h:14762
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.h:14787
Definition json.h:5363
#define TOML_NODISCARD_CTOR
Definition preprocessor.hpp:446
#define TOML_TRIVIAL_ABI
Definition preprocessor.hpp:430
#define POXY_IMPLEMENTATION_DETAIL(...)
Definition preprocessor.hpp:633
#define TOML_CONSTRAINED_TEMPLATE(condition,...)
Definition preprocessor.hpp:1260
#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_CONST_INLINE_GETTER
Definition preprocessor.hpp:490