20#if TOML_LIFETIME_HOOKS
27#if TOML_LIFETIME_HOOKS
33 array::array(
const impl::array_init_elem* b,
const impl::array_init_elem* e) {
34#if TOML_LIFETIME_HOOKS
45 for (
auto it = b; it != e; it++) {
52 if (b->value) elems_.push_back(std::move(b->value));
59 elems_.reserve(other.elems_.
size());
60 for (
const auto& elem : other) elems_.emplace_back(impl::make_node(elem));
62#if TOML_LIFETIME_HOOKS
69 : node(std::move(other)), elems_(std::move(other.elems_)) {
70#if TOML_LIFETIME_HOOKS
80 elems_.reserve(rhs.elems_.
size());
81 for (
const auto& elem : rhs) elems_.emplace_back(impl::make_node(elem));
89 node::operator=(std::move(rhs));
90 elems_ = std::move(rhs.elems_);
96 void array::preinsertion_resize(
size_t idx,
size_t count) {
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]);
110 void array::insert_at_back(impl::node_ptr && elem) {
112 elems_.push_back(std::move(elem));
116 array::vector_iterator array::insert_at(const_vector_iterator pos, impl::node_ptr && elem) {
117 return elems_.insert(pos, std::move(elem));
123 if (elems_.empty())
return false;
125 if (ntype == node_type::none) ntype = elems_[0]->type();
127 for (
const auto& val : elems_)
128 if (val->type() != ntype)
return false;
136 if (elems_.empty()) {
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();
155 first_nonmatch = fnm;
161#if TOML_COMPILER_HAS_EXCEPTIONS
163 return *elems_.at(index);
176 elems_.reserve(new_capacity);
181 elems_.shrink_to_fit();
186 if (new_size < elems_.size()) elems_.resize(new_size);
191 return iterator{elems_.erase(const_vector_iterator{pos})};
196 return iterator{elems_.erase(const_vector_iterator{first}, const_vector_iterator{last})};
200 size_t array::total_leaf_count()
const noexcept {
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};
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);
217 elems_[dest_index++] = std::move(child.elems_[i]);
223 if (elems_.empty())
return *
this;
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();
230 size_after_flattening--;
231 const auto leaf_count = arr->total_leaf_count();
232 if (leaf_count > 0u) {
233 requires_flattening =
true;
234 size_after_flattening += leaf_count;
236 elems_.erase(elems_.cbegin() +
static_cast<ptrdiff_t
>(i));
239 if (!requires_flattening)
return *
this;
241 elems_.reserve(size_after_flattening);
244 while (i < elems_.size()) {
245 auto arr = elems_[i]->as_array();
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);
262 if (elems_.empty())
return *
this;
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));
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;
297 const bool equal = lhs.elems_[i]->visit([&](
const auto& lhs_)
noexcept {
298 return lhs_ == *
reinterpret_cast<std::remove_reference_t<decltype(lhs_)
>*>(&rhs_);
300 if (!equal)
return false;