fixed array::insert not working correctly in some cases
also: - improved the documentation for table and array - fixed documentation font on mobile
This commit is contained in:
parent
35ada5d851
commit
539aad89f4
@ -70,7 +70,7 @@ EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = NO
|
||||
|
@ -47,7 +47,7 @@ article div > section > section
|
||||
|
||||
pre, code, .tpp-enable-if > a
|
||||
{
|
||||
font-family: 'Consolas', 'Source Sans Pro', monospace;
|
||||
font-family: 'Consolas', 'Source Code Pro', monospace, monospace, monospace;
|
||||
}
|
||||
|
||||
a.tpp-external
|
||||
|
@ -3,10 +3,8 @@
|
||||
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//# {{
|
||||
#ifndef INCLUDE_TOMLPLUSPLUS_H
|
||||
#define INCLUDE_TOMLPLUSPLUS_H
|
||||
//# }}
|
||||
|
||||
//# Note: most of these would be included transitively but
|
||||
//# they're listed explicitly here because this file
|
||||
@ -135,6 +133,4 @@
|
||||
#undef TOML_USING_ANON_NAMESPACE
|
||||
#endif
|
||||
|
||||
//# {{
|
||||
#endif // INCLUDE_TOMLPLUSPLUS_H
|
||||
//# }}
|
||||
|
@ -225,57 +225,69 @@ TOML_IMPL_NAMESPACE_END
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
/// \brief A RandomAccessIterator for iterating over nodes in a toml::array.
|
||||
/// \brief A RandomAccessIterator for iterating over elements in a toml::array.
|
||||
using array_iterator = impl::array_iterator<false>;
|
||||
|
||||
/// \brief A RandomAccessIterator for iterating over const nodes in a toml::array.
|
||||
/// \brief A RandomAccessIterator for iterating over const elements in a toml::array.
|
||||
using const_array_iterator = impl::array_iterator<true>;
|
||||
|
||||
/// \brief A TOML array.
|
||||
///
|
||||
/// \detail The interface of this type is modeled after std::vector, with some
|
||||
/// additional considerations made for the heterogeneous nature of a
|
||||
/// TOML array. \cpp
|
||||
/// TOML array.
|
||||
///
|
||||
/// auto tbl = toml::parse("arr = [1, 2, 3, 4, 'five']"sv);
|
||||
/// auto& arr = *tbl.get_as<toml::array>("arr");
|
||||
/// std::cout << arr << std::endl;
|
||||
/// \godbolt{sjK4da}
|
||||
///
|
||||
/// for (size_t i = 0; i < arr.size(); i++)
|
||||
/// \cpp
|
||||
///
|
||||
/// toml::table tbl = toml::parse(R"(
|
||||
/// arr = [1, 2, 3, 4, 'five']
|
||||
/// )"sv);
|
||||
///
|
||||
/// // get the element as an array
|
||||
/// toml::array& arr = *tbl.get_as<toml::array>("arr");
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// // increment each element with visit()
|
||||
/// for (auto&& elem : arr)
|
||||
/// {
|
||||
/// arr[i].visit([](auto&& el) noexcept
|
||||
/// {
|
||||
/// if constexpr (toml::is_number<decltype(el)>)
|
||||
/// (*el)++;
|
||||
/// else if constexpr (toml::is_string<decltype(el)>)
|
||||
/// el = "six"sv;
|
||||
/// });
|
||||
/// elem.visit([](auto&& el) noexcept
|
||||
/// {
|
||||
/// if constexpr (toml::is_number<decltype(el)>)
|
||||
/// (*el)++;
|
||||
/// else if constexpr (toml::is_string<decltype(el)>)
|
||||
/// el = "six"sv;
|
||||
/// });
|
||||
/// }
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// // add and remove elements
|
||||
/// arr.push_back(7);
|
||||
/// arr.push_back(8.0f);
|
||||
/// arr.push_back("nine"sv);
|
||||
/// arr.erase(arr.cbegin());
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.emplace_back<toml::array>(10, 11.0);
|
||||
/// std::cout << arr << std::endl;
|
||||
/// // emplace elements
|
||||
/// arr.emplace_back<std::string>("ten");
|
||||
/// arr.emplace_back<toml::array>(11, 12.0);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, 2, 3, 4, "five"]
|
||||
/// [2, 3, 4, 5, "six"]
|
||||
/// [3, 4, 5, "six", 7, 8.0, "nine"]
|
||||
/// [3, 4, 5, "six", 7, 8.0, "nine", [10, 11.0]]
|
||||
/// [ 1, 2, 3, 4, 'five' ]
|
||||
/// [ 2, 3, 4, 5, 'six' ]
|
||||
/// [ 3, 4, 5, 'six', 7, 8.0, 'nine' ]
|
||||
/// [ 3, 4, 5, 'six', 7, 8.0, 'nine', 'ten', [ 11, 12.0 ] ]
|
||||
/// \eout
|
||||
class TOML_API array final
|
||||
: public node
|
||||
{
|
||||
private:
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
std::vector<std::unique_ptr<node>> values;
|
||||
std::vector<std::unique_ptr<node>> elements;
|
||||
|
||||
void preinsertion_resize(size_t idx, size_t count) noexcept;
|
||||
|
||||
@ -287,9 +299,9 @@ TOML_NAMESPACE_START
|
||||
using reference = node&;
|
||||
using const_reference = const node&;
|
||||
|
||||
/// \brief A RandomAccessIterator for iterating over nodes in a toml::array.
|
||||
/// \brief A RandomAccessIterator for iterating over elements in a toml::array.
|
||||
using iterator = array_iterator;
|
||||
/// \brief A RandomAccessIterator for iterating over const nodes in a toml::array.
|
||||
/// \brief A RandomAccessIterator for iterating over const elements in a toml::array.
|
||||
using const_iterator = const_array_iterator;
|
||||
|
||||
/// \brief Default constructor.
|
||||
@ -300,16 +312,16 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD_CTOR
|
||||
array(array&& other) noexcept;
|
||||
|
||||
/// \brief Constructs an array with one or more initial values.
|
||||
/// \brief Constructs an array with one or more initial elements.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 2.0, "three"sv, toml::array{ 4, 5 } };
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, 2.0, "three", [4, 5]]
|
||||
/// [ 1, 2.0, 'three', [ 4, 5 ] ]
|
||||
/// \eout
|
||||
///
|
||||
/// \remark \parblock If you need to construct an array with one child array element, the array's move constructor
|
||||
@ -318,8 +330,8 @@ TOML_NAMESPACE_START
|
||||
/// // desired result: [ [ 42 ] ]
|
||||
/// auto bad = toml::array{ toml::array{ 42 } }
|
||||
/// auto good = toml::array{ toml::inserter{ toml::array{ 42 } } }
|
||||
/// std::cout << "bad: " << bad << std::endl;
|
||||
/// std::cout << "good:" << good << std::endl;
|
||||
/// std::cout << "bad: " << bad << "\n";
|
||||
/// std::cout << "good:" << good << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -329,20 +341,20 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \endparblock
|
||||
///
|
||||
/// \tparam U One of the TOML node or value types (or a type promotable to one).
|
||||
/// \tparam V One of the TOML node or value types (or a type promotable to one).
|
||||
/// \param val The value used to initialize node 0.
|
||||
/// \param vals The values used to initialize nodes 1...N.
|
||||
template <typename U, typename... V>
|
||||
/// \tparam ElemType One of the TOML node or value types (or a type promotable to one).
|
||||
/// \tparam ElemTypes One of the TOML node or value types (or a type promotable to one).
|
||||
/// \param val The node or value used to initialize element 0.
|
||||
/// \param vals The nodes or values used to initialize elements 1...N.
|
||||
template <typename ElemType, typename... ElemTypes>
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit array(U&& val, V&&... vals)
|
||||
explicit array(ElemType&& val, ElemTypes&&... vals)
|
||||
{
|
||||
values.reserve(sizeof...(V) + 1_sz);
|
||||
values.emplace_back(impl::make_node(std::forward<U>(val)));
|
||||
if constexpr (sizeof...(V) > 0)
|
||||
elements.reserve(sizeof...(ElemTypes) + 1_sz);
|
||||
elements.emplace_back(impl::make_node(std::forward<ElemType>(val)));
|
||||
if constexpr (sizeof...(ElemTypes) > 0)
|
||||
{
|
||||
(
|
||||
values.emplace_back(impl::make_node(std::forward<V>(vals))),
|
||||
elements.emplace_back(impl::make_node(std::forward<ElemTypes>(vals))),
|
||||
...
|
||||
);
|
||||
}
|
||||
@ -365,63 +377,63 @@ TOML_NAMESPACE_START
|
||||
[[nodiscard]] array* as_array() noexcept override;
|
||||
[[nodiscard]] const array* as_array() const noexcept override;
|
||||
|
||||
/// \brief Checks if the array contains nodes of only one type.
|
||||
/// \brief Checks if the array contains elements of only one type.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << "homogenous: "sv << arr.is_homogeneous(toml::node_type::none) << std::endl;
|
||||
/// std::cout << "all floats: "sv << arr.is_homogeneous(toml::node_type::floating_point) << std::endl;
|
||||
/// std::cout << "all arrays: "sv << arr.is_homogeneous(toml::node_type::array) << std::endl;
|
||||
/// std::cout << "all integers: "sv << arr.is_homogeneous(toml::node_type::integer) << std::endl;
|
||||
/// std::cout << "homogenous: "sv << arr.is_homogeneous(toml::node_type::none) << "\n";
|
||||
/// std::cout << "all floats: "sv << arr.is_homogeneous(toml::node_type::floating_point) << "\n";
|
||||
/// std::cout << "all arrays: "sv << arr.is_homogeneous(toml::node_type::array) << "\n";
|
||||
/// std::cout << "all ints: "sv << arr.is_homogeneous(toml::node_type::integer) << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// homogeneous: true
|
||||
/// all doubles: false
|
||||
/// all floats: false
|
||||
/// all arrays: false
|
||||
/// all integers: true
|
||||
/// all ints: true
|
||||
/// \eout
|
||||
///
|
||||
/// \param type A TOML node type. <br>
|
||||
/// <strong><em>`toml::node_type::none`: </em></strong> "is every node the same type?"
|
||||
/// <strong><em>Anything else:</em></strong> "is every node one of these?" <br>
|
||||
/// <strong><em>toml::node_type::none: </em></strong> "is every node the same type?" <br>
|
||||
/// <strong><em>Anything else:</em></strong> "is every node one of these?"
|
||||
///
|
||||
/// \returns True if the array was homogeneous.
|
||||
///
|
||||
/// \remarks Always returns `false` for empty arrays.
|
||||
[[nodiscard]] bool is_homogeneous(node_type type) const noexcept;
|
||||
|
||||
/// \brief Checks if the array contains nodes of only one type.
|
||||
/// \brief Checks if the array contains elements of only one type.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << "homogenous: "sv << arr.is_homogeneous() << std::endl;
|
||||
/// std::cout << "all doubles: "sv << arr.is_homogeneous<double>() << std::endl;
|
||||
/// std::cout << "all arrays: "sv << arr.is_homogeneous<toml::array>() << std::endl;
|
||||
/// std::cout << "all integers: "sv << arr.is_homogeneous<int64_t>() << std::endl;
|
||||
/// std::cout << "homogenous: "sv << arr.is_homogeneous() << "\n";
|
||||
/// std::cout << "all doubles: "sv << arr.is_homogeneous<double>() << "\n";
|
||||
/// std::cout << "all arrays: "sv << arr.is_homogeneous<toml::array>() << "\n";
|
||||
/// std::cout << "all integers: "sv << arr.is_homogeneous<int64_t>() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// homogeneous: true
|
||||
/// all doubles: false
|
||||
/// all arrays: false
|
||||
/// homogeneous: true
|
||||
/// all doubles: false
|
||||
/// all arrays: false
|
||||
/// all integers: true
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam T A TOML node type. <br>
|
||||
/// <strong><em>Left as `void`:</em></strong> "is every node the same type?"
|
||||
/// <strong><em>Explicitly specified:</em></strong> "is every node a T?" <br>
|
||||
/// \tparam ElemType A TOML node or value type. <br>
|
||||
/// <strong><em>Left as `void`:</em></strong> "is every node the same type?" <br>
|
||||
/// <strong><em>Explicitly specified:</em></strong> "is every node a T?"
|
||||
///
|
||||
/// \returns True if the array was homogeneous.
|
||||
///
|
||||
/// \remarks Always returns `false` for empty arrays.
|
||||
template <typename T = void>
|
||||
template <typename ElemType = void>
|
||||
[[nodiscard]]
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
static_assert(
|
||||
std::is_void_v<type>
|
||||
|| ((impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>),
|
||||
@ -438,76 +450,76 @@ TOML_NAMESPACE_START
|
||||
/// \brief Returns true if this array contains only tables.
|
||||
[[nodiscard]] bool is_array_of_tables() const noexcept override;
|
||||
|
||||
/// \brief Gets a reference to the node at a specific index.
|
||||
/// \brief Gets a reference to the element at a specific index.
|
||||
[[nodiscard]] node& operator[] (size_t index) noexcept;
|
||||
/// \brief Gets a reference to the node at a specific index.
|
||||
/// \brief Gets a reference to the element at a specific index.
|
||||
[[nodiscard]] const node& operator[] (size_t index) const noexcept;
|
||||
|
||||
/// \brief Returns a reference to the first node in the array.
|
||||
/// \brief Returns a reference to the first element in the array.
|
||||
[[nodiscard]] node& front() noexcept;
|
||||
/// \brief Returns a reference to the first node in the array.
|
||||
/// \brief Returns a reference to the first element in the array.
|
||||
[[nodiscard]] const node& front() const noexcept;
|
||||
/// \brief Returns a reference to the last node in the array.
|
||||
/// \brief Returns a reference to the last element in the array.
|
||||
[[nodiscard]] node& back() noexcept;
|
||||
/// \brief Returns a reference to the last node in the array.
|
||||
/// \brief Returns a reference to the last element in the array.
|
||||
[[nodiscard]] const node& back() const noexcept;
|
||||
|
||||
/// \brief Returns an iterator to the first node.
|
||||
/// \brief Returns an iterator to the first element.
|
||||
[[nodiscard]] iterator begin() noexcept;
|
||||
/// \brief Returns an iterator to the first node.
|
||||
/// \brief Returns an iterator to the first element.
|
||||
[[nodiscard]] const_iterator begin() const noexcept;
|
||||
/// \brief Returns an iterator to the first node.
|
||||
/// \brief Returns an iterator to the first element.
|
||||
[[nodiscard]] const_iterator cbegin() const noexcept;
|
||||
|
||||
/// \brief Returns an iterator to one-past-the-last node.
|
||||
/// \brief Returns an iterator to one-past-the-last element.
|
||||
[[nodiscard]] iterator end() noexcept;
|
||||
/// \brief Returns an iterator to one-past-the-last node.
|
||||
/// \brief Returns an iterator to one-past-the-last element.
|
||||
[[nodiscard]] const_iterator end() const noexcept;
|
||||
/// \brief Returns an iterator to one-past-the-last node.
|
||||
/// \brief Returns an iterator to one-past-the-last element.
|
||||
[[nodiscard]] const_iterator cend() const noexcept;
|
||||
|
||||
/// \brief Returns true if the array is empty.
|
||||
[[nodiscard]] bool empty() const noexcept;
|
||||
/// \brief Returns the number of nodes in the array.
|
||||
/// \brief Returns the number of elements in the array.
|
||||
[[nodiscard]] size_t size() const noexcept;
|
||||
/// \brief Reserves internal storage capacity up to a pre-determined number of nodes.
|
||||
/// \brief Reserves internal storage capacity up to a pre-determined number of elements.
|
||||
void reserve(size_t new_capacity);
|
||||
/// \brief Removes all nodes from the array.
|
||||
/// \brief Removes all elements from the array.
|
||||
void clear() noexcept;
|
||||
|
||||
/// \brief Returns the maximum number of nodes that can be stored in an array on the current platform.
|
||||
/// \brief Returns the maximum number of elements that can be stored in an array on the current platform.
|
||||
[[nodiscard]] size_t max_size() const noexcept;
|
||||
/// \brief Returns the current max number of nodes that may be held in the array's internal storage.
|
||||
/// \brief Returns the current max number of elements that may be held in the array's internal storage.
|
||||
[[nodiscard]] size_t capacity() const noexcept;
|
||||
/// \brief Requests the removal of any unused internal storage capacity.
|
||||
void shrink_to_fit();
|
||||
|
||||
/// \brief Inserts a new node at a specific position in the array.
|
||||
/// \brief Inserts a new element at a specific position in the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 3 };
|
||||
/// arr.insert(arr.cbegin() + 1, "two");
|
||||
/// arr.insert(arr.cend(), toml::array{ 4, 5 });
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, "two", 3, [4, 5]]
|
||||
/// [ 1, 'two', 3, [ 4, 5 ] ]
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam U One of the TOML node or value types (or a type promotable to one).
|
||||
/// \param pos The insertion position.
|
||||
/// \param val The value being inserted.
|
||||
/// \tparam ElemType One of the TOML node or value types (or a type promotable to one).
|
||||
/// \param pos The insertion position.
|
||||
/// \param val The node or value being inserted.
|
||||
///
|
||||
/// \returns An iterator to the inserted value.
|
||||
template <typename U>
|
||||
iterator insert(const_iterator pos, U&& val) noexcept
|
||||
/// \returns An iterator to the newly-inserted element.
|
||||
template <typename ElemType>
|
||||
iterator insert(const_iterator pos, ElemType&& val) noexcept
|
||||
{
|
||||
return { values.emplace(pos.raw_, impl::make_node(std::forward<U>(val))) };
|
||||
return { elements.emplace(pos.raw_, impl::make_node(std::forward<ElemType>(val))) };
|
||||
}
|
||||
|
||||
/// \brief Repeatedly inserts a value starting at a specific position in the array.
|
||||
/// \brief Repeatedly inserts a new element starting at a specific position in the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{
|
||||
@ -515,375 +527,378 @@ TOML_NAMESPACE_START
|
||||
/// "and immediately we knew peace was never an option."
|
||||
/// };
|
||||
/// arr.insert(arr.cbegin() + 1, 3, "honk");
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [
|
||||
/// "with an evil twinkle in its eye the goose said",
|
||||
/// "honk",
|
||||
/// "honk",
|
||||
/// "honk",
|
||||
/// "and immediately we knew peace was never an option."
|
||||
/// 'with an evil twinkle in its eye the goose said',
|
||||
/// 'honk',
|
||||
/// 'honk',
|
||||
/// 'honk',
|
||||
/// 'and immediately we knew peace was never an option.'
|
||||
/// ]
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam U One of the TOML value types (or a type promotable to one).
|
||||
/// \param pos The insertion position.
|
||||
/// \param count The number of times the value should be inserted.
|
||||
/// \param val The value being inserted.
|
||||
/// \tparam ElemType One of the TOML node or value types (or a type promotable to one).
|
||||
/// \param pos The insertion position.
|
||||
/// \param count The number of times the node or value should be inserted.
|
||||
/// \param val The node or value being inserted.
|
||||
///
|
||||
/// \returns An iterator to the first inserted value (or a copy of `pos` if count was 0).
|
||||
template <typename U>
|
||||
iterator insert(const_iterator pos, size_t count, U&& val) noexcept
|
||||
/// \returns An iterator to the first newly-inserted element (or a copy of `pos` if count was 0).
|
||||
template <typename ElemType>
|
||||
iterator insert(const_iterator pos, size_t count, ElemType&& val) noexcept
|
||||
{
|
||||
switch (count)
|
||||
{
|
||||
case 0: return { values.begin() + (pos.raw_ - values.cbegin()) };
|
||||
case 1: return insert(pos, std::forward<U>(val));
|
||||
case 0: return { elements.begin() + (pos.raw_ - elements.cbegin()) };
|
||||
case 1: return insert(pos, std::forward<ElemType>(val));
|
||||
default:
|
||||
{
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - values.cbegin());
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
|
||||
preinsertion_resize(start_idx, count);
|
||||
size_t i = start_idx;
|
||||
for (size_t e = start_idx + count - 1_sz; i < e; i++)
|
||||
values[i].reset(impl::make_node(val));
|
||||
elements[i].reset(impl::make_node(val));
|
||||
|
||||
//# potentially move the initial value into the last element
|
||||
values[i].reset(impl::make_node(std::forward<U>(val)));
|
||||
return { values.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
elements[i].reset(impl::make_node(std::forward<ElemType>(val)));
|
||||
return { elements.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Inserts a range of values into the array at a specific position.
|
||||
/// \brief Inserts a range of elements into the array at a specific position.
|
||||
///
|
||||
/// \tparam Iter An iterator type. Must satisfy ForwardIterator.
|
||||
/// \param pos The insertion position.
|
||||
/// \param first Iterator to the first value being inserted.
|
||||
/// \param last Iterator to the one-past-the-last value being inserted.
|
||||
/// \param first Iterator to the first node or value being inserted.
|
||||
/// \param last Iterator to the one-past-the-last node or value being inserted.
|
||||
///
|
||||
/// \returns An iterator to the first inserted value (or a copy of `pos` if `first` == `last`).
|
||||
/// \returns An iterator to the first newly-inserted element (or a copy of `pos` if `first` >= `last`).
|
||||
template <typename Iter>
|
||||
iterator insert(const_iterator pos, Iter first, Iter last) noexcept
|
||||
{
|
||||
const auto count = std::distance(first, last);
|
||||
switch (count)
|
||||
if (count <= 0)
|
||||
return { elements.begin() + (pos.raw_ - elements.cbegin()) };
|
||||
else if (count == 1)
|
||||
return insert(pos, *first);
|
||||
else
|
||||
{
|
||||
case 0: return { values.begin() + (pos.raw_ - values.cbegin()) };
|
||||
case 1: return insert(pos, *first);
|
||||
default:
|
||||
{
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - values.cbegin());
|
||||
preinsertion_resize(start_idx, count);
|
||||
size_t i = start_idx;
|
||||
for (auto it = first; it != last; it++)
|
||||
values[i].reset(impl::make_node(*it));
|
||||
return { values.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
}
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
|
||||
preinsertion_resize(start_idx, static_cast<size_t>(count));
|
||||
size_t i = start_idx;
|
||||
for (auto it = first; it != last; it++)
|
||||
elements[i++].reset(impl::make_node(*it));
|
||||
return { elements.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Inserts a range of values into the array at a specific position.
|
||||
/// \brief Inserts a range of elements into the array at a specific position.
|
||||
///
|
||||
/// \tparam U One of the TOML value types (or a type promotable to one).
|
||||
/// \param pos The insertion position.
|
||||
/// \param ilist An initializer list containing the values to be inserted.
|
||||
/// \tparam ElemType One of the TOML node or value types (or a type promotable to one).
|
||||
/// \param pos The insertion position.
|
||||
/// \param ilist An initializer list containing the values to be inserted.
|
||||
///
|
||||
/// \returns An iterator to the first inserted value (or a copy of `pos` if `ilist` was empty).
|
||||
template <typename U>
|
||||
iterator insert(const_iterator pos, std::initializer_list<U> ilist) noexcept
|
||||
/// \returns An iterator to the first newly-inserted element (or a copy of `pos` if `ilist` was empty).
|
||||
template <typename ElemType>
|
||||
iterator insert(const_iterator pos, std::initializer_list<ElemType> ilist) noexcept
|
||||
{
|
||||
switch (ilist.size())
|
||||
{
|
||||
case 0: return { values.begin() + (pos.raw_ - values.cbegin()) };
|
||||
case 0: return { elements.begin() + (pos.raw_ - elements.cbegin()) };
|
||||
case 1: return insert(pos, *ilist.begin());
|
||||
default:
|
||||
{
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - values.cbegin());
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
|
||||
preinsertion_resize(start_idx, ilist.size());
|
||||
size_t i = start_idx;
|
||||
for (auto& val : ilist)
|
||||
values[i].reset(impl::make_node(val));
|
||||
return { values.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
elements[i++].reset(impl::make_node(val));
|
||||
return { elements.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Emplaces a new value at a specific position in the array.
|
||||
/// \brief Emplaces a new element at a specific position in the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 2 };
|
||||
///
|
||||
/// //add a string using std::string's substring constructor
|
||||
/// arr.emplace<std::string>(arr.cbegin() + 1, "this is not a drill"sv, 14, 5);
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, "drill", 2]
|
||||
/// [ 1, 'drill', 2 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam U One of the TOML node or value types.
|
||||
/// \tparam V Value constructor argument types.
|
||||
/// \param pos The insertion position.
|
||||
/// \param args Arguments to forward to the value's constructor.
|
||||
/// \tparam ElemType One of the TOML node or value types.
|
||||
/// \tparam Args Value constructor argument types.
|
||||
/// \param pos The insertion position.
|
||||
/// \param args Arguments to forward to the value's constructor.
|
||||
///
|
||||
/// \returns An iterator to the inserted value.
|
||||
/// \returns An iterator to the inserted element.
|
||||
///
|
||||
/// \remarks There is no difference between insert() and emplace()
|
||||
/// for trivial value types (floats, ints, bools).
|
||||
template <typename U, typename... V>
|
||||
iterator emplace(const_iterator pos, V&&... args) noexcept
|
||||
template <typename ElemType, typename... Args>
|
||||
iterator emplace(const_iterator pos, Args&&... args) noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<U>;
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
static_assert(
|
||||
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
|
||||
"Emplacement type parameter must be one of:"
|
||||
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
|
||||
);
|
||||
|
||||
return { values.emplace(pos.raw_, new impl::wrap_node<type>{ std::forward<V>(args)...} ) };
|
||||
return { elements.emplace(pos.raw_, new impl::wrap_node<type>{ std::forward<Args>(args)...} ) };
|
||||
}
|
||||
|
||||
/// \brief Removes the specified node from the array.
|
||||
/// \brief Removes the specified element from the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.erase(arr.cbegin() + 1);
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, 2, 3]
|
||||
/// [1, 3]
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1, 3 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \param pos Iterator to the node being erased.
|
||||
/// \param pos Iterator to the element being erased.
|
||||
///
|
||||
/// \returns Iterator to the first node immediately following the removed node.
|
||||
/// \returns Iterator to the first element immediately following the removed element.
|
||||
iterator erase(const_iterator pos) noexcept;
|
||||
|
||||
/// \brief Removes the nodes in the range [first, last) from the array.
|
||||
/// \brief Removes the elements in the range [first, last) from the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, "bad", "karma" 2 };
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.erase(arr.cbegin() + 1, arr.cbegin() + 3);
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, "bad", "karma", 3]
|
||||
/// [1, 3]
|
||||
/// [ 1, 'bad', 'karma', 3 ]
|
||||
/// [ 1, 3 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \param first Iterator to the first node being erased.
|
||||
/// \param last Iterator to the one-past-the-last node being erased.
|
||||
/// \param first Iterator to the first element being erased.
|
||||
/// \param last Iterator to the one-past-the-last element being erased.
|
||||
///
|
||||
/// \returns Iterator to the first node immediately following the last removed node.
|
||||
/// \returns Iterator to the first element immediately following the last removed element.
|
||||
iterator erase(const_iterator first, const_iterator last) noexcept;
|
||||
|
||||
/// \brief Resizes the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// \detail \godbolt{W5zqx3}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.resize(6, 42);
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.resize(2, 0);
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, 2, 3]
|
||||
/// [1, 2, 3, 42, 42, 42]
|
||||
/// [1, 2]
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1, 2, 3, 42, 42, 42 ]
|
||||
/// [ 1, 2 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam U One of the TOML value types (or a type promotable to one).
|
||||
/// \tparam ElemType One of the TOML node or value types (or a type promotable to one).
|
||||
///
|
||||
/// \param new_size New number of elements the array will have.
|
||||
/// \param default_init_val The value used to initialize new elements if the array needs to grow.
|
||||
template <typename U>
|
||||
void resize(size_t new_size, U&& default_init_val) noexcept
|
||||
/// \param new_size The number of elements the array will have after resizing.
|
||||
/// \param default_init_val The node or value used to initialize new elements if the array needs to grow.
|
||||
template <typename ElemType>
|
||||
void resize(size_t new_size, ElemType&& default_init_val) noexcept
|
||||
{
|
||||
if (!new_size)
|
||||
values.clear();
|
||||
else if (new_size < values.size())
|
||||
values.resize(new_size);
|
||||
else if (new_size > values.size())
|
||||
insert(cend(), new_size - values.size(), std::forward<U>(default_init_val));
|
||||
elements.clear();
|
||||
else if (new_size < elements.size())
|
||||
elements.resize(new_size);
|
||||
else if (new_size > elements.size())
|
||||
insert(cend(), new_size - elements.size(), std::forward<ElemType>(default_init_val));
|
||||
}
|
||||
|
||||
/// \brief Shrinks the array to the given size.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// \detail \godbolt{rxEzK5}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.truncate(5); // no-op
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.truncate(1);
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, 2, 3]
|
||||
/// [1, 2, 3]
|
||||
/// [1]
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1]
|
||||
/// \eout
|
||||
///
|
||||
/// \remarks Does nothing if the requested size is larger than or equal to the current size.
|
||||
void truncate(size_t new_size);
|
||||
|
||||
/// \brief Appends a new value to the end of the array.
|
||||
/// \brief Appends a new element to the end of the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 2 };
|
||||
/// arr.push_back(3);
|
||||
/// arr.push_back(4.0);
|
||||
/// arr.push_back(toml::array{ 5, "six"sv });
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, 2, 3, 4.0, [5, "six"]]
|
||||
/// [ 1, 2, 3, 4.0, [ 5, 'six' ] ]
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam U One of the TOML value types (or a type promotable to one).
|
||||
/// \param val The value being added.
|
||||
/// \tparam ElemType One of the TOML node or value types (or a type promotable to one).
|
||||
/// \param val The node or value being added.
|
||||
///
|
||||
/// \returns A reference to the newly-constructed value node.
|
||||
template <typename U>
|
||||
decltype(auto) push_back(U&& val) noexcept
|
||||
/// \returns A reference to the newly-constructed element.
|
||||
template <typename ElemType>
|
||||
decltype(auto) push_back(ElemType&& val) noexcept
|
||||
{
|
||||
auto nde = impl::make_node(std::forward<U>(val));
|
||||
values.emplace_back(nde);
|
||||
auto nde = impl::make_node(std::forward<ElemType>(val));
|
||||
elements.emplace_back(nde);
|
||||
return *nde;
|
||||
}
|
||||
|
||||
/// \brief Emplaces a new value at the end of the array.
|
||||
/// \brief Emplaces a new element at the end of the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 2 };
|
||||
/// arr.emplace_back<toml::array>(3, "four"sv);
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, 2, [3, "four"]]
|
||||
/// [ 1, 2, [ 3, 'four' ] ]
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam U One of the TOML value types.
|
||||
/// \tparam V Value constructor argument types.
|
||||
/// \param args Arguments to forward to the value's constructor.
|
||||
/// \tparam ElemType One of the TOML node or value types.
|
||||
/// \tparam Args Value constructor argument types.
|
||||
/// \param args Arguments to forward to the value's constructor.
|
||||
///
|
||||
/// \returns A reference to the newly-constructed value node.
|
||||
/// \returns A reference to the newly-constructed element.
|
||||
///
|
||||
/// \remarks There is no difference between push_back and emplace_back
|
||||
/// \remarks There is no difference between push_back() and emplace_back()
|
||||
/// For trivial value types (floats, ints, bools).
|
||||
template <typename U, typename... V>
|
||||
decltype(auto) emplace_back(V&&... args) noexcept
|
||||
template <typename ElemType, typename... Args>
|
||||
decltype(auto) emplace_back(Args&&... args) noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<U>;
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
static_assert(
|
||||
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
|
||||
"Emplacement type parameter must be one of:"
|
||||
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
|
||||
);
|
||||
|
||||
auto nde = new impl::wrap_node<type>{ std::forward<V>(args)... };
|
||||
values.emplace_back(nde);
|
||||
auto nde = new impl::wrap_node<type>{ std::forward<Args>(args)... };
|
||||
elements.emplace_back(nde);
|
||||
return *nde;
|
||||
}
|
||||
|
||||
/// \brief Removes the last node from the array.
|
||||
/// \brief Removes the last element from the array.
|
||||
void pop_back() noexcept;
|
||||
|
||||
/// \brief Gets the node at a specific index.
|
||||
/// \brief Gets the element at a specific index.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 99, "bottles of beer on the wall" };
|
||||
/// std::cout << "node [0] exists: "sv << !!arr.get(0) << std::endl;
|
||||
/// std::cout << "node [1] exists: "sv << !!arr.get(1) << std::endl;
|
||||
/// std::cout << "node [2] exists: "sv << !!arr.get(2) << std::endl;
|
||||
/// if (auto val = arr.get(0))
|
||||
/// std::cout << "node [0] was an "sv << val->type() << std::endl;
|
||||
/// std::cout << "element [0] exists: "sv << !!arr.get(0) << "\n";
|
||||
/// std::cout << "element [1] exists: "sv << !!arr.get(1) << "\n";
|
||||
/// std::cout << "element [2] exists: "sv << !!arr.get(2) << "\n";
|
||||
/// if (toml::node* val = arr.get(0))
|
||||
/// std::cout << "element [0] is an "sv << val->type() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// node [0] exists: true
|
||||
/// node [1] exists: true
|
||||
/// node [2] exists: false
|
||||
/// node [0] was an integer
|
||||
/// element [0] exists: true
|
||||
/// element [1] exists: true
|
||||
/// element [2] exists: false
|
||||
/// element [0] is an integer
|
||||
/// \eout
|
||||
///
|
||||
/// \param index The node's index.
|
||||
/// \param index The element's index.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified index if one existed, or nullptr.
|
||||
/// \returns A pointer to the element at the specified index if one existed, or nullptr.
|
||||
[[nodiscard]] node* get(size_t index) noexcept;
|
||||
|
||||
/// \brief Gets the node at a specific index (const overload).
|
||||
/// \brief Gets the element at a specific index (const overload).
|
||||
///
|
||||
/// \param index The node's index.
|
||||
/// \param index The element's index.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified index if one existed, or nullptr.
|
||||
/// \returns A pointer to the element at the specified index if one existed, or nullptr.
|
||||
[[nodiscard]] const node* get(size_t index) const noexcept;
|
||||
|
||||
/// \brief Gets the node at a specific index if it is a particular type.
|
||||
/// \brief Gets the element at a specific index if it is a particular type.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 42, "is the meaning of life, apparently."sv };
|
||||
/// if (auto val = arr.get_as<int64_t>(0))
|
||||
/// std::cout << "node [0] was an integer with value "sv << **val << std::endl;
|
||||
/// if (toml::value<int64_t>* val = arr.get_as<int64_t>(0))
|
||||
/// std::cout << "element [0] is an integer with value "sv << *val << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// node [0] was an integer with value 42
|
||||
/// element [0] is an integer with value 42
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam T The node's type.
|
||||
/// \param index The node's index.
|
||||
/// \tparam ElemType The element's type.
|
||||
/// \param index The element's index.
|
||||
///
|
||||
/// \returns A pointer to the selected node if it existed and was of the specified type, or nullptr.
|
||||
template <typename T>
|
||||
/// \returns A pointer to the selected element if it existed and was of the specified type, or nullptr.
|
||||
template <typename ElemType>
|
||||
[[nodiscard]]
|
||||
impl::wrap_node<T>* get_as(size_t index) noexcept
|
||||
impl::wrap_node<ElemType>* get_as(size_t index) noexcept
|
||||
{
|
||||
if (auto val = get(index))
|
||||
return val->as<T>();
|
||||
return val->as<ElemType>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Gets the node at a specific index if it is a particular type (const overload).
|
||||
/// \brief Gets the element at a specific index if it is a particular type (const overload).
|
||||
///
|
||||
/// \tparam T The node's type.
|
||||
/// \param index The node's index.
|
||||
/// \tparam ElemType The element's type.
|
||||
/// \param index The element's index.
|
||||
///
|
||||
/// \returns A pointer to the selected node if it existed and was of the specified type, or nullptr.
|
||||
template <typename T>
|
||||
/// \returns A pointer to the selected element if it existed and was of the specified type, or nullptr.
|
||||
template <typename ElemType>
|
||||
[[nodiscard]]
|
||||
const impl::wrap_node<T>* get_as(size_t index) const noexcept
|
||||
const impl::wrap_node<ElemType>* get_as(size_t index) const noexcept
|
||||
{
|
||||
if (auto val = get(index))
|
||||
return val->as<T>();
|
||||
return val->as<ElemType>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -892,7 +907,7 @@ TOML_NAMESPACE_START
|
||||
/// \param lhs The LHS array.
|
||||
/// \param rhs The RHS array.
|
||||
///
|
||||
/// \returns True if the arrays contained the same values.
|
||||
/// \returns True if the arrays contained the same elements.
|
||||
friend bool operator == (const array& lhs, const array& rhs) noexcept;
|
||||
|
||||
/// \brief Inequality operator.
|
||||
@ -900,7 +915,7 @@ TOML_NAMESPACE_START
|
||||
/// \param lhs The LHS array.
|
||||
/// \param rhs The RHS array.
|
||||
///
|
||||
/// \returns True if the arrays did not contain the same values.
|
||||
/// \returns True if the arrays did not contain the same elements.
|
||||
friend bool operator != (const array& lhs, const array& rhs) noexcept;
|
||||
|
||||
private:
|
||||
@ -960,24 +975,25 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
///
|
||||
/// auto arr = toml::array{ 1, 2, toml::array{ 3, 4, toml::array{ 5 } }, 6, toml::array{} };
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.flatten();
|
||||
/// std::cout << arr << std::endl;
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [1, 2, [3, 4, [5]], 6, []]
|
||||
/// [1, 2, 3, 4, 5, 6]
|
||||
/// [ 1, 2, [ 3, 4, [ 5 ] ], 6, [] ]
|
||||
/// [ 1, 2, 3, 4, 5, 6 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \remarks Arrays inside child tables are not flattened.
|
||||
///
|
||||
/// A reference to the array.
|
||||
/// \returns A reference to the array.
|
||||
array& flatten() &;
|
||||
|
||||
/// \brief Flattens this array, recursively hoisting the contents of child arrays up into itself (rvalue overload).
|
||||
/// \returns An rvalue reference to the array.
|
||||
array&& flatten() &&
|
||||
{
|
||||
return static_cast<toml::array&&>(static_cast<toml::array&>(*this).flatten());
|
||||
|
@ -22,13 +22,16 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::preinsertion_resize(size_t idx, size_t count) noexcept
|
||||
{
|
||||
const auto new_size = values.size() + count;
|
||||
const auto inserting_at_end = idx == values.size();
|
||||
values.resize(new_size);
|
||||
TOML_ASSERT(idx <= elements.size());
|
||||
TOML_ASSERT(count >= 1_sz);
|
||||
const auto old_size = elements.size();
|
||||
const auto new_size = old_size + count;
|
||||
const auto inserting_at_end = idx == old_size;
|
||||
elements.resize(new_size);
|
||||
if (!inserting_at_end)
|
||||
{
|
||||
for (size_t r = new_size, e = idx + count, l = e; r-- > e; l--)
|
||||
values[r] = std::move(values[l]);
|
||||
for(size_t left = old_size, right = new_size - 1_sz; left --> idx; right--)
|
||||
elements[right] = std::move(elements[left]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,14 +41,14 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
values{ std::move(other.values) }
|
||||
elements{ std::move(other.elements) }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator= (array&& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
values = std::move(rhs.values);
|
||||
elements = std::move(rhs.elements);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -58,69 +61,69 @@ TOML_NAMESPACE_START
|
||||
TOML_MEMBER_ATTR(const) const array* array::as_array() const noexcept { return this; }
|
||||
TOML_MEMBER_ATTR(const) array* array::as_array() noexcept { return this; }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) const node& array::operator[] (size_t index) const noexcept { return *values[index]; }
|
||||
TOML_MEMBER_ATTR(pure) node& array::operator[] (size_t index) noexcept { return *values[index]; }
|
||||
TOML_MEMBER_ATTR(pure) const node& array::operator[] (size_t index) const noexcept { return *elements[index]; }
|
||||
TOML_MEMBER_ATTR(pure) node& array::operator[] (size_t index) noexcept { return *elements[index]; }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) const node& array::front() const noexcept { return *values.front(); }
|
||||
TOML_MEMBER_ATTR(pure) const node& array::back() const noexcept { return *values.back(); }
|
||||
TOML_MEMBER_ATTR(pure) node& array::front() noexcept { return *values.front(); }
|
||||
TOML_MEMBER_ATTR(pure) node& array::back() noexcept { return *values.back(); }
|
||||
TOML_MEMBER_ATTR(pure) const node& array::front() const noexcept { return *elements.front(); }
|
||||
TOML_MEMBER_ATTR(pure) const node& array::back() const noexcept { return *elements.back(); }
|
||||
TOML_MEMBER_ATTR(pure) node& array::front() noexcept { return *elements.front(); }
|
||||
TOML_MEMBER_ATTR(pure) node& array::back() noexcept { return *elements.back(); }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::begin() const noexcept { return { values.begin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::end() const noexcept { return { values.end() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::cbegin() const noexcept { return { values.cbegin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::cend() const noexcept { return { values.cend() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::iterator array::begin() noexcept { return { values.begin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::iterator array::end() noexcept { return { values.end() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::begin() const noexcept { return { elements.begin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::end() const noexcept { return { elements.end() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::cbegin() const noexcept { return { elements.cbegin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::cend() const noexcept { return { elements.cend() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::iterator array::begin() noexcept { return { elements.begin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::iterator array::end() noexcept { return { elements.end() }; }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) size_t array::size() const noexcept { return values.size(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t array::capacity() const noexcept { return values.capacity(); }
|
||||
TOML_MEMBER_ATTR(pure) bool array::empty() const noexcept { return values.empty(); }
|
||||
TOML_MEMBER_ATTR(const) size_t array::max_size() const noexcept { return values.max_size(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t array::size() const noexcept { return elements.size(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t array::capacity() const noexcept { return elements.capacity(); }
|
||||
TOML_MEMBER_ATTR(pure) bool array::empty() const noexcept { return elements.empty(); }
|
||||
TOML_MEMBER_ATTR(const) size_t array::max_size() const noexcept { return elements.max_size(); }
|
||||
|
||||
TOML_EXTERNAL_LINKAGE void array::reserve(size_t new_capacity) { values.reserve(new_capacity); }
|
||||
TOML_EXTERNAL_LINKAGE void array::clear() noexcept { values.clear(); }
|
||||
TOML_EXTERNAL_LINKAGE void array::shrink_to_fit() { values.shrink_to_fit(); }
|
||||
TOML_EXTERNAL_LINKAGE void array::reserve(size_t new_capacity) { elements.reserve(new_capacity); }
|
||||
TOML_EXTERNAL_LINKAGE void array::clear() noexcept { elements.clear(); }
|
||||
TOML_EXTERNAL_LINKAGE void array::shrink_to_fit() { elements.shrink_to_fit(); }
|
||||
|
||||
#undef TOML_MEMBER_ATTR
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::truncate(size_t new_size)
|
||||
{
|
||||
if (new_size < values.size())
|
||||
values.resize(new_size);
|
||||
if (new_size < elements.size())
|
||||
elements.resize(new_size);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator pos) noexcept
|
||||
{
|
||||
return { values.erase(pos.raw_) };
|
||||
return { elements.erase(pos.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator first, const_iterator last) noexcept
|
||||
{
|
||||
return { values.erase(first.raw_, last.raw_) };
|
||||
return { elements.erase(first.raw_, last.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::pop_back() noexcept
|
||||
{
|
||||
values.pop_back();
|
||||
elements.pop_back();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
node* array::get(size_t index) noexcept
|
||||
{
|
||||
return index < values.size() ? values[index].get() : nullptr;
|
||||
return index < elements.size() ? elements[index].get() : nullptr;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
const node* array::get(size_t index) const noexcept
|
||||
{
|
||||
return index < values.size() ? values[index].get() : nullptr;
|
||||
return index < elements.size() ? elements[index].get() : nullptr;
|
||||
}
|
||||
|
||||
TOML_API
|
||||
@ -129,17 +132,17 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.values.size() != rhs.values.size())
|
||||
if (lhs.elements.size() != rhs.elements.size())
|
||||
return false;
|
||||
for (size_t i = 0, e = lhs.values.size(); i < e; i++)
|
||||
for (size_t i = 0, e = lhs.elements.size(); i < e; i++)
|
||||
{
|
||||
const auto lhs_type = lhs.values[i]->type();
|
||||
const node& rhs_ = *rhs.values[i];
|
||||
const auto lhs_type = lhs.elements[i]->type();
|
||||
const node& rhs_ = *rhs.elements[i];
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = lhs.values[i]->visit([&](const auto& lhs_) noexcept
|
||||
const bool equal = lhs.elements[i]->visit([&](const auto& lhs_) noexcept
|
||||
{
|
||||
return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_);
|
||||
});
|
||||
@ -160,9 +163,9 @@ TOML_NAMESPACE_START
|
||||
size_t array::total_leaf_count() const noexcept
|
||||
{
|
||||
size_t leaves{};
|
||||
for (size_t i = 0, e = values.size(); i < e; i++)
|
||||
for (size_t i = 0, e = elements.size(); i < e; i++)
|
||||
{
|
||||
auto arr = values[i]->as_array();
|
||||
auto arr = elements[i]->as_array();
|
||||
leaves += arr ? arr->total_leaf_count() : 1_sz;
|
||||
}
|
||||
return leaves;
|
||||
@ -173,29 +176,29 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
for (size_t i = 0, e = child.size(); i < e; i++)
|
||||
{
|
||||
auto type = child.values[i]->type();
|
||||
auto type = child.elements[i]->type();
|
||||
if (type == node_type::array)
|
||||
{
|
||||
array& arr = *reinterpret_cast<array*>(child.values[i].get());
|
||||
array& arr = *reinterpret_cast<array*>(child.elements[i].get());
|
||||
if (!arr.empty())
|
||||
flatten_child(std::move(arr), dest_index);
|
||||
}
|
||||
else
|
||||
values[dest_index++] = std::move(child.values[i]);
|
||||
elements[dest_index++] = std::move(child.elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::flatten() &
|
||||
{
|
||||
if (values.empty())
|
||||
if (elements.empty())
|
||||
return *this;
|
||||
|
||||
bool requires_flattening = false;
|
||||
size_t size_after_flattening = values.size();
|
||||
for (size_t i = values.size(); i --> 0_sz;)
|
||||
size_t size_after_flattening = elements.size();
|
||||
for (size_t i = elements.size(); i --> 0_sz;)
|
||||
{
|
||||
auto arr = values[i]->as_array();
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
continue;
|
||||
size_after_flattening--; //discount the array itself
|
||||
@ -206,25 +209,25 @@ TOML_NAMESPACE_START
|
||||
size_after_flattening += leaf_count;
|
||||
}
|
||||
else
|
||||
values.erase(values.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
elements.erase(elements.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
}
|
||||
|
||||
if (!requires_flattening)
|
||||
return *this;
|
||||
|
||||
values.reserve(size_after_flattening);
|
||||
elements.reserve(size_after_flattening);
|
||||
|
||||
size_t i = 0;
|
||||
while (i < values.size())
|
||||
while (i < elements.size())
|
||||
{
|
||||
auto arr = values[i]->as_array();
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_ptr<node> arr_storage = std::move(values[i]);
|
||||
std::unique_ptr<node> arr_storage = std::move(elements[i]);
|
||||
const auto leaf_count = arr->total_leaf_count();
|
||||
if (leaf_count > 1_sz)
|
||||
preinsertion_resize(i + 1_sz, leaf_count - 1_sz);
|
||||
@ -237,13 +240,13 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_homogeneous(node_type type) const noexcept
|
||||
{
|
||||
if (values.empty())
|
||||
if (elements.empty())
|
||||
return false;
|
||||
|
||||
if (type == node_type::none)
|
||||
type = values[0]->type();
|
||||
type = elements[0]->type();
|
||||
|
||||
for (const auto& val : values)
|
||||
for (const auto& val : elements)
|
||||
if (val->type() != type)
|
||||
return false;
|
||||
|
||||
|
@ -145,9 +145,6 @@ TOML_NAMESPACE_START // abi namespace
|
||||
template <typename T>
|
||||
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
//template <typename T, typename... U>
|
||||
//struct is_one_of_ : std::integral_constant<bool, (false || ... || std::is_same_v<T, U>)> {};
|
||||
|
||||
template <typename T, typename... U>
|
||||
inline constexpr bool is_one_of = (false || ... || std::is_same_v<T, U>);
|
||||
|
||||
@ -224,17 +221,17 @@ TOML_NAMESPACE_START // abi namespace
|
||||
{
|
||||
/// \brief Convenience literal operators for working with toml++.
|
||||
///
|
||||
/// \detail This namespace exists so you can safely hoist the UDL operators into another scope
|
||||
/// without dragging in everything in the toml namespace: \cpp
|
||||
/// \detail This namespace exists so you can safely hoist the toml++ literal operators into another scope
|
||||
/// without dragging in everything from the toml namespace: \cpp
|
||||
///
|
||||
/// #include <toml++/toml.h>
|
||||
/// using namespace toml::literals;
|
||||
///
|
||||
/// int main()
|
||||
/// {
|
||||
/// auto tbl = "vals = [1, 2, 3]"_toml;
|
||||
/// toml::table tbl = "vals = [1, 2, 3]"_toml;
|
||||
///
|
||||
/// // ... do stuff with the table generated by the "_toml" UDL ...
|
||||
/// // ... do stuff with the table generated by the "_toml" literal ...
|
||||
///
|
||||
/// return 0;
|
||||
/// }
|
||||
|
@ -2456,7 +2456,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
auto child = parent->get(key.segments[i]);
|
||||
if (!child)
|
||||
{
|
||||
child = parent->values.emplace(
|
||||
child = parent->map.emplace(
|
||||
key.segments[i],
|
||||
new toml::table{}
|
||||
).first->second.get();
|
||||
@ -2472,9 +2472,9 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
// table arrays are a special case;
|
||||
// the spec dictates we select the most recently declared element in the array.
|
||||
TOML_ASSERT(!child->ref_cast<array>().values.empty());
|
||||
TOML_ASSERT(child->ref_cast<array>().values.back()->is_table());
|
||||
parent = &child->ref_cast<array>().values.back()->ref_cast<table>();
|
||||
TOML_ASSERT(!child->ref_cast<array>().elements.empty());
|
||||
TOML_ASSERT(child->ref_cast<array>().elements.back()->is_table());
|
||||
parent = &child->ref_cast<array>().elements.back()->ref_cast<table>();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2501,22 +2501,22 @@ TOML_IMPL_NAMESPACE_START
|
||||
// set the starting regions, and return the table element
|
||||
if (is_arr)
|
||||
{
|
||||
auto tab_arr = &parent->values.emplace(
|
||||
auto tab_arr = &parent->map.emplace(
|
||||
key.segments.back(),
|
||||
new toml::array{}
|
||||
).first->second->ref_cast<array>();
|
||||
table_arrays.push_back(tab_arr);
|
||||
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
|
||||
tab_arr->values.emplace_back(new toml::table{});
|
||||
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
return &tab_arr->values.back()->ref_cast<table>();
|
||||
tab_arr->elements.emplace_back(new toml::table{});
|
||||
tab_arr->elements.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
return &tab_arr->elements.back()->ref_cast<table>();
|
||||
}
|
||||
|
||||
//otherwise we're just making a table
|
||||
else
|
||||
{
|
||||
auto tab = &parent->values.emplace(
|
||||
auto tab = &parent->map.emplace(
|
||||
key.segments.back(),
|
||||
new toml::table{})
|
||||
.first->second->ref_cast<table>();
|
||||
@ -2534,9 +2534,9 @@ TOML_IMPL_NAMESPACE_START
|
||||
if (is_arr && matching_node->is_array() && find(table_arrays, &matching_node->ref_cast<array>()))
|
||||
{
|
||||
auto tab_arr = &matching_node->ref_cast<array>();
|
||||
tab_arr->values.emplace_back(new toml::table{});
|
||||
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
return &tab_arr->values.back()->ref_cast<table>();
|
||||
tab_arr->elements.emplace_back(new toml::table{});
|
||||
tab_arr->elements.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
return &tab_arr->elements.back()->ref_cast<table>();
|
||||
}
|
||||
|
||||
else if (!is_arr
|
||||
@ -2582,7 +2582,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
auto child = tab->get(kvp.key.segments[i]);
|
||||
if (!child)
|
||||
{
|
||||
child = tab->values.emplace(
|
||||
child = tab->map.emplace(
|
||||
std::move(kvp.key.segments[i]),
|
||||
new toml::table{}
|
||||
).first->second.get();
|
||||
@ -2615,7 +2615,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
return_if_error();
|
||||
tab->values.emplace(
|
||||
tab->map.emplace(
|
||||
std::move(kvp.key.segments.back()),
|
||||
std::unique_ptr<node>{ kvp.value }
|
||||
);
|
||||
@ -2689,7 +2689,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
return;
|
||||
|
||||
auto end = nde.source_.end;
|
||||
for (auto& [k, v] : tbl.values)
|
||||
for (auto& [k, v] : tbl.map)
|
||||
{
|
||||
(void)k;
|
||||
update_region_ends(*v);
|
||||
@ -2701,7 +2701,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
auto& arr = nde.ref_cast<array>();
|
||||
auto end = nde.source_.end;
|
||||
for (auto& v : arr.values)
|
||||
for (auto& v : arr.elements)
|
||||
{
|
||||
update_region_ends(*v);
|
||||
if (end < v->source_.end)
|
||||
@ -2773,7 +2773,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
advance_and_return_if_error_or_eof({});
|
||||
|
||||
auto arr = new array{};
|
||||
auto& vals = arr->values;
|
||||
auto& vals = arr->elements;
|
||||
enum parse_elem : int
|
||||
{
|
||||
none,
|
||||
|
@ -490,9 +490,8 @@ is no longer necessary.
|
||||
//#====================================================================================================================
|
||||
|
||||
#include "toml_version.h"
|
||||
//# {{
|
||||
|
||||
#define TOML_LIB_SINGLE_HEADER 0
|
||||
//# }}
|
||||
|
||||
#define TOML_MAKE_VERSION(maj, min, rev) \
|
||||
((maj) * 1000 + (min) * 25 + (rev))
|
||||
|
@ -213,7 +213,7 @@ TOML_NAMESPACE_START
|
||||
private:
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
|
||||
impl::string_map<std::unique_ptr<node>> values;
|
||||
impl::string_map<std::unique_ptr<node>> map;
|
||||
bool inline_ = false;
|
||||
|
||||
table(impl::table_init_pair*, size_t) noexcept;
|
||||
@ -237,7 +237,7 @@ TOML_NAMESPACE_START
|
||||
/// { "bar", 2.0 },
|
||||
/// { "kek", "three" }
|
||||
/// }};
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
@ -293,19 +293,21 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// \brief Sets whether this table is a TOML inline table.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// \detail \godbolt{an9xdj}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto tbl = toml::table{{
|
||||
/// { "a", 1 },
|
||||
/// { "b", 2 },
|
||||
/// { "c", 3 },
|
||||
/// { "d", toml::table{{ { "e", 4 } }} }
|
||||
/// }};
|
||||
/// std::cout << "is inline? "sv << tbl.is_inline() << std::endl;
|
||||
/// std::cout << tbl << std::endl << std::endl;
|
||||
/// std::cout << "is inline? "sv << tbl.is_inline() << "\n";
|
||||
/// std::cout << tbl << "\n\n";
|
||||
///
|
||||
/// tbl.is_inline(!tbl.is_inline());
|
||||
/// std::cout << "is inline? "sv << tbl.is_inline() << std::endl;
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << "is inline? "sv << tbl.is_inline() << "\n";
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
@ -314,9 +316,11 @@ TOML_NAMESPACE_START
|
||||
/// a = 1
|
||||
/// b = 2
|
||||
/// c = 3
|
||||
///
|
||||
/// [d]
|
||||
/// e = 4
|
||||
///
|
||||
///
|
||||
/// is inline? true
|
||||
/// { a = 1, b = 2, c = 3, d = { e = 4 } }
|
||||
/// \eout
|
||||
@ -411,63 +415,71 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// \brief Inserts a new value at a specific key if one did not already exist.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// \detail \godbolt{bMnW5r}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto tbl = toml::table{{
|
||||
/// { "a", 1 },
|
||||
/// { "b", 2 },
|
||||
/// { "c", 3 }
|
||||
/// }};
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// for (auto k : { "a", "d" })
|
||||
/// {
|
||||
/// auto result = tbl.insert(k, 42);
|
||||
/// std::cout << "inserted with key '"sv << k << "': "sv << result.second << std::endl;
|
||||
/// std::cout << "inserted with key '"sv << k << "': "sv << result.second << "\n";
|
||||
/// }
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// { a = 1, b = 2, c = 3 }
|
||||
/// a = 1
|
||||
/// b = 2
|
||||
/// c = 3
|
||||
///
|
||||
/// inserted with key 'a': false
|
||||
/// inserted with key 'd': true
|
||||
/// { a = 1, b = 2, c = 3, d = 42 }
|
||||
/// a = 1
|
||||
/// b = 2
|
||||
/// c = 3
|
||||
/// d = 42
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam K std::string (or a type convertible to it).
|
||||
/// \tparam V One of the TOML value types (or a type promotable to one).
|
||||
/// \param key The key at which to insert the new value.
|
||||
/// \param val The new value to insert.
|
||||
/// \tparam KeyType std::string (or a type convertible to it).
|
||||
/// \tparam ValueType One of the TOML ndoe or value types (or a type promotable to one).
|
||||
/// \param key The key at which to insert the new value.
|
||||
/// \param val The new value to insert.
|
||||
///
|
||||
/// \returns A std::pair containing:
|
||||
/// - An iterator to the insertion position (or the position of the value that prevented insertion)
|
||||
/// - A boolean indicating if the insertion was successful.
|
||||
template <typename K, typename V, typename = std::enable_if_t<
|
||||
std::is_convertible_v<K&&, std::string_view>
|
||||
|| impl::is_wide_string<K>
|
||||
template <typename KeyType, typename ValueType, typename = std::enable_if_t<
|
||||
std::is_convertible_v<KeyType&&, std::string_view>
|
||||
|| impl::is_wide_string<KeyType>
|
||||
>>
|
||||
std::pair<iterator, bool> insert(K&& key, V&& val) noexcept
|
||||
std::pair<iterator, bool> insert(KeyType&& key, ValueType&& val) noexcept
|
||||
{
|
||||
static_assert(
|
||||
!impl::is_wide_string<K> || TOML_WINDOWS_COMPAT,
|
||||
!impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT,
|
||||
"Insertion using wide-character keys is only supported on Windows with TOML_WINDOWS_COMPAT enabled."
|
||||
);
|
||||
|
||||
if constexpr (impl::is_wide_string<K>)
|
||||
if constexpr (impl::is_wide_string<KeyType>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
return insert(impl::narrow(std::forward<K>(key)), std::forward<V>(val));
|
||||
return insert(impl::narrow(std::forward<KeyType>(key)), std::forward<ValueType>(val));
|
||||
#else
|
||||
static_assert(impl::dependent_false<K>, "Evaluated unreachable branch!");
|
||||
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ipos = values.lower_bound(key);
|
||||
if (ipos == values.end() || ipos->first != key)
|
||||
auto ipos = map.lower_bound(key);
|
||||
if (ipos == map.end() || ipos->first != key)
|
||||
{
|
||||
ipos = values.emplace_hint(ipos, std::forward<K>(key), impl::make_node(std::forward<V>(val)));
|
||||
ipos = map.emplace_hint(ipos, std::forward<KeyType>(key), impl::make_node(std::forward<ValueType>(val)));
|
||||
return { ipos, true };
|
||||
}
|
||||
return { ipos, false };
|
||||
@ -476,26 +488,34 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// \brief Inserts a series of key-value pairs into the table.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// \detail \godbolt{bzYcce}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto tbl = toml::table{{
|
||||
/// { "a", 1 },
|
||||
/// { "b", 2 },
|
||||
/// { "c", 3 }
|
||||
/// }};
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// auto kvps = std::array<std::pair<std::string, int>>{{
|
||||
/// auto kvps = std::array<std::pair<std::string, int>, 2>{{
|
||||
/// { "d", 42 },
|
||||
/// { "a", 43 }
|
||||
/// { "a", 43 } // won't be inserted, 'a' already exists
|
||||
/// }};
|
||||
/// tbl.insert(kvps.begin(), kvps.end());
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// { a = 1, b = 2, c = 3 }
|
||||
/// { a = 1, b = 2, c = 3, d = 42 } //"a" already existed
|
||||
/// a = 1
|
||||
/// b = 2
|
||||
/// c = 3
|
||||
///
|
||||
/// a = 1
|
||||
/// b = 2
|
||||
/// c = 3
|
||||
/// d = 42
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam Iter An InputIterator to a collection of key-value pairs.
|
||||
@ -524,66 +544,74 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// \brief Inserts or assigns a value at a specific key.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// \detail \godbolt{ddK563}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto tbl = toml::table{{
|
||||
/// { "a", 1 },
|
||||
/// { "b", 2 },
|
||||
/// { "c", 3 }
|
||||
/// }};
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// for (auto k : { "a", "d" })
|
||||
/// {
|
||||
/// auto result = tbl.insert_or_assign(k, 42);
|
||||
/// std::cout << "value at key '"sv << k
|
||||
/// << "' was "sv << (result.second ? "inserted"sv : "assigned"sv) << std::endl;
|
||||
/// << "' was "sv << (result.second ? "inserted"sv : "assigned"sv) << "\n";
|
||||
/// }
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// { a = 1, b = 2, c = 3 }
|
||||
/// a = 1
|
||||
/// b = 2
|
||||
/// c = 3
|
||||
///
|
||||
/// value at key 'a' was assigned
|
||||
/// value at key 'd' was inserted
|
||||
/// { a = 42, b = 2, c = 3, d = 42 }
|
||||
/// a = 42
|
||||
/// b = 2
|
||||
/// c = 3
|
||||
/// d = 42
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam K std::string (or a type convertible to it).
|
||||
/// \tparam V One of the TOML value types (or a type promotable to one).
|
||||
/// \param key The key at which to insert or assign the value.
|
||||
/// \param val The value to insert/assign.
|
||||
/// \tparam KeyType std::string (or a type convertible to it).
|
||||
/// \tparam ValueType One of the TOML node or value types (or a type promotable to one).
|
||||
/// \param key The key at which to insert or assign the value.
|
||||
/// \param val The value to insert/assign.
|
||||
///
|
||||
/// \returns A std::pair containing:
|
||||
/// - An iterator to the value's position
|
||||
/// - A boolean containing `true` if the value was inserted, `false` if it was assigned.
|
||||
template <typename K, typename V>
|
||||
std::pair<iterator, bool> insert_or_assign(K&& key, V&& val) noexcept
|
||||
template <typename KeyType, typename ValueType>
|
||||
std::pair<iterator, bool> insert_or_assign(KeyType&& key, ValueType&& val) noexcept
|
||||
{
|
||||
static_assert(
|
||||
!impl::is_wide_string<K> || TOML_WINDOWS_COMPAT,
|
||||
!impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT,
|
||||
"Insertion using wide-character keys is only supported on Windows with TOML_WINDOWS_COMPAT enabled."
|
||||
);
|
||||
|
||||
if constexpr (impl::is_wide_string<K>)
|
||||
if constexpr (impl::is_wide_string<KeyType>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
return insert_or_assign(impl::narrow(std::forward<K>(key)), std::forward<V>(val));
|
||||
return insert_or_assign(impl::narrow(std::forward<KeyType>(key)), std::forward<ValueType>(val));
|
||||
#else
|
||||
static_assert(impl::dependent_false<K>, "Evaluated unreachable branch!");
|
||||
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ipos = values.lower_bound(key);
|
||||
if (ipos == values.end() || ipos->first != key)
|
||||
auto ipos = map.lower_bound(key);
|
||||
if (ipos == map.end() || ipos->first != key)
|
||||
{
|
||||
ipos = values.emplace_hint(ipos, std::forward<K>(key), impl::make_node(std::forward<V>(val)));
|
||||
ipos = map.emplace_hint(ipos, std::forward<KeyType>(key), impl::make_node(std::forward<ValueType>(val)));
|
||||
return { ipos, true };
|
||||
}
|
||||
else
|
||||
{
|
||||
(*ipos).second.reset(impl::make_node(std::forward<V>(val)));
|
||||
(*ipos).second.reset(impl::make_node(std::forward<ValueType>(val)));
|
||||
return { ipos, false };
|
||||
}
|
||||
}
|
||||
@ -597,15 +625,15 @@ TOML_NAMESPACE_START
|
||||
/// { "b", 2 },
|
||||
/// { "c", 3 }
|
||||
/// }};
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// for (auto k : { "a", "d" })
|
||||
/// {
|
||||
/// // add a string using std::string's substring constructor
|
||||
/// auto result = tbl.emplace<std::string>(k, "this is not a drill"sv, 14, 5);
|
||||
/// std::cout << "emplaced with key '"sv << k << "': "sv << result.second << std::endl;
|
||||
/// std::cout << "emplaced with key '"sv << k << "': "sv << result.second << "\n";
|
||||
/// }
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
@ -616,50 +644,50 @@ TOML_NAMESPACE_START
|
||||
/// { a = 1, b = 2, c = 3, d = "drill" }
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam U One of the TOML node or value types.
|
||||
/// \tparam K std::string (or a type convertible to it).
|
||||
/// \tparam V Value constructor argument types.
|
||||
/// \param key The key at which to emplace the new value.
|
||||
/// \param args Arguments to forward to the value's constructor.
|
||||
/// \tparam ValueType One of the TOML node or value types.
|
||||
/// \tparam KeyType std::string (or a type convertible to it).
|
||||
/// \tparam ValueArgs Value constructor argument types.
|
||||
/// \param key The key at which to emplace the new value.
|
||||
/// \param args Arguments to forward to the value's constructor.
|
||||
///
|
||||
/// \returns A std::pair containing:
|
||||
/// - An iterator to the emplacement position (or the position of the value that prevented emplacement)
|
||||
/// - A boolean indicating if the emplacement was successful.
|
||||
///
|
||||
/// \remark There is no difference between insert() and emplace() for trivial value types (floats, ints, bools).
|
||||
template <typename U, typename K, typename... V>
|
||||
std::pair<iterator, bool> emplace(K&& key, V&&... args) noexcept
|
||||
template <typename ValueType, typename KeyType, typename... ValueArgs>
|
||||
std::pair<iterator, bool> emplace(KeyType&& key, ValueArgs&&... args) noexcept
|
||||
{
|
||||
static_assert(
|
||||
!impl::is_wide_string<K> || TOML_WINDOWS_COMPAT,
|
||||
!impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT,
|
||||
"Emplacement using wide-character keys is only supported on Windows with TOML_WINDOWS_COMPAT enabled."
|
||||
);
|
||||
|
||||
if constexpr (impl::is_wide_string<K>)
|
||||
if constexpr (impl::is_wide_string<KeyType>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
return emplace<U>(impl::narrow(std::forward<K>(key)), std::forward<V>(args)...);
|
||||
return emplace<ValueType>(impl::narrow(std::forward<KeyType>(key)), std::forward<ValueArgs>(args)...);
|
||||
#else
|
||||
static_assert(impl::dependent_false<U>, "Evaluated unreachable branch!");
|
||||
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
using type = impl::unwrap_node<U>;
|
||||
using type = impl::unwrap_node<ValueType>;
|
||||
static_assert(
|
||||
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
|
||||
"The emplacement type argument of table::emplace() must be one of:"
|
||||
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
|
||||
);
|
||||
|
||||
auto ipos = values.lower_bound(key);
|
||||
if (ipos == values.end() || ipos->first != key)
|
||||
auto ipos = map.lower_bound(key);
|
||||
if (ipos == map.end() || ipos->first != key)
|
||||
{
|
||||
ipos = values.emplace_hint(
|
||||
ipos = map.emplace_hint(
|
||||
ipos,
|
||||
std::forward<K>(key),
|
||||
new impl::wrap_node<type>{ std::forward<V>(args)... }
|
||||
std::forward<KeyType>(key),
|
||||
new impl::wrap_node<type>{ std::forward<ValueArgs>(args)... }
|
||||
);
|
||||
return { ipos, true };
|
||||
}
|
||||
@ -675,10 +703,10 @@ TOML_NAMESPACE_START
|
||||
/// { "b", 2 },
|
||||
/// { "c", 3 }
|
||||
/// }};
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// tbl.erase(tbl.begin() + 1);
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
@ -700,10 +728,10 @@ TOML_NAMESPACE_START
|
||||
/// { "b", 2 },
|
||||
/// { "c", 3 }
|
||||
/// }};
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// tbl.erase(tbl.cbegin() + 1);
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
@ -726,10 +754,10 @@ TOML_NAMESPACE_START
|
||||
/// { "c", "karma" },
|
||||
/// { "d", 2 }
|
||||
/// }};
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// tbl.erase(tbl.cbegin() + 1, tbl.cbegin() + 3);
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
@ -752,11 +780,11 @@ TOML_NAMESPACE_START
|
||||
/// { "b", 2 },
|
||||
/// { "c", 3 }
|
||||
/// }};
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// std::cout << tbl.erase("b") << std::endl;
|
||||
/// std::cout << tbl.erase("not an existing key") << std::endl;
|
||||
/// std::cout << tbl << std::endl;
|
||||
/// std::cout << tbl.erase("b") << "\n";
|
||||
/// std::cout << tbl.erase("not an existing key") << "\n";
|
||||
/// std::cout << tbl << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
@ -838,11 +866,11 @@ TOML_NAMESPACE_START
|
||||
/// { "a", 42, },
|
||||
/// { "b", "is the meaning of life, apparently." }
|
||||
/// }};
|
||||
/// std::cout << R"(node ["a"] exists: )"sv << !!arr.get("a") << std::endl;
|
||||
/// std::cout << R"(node ["b"] exists: )"sv << !!arr.get("b") << std::endl;
|
||||
/// std::cout << R"(node ["c"] exists: )"sv << !!arr.get("c") << std::endl;
|
||||
/// std::cout << R"(node ["a"] exists: )"sv << !!arr.get("a") << "\n";
|
||||
/// std::cout << R"(node ["b"] exists: )"sv << !!arr.get("b") << "\n";
|
||||
/// std::cout << R"(node ["c"] exists: )"sv << !!arr.get("c") << "\n";
|
||||
/// if (auto val = arr.get("a"))
|
||||
/// std::cout << R"(node ["a"] was an )"sv << val->type() << std::endl;
|
||||
/// std::cout << R"(node ["a"] was an )"sv << val->type() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
@ -935,7 +963,7 @@ TOML_NAMESPACE_START
|
||||
/// { "b", "is the meaning of life, apparently." }
|
||||
/// }};
|
||||
/// if (auto val = arr.get_as<int64_t>("a"))
|
||||
/// std::cout << R"(node ["a"] was an integer with value )"sv << **val << std::endl;
|
||||
/// std::cout << R"(node ["a"] was an integer with value )"sv << **val << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
@ -943,60 +971,60 @@ TOML_NAMESPACE_START
|
||||
/// node ["a"] was an integer with value 42
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam T The node's type.
|
||||
/// \param key The node's key.
|
||||
/// \tparam ValueType One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
|
||||
template <typename T>
|
||||
template <typename ValueType>
|
||||
[[nodiscard]]
|
||||
impl::wrap_node<T>* get_as(std::string_view key) noexcept
|
||||
impl::wrap_node<ValueType>* get_as(std::string_view key) noexcept
|
||||
{
|
||||
return do_get_as<T>(values, key);
|
||||
return do_get_as<ValueType>(map, key);
|
||||
}
|
||||
|
||||
/// \brief Gets the node at a specific key if it is a particular type (const overload).
|
||||
///
|
||||
/// \tparam T The node's type.
|
||||
/// \param key The node's key.
|
||||
/// \tparam ValueType One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
|
||||
template <typename T>
|
||||
template <typename ValueType>
|
||||
[[nodiscard]]
|
||||
const impl::wrap_node<T>* get_as(std::string_view key) const noexcept
|
||||
const impl::wrap_node<ValueType>* get_as(std::string_view key) const noexcept
|
||||
{
|
||||
return do_get_as<T>(values, key);
|
||||
return do_get_as<ValueType>(map, key);
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Gets the node at a specific key if it is a particular type.
|
||||
///
|
||||
/// \tparam T The node's type.
|
||||
/// \param key The node's key.
|
||||
/// \tparam ValueType One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
|
||||
///
|
||||
/// \attention This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
template <typename T>
|
||||
template <typename ValueType>
|
||||
[[nodiscard]]
|
||||
impl::wrap_node<T>* get_as(std::wstring_view key) noexcept
|
||||
impl::wrap_node<ValueType>* get_as(std::wstring_view key) noexcept
|
||||
{
|
||||
return get_as<T>(impl::narrow(key));
|
||||
return get_as<ValueType>(impl::narrow(key));
|
||||
}
|
||||
|
||||
/// \brief Gets the node at a specific key if it is a particular type (const overload).
|
||||
///
|
||||
/// \tparam T The node's type.
|
||||
/// \param key The node's key.
|
||||
/// \tparam ValueType One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
|
||||
///
|
||||
/// \attention This overload is only available when #TOML_WINDOWS_COMPAT is enabled.
|
||||
template <typename T>
|
||||
template <typename ValueType>
|
||||
[[nodiscard]]
|
||||
const impl::wrap_node<T>* get_as(std::wstring_view key) const noexcept
|
||||
const impl::wrap_node<ValueType>* get_as(std::wstring_view key) const noexcept
|
||||
{
|
||||
return get_as<T>(impl::narrow(key));
|
||||
return get_as<ValueType>(impl::narrow(key));
|
||||
}
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
@ -1006,7 +1034,7 @@ TOML_NAMESPACE_START
|
||||
/// \param lhs The LHS table.
|
||||
/// \param rhs The RHS table.
|
||||
///
|
||||
/// \returns True if the tables contained the same keys and values.
|
||||
/// \returns True if the tables contained the same keys and map.
|
||||
friend bool operator == (const table& lhs, const table& rhs) noexcept;
|
||||
|
||||
/// \brief Inequality operator.
|
||||
@ -1014,7 +1042,7 @@ TOML_NAMESPACE_START
|
||||
/// \param lhs The LHS table.
|
||||
/// \param rhs The RHS table.
|
||||
///
|
||||
/// \returns True if the tables did not contain the same keys and values.
|
||||
/// \returns True if the tables did not contain the same keys and map.
|
||||
friend bool operator != (const table& lhs, const table& rhs) noexcept;
|
||||
|
||||
/// \brief Prints the table out to a stream as formatted TOML.
|
||||
|
@ -25,7 +25,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
values.insert_or_assign(
|
||||
map.insert_or_assign(
|
||||
std::move(pairs[i].key),
|
||||
std::move(pairs[i].value)
|
||||
);
|
||||
@ -38,7 +38,7 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(table&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
values{ std::move(other.values) },
|
||||
map{ std::move(other.map) },
|
||||
inline_{ other.inline_ }
|
||||
{}
|
||||
|
||||
@ -46,7 +46,7 @@ TOML_NAMESPACE_START
|
||||
table& table::operator = (table&& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
values = std::move(rhs.values);
|
||||
map = std::move(rhs.map);
|
||||
inline_ = rhs.inline_;
|
||||
return *this;
|
||||
}
|
||||
@ -63,16 +63,16 @@ TOML_NAMESPACE_START
|
||||
TOML_MEMBER_ATTR(pure) bool table::is_inline() const noexcept { return inline_; }
|
||||
TOML_EXTERNAL_LINKAGE void table::is_inline(bool val) noexcept { inline_ = val; }
|
||||
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::begin() const noexcept { return { values.begin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::end() const noexcept { return { values.end() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::cbegin() const noexcept { return { values.cbegin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::cend() const noexcept { return { values.cend() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::iterator table::begin() noexcept { return { values.begin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::iterator table::end() noexcept { return { values.end() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::begin() const noexcept { return { map.begin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::end() const noexcept { return { map.end() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::cbegin() const noexcept { return { map.cbegin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::cend() const noexcept { return { map.cend() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::iterator table::begin() noexcept { return { map.begin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::iterator table::end() noexcept { return { map.end() }; }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) bool table::empty() const noexcept { return values.empty(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t table::size() const noexcept { return values.size(); }
|
||||
TOML_EXTERNAL_LINKAGE void table::clear() noexcept { values.clear(); }
|
||||
TOML_MEMBER_ATTR(pure) bool table::empty() const noexcept { return map.empty(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t table::size() const noexcept { return map.size(); }
|
||||
TOML_EXTERNAL_LINKAGE void table::clear() noexcept { map.clear(); }
|
||||
|
||||
#undef TOML_MEMBER_ATTR
|
||||
|
||||
@ -90,27 +90,27 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::erase(iterator pos) noexcept
|
||||
{
|
||||
return { values.erase(pos.raw_) };
|
||||
return { map.erase(pos.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::erase(const_iterator pos) noexcept
|
||||
{
|
||||
return { values.erase(pos.raw_) };
|
||||
return { map.erase(pos.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::erase(const_iterator first, const_iterator last) noexcept
|
||||
{
|
||||
return { values.erase(first.raw_, last.raw_) };
|
||||
return { map.erase(first.raw_, last.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::erase(std::string_view key) noexcept
|
||||
{
|
||||
if (auto it = values.find(key); it != values.end())
|
||||
if (auto it = map.find(key); it != map.end())
|
||||
{
|
||||
values.erase(it);
|
||||
map.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -119,31 +119,31 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node* table::get(std::string_view key) noexcept
|
||||
{
|
||||
return do_get(values, key);
|
||||
return do_get(map, key);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
const node* table::get(std::string_view key) const noexcept
|
||||
{
|
||||
return do_get(values, key);
|
||||
return do_get(map, key);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::find(std::string_view key) noexcept
|
||||
{
|
||||
return { values.find(key) };
|
||||
return { map.find(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::const_iterator table::find(std::string_view key) const noexcept
|
||||
{
|
||||
return { values.find(key) };
|
||||
return { map.find(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::contains(std::string_view key) const noexcept
|
||||
{
|
||||
return do_contains(values, key);
|
||||
return do_contains(map, key);
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
@ -203,10 +203,10 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.values.size() != rhs.values.size())
|
||||
if (lhs.map.size() != rhs.map.size())
|
||||
return false;
|
||||
|
||||
for (auto l = lhs.values.begin(), r = rhs.values.begin(), e = lhs.values.end(); l != e; l++, r++)
|
||||
for (auto l = lhs.map.begin(), r = rhs.map.begin(), e = lhs.map.end(); l != e; l++, r++)
|
||||
{
|
||||
if (l->first != r->first)
|
||||
return false;
|
||||
|
@ -84,7 +84,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
using traits = value_traits<T>;
|
||||
if constexpr (!traits::is_signed)
|
||||
{
|
||||
if constexpr ((sizeof(T) * CHAR_BIT) <= 53) // 53 bits < int64_max < 54 bits
|
||||
if constexpr ((sizeof(T) * CHAR_BIT) < 63) // 63 bits == int64_max
|
||||
{
|
||||
using common_t = decltype(int64_t{} + T{});
|
||||
if (val < int64_t{} || static_cast<common_t>(val) > static_cast<common_t>(traits::max))
|
||||
|
@ -79,6 +79,7 @@ type_names = [
|
||||
'default_formatter',
|
||||
'format_flags',
|
||||
'inserter',
|
||||
'node_type',
|
||||
]
|
||||
all_namespaces = [
|
||||
'std',
|
||||
|
@ -91,6 +91,13 @@ def main():
|
||||
source_text = re.sub(blank_lines_between_returns_pattern, '\\1\n\\2', source_text, 0, re.I | re.M)
|
||||
source_text = source_text.strip() + '\n'
|
||||
|
||||
# change TOML_LIB_SINGLE_HEADER to 1
|
||||
source_text = re.sub(
|
||||
'#\s*define\s+TOML_LIB_SINGLE_HEADER\s+[0-9]+',
|
||||
'#define TOML_LIB_SINGLE_HEADER 1',
|
||||
source_text, 0, re.I
|
||||
)
|
||||
|
||||
# extract library version
|
||||
library_version = {
|
||||
'major': 0,
|
||||
@ -145,16 +152,8 @@ def main():
|
||||
write(line)
|
||||
write('//')
|
||||
write(utils.make_divider())
|
||||
write('// clang-format off')
|
||||
write('#ifndef INCLUDE_TOMLPLUSPLUS_H')
|
||||
write('#define INCLUDE_TOMLPLUSPLUS_H')
|
||||
write('')
|
||||
write('#define TOML_LIB_SINGLE_HEADER 1')
|
||||
write('')
|
||||
write(source_text)
|
||||
write('')
|
||||
write('#endif // INCLUDE_TOMLPLUSPLUS_H')
|
||||
write('// clang-format on')
|
||||
|
||||
output_str = output.getvalue().strip()
|
||||
|
||||
@ -171,6 +170,7 @@ def main():
|
||||
if m:
|
||||
defines[m.group(1)] = defined
|
||||
ignore_list = ( # macros that are meant to stay public (user configs etc)
|
||||
'INCLUDE_TOMLPLUSPLUS_H',
|
||||
'TOML_API',
|
||||
'TOML_UNRELEASED_FEATURES',
|
||||
'TOML_LARGE_FILES',
|
||||
|
@ -157,6 +157,8 @@ TEST_CASE("arrays - equality")
|
||||
TEST_CASE("arrays - insertion and erasure")
|
||||
{
|
||||
array arr;
|
||||
|
||||
// insert(const_iterator pos, ElemType&& val)
|
||||
auto it = arr.insert(arr.cbegin(), 42);
|
||||
CHECK(it == arr.begin());
|
||||
CHECK(arr.size() == 1_sz);
|
||||
@ -165,6 +167,7 @@ TEST_CASE("arrays - insertion and erasure")
|
||||
CHECK(*arr.get_as<int64_t>(0_sz) == 42);
|
||||
REQUIRE(arr == array{ 42 });
|
||||
|
||||
// insert(const_iterator pos, size_t count, ElemType&& val)
|
||||
it = arr.insert(arr.cend(), 3, 10.0f);
|
||||
CHECK(it == arr.begin() + 1);
|
||||
CHECK(arr.size() == 4_sz);
|
||||
@ -176,6 +179,7 @@ TEST_CASE("arrays - insertion and erasure")
|
||||
CHECK(*arr.get_as<double>(3_sz) == 10.0);
|
||||
REQUIRE(arr == array{ 42, 10.0, 10.0, 10.0 });
|
||||
|
||||
// emplace(const_iterator pos, Args &&... args) noexcept
|
||||
it = arr.emplace<array>(arr.cbegin(), 1, 2, 3);
|
||||
CHECK(it == arr.begin());
|
||||
CHECK(arr.size() == 5_sz);
|
||||
@ -183,6 +187,7 @@ TEST_CASE("arrays - insertion and erasure")
|
||||
CHECK(arr.get_as<array>(0_sz)->size() == 3_sz);
|
||||
REQUIRE(arr == array{ array{ 1, 2, 3 }, 42, 10.0, 10.0, 10.0 });
|
||||
|
||||
// push_back(ElemType&& val) noexcept
|
||||
{
|
||||
decltype(auto) val = arr.push_back("test"sv);
|
||||
CHECK(arr.size() == 6_sz);
|
||||
@ -193,6 +198,7 @@ TEST_CASE("arrays - insertion and erasure")
|
||||
REQUIRE(arr == array{ array{ 1, 2, 3 }, 42, 10.0, 10.0, 10.0, "test"sv });
|
||||
}
|
||||
|
||||
// decltype(auto) emplace_back(Args&&... args) noexcept
|
||||
{
|
||||
decltype(auto) val = arr.emplace_back<std::string>("test2"sv);
|
||||
CHECK(arr.size() == 7_sz);
|
||||
@ -203,12 +209,13 @@ TEST_CASE("arrays - insertion and erasure")
|
||||
REQUIRE(arr == array{ array{ 1, 2, 3 }, 42, 10.0, 10.0, 10.0, "test"sv, "test2"sv });
|
||||
}
|
||||
|
||||
// erase(const_iterator pos) noexcept;
|
||||
it = arr.erase(arr.cbegin());
|
||||
REQUIRE(arr == array{ 42, 10.0, 10.0, 10.0, "test"sv, "test2"sv });
|
||||
CHECK(it == arr.begin());
|
||||
CHECK(arr.size() == 6_sz);
|
||||
|
||||
|
||||
// erase(const_iterator first, const_iterator last) noexcept;
|
||||
it = arr.erase(arr.cbegin() + 2, arr.cbegin() + 4);
|
||||
REQUIRE(arr == array{ 42, 10.0, "test"sv, "test2"sv });
|
||||
CHECK(it == arr.begin() + 2);
|
||||
@ -223,8 +230,66 @@ TEST_CASE("arrays - insertion and erasure")
|
||||
CHECK(arr.size() == 0_sz);
|
||||
CHECK(arr.empty());
|
||||
|
||||
// insert(const_iterator pos, Iter first, Iter last)
|
||||
{
|
||||
auto vals = std::vector{ 1.0, 2.0, 3.0 };
|
||||
arr.insert(arr.cbegin(), vals.begin(), vals.end());
|
||||
CHECK(arr.size() == 3_sz);
|
||||
REQUIRE(arr.get_as<double>(0_sz));
|
||||
CHECK(*arr.get_as<double>(0_sz) == 1.0);
|
||||
REQUIRE(arr.get_as<double>(1_sz));
|
||||
CHECK(*arr.get_as<double>(1_sz) == 2.0);
|
||||
REQUIRE(arr.get_as<double>(2_sz));
|
||||
CHECK(*arr.get_as<double>(2_sz) == 3.0);
|
||||
|
||||
arr.insert(arr.cbegin() + 1, vals.begin(), vals.end());
|
||||
CHECK(arr.size() == 6_sz);
|
||||
REQUIRE(arr.get_as<double>(0_sz));
|
||||
CHECK(*arr.get_as<double>(0_sz) == 1.0);
|
||||
REQUIRE(arr.get_as<double>(1_sz));
|
||||
CHECK(*arr.get_as<double>(1_sz) == 1.0);
|
||||
REQUIRE(arr.get_as<double>(2_sz));
|
||||
CHECK(*arr.get_as<double>(2_sz) == 2.0);
|
||||
REQUIRE(arr.get_as<double>(3_sz));
|
||||
CHECK(*arr.get_as<double>(3_sz) == 3.0);
|
||||
REQUIRE(arr.get_as<double>(4_sz));
|
||||
CHECK(*arr.get_as<double>(4_sz) == 2.0);
|
||||
REQUIRE(arr.get_as<double>(5_sz));
|
||||
CHECK(*arr.get_as<double>(5_sz) == 3.0);
|
||||
}
|
||||
|
||||
// iterator insert(const_iterator pos, std::initializer_list<ElemType> ilist) noexcept
|
||||
{
|
||||
arr.clear();
|
||||
|
||||
arr.insert(arr.cbegin(), { 1.0, 2.0, 3.0 });
|
||||
CHECK(arr.size() == 3_sz);
|
||||
REQUIRE(arr.get_as<double>(0_sz));
|
||||
CHECK(*arr.get_as<double>(0_sz) == 1.0);
|
||||
REQUIRE(arr.get_as<double>(1_sz));
|
||||
CHECK(*arr.get_as<double>(1_sz) == 2.0);
|
||||
REQUIRE(arr.get_as<double>(2_sz));
|
||||
CHECK(*arr.get_as<double>(2_sz) == 3.0);
|
||||
|
||||
arr.insert(arr.cbegin() + 1, { 1.0, 2.0, 3.0 });
|
||||
CHECK(arr.size() == 6_sz);
|
||||
REQUIRE(arr.get_as<double>(0_sz));
|
||||
CHECK(*arr.get_as<double>(0_sz) == 1.0);
|
||||
REQUIRE(arr.get_as<double>(1_sz));
|
||||
CHECK(*arr.get_as<double>(1_sz) == 1.0);
|
||||
REQUIRE(arr.get_as<double>(2_sz));
|
||||
CHECK(*arr.get_as<double>(2_sz) == 2.0);
|
||||
REQUIRE(arr.get_as<double>(3_sz));
|
||||
CHECK(*arr.get_as<double>(3_sz) == 3.0);
|
||||
REQUIRE(arr.get_as<double>(4_sz));
|
||||
CHECK(*arr.get_as<double>(4_sz) == 2.0);
|
||||
REQUIRE(arr.get_as<double>(5_sz));
|
||||
CHECK(*arr.get_as<double>(5_sz) == 3.0);
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
arr.clear();
|
||||
it = arr.insert(arr.cbegin(), L"test");
|
||||
REQUIRE(*arr.get_as<std::string>(0_sz) == "test"sv);
|
||||
|
||||
@ -257,7 +322,7 @@ TEST_CASE("arrays - flattening")
|
||||
{
|
||||
array arr{
|
||||
array{},
|
||||
array{array{}},
|
||||
array{inserter{array{}}},
|
||||
array{array{},array{array{},array{}},array{}},
|
||||
array{array{array{array{array{array{ 1 }}}}}}
|
||||
};
|
||||
|
426
toml.hpp
426
toml.hpp
@ -41,12 +41,9 @@
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// clang-format off
|
||||
#ifndef INCLUDE_TOMLPLUSPLUS_H
|
||||
#define INCLUDE_TOMLPLUSPLUS_H
|
||||
|
||||
#define TOML_LIB_SINGLE_HEADER 1
|
||||
|
||||
//-------------- ↓ toml_preprocessor.h -------------------------------------------------------------------------------
|
||||
#if 1
|
||||
|
||||
@ -507,6 +504,8 @@ is no longer necessary.
|
||||
#define TOML_LANG_MINOR 0
|
||||
#define TOML_LANG_PATCH 0
|
||||
|
||||
#define TOML_LIB_SINGLE_HEADER 1
|
||||
|
||||
#define TOML_MAKE_VERSION(maj, min, rev) \
|
||||
((maj) * 1000 + (min) * 25 + (rev))
|
||||
|
||||
@ -714,9 +713,6 @@ TOML_NAMESPACE_START // abi namespace
|
||||
template <typename T>
|
||||
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
//template <typename T, typename... U>
|
||||
//struct is_one_of_ : std::integral_constant<bool, (false || ... || std::is_same_v<T, U>)> {};
|
||||
|
||||
template <typename T, typename... U>
|
||||
inline constexpr bool is_one_of = (false || ... || std::is_same_v<T, U>);
|
||||
|
||||
@ -2554,7 +2550,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
using traits = value_traits<T>;
|
||||
if constexpr (!traits::is_signed)
|
||||
{
|
||||
if constexpr ((sizeof(T) * CHAR_BIT) <= 53) // 53 bits < int64_max < 54 bits
|
||||
if constexpr ((sizeof(T) * CHAR_BIT) < 63) // 63 bits == int64_max
|
||||
{
|
||||
using common_t = decltype(int64_t{} + T{});
|
||||
if (val < int64_t{} || static_cast<common_t>(val) > static_cast<common_t>(traits::max))
|
||||
@ -3445,7 +3441,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
private:
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
std::vector<std::unique_ptr<node>> values;
|
||||
std::vector<std::unique_ptr<node>> elements;
|
||||
|
||||
void preinsertion_resize(size_t idx, size_t count) noexcept;
|
||||
|
||||
@ -3465,16 +3461,16 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD_CTOR
|
||||
array(array&& other) noexcept;
|
||||
|
||||
template <typename U, typename... V>
|
||||
template <typename ElemType, typename... ElemTypes>
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit array(U&& val, V&&... vals)
|
||||
explicit array(ElemType&& val, ElemTypes&&... vals)
|
||||
{
|
||||
values.reserve(sizeof...(V) + 1_sz);
|
||||
values.emplace_back(impl::make_node(std::forward<U>(val)));
|
||||
if constexpr (sizeof...(V) > 0)
|
||||
elements.reserve(sizeof...(ElemTypes) + 1_sz);
|
||||
elements.emplace_back(impl::make_node(std::forward<ElemType>(val)));
|
||||
if constexpr (sizeof...(ElemTypes) > 0)
|
||||
{
|
||||
(
|
||||
values.emplace_back(impl::make_node(std::forward<V>(vals))),
|
||||
elements.emplace_back(impl::make_node(std::forward<ElemTypes>(vals))),
|
||||
...
|
||||
);
|
||||
}
|
||||
@ -3493,11 +3489,11 @@ TOML_NAMESPACE_START
|
||||
[[nodiscard]] const array* as_array() const noexcept override;
|
||||
[[nodiscard]] bool is_homogeneous(node_type type) const noexcept;
|
||||
|
||||
template <typename T = void>
|
||||
template <typename ElemType = void>
|
||||
[[nodiscard]]
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
static_assert(
|
||||
std::is_void_v<type>
|
||||
|| ((impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>),
|
||||
@ -3533,29 +3529,29 @@ TOML_NAMESPACE_START
|
||||
[[nodiscard]] size_t capacity() const noexcept;
|
||||
void shrink_to_fit();
|
||||
|
||||
template <typename U>
|
||||
iterator insert(const_iterator pos, U&& val) noexcept
|
||||
template <typename ElemType>
|
||||
iterator insert(const_iterator pos, ElemType&& val) noexcept
|
||||
{
|
||||
return { values.emplace(pos.raw_, impl::make_node(std::forward<U>(val))) };
|
||||
return { elements.emplace(pos.raw_, impl::make_node(std::forward<ElemType>(val))) };
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
iterator insert(const_iterator pos, size_t count, U&& val) noexcept
|
||||
template <typename ElemType>
|
||||
iterator insert(const_iterator pos, size_t count, ElemType&& val) noexcept
|
||||
{
|
||||
switch (count)
|
||||
{
|
||||
case 0: return { values.begin() + (pos.raw_ - values.cbegin()) };
|
||||
case 1: return insert(pos, std::forward<U>(val));
|
||||
case 0: return { elements.begin() + (pos.raw_ - elements.cbegin()) };
|
||||
case 1: return insert(pos, std::forward<ElemType>(val));
|
||||
default:
|
||||
{
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - values.cbegin());
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
|
||||
preinsertion_resize(start_idx, count);
|
||||
size_t i = start_idx;
|
||||
for (size_t e = start_idx + count - 1_sz; i < e; i++)
|
||||
values[i].reset(impl::make_node(val));
|
||||
elements[i].reset(impl::make_node(val));
|
||||
|
||||
values[i].reset(impl::make_node(std::forward<U>(val)));
|
||||
return { values.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
elements[i].reset(impl::make_node(std::forward<ElemType>(val)));
|
||||
return { elements.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3564,90 +3560,89 @@ TOML_NAMESPACE_START
|
||||
iterator insert(const_iterator pos, Iter first, Iter last) noexcept
|
||||
{
|
||||
const auto count = std::distance(first, last);
|
||||
switch (count)
|
||||
if (count <= 0)
|
||||
return { elements.begin() + (pos.raw_ - elements.cbegin()) };
|
||||
else if (count == 1)
|
||||
return insert(pos, *first);
|
||||
else
|
||||
{
|
||||
case 0: return { values.begin() + (pos.raw_ - values.cbegin()) };
|
||||
case 1: return insert(pos, *first);
|
||||
default:
|
||||
{
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - values.cbegin());
|
||||
preinsertion_resize(start_idx, count);
|
||||
size_t i = start_idx;
|
||||
for (auto it = first; it != last; it++)
|
||||
values[i].reset(impl::make_node(*it));
|
||||
return { values.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
}
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
|
||||
preinsertion_resize(start_idx, static_cast<size_t>(count));
|
||||
size_t i = start_idx;
|
||||
for (auto it = first; it != last; it++)
|
||||
elements[i++].reset(impl::make_node(*it));
|
||||
return { elements.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
iterator insert(const_iterator pos, std::initializer_list<U> ilist) noexcept
|
||||
template <typename ElemType>
|
||||
iterator insert(const_iterator pos, std::initializer_list<ElemType> ilist) noexcept
|
||||
{
|
||||
switch (ilist.size())
|
||||
{
|
||||
case 0: return { values.begin() + (pos.raw_ - values.cbegin()) };
|
||||
case 0: return { elements.begin() + (pos.raw_ - elements.cbegin()) };
|
||||
case 1: return insert(pos, *ilist.begin());
|
||||
default:
|
||||
{
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - values.cbegin());
|
||||
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
|
||||
preinsertion_resize(start_idx, ilist.size());
|
||||
size_t i = start_idx;
|
||||
for (auto& val : ilist)
|
||||
values[i].reset(impl::make_node(val));
|
||||
return { values.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
elements[i++].reset(impl::make_node(val));
|
||||
return { elements.begin() + static_cast<ptrdiff_t>(start_idx) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U, typename... V>
|
||||
iterator emplace(const_iterator pos, V&&... args) noexcept
|
||||
template <typename ElemType, typename... Args>
|
||||
iterator emplace(const_iterator pos, Args&&... args) noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<U>;
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
static_assert(
|
||||
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
|
||||
"Emplacement type parameter must be one of:"
|
||||
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
|
||||
);
|
||||
|
||||
return { values.emplace(pos.raw_, new impl::wrap_node<type>{ std::forward<V>(args)...} ) };
|
||||
return { elements.emplace(pos.raw_, new impl::wrap_node<type>{ std::forward<Args>(args)...} ) };
|
||||
}
|
||||
|
||||
iterator erase(const_iterator pos) noexcept;
|
||||
iterator erase(const_iterator first, const_iterator last) noexcept;
|
||||
|
||||
template <typename U>
|
||||
void resize(size_t new_size, U&& default_init_val) noexcept
|
||||
template <typename ElemType>
|
||||
void resize(size_t new_size, ElemType&& default_init_val) noexcept
|
||||
{
|
||||
if (!new_size)
|
||||
values.clear();
|
||||
else if (new_size < values.size())
|
||||
values.resize(new_size);
|
||||
else if (new_size > values.size())
|
||||
insert(cend(), new_size - values.size(), std::forward<U>(default_init_val));
|
||||
elements.clear();
|
||||
else if (new_size < elements.size())
|
||||
elements.resize(new_size);
|
||||
else if (new_size > elements.size())
|
||||
insert(cend(), new_size - elements.size(), std::forward<ElemType>(default_init_val));
|
||||
}
|
||||
|
||||
void truncate(size_t new_size);
|
||||
|
||||
template <typename U>
|
||||
decltype(auto) push_back(U&& val) noexcept
|
||||
template <typename ElemType>
|
||||
decltype(auto) push_back(ElemType&& val) noexcept
|
||||
{
|
||||
auto nde = impl::make_node(std::forward<U>(val));
|
||||
values.emplace_back(nde);
|
||||
auto nde = impl::make_node(std::forward<ElemType>(val));
|
||||
elements.emplace_back(nde);
|
||||
return *nde;
|
||||
}
|
||||
|
||||
template <typename U, typename... V>
|
||||
decltype(auto) emplace_back(V&&... args) noexcept
|
||||
template <typename ElemType, typename... Args>
|
||||
decltype(auto) emplace_back(Args&&... args) noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<U>;
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
static_assert(
|
||||
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
|
||||
"Emplacement type parameter must be one of:"
|
||||
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
|
||||
);
|
||||
|
||||
auto nde = new impl::wrap_node<type>{ std::forward<V>(args)... };
|
||||
values.emplace_back(nde);
|
||||
auto nde = new impl::wrap_node<type>{ std::forward<Args>(args)... };
|
||||
elements.emplace_back(nde);
|
||||
return *nde;
|
||||
}
|
||||
|
||||
@ -3655,21 +3650,21 @@ TOML_NAMESPACE_START
|
||||
[[nodiscard]] node* get(size_t index) noexcept;
|
||||
[[nodiscard]] const node* get(size_t index) const noexcept;
|
||||
|
||||
template <typename T>
|
||||
template <typename ElemType>
|
||||
[[nodiscard]]
|
||||
impl::wrap_node<T>* get_as(size_t index) noexcept
|
||||
impl::wrap_node<ElemType>* get_as(size_t index) noexcept
|
||||
{
|
||||
if (auto val = get(index))
|
||||
return val->as<T>();
|
||||
return val->as<ElemType>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename ElemType>
|
||||
[[nodiscard]]
|
||||
const impl::wrap_node<T>* get_as(size_t index) const noexcept
|
||||
const impl::wrap_node<ElemType>* get_as(size_t index) const noexcept
|
||||
{
|
||||
if (auto val = get(index))
|
||||
return val->as<T>();
|
||||
return val->as<ElemType>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -3942,7 +3937,7 @@ TOML_NAMESPACE_START
|
||||
private:
|
||||
friend class TOML_PARSER_TYPENAME;
|
||||
|
||||
impl::string_map<std::unique_ptr<node>> values;
|
||||
impl::string_map<std::unique_ptr<node>> map;
|
||||
bool inline_ = false;
|
||||
|
||||
table(impl::table_init_pair*, size_t) noexcept;
|
||||
@ -3996,31 +3991,31 @@ TOML_NAMESPACE_START
|
||||
[[nodiscard]] size_t size() const noexcept;
|
||||
void clear() noexcept;
|
||||
|
||||
template <typename K, typename V, typename = std::enable_if_t<
|
||||
std::is_convertible_v<K&&, std::string_view>
|
||||
|| impl::is_wide_string<K>
|
||||
template <typename KeyType, typename ValueType, typename = std::enable_if_t<
|
||||
std::is_convertible_v<KeyType&&, std::string_view>
|
||||
|| impl::is_wide_string<KeyType>
|
||||
>>
|
||||
std::pair<iterator, bool> insert(K&& key, V&& val) noexcept
|
||||
std::pair<iterator, bool> insert(KeyType&& key, ValueType&& val) noexcept
|
||||
{
|
||||
static_assert(
|
||||
!impl::is_wide_string<K> || TOML_WINDOWS_COMPAT,
|
||||
!impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT,
|
||||
"Insertion using wide-character keys is only supported on Windows with TOML_WINDOWS_COMPAT enabled."
|
||||
);
|
||||
|
||||
if constexpr (impl::is_wide_string<K>)
|
||||
if constexpr (impl::is_wide_string<KeyType>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
return insert(impl::narrow(std::forward<K>(key)), std::forward<V>(val));
|
||||
return insert(impl::narrow(std::forward<KeyType>(key)), std::forward<ValueType>(val));
|
||||
#else
|
||||
static_assert(impl::dependent_false<K>, "Evaluated unreachable branch!");
|
||||
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ipos = values.lower_bound(key);
|
||||
if (ipos == values.end() || ipos->first != key)
|
||||
auto ipos = map.lower_bound(key);
|
||||
if (ipos == map.end() || ipos->first != key)
|
||||
{
|
||||
ipos = values.emplace_hint(ipos, std::forward<K>(key), impl::make_node(std::forward<V>(val)));
|
||||
ipos = map.emplace_hint(ipos, std::forward<KeyType>(key), impl::make_node(std::forward<ValueType>(val)));
|
||||
return { ipos, true };
|
||||
}
|
||||
return { ipos, false };
|
||||
@ -4044,71 +4039,71 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
std::pair<iterator, bool> insert_or_assign(K&& key, V&& val) noexcept
|
||||
template <typename KeyType, typename ValueType>
|
||||
std::pair<iterator, bool> insert_or_assign(KeyType&& key, ValueType&& val) noexcept
|
||||
{
|
||||
static_assert(
|
||||
!impl::is_wide_string<K> || TOML_WINDOWS_COMPAT,
|
||||
!impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT,
|
||||
"Insertion using wide-character keys is only supported on Windows with TOML_WINDOWS_COMPAT enabled."
|
||||
);
|
||||
|
||||
if constexpr (impl::is_wide_string<K>)
|
||||
if constexpr (impl::is_wide_string<KeyType>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
return insert_or_assign(impl::narrow(std::forward<K>(key)), std::forward<V>(val));
|
||||
return insert_or_assign(impl::narrow(std::forward<KeyType>(key)), std::forward<ValueType>(val));
|
||||
#else
|
||||
static_assert(impl::dependent_false<K>, "Evaluated unreachable branch!");
|
||||
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ipos = values.lower_bound(key);
|
||||
if (ipos == values.end() || ipos->first != key)
|
||||
auto ipos = map.lower_bound(key);
|
||||
if (ipos == map.end() || ipos->first != key)
|
||||
{
|
||||
ipos = values.emplace_hint(ipos, std::forward<K>(key), impl::make_node(std::forward<V>(val)));
|
||||
ipos = map.emplace_hint(ipos, std::forward<KeyType>(key), impl::make_node(std::forward<ValueType>(val)));
|
||||
return { ipos, true };
|
||||
}
|
||||
else
|
||||
{
|
||||
(*ipos).second.reset(impl::make_node(std::forward<V>(val)));
|
||||
(*ipos).second.reset(impl::make_node(std::forward<ValueType>(val)));
|
||||
return { ipos, false };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U, typename K, typename... V>
|
||||
std::pair<iterator, bool> emplace(K&& key, V&&... args) noexcept
|
||||
template <typename ValueType, typename KeyType, typename... ValueArgs>
|
||||
std::pair<iterator, bool> emplace(KeyType&& key, ValueArgs&&... args) noexcept
|
||||
{
|
||||
static_assert(
|
||||
!impl::is_wide_string<K> || TOML_WINDOWS_COMPAT,
|
||||
!impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT,
|
||||
"Emplacement using wide-character keys is only supported on Windows with TOML_WINDOWS_COMPAT enabled."
|
||||
);
|
||||
|
||||
if constexpr (impl::is_wide_string<K>)
|
||||
if constexpr (impl::is_wide_string<KeyType>)
|
||||
{
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
return emplace<U>(impl::narrow(std::forward<K>(key)), std::forward<V>(args)...);
|
||||
return emplace<ValueType>(impl::narrow(std::forward<KeyType>(key)), std::forward<ValueArgs>(args)...);
|
||||
#else
|
||||
static_assert(impl::dependent_false<U>, "Evaluated unreachable branch!");
|
||||
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
using type = impl::unwrap_node<U>;
|
||||
using type = impl::unwrap_node<ValueType>;
|
||||
static_assert(
|
||||
(impl::is_native<type> || impl::is_one_of<type, table, array>) && !impl::is_cvref<type>,
|
||||
"The emplacement type argument of table::emplace() must be one of:"
|
||||
TOML_SA_UNWRAPPED_NODE_TYPE_LIST
|
||||
);
|
||||
|
||||
auto ipos = values.lower_bound(key);
|
||||
if (ipos == values.end() || ipos->first != key)
|
||||
auto ipos = map.lower_bound(key);
|
||||
if (ipos == map.end() || ipos->first != key)
|
||||
{
|
||||
ipos = values.emplace_hint(
|
||||
ipos = map.emplace_hint(
|
||||
ipos,
|
||||
std::forward<K>(key),
|
||||
new impl::wrap_node<type>{ std::forward<V>(args)... }
|
||||
std::forward<KeyType>(key),
|
||||
new impl::wrap_node<type>{ std::forward<ValueArgs>(args)... }
|
||||
);
|
||||
return { ipos, true };
|
||||
}
|
||||
@ -4189,34 +4184,34 @@ TOML_NAMESPACE_START
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
template <typename T>
|
||||
template <typename ValueType>
|
||||
[[nodiscard]]
|
||||
impl::wrap_node<T>* get_as(std::string_view key) noexcept
|
||||
impl::wrap_node<ValueType>* get_as(std::string_view key) noexcept
|
||||
{
|
||||
return do_get_as<T>(values, key);
|
||||
return do_get_as<ValueType>(map, key);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename ValueType>
|
||||
[[nodiscard]]
|
||||
const impl::wrap_node<T>* get_as(std::string_view key) const noexcept
|
||||
const impl::wrap_node<ValueType>* get_as(std::string_view key) const noexcept
|
||||
{
|
||||
return do_get_as<T>(values, key);
|
||||
return do_get_as<ValueType>(map, key);
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
template <typename T>
|
||||
template <typename ValueType>
|
||||
[[nodiscard]]
|
||||
impl::wrap_node<T>* get_as(std::wstring_view key) noexcept
|
||||
impl::wrap_node<ValueType>* get_as(std::wstring_view key) noexcept
|
||||
{
|
||||
return get_as<T>(impl::narrow(key));
|
||||
return get_as<ValueType>(impl::narrow(key));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename ValueType>
|
||||
[[nodiscard]]
|
||||
const impl::wrap_node<T>* get_as(std::wstring_view key) const noexcept
|
||||
const impl::wrap_node<ValueType>* get_as(std::wstring_view key) const noexcept
|
||||
{
|
||||
return get_as<T>(impl::narrow(key));
|
||||
return get_as<ValueType>(impl::narrow(key));
|
||||
}
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
@ -7302,13 +7297,16 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::preinsertion_resize(size_t idx, size_t count) noexcept
|
||||
{
|
||||
const auto new_size = values.size() + count;
|
||||
const auto inserting_at_end = idx == values.size();
|
||||
values.resize(new_size);
|
||||
TOML_ASSERT(idx <= elements.size());
|
||||
TOML_ASSERT(count >= 1_sz);
|
||||
const auto old_size = elements.size();
|
||||
const auto new_size = old_size + count;
|
||||
const auto inserting_at_end = idx == old_size;
|
||||
elements.resize(new_size);
|
||||
if (!inserting_at_end)
|
||||
{
|
||||
for (size_t r = new_size, e = idx + count, l = e; r-- > e; l--)
|
||||
values[r] = std::move(values[l]);
|
||||
for(size_t left = old_size, right = new_size - 1_sz; left --> idx; right--)
|
||||
elements[right] = std::move(elements[left]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7318,14 +7316,14 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
values{ std::move(other.values) }
|
||||
elements{ std::move(other.elements) }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator= (array&& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
values = std::move(rhs.values);
|
||||
elements = std::move(rhs.elements);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -7338,69 +7336,69 @@ TOML_NAMESPACE_START
|
||||
TOML_MEMBER_ATTR(const) const array* array::as_array() const noexcept { return this; }
|
||||
TOML_MEMBER_ATTR(const) array* array::as_array() noexcept { return this; }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) const node& array::operator[] (size_t index) const noexcept { return *values[index]; }
|
||||
TOML_MEMBER_ATTR(pure) node& array::operator[] (size_t index) noexcept { return *values[index]; }
|
||||
TOML_MEMBER_ATTR(pure) const node& array::operator[] (size_t index) const noexcept { return *elements[index]; }
|
||||
TOML_MEMBER_ATTR(pure) node& array::operator[] (size_t index) noexcept { return *elements[index]; }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) const node& array::front() const noexcept { return *values.front(); }
|
||||
TOML_MEMBER_ATTR(pure) const node& array::back() const noexcept { return *values.back(); }
|
||||
TOML_MEMBER_ATTR(pure) node& array::front() noexcept { return *values.front(); }
|
||||
TOML_MEMBER_ATTR(pure) node& array::back() noexcept { return *values.back(); }
|
||||
TOML_MEMBER_ATTR(pure) const node& array::front() const noexcept { return *elements.front(); }
|
||||
TOML_MEMBER_ATTR(pure) const node& array::back() const noexcept { return *elements.back(); }
|
||||
TOML_MEMBER_ATTR(pure) node& array::front() noexcept { return *elements.front(); }
|
||||
TOML_MEMBER_ATTR(pure) node& array::back() noexcept { return *elements.back(); }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::begin() const noexcept { return { values.begin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::end() const noexcept { return { values.end() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::cbegin() const noexcept { return { values.cbegin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::cend() const noexcept { return { values.cend() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::iterator array::begin() noexcept { return { values.begin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::iterator array::end() noexcept { return { values.end() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::begin() const noexcept { return { elements.begin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::end() const noexcept { return { elements.end() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::cbegin() const noexcept { return { elements.cbegin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::const_iterator array::cend() const noexcept { return { elements.cend() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::iterator array::begin() noexcept { return { elements.begin() }; }
|
||||
TOML_MEMBER_ATTR(pure) array::iterator array::end() noexcept { return { elements.end() }; }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) size_t array::size() const noexcept { return values.size(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t array::capacity() const noexcept { return values.capacity(); }
|
||||
TOML_MEMBER_ATTR(pure) bool array::empty() const noexcept { return values.empty(); }
|
||||
TOML_MEMBER_ATTR(const) size_t array::max_size() const noexcept { return values.max_size(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t array::size() const noexcept { return elements.size(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t array::capacity() const noexcept { return elements.capacity(); }
|
||||
TOML_MEMBER_ATTR(pure) bool array::empty() const noexcept { return elements.empty(); }
|
||||
TOML_MEMBER_ATTR(const) size_t array::max_size() const noexcept { return elements.max_size(); }
|
||||
|
||||
TOML_EXTERNAL_LINKAGE void array::reserve(size_t new_capacity) { values.reserve(new_capacity); }
|
||||
TOML_EXTERNAL_LINKAGE void array::clear() noexcept { values.clear(); }
|
||||
TOML_EXTERNAL_LINKAGE void array::shrink_to_fit() { values.shrink_to_fit(); }
|
||||
TOML_EXTERNAL_LINKAGE void array::reserve(size_t new_capacity) { elements.reserve(new_capacity); }
|
||||
TOML_EXTERNAL_LINKAGE void array::clear() noexcept { elements.clear(); }
|
||||
TOML_EXTERNAL_LINKAGE void array::shrink_to_fit() { elements.shrink_to_fit(); }
|
||||
|
||||
#undef TOML_MEMBER_ATTR
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::truncate(size_t new_size)
|
||||
{
|
||||
if (new_size < values.size())
|
||||
values.resize(new_size);
|
||||
if (new_size < elements.size())
|
||||
elements.resize(new_size);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator pos) noexcept
|
||||
{
|
||||
return { values.erase(pos.raw_) };
|
||||
return { elements.erase(pos.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator first, const_iterator last) noexcept
|
||||
{
|
||||
return { values.erase(first.raw_, last.raw_) };
|
||||
return { elements.erase(first.raw_, last.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::pop_back() noexcept
|
||||
{
|
||||
values.pop_back();
|
||||
elements.pop_back();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
node* array::get(size_t index) noexcept
|
||||
{
|
||||
return index < values.size() ? values[index].get() : nullptr;
|
||||
return index < elements.size() ? elements[index].get() : nullptr;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
TOML_ATTR(pure)
|
||||
const node* array::get(size_t index) const noexcept
|
||||
{
|
||||
return index < values.size() ? values[index].get() : nullptr;
|
||||
return index < elements.size() ? elements[index].get() : nullptr;
|
||||
}
|
||||
|
||||
TOML_API
|
||||
@ -7409,17 +7407,17 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.values.size() != rhs.values.size())
|
||||
if (lhs.elements.size() != rhs.elements.size())
|
||||
return false;
|
||||
for (size_t i = 0, e = lhs.values.size(); i < e; i++)
|
||||
for (size_t i = 0, e = lhs.elements.size(); i < e; i++)
|
||||
{
|
||||
const auto lhs_type = lhs.values[i]->type();
|
||||
const node& rhs_ = *rhs.values[i];
|
||||
const auto lhs_type = lhs.elements[i]->type();
|
||||
const node& rhs_ = *rhs.elements[i];
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = lhs.values[i]->visit([&](const auto& lhs_) noexcept
|
||||
const bool equal = lhs.elements[i]->visit([&](const auto& lhs_) noexcept
|
||||
{
|
||||
return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_);
|
||||
});
|
||||
@ -7440,9 +7438,9 @@ TOML_NAMESPACE_START
|
||||
size_t array::total_leaf_count() const noexcept
|
||||
{
|
||||
size_t leaves{};
|
||||
for (size_t i = 0, e = values.size(); i < e; i++)
|
||||
for (size_t i = 0, e = elements.size(); i < e; i++)
|
||||
{
|
||||
auto arr = values[i]->as_array();
|
||||
auto arr = elements[i]->as_array();
|
||||
leaves += arr ? arr->total_leaf_count() : 1_sz;
|
||||
}
|
||||
return leaves;
|
||||
@ -7453,29 +7451,29 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
for (size_t i = 0, e = child.size(); i < e; i++)
|
||||
{
|
||||
auto type = child.values[i]->type();
|
||||
auto type = child.elements[i]->type();
|
||||
if (type == node_type::array)
|
||||
{
|
||||
array& arr = *reinterpret_cast<array*>(child.values[i].get());
|
||||
array& arr = *reinterpret_cast<array*>(child.elements[i].get());
|
||||
if (!arr.empty())
|
||||
flatten_child(std::move(arr), dest_index);
|
||||
}
|
||||
else
|
||||
values[dest_index++] = std::move(child.values[i]);
|
||||
elements[dest_index++] = std::move(child.elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::flatten() &
|
||||
{
|
||||
if (values.empty())
|
||||
if (elements.empty())
|
||||
return *this;
|
||||
|
||||
bool requires_flattening = false;
|
||||
size_t size_after_flattening = values.size();
|
||||
for (size_t i = values.size(); i --> 0_sz;)
|
||||
size_t size_after_flattening = elements.size();
|
||||
for (size_t i = elements.size(); i --> 0_sz;)
|
||||
{
|
||||
auto arr = values[i]->as_array();
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
continue;
|
||||
size_after_flattening--; //discount the array itself
|
||||
@ -7486,25 +7484,25 @@ TOML_NAMESPACE_START
|
||||
size_after_flattening += leaf_count;
|
||||
}
|
||||
else
|
||||
values.erase(values.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
elements.erase(elements.cbegin() + static_cast<ptrdiff_t>(i));
|
||||
}
|
||||
|
||||
if (!requires_flattening)
|
||||
return *this;
|
||||
|
||||
values.reserve(size_after_flattening);
|
||||
elements.reserve(size_after_flattening);
|
||||
|
||||
size_t i = 0;
|
||||
while (i < values.size())
|
||||
while (i < elements.size())
|
||||
{
|
||||
auto arr = values[i]->as_array();
|
||||
auto arr = elements[i]->as_array();
|
||||
if (!arr)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_ptr<node> arr_storage = std::move(values[i]);
|
||||
std::unique_ptr<node> arr_storage = std::move(elements[i]);
|
||||
const auto leaf_count = arr->total_leaf_count();
|
||||
if (leaf_count > 1_sz)
|
||||
preinsertion_resize(i + 1_sz, leaf_count - 1_sz);
|
||||
@ -7517,13 +7515,13 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_homogeneous(node_type type) const noexcept
|
||||
{
|
||||
if (values.empty())
|
||||
if (elements.empty())
|
||||
return false;
|
||||
|
||||
if (type == node_type::none)
|
||||
type = values[0]->type();
|
||||
type = elements[0]->type();
|
||||
|
||||
for (const auto& val : values)
|
||||
for (const auto& val : elements)
|
||||
if (val->type() != type)
|
||||
return false;
|
||||
return true;
|
||||
@ -7556,7 +7554,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
values.insert_or_assign(
|
||||
map.insert_or_assign(
|
||||
std::move(pairs[i].key),
|
||||
std::move(pairs[i].value)
|
||||
);
|
||||
@ -7569,7 +7567,7 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(table&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
values{ std::move(other.values) },
|
||||
map{ std::move(other.map) },
|
||||
inline_{ other.inline_ }
|
||||
{}
|
||||
|
||||
@ -7577,7 +7575,7 @@ TOML_NAMESPACE_START
|
||||
table& table::operator = (table&& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
values = std::move(rhs.values);
|
||||
map = std::move(rhs.map);
|
||||
inline_ = rhs.inline_;
|
||||
return *this;
|
||||
}
|
||||
@ -7594,16 +7592,16 @@ TOML_NAMESPACE_START
|
||||
TOML_MEMBER_ATTR(pure) bool table::is_inline() const noexcept { return inline_; }
|
||||
TOML_EXTERNAL_LINKAGE void table::is_inline(bool val) noexcept { inline_ = val; }
|
||||
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::begin() const noexcept { return { values.begin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::end() const noexcept { return { values.end() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::cbegin() const noexcept { return { values.cbegin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::cend() const noexcept { return { values.cend() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::iterator table::begin() noexcept { return { values.begin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::iterator table::end() noexcept { return { values.end() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::begin() const noexcept { return { map.begin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::end() const noexcept { return { map.end() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::cbegin() const noexcept { return { map.cbegin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::const_iterator table::cend() const noexcept { return { map.cend() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::iterator table::begin() noexcept { return { map.begin() }; }
|
||||
TOML_EXTERNAL_LINKAGE table::iterator table::end() noexcept { return { map.end() }; }
|
||||
|
||||
TOML_MEMBER_ATTR(pure) bool table::empty() const noexcept { return values.empty(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t table::size() const noexcept { return values.size(); }
|
||||
TOML_EXTERNAL_LINKAGE void table::clear() noexcept { values.clear(); }
|
||||
TOML_MEMBER_ATTR(pure) bool table::empty() const noexcept { return map.empty(); }
|
||||
TOML_MEMBER_ATTR(pure) size_t table::size() const noexcept { return map.size(); }
|
||||
TOML_EXTERNAL_LINKAGE void table::clear() noexcept { map.clear(); }
|
||||
|
||||
#undef TOML_MEMBER_ATTR
|
||||
|
||||
@ -7621,27 +7619,27 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::erase(iterator pos) noexcept
|
||||
{
|
||||
return { values.erase(pos.raw_) };
|
||||
return { map.erase(pos.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::erase(const_iterator pos) noexcept
|
||||
{
|
||||
return { values.erase(pos.raw_) };
|
||||
return { map.erase(pos.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::erase(const_iterator first, const_iterator last) noexcept
|
||||
{
|
||||
return { values.erase(first.raw_, last.raw_) };
|
||||
return { map.erase(first.raw_, last.raw_) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::erase(std::string_view key) noexcept
|
||||
{
|
||||
if (auto it = values.find(key); it != values.end())
|
||||
if (auto it = map.find(key); it != map.end())
|
||||
{
|
||||
values.erase(it);
|
||||
map.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -7650,31 +7648,31 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
node* table::get(std::string_view key) noexcept
|
||||
{
|
||||
return do_get(values, key);
|
||||
return do_get(map, key);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
const node* table::get(std::string_view key) const noexcept
|
||||
{
|
||||
return do_get(values, key);
|
||||
return do_get(map, key);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::find(std::string_view key) noexcept
|
||||
{
|
||||
return { values.find(key) };
|
||||
return { map.find(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::const_iterator table::find(std::string_view key) const noexcept
|
||||
{
|
||||
return { values.find(key) };
|
||||
return { map.find(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::contains(std::string_view key) const noexcept
|
||||
{
|
||||
return do_contains(values, key);
|
||||
return do_contains(map, key);
|
||||
}
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
@ -7734,10 +7732,10 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.values.size() != rhs.values.size())
|
||||
if (lhs.map.size() != rhs.map.size())
|
||||
return false;
|
||||
|
||||
for (auto l = lhs.values.begin(), r = rhs.values.begin(), e = lhs.values.end(); l != e; l++, r++)
|
||||
for (auto l = lhs.map.begin(), r = rhs.map.begin(), e = lhs.map.end(); l != e; l++, r++)
|
||||
{
|
||||
if (l->first != r->first)
|
||||
return false;
|
||||
@ -10638,7 +10636,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
auto child = parent->get(key.segments[i]);
|
||||
if (!child)
|
||||
{
|
||||
child = parent->values.emplace(
|
||||
child = parent->map.emplace(
|
||||
key.segments[i],
|
||||
new toml::table{}
|
||||
).first->second.get();
|
||||
@ -10654,9 +10652,9 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
// table arrays are a special case;
|
||||
// the spec dictates we select the most recently declared element in the array.
|
||||
TOML_ASSERT(!child->ref_cast<array>().values.empty());
|
||||
TOML_ASSERT(child->ref_cast<array>().values.back()->is_table());
|
||||
parent = &child->ref_cast<array>().values.back()->ref_cast<table>();
|
||||
TOML_ASSERT(!child->ref_cast<array>().elements.empty());
|
||||
TOML_ASSERT(child->ref_cast<array>().elements.back()->is_table());
|
||||
parent = &child->ref_cast<array>().elements.back()->ref_cast<table>();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -10683,22 +10681,22 @@ TOML_IMPL_NAMESPACE_START
|
||||
// set the starting regions, and return the table element
|
||||
if (is_arr)
|
||||
{
|
||||
auto tab_arr = &parent->values.emplace(
|
||||
auto tab_arr = &parent->map.emplace(
|
||||
key.segments.back(),
|
||||
new toml::array{}
|
||||
).first->second->ref_cast<array>();
|
||||
table_arrays.push_back(tab_arr);
|
||||
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
|
||||
tab_arr->values.emplace_back(new toml::table{});
|
||||
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
return &tab_arr->values.back()->ref_cast<table>();
|
||||
tab_arr->elements.emplace_back(new toml::table{});
|
||||
tab_arr->elements.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
return &tab_arr->elements.back()->ref_cast<table>();
|
||||
}
|
||||
|
||||
//otherwise we're just making a table
|
||||
else
|
||||
{
|
||||
auto tab = &parent->values.emplace(
|
||||
auto tab = &parent->map.emplace(
|
||||
key.segments.back(),
|
||||
new toml::table{})
|
||||
.first->second->ref_cast<table>();
|
||||
@ -10716,9 +10714,9 @@ TOML_IMPL_NAMESPACE_START
|
||||
if (is_arr && matching_node->is_array() && find(table_arrays, &matching_node->ref_cast<array>()))
|
||||
{
|
||||
auto tab_arr = &matching_node->ref_cast<array>();
|
||||
tab_arr->values.emplace_back(new toml::table{});
|
||||
tab_arr->values.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
return &tab_arr->values.back()->ref_cast<table>();
|
||||
tab_arr->elements.emplace_back(new toml::table{});
|
||||
tab_arr->elements.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
|
||||
return &tab_arr->elements.back()->ref_cast<table>();
|
||||
}
|
||||
|
||||
else if (!is_arr
|
||||
@ -10764,7 +10762,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
auto child = tab->get(kvp.key.segments[i]);
|
||||
if (!child)
|
||||
{
|
||||
child = tab->values.emplace(
|
||||
child = tab->map.emplace(
|
||||
std::move(kvp.key.segments[i]),
|
||||
new toml::table{}
|
||||
).first->second.get();
|
||||
@ -10797,7 +10795,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
return_if_error();
|
||||
tab->values.emplace(
|
||||
tab->map.emplace(
|
||||
std::move(kvp.key.segments.back()),
|
||||
std::unique_ptr<node>{ kvp.value }
|
||||
);
|
||||
@ -10869,7 +10867,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
return;
|
||||
|
||||
auto end = nde.source_.end;
|
||||
for (auto& [k, v] : tbl.values)
|
||||
for (auto& [k, v] : tbl.map)
|
||||
{
|
||||
(void)k;
|
||||
update_region_ends(*v);
|
||||
@ -10881,7 +10879,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
auto& arr = nde.ref_cast<array>();
|
||||
auto end = nde.source_.end;
|
||||
for (auto& v : arr.values)
|
||||
for (auto& v : arr.elements)
|
||||
{
|
||||
update_region_ends(*v);
|
||||
if (end < v->source_.end)
|
||||
@ -10953,7 +10951,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
advance_and_return_if_error_or_eof({});
|
||||
|
||||
auto arr = new array{};
|
||||
auto& vals = arr->values;
|
||||
auto& vals = arr->elements;
|
||||
enum parse_elem : int
|
||||
{
|
||||
none,
|
||||
@ -11446,6 +11444,4 @@ TOML_NAMESPACE_END
|
||||
#undef TOML_USING_ANON_NAMESPACE
|
||||
#endif
|
||||
|
||||
|
||||
#endif // INCLUDE_TOMLPLUSPLUS_H
|
||||
// clang-format on
|
||||
|
Loading…
Reference in New Issue
Block a user