NeBuild dev
Loading...
Searching...
No Matches
array.inl
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// # {{
8#include "preprocessor.hpp"
9#if !TOML_IMPLEMENTATION
10#error This is an implementation-only header.
11#endif
12// # }}
13
14#include "array.hpp"
15#include "header_start.hpp"
16
19 array::array() noexcept {
20#if TOML_LIFETIME_HOOKS
21 TOML_ARRAY_CREATED;
22#endif
23 }
24
26 array::~array() noexcept {
27#if TOML_LIFETIME_HOOKS
28 TOML_ARRAY_DESTROYED;
29#endif
30 }
31
33 array::array(const impl::array_init_elem* b, const impl::array_init_elem* e) {
34#if TOML_LIFETIME_HOOKS
35 TOML_ARRAY_CREATED;
36#endif
37
40 TOML_ASSERT_ASSUME(b <= e);
41
42 if TOML_UNLIKELY (b == e) return;
43
44 size_t cap{};
45 for (auto it = b; it != e; it++) {
46 if (it->value) cap++;
47 }
48 if TOML_UNLIKELY (!cap) return;
49
50 elems_.reserve(cap);
51 for (; b != e; b++) {
52 if (b->value) elems_.push_back(std::move(b->value));
53 }
54 }
55
57 array::array(const array& other) //
58 : node(other) {
59 elems_.reserve(other.elems_.size());
60 for (const auto& elem : other) elems_.emplace_back(impl::make_node(elem));
61
62#if TOML_LIFETIME_HOOKS
63 TOML_ARRAY_CREATED;
64#endif
65 }
66
68 array::array(array && other) noexcept //
69 : node(std::move(other)), elems_(std::move(other.elems_)) {
70#if TOML_LIFETIME_HOOKS
71 TOML_ARRAY_CREATED;
72#endif
73 }
74
76 array& array::operator=(const array& rhs) {
77 if (&rhs != this) {
78 node::operator=(rhs);
79 elems_.clear();
80 elems_.reserve(rhs.elems_.size());
81 for (const auto& elem : rhs) elems_.emplace_back(impl::make_node(elem));
82 }
83 return *this;
84 }
85
87 array& array::operator=(array&& rhs) noexcept {
88 if (&rhs != this) {
89 node::operator=(std::move(rhs));
90 elems_ = std::move(rhs.elems_);
91 }
92 return *this;
93 }
94
96 void array::preinsertion_resize(size_t idx, size_t count) {
97 TOML_ASSERT(idx <= elems_.size());
98 TOML_ASSERT_ASSUME(count >= 1u);
99 const auto old_size = elems_.size();
100 const auto new_size = old_size + count;
101 const auto inserting_at_end = idx == old_size;
102 elems_.resize(new_size);
103 if (!inserting_at_end) {
104 for (size_t left = old_size, right = new_size - 1u; left-- > idx; right--)
105 elems_[right] = std::move(elems_[left]);
106 }
107 }
108
110 void array::insert_at_back(impl::node_ptr && elem) {
111 TOML_ASSERT(elem);
112 elems_.push_back(std::move(elem));
113 }
114
116 array::vector_iterator array::insert_at(const_vector_iterator pos, impl::node_ptr && elem) {
117 return elems_.insert(pos, std::move(elem));
118 }
119
122 bool array::is_homogeneous(node_type ntype) const noexcept {
123 if (elems_.empty()) return false;
124
125 if (ntype == node_type::none) ntype = elems_[0]->type();
126
127 for (const auto& val : elems_)
128 if (val->type() != ntype) return false;
129
130 return true;
131 }
132
135 bool array::is_homogeneous(node_type ntype, node * &first_nonmatch) noexcept {
136 if (elems_.empty()) {
137 first_nonmatch = {};
138 return false;
139 }
140 if (ntype == node_type::none) ntype = elems_[0]->type();
141 for (const auto& val : elems_) {
142 if (val->type() != ntype) {
143 first_nonmatch = val.get();
144 return false;
145 }
146 }
147 return true;
148 }
149
152 bool array::is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept {
153 node* fnm = nullptr;
154 const auto result = const_cast<array&>(*this).is_homogeneous(ntype, fnm);
155 first_nonmatch = fnm;
156 return result;
157 }
158
160 node& array::at(size_t index) {
161#if TOML_COMPILER_HAS_EXCEPTIONS
162
163 return *elems_.at(index);
164
165#else
166
167 auto n = get(index);
168 TOML_ASSERT_ASSUME(n && "element index not found in array!");
169 return *n;
170
171#endif
172 }
173
175 void array::reserve(size_t new_capacity) {
176 elems_.reserve(new_capacity);
177 }
178
180 void array::shrink_to_fit() {
181 elems_.shrink_to_fit();
182 }
183
185 void array::truncate(size_t new_size) {
186 if (new_size < elems_.size()) elems_.resize(new_size);
187 }
188
190 array::iterator array::erase(const_iterator pos) noexcept {
191 return iterator{elems_.erase(const_vector_iterator{pos})};
192 }
193
195 array::iterator array::erase(const_iterator first, const_iterator last) noexcept {
196 return iterator{elems_.erase(const_vector_iterator{first}, const_vector_iterator{last})};
197 }
198
200 size_t array::total_leaf_count() const noexcept {
201 size_t leaves{};
202 for (size_t i = 0, e = elems_.size(); i < e; i++) {
203 auto arr = elems_[i]->as_array();
204 leaves += arr ? arr->total_leaf_count() : size_t{1};
205 }
206 return leaves;
207 }
208
210 void array::flatten_child(array && child, size_t & dest_index) noexcept {
211 for (size_t i = 0, e = child.size(); i < e; i++) {
212 auto type = child.elems_[i]->type();
213 if (type == node_type::array) {
214 array& arr = *reinterpret_cast<array*>(child.elems_[i].get());
215 if (!arr.empty()) flatten_child(std::move(arr), dest_index);
216 } else
217 elems_[dest_index++] = std::move(child.elems_[i]);
218 }
219 }
220
223 if (elems_.empty()) return *this;
224
225 bool requires_flattening = false;
226 size_t size_after_flattening = elems_.size();
227 for (size_t i = elems_.size(); i-- > 0u;) {
228 auto arr = elems_[i]->as_array();
229 if (!arr) continue;
230 size_after_flattening--; // discount the array itself
231 const auto leaf_count = arr->total_leaf_count();
232 if (leaf_count > 0u) {
233 requires_flattening = true;
234 size_after_flattening += leaf_count;
235 } else
236 elems_.erase(elems_.cbegin() + static_cast<ptrdiff_t>(i));
237 }
238
239 if (!requires_flattening) return *this;
240
241 elems_.reserve(size_after_flattening);
242
243 size_t i = 0;
244 while (i < elems_.size()) {
245 auto arr = elems_[i]->as_array();
246 if (!arr) {
247 i++;
248 continue;
249 }
250
251 impl::node_ptr arr_storage = std::move(elems_[i]);
252 const auto leaf_count = arr->total_leaf_count();
253 if (leaf_count > 1u) preinsertion_resize(i + 1u, leaf_count - 1u);
254 flatten_child(std::move(*arr), i); // increments i
255 }
256
257 return *this;
258 }
259
261 array& array::prune(bool recursive)& noexcept {
262 if (elems_.empty()) return *this;
263
264 for (size_t i = elems_.size(); i-- > 0u;) {
265 if (auto arr = elems_[i]->as_array()) {
266 if (recursive) arr->prune(true);
267 if (arr->empty()) elems_.erase(elems_.cbegin() + static_cast<ptrdiff_t>(i));
268 } else if (auto tbl = elems_[i]->as_table()) {
269 if (recursive) tbl->prune(true);
270 if (tbl->empty()) elems_.erase(elems_.cbegin() + static_cast<ptrdiff_t>(i));
271 }
272 }
273
274 return *this;
275 }
276
278 void array::pop_back() noexcept {
279 elems_.pop_back();
280 }
281
283 void array::clear() noexcept {
284 elems_.clear();
285 }
286
288 bool TOML_CALLCONV array::equal(const array& lhs, const array& rhs) noexcept {
289 if (&lhs == &rhs) return true;
290 if (lhs.elems_.size() != rhs.elems_.size()) return false;
291 for (size_t i = 0, e = lhs.elems_.size(); i < e; i++) {
292 const auto lhs_type = lhs.elems_[i]->type();
293 const node& rhs_ = *rhs.elems_[i];
294 const auto rhs_type = rhs_.type();
295 if (lhs_type != rhs_type) return false;
296
297 const bool equal = lhs.elems_[i]->visit([&](const auto& lhs_) noexcept {
298 return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_);
299 });
300 if (!equal) return false;
301 }
302 return true;
303 }
304}
306
307#include "header_end.hpp"
TOML_NAMESPACE_START
Definition array.inl:17
A TOML array.
Definition array.hpp:285
TOML_PURE_INLINE_GETTER node * get(size_t index) noexcept
Gets a pointer to the element at a specific index.
Definition array.hpp:685
TOML_EXPORTED_MEMBER_FUNCTION void reserve(size_t new_capacity)
Reserves internal storage capacity up to a pre-determined number of elements.
TOML_EXPORTED_MEMBER_FUNCTION ~array() noexcept
TOML_EXPORTED_MEMBER_FUNCTION array & operator=(array &&rhs) noexcept
Move-assignment operator.
TOML_EXPORTED_MEMBER_FUNCTION iterator erase(const_iterator pos) noexcept
Removes the specified element from the array.
TOML_EXPORTED_MEMBER_FUNCTION void pop_back() noexcept
Removes the last element from the array.
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_EXPORTED_MEMBER_FUNCTION array & prune(bool recursive=true) &noexcept
Removes empty child arrays and tables.
TOML_EXPORTED_MEMBER_FUNCTION void clear() noexcept
Removes all elements from the array.
TOML_EXPORTED_MEMBER_FUNCTION void truncate(size_t new_size)
Shrinks the array to the given size.
TOML_CONST_INLINE_GETTER node_type type() const noexcept final
Returns #toml::node_type::array.
Definition array.hpp:412
TOML_NODISCARD bool empty() const noexcept
Returns true if the array is empty.
Definition array.hpp:1129
TOML_PURE_GETTER TOML_EXPORTED_MEMBER_FUNCTION bool is_homogeneous(node_type ntype) const noexcept final
TOML_EXPORTED_MEMBER_FUNCTION array & flatten() &
Flattens this array, recursively hoisting the contents of child arrays up into itself.
array_iterator iterator
A RandomAccessIterator for iterating over elements in a toml::array.
Definition array.hpp:803
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 size_t size() const noexcept
Returns the number of elements in the array.
Definition array.hpp:1136
#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_ASSERT(expr)
Sets the assert function used by the library. \detail Defaults to the standard C assert().
Definition preprocessor.hpp:1185
#define TOML_ASSERT_ASSUME(expr)
Definition preprocessor.hpp:1190
#define TOML_UNLIKELY(...)
Definition preprocessor.hpp:538
#define TOML_EXTERNAL_LINKAGE
Definition preprocessor.hpp:1339
#define TOML_PURE_GETTER
Definition preprocessor.hpp:474
#define TOML_NAMESPACE_END
Definition preprocessor.hpp:1320