9#if !TOML_IMPLEMENTATION
10#error This is an implementation-only header.
19 array::array()
noexcept {
20#if TOML_LIFETIME_HOOKS
26 array::~array()
noexcept {
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));
57 array::array(
const array& other)
59 elems_.reserve(other.elems_.
size());
60 for (
const auto& elem : other) elems_.emplace_back(impl::make_node(elem));
62#if TOML_LIFETIME_HOOKS
68 array::array(
array && other)
noexcept
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) {
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));
122 bool array::is_homogeneous(node_type ntype)
const noexcept {
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;
135 bool array::is_homogeneous(node_type ntype, node * &first_nonmatch)
noexcept {
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();
152 bool array::is_homogeneous(node_type ntype,
const node*& first_nonmatch)
const noexcept {
155 first_nonmatch = fnm;
160 node& array::at(
size_t index) {
161#if TOML_COMPILER_HAS_EXCEPTIONS
163 return *elems_.at(
index);
180 void array::shrink_to_fit() {
181 elems_.shrink_to_fit();
185 void array::truncate(
size_t new_size) {
186 if (new_size < elems_.size()) elems_.resize(new_size);
190 array::iterator array::erase(const_iterator
pos)
noexcept {
191 return iterator{elems_.erase(const_vector_iterator{
pos})};
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})};
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]);
222 array& array::flatten() & {
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-- > 0
u;) {
228 auto arr = elems_[
i]->as_array();
230 size_after_flattening--;
231 const auto leaf_count = arr->total_leaf_count();
232 if (leaf_count > 0
u) {
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);
261 array& array::prune(
bool recursive) &
noexcept {
262 if (elems_.empty())
return *
this;
264 for (
size_t i = elems_.size();
i-- > 0
u;) {
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));
278 void array::pop_back()
noexcept {
283 void array::clear()
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;
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;
void count(T, T, const U &,...)
bool equal(const T &x, const U &y)
TOML_EXPORTED_MEMBER_FUNCTION iterator erase(const_iterator pos) noexcept
Removes the specified element from the array.
TOML_EXPORTED_MEMBER_FUNCTION array & prune(bool recursive=true) &noexcept
Removes empty child arrays and tables.
TOML_NODISCARD bool empty() const noexcept
Returns true if the array is empty.
TOML_PURE_GETTER TOML_EXPORTED_MEMBER_FUNCTION bool is_homogeneous(node_type ntype) const noexcept final
TOML_NODISCARD size_t size() const noexcept
Returns the number of elements in the array.
#define TOML_CALLCONV
Calling convention to apply to exported free/static functions. \detail Not defined by default (let th...
#define TOML_ASSERT(expr)
Sets the assert function used by the library. \detail Defaults to the standard C assert().
#define TOML_ASSERT_ASSUME(expr)
#define TOML_UNLIKELY(...)
#define TOML_EXTERNAL_LINKAGE
#define TOML_NAMESPACE_END