added preserve_source_value_flags

also:
- fixed natvis file for v3 namespace
- small refactors
This commit is contained in:
Mark Gillard 2021-10-29 16:28:04 +03:00
parent 1bf09fe500
commit 97132cb27c
16 changed files with 347 additions and 426 deletions

View File

@ -9,7 +9,7 @@ assignees: marzer
<!-- <!--
Replace the HTML comments below with the requested information. Replace the HTML comments below with the requested information.
Please DO NOT delete this template and roll your own! Please don't delete this template and roll your own!
Thanks for contributing! Thanks for contributing!
--> -->

View File

@ -9,7 +9,7 @@ assignees: marzer
<!-- <!--
Replace the HTML comments below with the requested information. Replace the HTML comments below with the requested information.
Please DO NOT delete this template and roll your own! Please don't delete this template and roll your own!
Thanks for contributing! Thanks for contributing!
--> -->

View File

@ -3,8 +3,10 @@ Contributions are very welcome! Either by [reporting issues] or submitting pull
If you wish to submit a PR, please be aware that: If you wish to submit a PR, please be aware that:
- The single-header file `toml.hpp` is generated by a script; make your changes in the files in - The single-header file `toml.hpp` is generated by a script; make your changes in the files in
`include`, **not** in `toml.hpp`. `include`, **not** in `toml.hpp`.
- Your changes should compile warning-free on at least one of gcc 8.3.0, clang 8.0, and MSVC 19.2X - Your changes should compile warning-free on at least one of:
(Visual Studio 2019). All three is a bonus. - GCC 8 or higher
- Clang 8 or higher
- MSVC 19.2X (Visual Studio 2019) or higher
- You should regenerate the single-header file as part of your PR (a CI check will fail if you don't). - You should regenerate the single-header file as part of your PR (a CI check will fail if you don't).
<br> <br>

View File

@ -249,7 +249,7 @@ TOML_NAMESPACE_START
/// \cond /// \cond
friend class TOML_PARSER_TYPENAME; friend class TOML_PARSER_TYPENAME;
std::vector<std::unique_ptr<node>> elements; std::vector<std::unique_ptr<node>> elems_;
TOML_API TOML_API
void preinsertion_resize(size_t idx, size_t count); void preinsertion_resize(size_t idx, size_t count);
@ -262,7 +262,7 @@ TOML_NAMESPACE_START
if (!val) if (!val)
return; return;
} }
elements.emplace_back(impl::make_node(static_cast<T&&>(val), flags)); elems_.emplace_back(impl::make_node(static_cast<T&&>(val), flags));
} }
TOML_NODISCARD TOML_NODISCARD
@ -363,11 +363,11 @@ TOML_NAMESPACE_START
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
explicit array(ElemType&& val, ElemTypes&&... vals) explicit array(ElemType&& val, ElemTypes&&... vals)
{ {
elements.reserve(sizeof...(ElemTypes) + 1u); elems_.reserve(sizeof...(ElemTypes) + 1u);
emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), value_flags::none); emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), preserve_source_value_flags);
if constexpr (sizeof...(ElemTypes) > 0) if constexpr (sizeof...(ElemTypes) > 0)
{ {
(emplace_back_if_not_empty_view(static_cast<ElemTypes&&>(vals), value_flags::none), ...); (emplace_back_if_not_empty_view(static_cast<ElemTypes&&>(vals), preserve_source_value_flags), ...);
} }
#if TOML_LIFETIME_HOOKS #if TOML_LIFETIME_HOOKS
@ -442,130 +442,130 @@ TOML_NAMESPACE_START
TOML_NODISCARD TOML_NODISCARD
node& operator[](size_t index) noexcept node& operator[](size_t index) noexcept
{ {
return *elements[index]; return *elems_[index];
} }
/// \brief Gets a reference to the element at a specific index. /// \brief Gets a reference to the element at a specific index.
TOML_NODISCARD TOML_NODISCARD
const node& operator[](size_t index) const noexcept const node& operator[](size_t index) const noexcept
{ {
return *elements[index]; return *elems_[index];
} }
/// \brief Returns a reference to the first element in the array. /// \brief Returns a reference to the first element in the array.
TOML_NODISCARD TOML_NODISCARD
node& front() noexcept node& front() noexcept
{ {
return *elements.front(); return *elems_.front();
} }
/// \brief Returns a reference to the first element in the array. /// \brief Returns a reference to the first element in the array.
TOML_NODISCARD TOML_NODISCARD
const node& front() const noexcept const node& front() const noexcept
{ {
return *elements.front(); return *elems_.front();
} }
/// \brief Returns a reference to the last element in the array. /// \brief Returns a reference to the last element in the array.
TOML_NODISCARD TOML_NODISCARD
node& back() noexcept node& back() noexcept
{ {
return *elements.back(); return *elems_.back();
} }
/// \brief Returns a reference to the last element in the array. /// \brief Returns a reference to the last element in the array.
TOML_NODISCARD TOML_NODISCARD
const node& back() const noexcept const node& back() const noexcept
{ {
return *elements.back(); return *elems_.back();
} }
/// \brief Returns an iterator to the first element. /// \brief Returns an iterator to the first element.
TOML_NODISCARD TOML_NODISCARD
iterator begin() noexcept iterator begin() noexcept
{ {
return { elements.begin() }; return { elems_.begin() };
} }
/// \brief Returns an iterator to the first element. /// \brief Returns an iterator to the first element.
TOML_NODISCARD TOML_NODISCARD
const_iterator begin() const noexcept const_iterator begin() const noexcept
{ {
return { elements.cbegin() }; return { elems_.cbegin() };
} }
/// \brief Returns an iterator to the first element. /// \brief Returns an iterator to the first element.
TOML_NODISCARD TOML_NODISCARD
const_iterator cbegin() const noexcept const_iterator cbegin() const noexcept
{ {
return { elements.cbegin() }; return { elems_.cbegin() };
} }
/// \brief Returns an iterator to one-past-the-last element. /// \brief Returns an iterator to one-past-the-last element.
TOML_NODISCARD TOML_NODISCARD
iterator end() noexcept iterator end() noexcept
{ {
return { elements.end() }; return { elems_.end() };
} }
/// \brief Returns an iterator to one-past-the-last element. /// \brief Returns an iterator to one-past-the-last element.
TOML_NODISCARD TOML_NODISCARD
const_iterator end() const noexcept const_iterator end() const noexcept
{ {
return { elements.cend() }; return { elems_.cend() };
} }
/// \brief Returns an iterator to one-past-the-last element. /// \brief Returns an iterator to one-past-the-last element.
TOML_NODISCARD TOML_NODISCARD
const_iterator cend() const noexcept const_iterator cend() const noexcept
{ {
return { elements.cend() }; return { elems_.cend() };
} }
/// \brief Returns true if the array is empty. /// \brief Returns true if the array is empty.
TOML_NODISCARD TOML_NODISCARD
bool empty() const noexcept bool empty() const noexcept
{ {
return elements.empty(); return elems_.empty();
} }
/// \brief Returns the number of elements in the array. /// \brief Returns the number of elements in the array.
TOML_NODISCARD TOML_NODISCARD
size_t size() const noexcept size_t size() const noexcept
{ {
return elements.size(); return elems_.size();
} }
/// \brief Reserves internal storage capacity up to a pre-determined number of elements. /// \brief Reserves internal storage capacity up to a pre-determined number of elements.
void reserve(size_t new_capacity) void reserve(size_t new_capacity)
{ {
elements.reserve(new_capacity); elems_.reserve(new_capacity);
} }
/// \brief Removes all elements from the array. /// \brief Removes all elements from the array.
void clear() noexcept void clear() noexcept
{ {
elements.clear(); elems_.clear();
} }
/// \brief Returns the maximum number of elements 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.
TOML_NODISCARD TOML_NODISCARD
size_t max_size() const noexcept size_t max_size() const noexcept
{ {
return elements.max_size(); return elems_.max_size();
} }
/// \brief Returns the current max number of elements 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.
TOML_NODISCARD TOML_NODISCARD
size_t capacity() const noexcept size_t capacity() const noexcept
{ {
return elements.capacity(); return elems_.capacity();
} }
/// \brief Requests the removal of any unused internal storage capacity. /// \brief Requests the removal of any unused internal storage capacity.
void shrink_to_fit() void shrink_to_fit()
{ {
elements.shrink_to_fit(); elems_.shrink_to_fit();
} }
/// \brief Inserts a new element at a specific position in the array. /// \brief Inserts a new element at a specific position in the array.
@ -588,9 +588,6 @@ TOML_NAMESPACE_START
/// \param val The node or value being inserted. /// \param val The node or value being inserted.
/// \param flags Value flags to apply to new values. /// \param flags Value flags to apply to new values.
/// ///
/// \note When `flags == value_flags::none` and `val` is a value node or node_view, any existing value
/// flags will be copied, _not_ set to none.
///
/// \returns \conditional_return{Valid input} /// \returns \conditional_return{Valid input}
/// An iterator to the newly-inserted element. /// An iterator to the newly-inserted element.
/// \conditional_return{Input is an empty toml::node_view} /// \conditional_return{Input is an empty toml::node_view}
@ -599,14 +596,14 @@ TOML_NAMESPACE_START
/// \attention The return value will always be `end()` if the input value was an empty toml::node_view, /// \attention The return value will always be `end()` if the input value was an empty toml::node_view,
/// because no insertion can take place. This is the only circumstance in which this can occur. /// because no insertion can take place. This is the only circumstance in which this can occur.
template <typename ElemType> template <typename ElemType>
iterator insert(const_iterator pos, ElemType&& val, value_flags flags = value_flags::none) iterator insert(const_iterator pos, ElemType&& val, value_flags flags = preserve_source_value_flags)
{ {
if constexpr (is_node_view<ElemType>) if constexpr (is_node_view<ElemType>)
{ {
if (!val) if (!val)
return end(); return end();
} }
return { elements.emplace(pos.raw_, impl::make_node(static_cast<ElemType&&>(val), flags)) }; return { elems_.emplace(pos.raw_, impl::make_node(static_cast<ElemType&&>(val), flags)) };
} }
/// \brief Repeatedly inserts a new element starting at a specific position in the array. /// \brief Repeatedly inserts a new element starting at a specific position in the array.
@ -638,9 +635,6 @@ TOML_NAMESPACE_START
/// \param val The node or value being inserted. /// \param val The node or value being inserted.
/// \param flags Value flags to apply to new values. /// \param flags Value flags to apply to new values.
/// ///
/// \note When `flags == value_flags::none` and `val` is a value node or node_view, any existing value
/// flags will be copied, _not_ set to none.
///
/// \returns \conditional_return{Valid input} /// \returns \conditional_return{Valid input}
/// An iterator to the newly-inserted element. /// An iterator to the newly-inserted element.
/// \conditional_return{count == 0} /// \conditional_return{count == 0}
@ -651,7 +645,10 @@ TOML_NAMESPACE_START
/// \attention The return value will always be `end()` if the input value was an empty toml::node_view, /// \attention The return value will always be `end()` if the input value was an empty toml::node_view,
/// because no insertion can take place. This is the only circumstance in which this can occur. /// because no insertion can take place. This is the only circumstance in which this can occur.
template <typename ElemType> template <typename ElemType>
iterator insert(const_iterator pos, size_t count, ElemType&& val, value_flags flags = value_flags::none) iterator insert(const_iterator pos,
size_t count,
ElemType&& val,
value_flags flags = preserve_source_value_flags)
{ {
if constexpr (is_node_view<ElemType>) if constexpr (is_node_view<ElemType>)
{ {
@ -660,19 +657,19 @@ TOML_NAMESPACE_START
} }
switch (count) switch (count)
{ {
case 0: return { elements.begin() + (pos.raw_ - elements.cbegin()) }; case 0: return { elems_.begin() + (pos.raw_ - elems_.cbegin()) };
case 1: return insert(pos, static_cast<ElemType&&>(val), flags); case 1: return insert(pos, static_cast<ElemType&&>(val), flags);
default: default:
{ {
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin()); const auto start_idx = static_cast<size_t>(pos.raw_ - elems_.cbegin());
preinsertion_resize(start_idx, count); preinsertion_resize(start_idx, count);
size_t i = start_idx; size_t i = start_idx;
for (size_t e = start_idx + count - 1u; i < e; i++) for (size_t e = start_idx + count - 1u; i < e; i++)
elements[i].reset(impl::make_node(val, flags)); elems_[i].reset(impl::make_node(val, flags));
//# potentially move the initial value into the last element //# potentially move the initial value into the last element
elements[i].reset(impl::make_node(static_cast<ElemType&&>(val), flags)); elems_[i].reset(impl::make_node(static_cast<ElemType&&>(val), flags));
return { elements.begin() + static_cast<ptrdiff_t>(start_idx) }; return { elems_.begin() + static_cast<ptrdiff_t>(start_idx) };
} }
} }
} }
@ -685,9 +682,6 @@ TOML_NAMESPACE_START
/// \param last Iterator to the one-past-the-last node or value being inserted. /// \param last Iterator to the one-past-the-last node or value being inserted.
/// \param flags Value flags to apply to new values. /// \param flags Value flags to apply to new values.
/// ///
/// \note When `flags == value_flags::none` and a source value is a value node or node_view, any existing value
/// flags will be copied, _not_ set to none.
///
/// \returns \conditional_return{Valid input} /// \returns \conditional_return{Valid input}
/// An iterator to the first newly-inserted element. /// An iterator to the first newly-inserted element.
/// \conditional_return{first >= last} /// \conditional_return{first >= last}
@ -695,11 +689,11 @@ TOML_NAMESPACE_START
/// \conditional_return{All objects in the range were empty toml::node_views} /// \conditional_return{All objects in the range were empty toml::node_views}
/// A copy of pos /// A copy of pos
template <typename Iter> template <typename Iter>
iterator insert(const_iterator pos, Iter first, Iter last, value_flags flags = value_flags::none) iterator insert(const_iterator pos, Iter first, Iter last, value_flags flags = preserve_source_value_flags)
{ {
const auto distance = std::distance(first, last); const auto distance = std::distance(first, last);
if (distance <= 0) if (distance <= 0)
return { elements.begin() + (pos.raw_ - elements.cbegin()) }; return { elems_.begin() + (pos.raw_ - elems_.cbegin()) };
else else
{ {
auto count = distance; auto count = distance;
@ -710,9 +704,9 @@ TOML_NAMESPACE_START
if (!(*it)) if (!(*it))
count--; count--;
if (!count) if (!count)
return { elements.begin() + (pos.raw_ - elements.cbegin()) }; return { elems_.begin() + (pos.raw_ - elems_.cbegin()) };
} }
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin()); const auto start_idx = static_cast<size_t>(pos.raw_ - elems_.cbegin());
preinsertion_resize(start_idx, static_cast<size_t>(count)); preinsertion_resize(start_idx, static_cast<size_t>(count));
size_t i = start_idx; size_t i = start_idx;
for (auto it = first; it != last; it++) for (auto it = first; it != last; it++)
@ -723,11 +717,11 @@ TOML_NAMESPACE_START
continue; continue;
} }
if constexpr (std::is_rvalue_reference_v<deref_type>) if constexpr (std::is_rvalue_reference_v<deref_type>)
elements[i++].reset(impl::make_node(std::move(*it), flags)); elems_[i++].reset(impl::make_node(std::move(*it), flags));
else else
elements[i++].reset(impl::make_node(*it, flags)); elems_[i++].reset(impl::make_node(*it, flags));
} }
return { elements.begin() + static_cast<ptrdiff_t>(start_idx) }; return { elems_.begin() + static_cast<ptrdiff_t>(start_idx) };
} }
} }
@ -739,9 +733,6 @@ TOML_NAMESPACE_START
/// \param ilist An initializer list containing the values to be inserted. /// \param ilist An initializer list containing the values to be inserted.
/// \param flags Value flags to apply to new values. /// \param flags Value flags to apply to new values.
/// ///
/// \note When `flags == value_flags::none` and a source value is a value node or node_view, any existing value
/// flags will be copied, _not_ set to none.
///
/// \returns \conditional_return{Valid input} /// \returns \conditional_return{Valid input}
/// An iterator to the first newly-inserted element. /// An iterator to the first newly-inserted element.
/// \conditional_return{Input list is empty} /// \conditional_return{Input list is empty}
@ -751,7 +742,7 @@ TOML_NAMESPACE_START
template <typename ElemType> template <typename ElemType>
iterator insert(const_iterator pos, iterator insert(const_iterator pos,
std::initializer_list<ElemType> ilist, std::initializer_list<ElemType> ilist,
value_flags flags = value_flags::none) value_flags flags = preserve_source_value_flags)
{ {
return insert(pos, ilist.begin(), ilist.end(), flags); return insert(pos, ilist.begin(), ilist.end(), flags);
} }
@ -787,7 +778,7 @@ TOML_NAMESPACE_START
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>, 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); "Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
return { elements.emplace(pos.raw_, new impl::wrap_node<type>{ static_cast<Args&&>(args)... }) }; return { elems_.emplace(pos.raw_, new impl::wrap_node<type>{ static_cast<Args&&>(args)... }) };
} }
/// \brief Removes the specified element from the array. /// \brief Removes the specified element from the array.
@ -811,7 +802,7 @@ TOML_NAMESPACE_START
/// \returns Iterator to the first element immediately following the removed element. /// \returns Iterator to the first element immediately following the removed element.
iterator erase(const_iterator pos) noexcept iterator erase(const_iterator pos) noexcept
{ {
return { elements.erase(pos.raw_) }; return { elems_.erase(pos.raw_) };
} }
/// \brief Removes the elements in the range [first, last) from the array. /// \brief Removes the elements in the range [first, last) from the array.
@ -836,7 +827,7 @@ TOML_NAMESPACE_START
/// \returns Iterator to the first element immediately following the last removed element. /// \returns Iterator to the first element immediately following the last removed element.
iterator erase(const_iterator first, const_iterator last) noexcept iterator erase(const_iterator first, const_iterator last) noexcept
{ {
return { elements.erase(first.raw_, last.raw_) }; return { elems_.erase(first.raw_, last.raw_) };
} }
/// \brief Resizes the array. /// \brief Resizes the array.
@ -873,11 +864,11 @@ TOML_NAMESPACE_START
"The default element type argument to toml::array::resize may not be toml::node_view."); "The default element type argument to toml::array::resize may not be toml::node_view.");
if (!new_size) if (!new_size)
elements.clear(); elems_.clear();
else if (new_size < elements.size()) else if (new_size < elems_.size())
elements.resize(new_size); elems_.resize(new_size);
else if (new_size > elements.size()) else if (new_size > elems_.size())
insert(cend(), new_size - elements.size(), static_cast<ElemType&&>(default_init_val)); insert(cend(), new_size - elems_.size(), static_cast<ElemType&&>(default_init_val));
} }
/// \brief Shrinks the array to the given size. /// \brief Shrinks the array to the given size.
@ -905,8 +896,8 @@ TOML_NAMESPACE_START
/// \remarks Does nothing if the requested size is larger than or equal to the current size. /// \remarks Does nothing if the requested size is larger than or equal to the current size.
void truncate(size_t new_size) void truncate(size_t new_size)
{ {
if (new_size < elements.size()) if (new_size < elems_.size())
elements.resize(new_size); elems_.resize(new_size);
} }
/// \brief Appends a new element to the end of the array. /// \brief Appends a new element to the end of the array.
@ -928,13 +919,10 @@ TOML_NAMESPACE_START
/// \param val The node or value being added. /// \param val The node or value being added.
/// \param flags Value flags to apply to new values. /// \param flags Value flags to apply to new values.
/// ///
/// \note When `flags == value_flags::none` and `val` is a value node or node_view, any existing value
/// flags will be copied, _not_ set to none.
///
/// \attention No insertion takes place if the input value is an empty toml::node_view. /// \attention No insertion takes place if the input value is an empty toml::node_view.
/// This is the only circumstance in which this can occur. /// This is the only circumstance in which this can occur.
template <typename ElemType> template <typename ElemType>
void push_back(ElemType&& val, value_flags flags = value_flags::none) void push_back(ElemType&& val, value_flags flags = preserve_source_value_flags)
{ {
emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), flags); emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), flags);
} }
@ -968,14 +956,14 @@ TOML_NAMESPACE_START
"Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST); "Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
auto nde = new impl::wrap_node<type>{ static_cast<Args&&>(args)... }; auto nde = new impl::wrap_node<type>{ static_cast<Args&&>(args)... };
elements.emplace_back(nde); elems_.emplace_back(nde);
return *nde; return *nde;
} }
/// \brief Removes the last element from the array. /// \brief Removes the last element from the array.
void pop_back() noexcept void pop_back() noexcept
{ {
elements.pop_back(); elems_.pop_back();
} }
/// \brief Gets the element at a specific index. /// \brief Gets the element at a specific index.
@ -1003,7 +991,7 @@ TOML_NAMESPACE_START
TOML_NODISCARD TOML_NODISCARD
node* get(size_t index) noexcept node* get(size_t index) noexcept
{ {
return index < elements.size() ? elements[index].get() : nullptr; return index < elems_.size() ? elems_[index].get() : nullptr;
} }
/// \brief Gets the element at a specific index (const overload). /// \brief Gets the element at a specific index (const overload).
@ -1014,7 +1002,7 @@ TOML_NAMESPACE_START
TOML_NODISCARD TOML_NODISCARD
const node* get(size_t index) const noexcept const node* get(size_t index) const noexcept
{ {
return index < elements.size() ? elements[index].get() : nullptr; return index < elems_.size() ? elems_[index].get() : nullptr;
} }
/// \brief Gets the element at a specific index if it is a particular type. /// \brief Gets the element at a specific index if it is a particular type.

View File

@ -46,9 +46,9 @@ TOML_NAMESPACE_START
array::array(const array& other) // array::array(const array& other) //
: node(other) : node(other)
{ {
elements.reserve(other.elements.size()); elems_.reserve(other.elems_.size());
for (const auto& elem : other) for (const auto& elem : other)
elements.emplace_back(impl::make_node(elem)); elems_.emplace_back(impl::make_node(elem));
#if TOML_LIFETIME_HOOKS #if TOML_LIFETIME_HOOKS
TOML_ARRAY_CREATED; TOML_ARRAY_CREATED;
@ -58,7 +58,7 @@ TOML_NAMESPACE_START
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
array::array(array && other) noexcept // array::array(array && other) noexcept //
: node(std::move(other)), : node(std::move(other)),
elements{ std::move(other.elements) } elems_{ std::move(other.elems_) }
{ {
#if TOML_LIFETIME_HOOKS #if TOML_LIFETIME_HOOKS
TOML_ARRAY_CREATED; TOML_ARRAY_CREATED;
@ -71,10 +71,10 @@ TOML_NAMESPACE_START
if (&rhs != this) if (&rhs != this)
{ {
node::operator=(rhs); node::operator=(rhs);
elements.clear(); elems_.clear();
elements.reserve(rhs.elements.size()); elems_.reserve(rhs.elems_.size());
for (const auto& elem : rhs) for (const auto& elem : rhs)
elements.emplace_back(impl::make_node(elem)); elems_.emplace_back(impl::make_node(elem));
} }
return *this; return *this;
} }
@ -85,7 +85,7 @@ TOML_NAMESPACE_START
if (&rhs != this) if (&rhs != this)
{ {
node::operator=(std::move(rhs)); node::operator=(std::move(rhs));
elements = std::move(rhs.elements); elems_ = std::move(rhs.elems_);
} }
return *this; return *this;
} }
@ -93,29 +93,29 @@ TOML_NAMESPACE_START
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
void array::preinsertion_resize(size_t idx, size_t count) void array::preinsertion_resize(size_t idx, size_t count)
{ {
TOML_ASSERT(idx <= elements.size()); TOML_ASSERT(idx <= elems_.size());
TOML_ASSERT(count >= 1u); TOML_ASSERT(count >= 1u);
const auto old_size = elements.size(); const auto old_size = elems_.size();
const auto new_size = old_size + count; const auto new_size = old_size + count;
const auto inserting_at_end = idx == old_size; const auto inserting_at_end = idx == old_size;
elements.resize(new_size); elems_.resize(new_size);
if (!inserting_at_end) if (!inserting_at_end)
{ {
for (size_t left = old_size, right = new_size - 1u; left-- > idx; right--) for (size_t left = old_size, right = new_size - 1u; left-- > idx; right--)
elements[right] = std::move(elements[left]); elems_[right] = std::move(elems_[left]);
} }
} }
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
bool array::is_homogeneous(node_type ntype) const noexcept bool array::is_homogeneous(node_type ntype) const noexcept
{ {
if (elements.empty()) if (elems_.empty())
return false; return false;
if (ntype == node_type::none) if (ntype == node_type::none)
ntype = elements[0]->type(); ntype = elems_[0]->type();
for (const auto& val : elements) for (const auto& val : elems_)
if (val->type() != ntype) if (val->type() != ntype)
return false; return false;
@ -125,13 +125,13 @@ TOML_NAMESPACE_START
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
bool array::is_homogeneous(node_type ntype, node * &first_nonmatch) noexcept bool array::is_homogeneous(node_type ntype, node * &first_nonmatch) noexcept
{ {
return TOML_ANON_NAMESPACE::array_is_homogeneous(elements, ntype, first_nonmatch); return TOML_ANON_NAMESPACE::array_is_homogeneous(elems_, ntype, first_nonmatch);
} }
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
bool array::is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept bool array::is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept
{ {
return TOML_ANON_NAMESPACE::array_is_homogeneous(elements, ntype, first_nonmatch); return TOML_ANON_NAMESPACE::array_is_homogeneous(elems_, ntype, first_nonmatch);
} }
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
@ -139,17 +139,17 @@ TOML_NAMESPACE_START
{ {
if (&lhs == &rhs) if (&lhs == &rhs)
return true; return true;
if (lhs.elements.size() != rhs.elements.size()) if (lhs.elems_.size() != rhs.elems_.size())
return false; return false;
for (size_t i = 0, e = lhs.elements.size(); i < e; i++) for (size_t i = 0, e = lhs.elems_.size(); i < e; i++)
{ {
const auto lhs_type = lhs.elements[i]->type(); const auto lhs_type = lhs.elems_[i]->type();
const node& rhs_ = *rhs.elements[i]; const node& rhs_ = *rhs.elems_[i];
const auto rhs_type = rhs_.type(); const auto rhs_type = rhs_.type();
if (lhs_type != rhs_type) if (lhs_type != rhs_type)
return false; return false;
const bool equal = lhs.elements[i]->visit( const bool equal = lhs.elems_[i]->visit(
[&](const auto& lhs_) noexcept [&](const auto& lhs_) noexcept
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); }); { return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
if (!equal) if (!equal)
@ -162,9 +162,9 @@ TOML_NAMESPACE_START
size_t array::total_leaf_count() const noexcept size_t array::total_leaf_count() const noexcept
{ {
size_t leaves{}; size_t leaves{};
for (size_t i = 0, e = elements.size(); i < e; i++) for (size_t i = 0, e = elems_.size(); i < e; i++)
{ {
auto arr = elements[i]->as_array(); auto arr = elems_[i]->as_array();
leaves += arr ? arr->total_leaf_count() : size_t{ 1 }; leaves += arr ? arr->total_leaf_count() : size_t{ 1 };
} }
return leaves; return leaves;
@ -175,29 +175,29 @@ TOML_NAMESPACE_START
{ {
for (size_t i = 0, e = child.size(); i < e; i++) for (size_t i = 0, e = child.size(); i < e; i++)
{ {
auto type = child.elements[i]->type(); auto type = child.elems_[i]->type();
if (type == node_type::array) if (type == node_type::array)
{ {
array& arr = *reinterpret_cast<array*>(child.elements[i].get()); array& arr = *reinterpret_cast<array*>(child.elems_[i].get());
if (!arr.empty()) if (!arr.empty())
flatten_child(std::move(arr), dest_index); flatten_child(std::move(arr), dest_index);
} }
else else
elements[dest_index++] = std::move(child.elements[i]); elems_[dest_index++] = std::move(child.elems_[i]);
} }
} }
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
array& array::flatten()& array& array::flatten()&
{ {
if (elements.empty()) if (elems_.empty())
return *this; return *this;
bool requires_flattening = false; bool requires_flattening = false;
size_t size_after_flattening = elements.size(); size_t size_after_flattening = elems_.size();
for (size_t i = elements.size(); i-- > 0u;) for (size_t i = elems_.size(); i-- > 0u;)
{ {
auto arr = elements[i]->as_array(); auto arr = elems_[i]->as_array();
if (!arr) if (!arr)
continue; continue;
size_after_flattening--; // discount the array itself size_after_flattening--; // discount the array itself
@ -208,25 +208,25 @@ TOML_NAMESPACE_START
size_after_flattening += leaf_count; size_after_flattening += leaf_count;
} }
else else
elements.erase(elements.cbegin() + static_cast<ptrdiff_t>(i)); elems_.erase(elems_.cbegin() + static_cast<ptrdiff_t>(i));
} }
if (!requires_flattening) if (!requires_flattening)
return *this; return *this;
elements.reserve(size_after_flattening); elems_.reserve(size_after_flattening);
size_t i = 0; size_t i = 0;
while (i < elements.size()) while (i < elems_.size())
{ {
auto arr = elements[i]->as_array(); auto arr = elems_[i]->as_array();
if (!arr) if (!arr)
{ {
i++; i++;
continue; continue;
} }
std::unique_ptr<node> arr_storage = std::move(elements[i]); std::unique_ptr<node> arr_storage = std::move(elems_[i]);
const auto leaf_count = arr->total_leaf_count(); const auto leaf_count = arr->total_leaf_count();
if (leaf_count > 1u) if (leaf_count > 1u)
preinsertion_resize(i + 1u, leaf_count - 1u); preinsertion_resize(i + 1u, leaf_count - 1u);

View File

@ -283,6 +283,11 @@ TOML_NAMESPACE_START // abi namespace
}; };
TOML_MAKE_FLAGS(value_flags); TOML_MAKE_FLAGS(value_flags);
/// \brief Special #toml::value_flags constant used for array + table insert functions to specify that any value
/// nodes being copied should not have their flags property overridden by the inserting function's `flags` argument.
inline constexpr value_flags preserve_source_value_flags =
POXY_IMPLEMENTATION_DETAIL(value_flags{ static_cast<std::underlying_type_t<value_flags>>(-1) });
/// \brief Format flags for modifying how TOML data is printed to streams. /// \brief Format flags for modifying how TOML data is printed to streams.
/// ///
/// \note Formatters may disregard/override any of these flags according to the requirements of their /// \note Formatters may disregard/override any of these flags according to the requirements of their
@ -868,9 +873,7 @@ TOML_NAMESPACE_END;
TOML_IMPL_NAMESPACE_START TOML_IMPL_NAMESPACE_START
{ {
template <typename T> template <typename T>
TOML_NODISCARD TOML_CONST_INLINE_GETTER
TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr std::underlying_type_t<T> unwrap_enum(T val) noexcept constexpr std::underlying_type_t<T> unwrap_enum(T val) noexcept
{ {
return static_cast<std::underlying_type_t<T>>(val); return static_cast<std::underlying_type_t<T>>(val);
@ -886,8 +889,7 @@ TOML_IMPL_NAMESPACE_START
nan nan
}; };
TOML_NODISCARD TOML_PURE_GETTER
TOML_ATTR(pure)
inline fp_class fpclassify(const double& val) noexcept inline fp_class fpclassify(const double& val) noexcept
{ {
static_assert(sizeof(uint64_t) == sizeof(double)); static_assert(sizeof(uint64_t) == sizeof(double));
@ -897,7 +899,7 @@ TOML_IMPL_NAMESPACE_START
static constexpr uint64_t mantissa = 0b0000000000001111111111111111111111111111111111111111111111111111ull; static constexpr uint64_t mantissa = 0b0000000000001111111111111111111111111111111111111111111111111111ull;
uint64_t val_bits; uint64_t val_bits;
memcpy(&val_bits, &val, sizeof(val)); std::memcpy(&val_bits, &val, sizeof(val));
if ((val_bits & exponent) != exponent) if ((val_bits & exponent) != exponent)
return fp_class::ok; return fp_class::ok;
if ((val_bits & mantissa)) if ((val_bits & mantissa))
@ -909,7 +911,7 @@ TOML_IMPL_NAMESPACE_START
// A: Because <algorithm> is _huge_ and std::find would be the only thing I used from it. // A: Because <algorithm> is _huge_ and std::find would be the only thing I used from it.
// I don't want to impose such a heavy compile-time burden on users. // I don't want to impose such a heavy compile-time burden on users.
template <typename Iterator, typename T> template <typename Iterator, typename T>
TOML_NODISCARD TOML_PURE_GETTER
inline auto find(Iterator start, Iterator end, const T& needle) noexcept // inline auto find(Iterator start, Iterator end, const T& needle) noexcept //
->decltype(&(*start)) ->decltype(&(*start))
{ {

View File

@ -4,5 +4,3 @@
#endif #endif
//# }} //# }}
TOML_PUSH_WARNINGS; TOML_PUSH_WARNINGS;
TOML_DISABLE_SPAM_WARNINGS;
TOML_DISABLE_SWITCH_WARNINGS;

View File

@ -37,11 +37,6 @@ TOML_IMPL_NAMESPACE_START
if constexpr (std::is_same_v<remove_cvref<T>, value_type>) if constexpr (std::is_same_v<remove_cvref<T>, value_type>)
{ {
out = new value_type{ static_cast<T&&>(val) }; out = new value_type{ static_cast<T&&>(val) };
// only override the flags if the new ones are nonzero
// (so the copy/move ctor does the right thing in the general case)
if (flags != value_flags::none)
out->flags(flags);
} }
// creating from raw value // creating from raw value
@ -63,17 +58,18 @@ TOML_IMPL_NAMESPACE_START
} }
else else
out = new value_type{ static_cast<T&&>(val) }; out = new value_type{ static_cast<T&&>(val) };
out->flags(flags);
} }
if (flags != preserve_source_value_flags)
out->flags(flags);
return out; return out;
} }
} }
template <typename T> template <typename T>
TOML_NODISCARD TOML_NODISCARD
auto* make_node(T && val, value_flags flags = value_flags::none) auto* make_node(T && val, value_flags flags = preserve_source_value_flags)
{ {
using type = unwrap_node<remove_cvref<T>>; using type = unwrap_node<remove_cvref<T>>;
if constexpr (std::is_same_v<type, node> || is_node_view<type>) if constexpr (std::is_same_v<type, node> || is_node_view<type>)
@ -96,7 +92,7 @@ TOML_IMPL_NAMESPACE_START
template <typename T> template <typename T>
TOML_NODISCARD TOML_NODISCARD
auto* make_node(inserter<T> && val, value_flags flags = value_flags::none) auto* make_node(inserter<T> && val, value_flags flags = preserve_source_value_flags)
{ {
return make_node(static_cast<T&&>(val.value), flags); return make_node(static_cast<T&&>(val.value), flags);
} }

View File

@ -81,22 +81,19 @@ TOML_ANON_NAMESPACE_START
position_ += 3u; position_ += 3u;
} }
TOML_NODISCARD TOML_PURE_INLINE_GETTER
TOML_ALWAYS_INLINE
constexpr bool eof() const noexcept constexpr bool eof() const noexcept
{ {
return position_ >= source_.length(); return position_ >= source_.length();
} }
TOML_NODISCARD TOML_PURE_INLINE_GETTER
TOML_ALWAYS_INLINE
constexpr bool peek_eof() const noexcept constexpr bool peek_eof() const noexcept
{ {
return eof(); return eof();
} }
TOML_NODISCARD TOML_CONST_INLINE_GETTER
TOML_ALWAYS_INLINE
constexpr bool error() const noexcept constexpr bool error() const noexcept
{ {
return false; return false;
@ -138,14 +135,12 @@ TOML_ANON_NAMESPACE_START
} }
TOML_NODISCARD TOML_NODISCARD
TOML_ALWAYS_INLINE
bool eof() const noexcept bool eof() const noexcept
{ {
return source_->eof(); return source_->eof();
} }
TOML_NODISCARD TOML_NODISCARD
TOML_ALWAYS_INLINE
bool peek_eof() const bool peek_eof() const
{ {
using stream_traits = typename std::remove_pointer_t<decltype(source_)>::traits_type; using stream_traits = typename std::remove_pointer_t<decltype(source_)>::traits_type;
@ -153,7 +148,6 @@ TOML_ANON_NAMESPACE_START
} }
TOML_NODISCARD TOML_NODISCARD
TOML_ALWAYS_INLINE
bool error() const noexcept bool error() const noexcept
{ {
return !(*source_); return !(*source_);
@ -175,21 +169,19 @@ TOML_ANON_NAMESPACE_START
char bytes[4]; char bytes[4];
source_position position; source_position position;
TOML_NODISCARD TOML_PURE_GETTER
std::string_view as_view() const noexcept std::string_view as_view() const noexcept
{ {
return bytes[3] ? std::string_view{ bytes, 4u } : std::string_view{ bytes }; return bytes[3] ? std::string_view{ bytes, 4u } : std::string_view{ bytes };
} }
TOML_NODISCARD TOML_PURE_GETTER
TOML_ATTR(pure)
constexpr operator const char32_t&() const noexcept constexpr operator const char32_t&() const noexcept
{ {
return value; return value;
} }
TOML_NODISCARD TOML_PURE_GETTER
TOML_ATTR(pure)
constexpr const char32_t& operator*() const noexcept constexpr const char32_t& operator*() const noexcept
{ {
return value; return value;
@ -3025,9 +3017,9 @@ TOML_IMPL_NAMESPACE_START
{ {
// table arrays are a special case; // table arrays are a special case;
// the spec dictates we select the most recently declared element in the array. // the spec dictates we select the most recently declared element in the array.
TOML_ASSERT(!child->ref_cast<array>().elements.empty()); TOML_ASSERT(!child->ref_cast<array>().elems_.empty());
TOML_ASSERT(child->ref_cast<array>().elements.back()->is_table()); TOML_ASSERT(child->ref_cast<array>().elems_.back()->is_table());
parent = &child->ref_cast<array>().elements.back()->ref_cast<table>(); parent = &child->ref_cast<array>().elems_.back()->ref_cast<table>();
} }
else else
{ {
@ -3060,9 +3052,9 @@ TOML_IMPL_NAMESPACE_START
table_arrays.push_back(tab_arr); table_arrays.push_back(tab_arr);
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() }; tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
tab_arr->elements.emplace_back(new table{}); tab_arr->elems_.emplace_back(new table{});
tab_arr->elements.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() }; tab_arr->elems_.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elements.back()->ref_cast<table>(); return &tab_arr->elems_.back()->ref_cast<table>();
} }
// otherwise we're just making a table // otherwise we're just making a table
@ -3084,9 +3076,9 @@ TOML_IMPL_NAMESPACE_START
&& impl::find(table_arrays.begin(), table_arrays.end(), &matching_node->ref_cast<array>())) && impl::find(table_arrays.begin(), table_arrays.end(), &matching_node->ref_cast<array>()))
{ {
auto tab_arr = &matching_node->ref_cast<array>(); auto tab_arr = &matching_node->ref_cast<array>();
tab_arr->elements.emplace_back(new table{}); tab_arr->elems_.emplace_back(new table{});
tab_arr->elements.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() }; tab_arr->elems_.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elements.back()->ref_cast<table>(); return &tab_arr->elems_.back()->ref_cast<table>();
} }
else if (!is_arr && matching_node->is_table() && !implicit_tables.empty()) else if (!is_arr && matching_node->is_table() && !implicit_tables.empty())
@ -3264,7 +3256,7 @@ TOML_IMPL_NAMESPACE_START
{ {
auto& arr = nde.ref_cast<array>(); auto& arr = nde.ref_cast<array>();
auto end = nde.source_.end; auto end = nde.source_.end;
for (auto& v : arr.elements) for (auto& v : arr.elems_)
{ {
update_region_ends(*v); update_region_ends(*v);
if (end < v->source_.end) if (end < v->source_.end)
@ -3328,7 +3320,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
node_ptr arr{ new array{} }; node_ptr arr{ new array{} };
auto& vals = reinterpret_cast<array*>(arr.get())->elements; auto& vals = reinterpret_cast<array*>(arr.get())->elems_;
enum parse_elem : int enum parse_elem : int
{ {
none, none,

View File

@ -159,21 +159,21 @@ TOML_IMPL_NAMESPACE_START
template <typename V> template <typename V>
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
table_init_pair(std::string&& k, V&& v, value_flags flags = value_flags::none) // table_init_pair(std::string&& k, V&& v, value_flags flags = preserve_source_value_flags) //
: key{ std::move(k) }, : key{ std::move(k) },
value{ make_node(static_cast<V&&>(v), flags) } value{ make_node(static_cast<V&&>(v), flags) }
{} {}
template <typename V> template <typename V>
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
table_init_pair(std::string_view k, V&& v, value_flags flags = value_flags::none) // table_init_pair(std::string_view k, V&& v, value_flags flags = preserve_source_value_flags) //
: key{ k }, : key{ k },
value{ make_node(static_cast<V&&>(v), flags) } value{ make_node(static_cast<V&&>(v), flags) }
{} {}
template <typename V> template <typename V>
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
table_init_pair(const char* k, V&& v, value_flags flags = value_flags::none) // table_init_pair(const char* k, V&& v, value_flags flags = preserve_source_value_flags) //
: key{ k }, : key{ k },
value{ make_node(static_cast<V&&>(v), flags) } value{ make_node(static_cast<V&&>(v), flags) }
{} {}
@ -182,21 +182,21 @@ TOML_IMPL_NAMESPACE_START
template <typename V> template <typename V>
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
table_init_pair(std::wstring&& k, V&& v, value_flags flags = value_flags::none) // table_init_pair(std::wstring&& k, V&& v, value_flags flags = preserve_source_value_flags) //
: key{ narrow(k) }, : key{ narrow(k) },
value{ make_node(static_cast<V&&>(v), flags) } value{ make_node(static_cast<V&&>(v), flags) }
{} {}
template <typename V> template <typename V>
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
table_init_pair(std::wstring_view k, V&& v, value_flags flags = value_flags::none) // table_init_pair(std::wstring_view k, V&& v, value_flags flags = preserve_source_value_flags) //
: key{ narrow(k) }, : key{ narrow(k) },
value{ make_node(static_cast<V&&>(v), flags) } value{ make_node(static_cast<V&&>(v), flags) }
{} {}
template <typename V> template <typename V>
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
table_init_pair(const wchar_t* k, V&& v, value_flags flags = value_flags::none) // table_init_pair(const wchar_t* k, V&& v, value_flags flags = preserve_source_value_flags) //
: key{ narrow(std::wstring_view{ k }) }, : key{ narrow(std::wstring_view{ k }) },
value{ make_node(static_cast<V&&>(v), flags) } value{ make_node(static_cast<V&&>(v), flags) }
{} {}
@ -652,9 +652,6 @@ TOML_NAMESPACE_START
/// \param val The new value to insert. /// \param val The new value to insert.
/// \param flags Value flags to apply to new values. /// \param flags Value flags to apply to new values.
/// ///
/// \note When `flags == value_flags::none` and `val` is a value node or node_view, any existing value
/// flags will be copied, _not_ set to none.
///
/// \returns \conditional_return{Valid input} /// \returns \conditional_return{Valid input}
/// <ul> /// <ul>
/// <li>An iterator to the insertion position (or the position of the value that prevented insertion) /// <li>An iterator to the insertion position (or the position of the value that prevented insertion)
@ -669,7 +666,9 @@ TOML_NAMESPACE_START
TOML_CONSTRAINED_TEMPLATE((std::is_convertible_v<KeyType&&, std::string_view> || impl::is_wide_string<KeyType>), TOML_CONSTRAINED_TEMPLATE((std::is_convertible_v<KeyType&&, std::string_view> || impl::is_wide_string<KeyType>),
typename KeyType, typename KeyType,
typename ValueType) typename ValueType)
std::pair<iterator, bool> insert(KeyType&& key, ValueType&& val, value_flags flags = value_flags::none) std::pair<iterator, bool> insert(KeyType&& key,
ValueType&& val,
value_flags flags = preserve_source_value_flags)
{ {
static_assert( static_assert(
!impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT, !impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT,
@ -740,15 +739,12 @@ TOML_NAMESPACE_START
/// \param last An iterator to one-past-the-last value in the input collection. /// \param last An iterator to one-past-the-last value in the input collection.
/// \param flags Value flags to apply to new values. /// \param flags Value flags to apply to new values.
/// ///
/// \note When `flags == value_flags::none` and a source value is a value node or node_view, any existing value
/// flags will be copied, _not_ set to none.
///
/// \remarks This function is morally equivalent to calling `insert(key, value)` for each /// \remarks This function is morally equivalent to calling `insert(key, value)` for each
/// key-value pair covered by the iterator range, so any values with keys already found in the /// key-value pair covered by the iterator range, so any values with keys already found in the
/// table will not be replaced. /// table will not be replaced.
TOML_CONSTRAINED_TEMPLATE((!std::is_convertible_v<Iter, std::string_view> && !impl::is_wide_string<Iter>), TOML_CONSTRAINED_TEMPLATE((!std::is_convertible_v<Iter, std::string_view> && !impl::is_wide_string<Iter>),
typename Iter) typename Iter)
void insert(Iter first, Iter last, value_flags flags = value_flags::none) void insert(Iter first, Iter last, value_flags flags = preserve_source_value_flags)
{ {
if (first == last) if (first == last)
return; return;
@ -803,9 +799,6 @@ TOML_NAMESPACE_START
/// \param val The value to insert/assign. /// \param val The value to insert/assign.
/// \param flags Value flags to apply to new values. /// \param flags Value flags to apply to new values.
/// ///
/// \note When `flags == value_flags::none` and `val` is a value node or node_view, any existing value
/// flags will be copied, _not_ set to none.
///
/// \returns \conditional_return{Valid input} /// \returns \conditional_return{Valid input}
/// <ul> /// <ul>
/// <li>An iterator to the value's position /// <li>An iterator to the value's position
@ -820,7 +813,7 @@ TOML_NAMESPACE_START
template <typename KeyType, typename ValueType> template <typename KeyType, typename ValueType>
std::pair<iterator, bool> insert_or_assign(KeyType&& key, std::pair<iterator, bool> insert_or_assign(KeyType&& key,
ValueType&& val, ValueType&& val,
value_flags flags = value_flags::none) value_flags flags = preserve_source_value_flags)
{ {
static_assert( static_assert(
!impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT, !impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT,

View File

@ -13,6 +13,8 @@
#include "impl/preprocessor.h" #include "impl/preprocessor.h"
TOML_PUSH_WARNINGS; TOML_PUSH_WARNINGS;
TOML_DISABLE_SPAM_WARNINGS;
TOML_DISABLE_SWITCH_WARNINGS;
#if TOML_MSVC #if TOML_MSVC
#pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch (false-positive) #pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch (false-positive)
#elif TOML_CLANG && !TOML_HEADER_ONLY && TOML_IMPLEMENTATION #elif TOML_CLANG && !TOML_HEADER_ONLY && TOML_IMPLEMENTATION

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="toml::v2::date"> <Type Name="toml::v3::date">
<Intrinsic Name="y" Expression="(int)year" /> <Intrinsic Name="y" Expression="(int)year" />
<Intrinsic Name="m" Expression="(int)month" /> <Intrinsic Name="m" Expression="(int)month" />
<Intrinsic Name="d" Expression="(int)day" /> <Intrinsic Name="d" Expression="(int)day" />
@ -20,7 +20,7 @@
</Expand> </Expand>
</Type> </Type>
<Type Name="toml::v2::time"> <Type Name="toml::v3::time">
<Intrinsic Name="h" Expression="(int)hour" /> <Intrinsic Name="h" Expression="(int)hour" />
<Intrinsic Name="m" Expression="(int)minute" /> <Intrinsic Name="m" Expression="(int)minute" />
<Intrinsic Name="s" Expression="(int)(second + (int)(nanosecond / 1000000000.0))" /> <Intrinsic Name="s" Expression="(int)(second + (int)(nanosecond / 1000000000.0))" />
@ -40,7 +40,7 @@
</Expand> </Expand>
</Type> </Type>
<Type Name="toml::v2::time_offset"> <Type Name="toml::v3::time_offset">
<Intrinsic Name="absmin" Expression="((int)minutes ^ ((int)minutes >> 31)) - ((int)minutes >> 31)" /> <Intrinsic Name="absmin" Expression="((int)minutes ^ ((int)minutes >> 31)) - ((int)minutes >> 31)" />
<Intrinsic Name="h" Expression="absmin() / 60u" /> <Intrinsic Name="h" Expression="absmin() / 60u" />
<Intrinsic Name="m" Expression="absmin() % 60u" /> <Intrinsic Name="m" Expression="absmin() % 60u" />
@ -58,7 +58,8 @@
</Expand> </Expand>
</Type> </Type>
<Type Name="toml::v2::stdopt::date_time"> <Type Name="toml::v3::stdopt::date_time">
<AlternativeType Name="toml::v3::custopt::date_time" />
<DisplayString Condition="offset._Has_value">{date}T{time}{offset}</DisplayString> <DisplayString Condition="offset._Has_value">{date}T{time}{offset}</DisplayString>
<DisplayString>{date}T{time}</DisplayString> <DisplayString>{date}T{time}</DisplayString>
<Expand> <Expand>
@ -68,21 +69,21 @@
</Expand> </Expand>
</Type> </Type>
<Type Name="toml::v2::value&lt;*&gt;" Priority="MediumLow"> <Type Name="toml::v3::value&lt;*&gt;" Priority="MediumLow">
<DisplayString>{{ {val_} }}</DisplayString> <DisplayString>{{ {val_} }}</DisplayString>
<Expand> <Expand>
<Item Name="val_" ExcludeView="simple">val_</Item> <Item Name="val_" ExcludeView="simple">val_</Item>
</Expand> </Expand>
</Type> </Type>
<Type Name="toml::v2::value&lt;std::basic_string&lt;char,*&gt;&gt;"> <Type Name="toml::v3::value&lt;std::basic_string&lt;char,*&gt;&gt;">
<DisplayString>{{ {val_,s8} }}</DisplayString> <DisplayString>{{ {val_,s8} }}</DisplayString>
<Expand> <Expand>
<Item Name="val_" ExcludeView="simple">val_,s8</Item> <Item Name="val_" ExcludeView="simple">val_,s8</Item>
</Expand> </Expand>
</Type> </Type>
<Type Name="toml::v2::source_position"> <Type Name="toml::v3::source_position">
<DisplayString>line {line}, column {column}</DisplayString> <DisplayString>line {line}, column {column}</DisplayString>
<Expand> <Expand>
<Item Name="line" ExcludeView="simple">line</Item> <Item Name="line" ExcludeView="simple">line</Item>
@ -90,17 +91,13 @@
</Expand> </Expand>
</Type> </Type>
<Type Name="toml::v2::impl::utf8_codepoint"> <Type Name="toml::v3::table">
<DisplayString>{&amp;bytes,s8} ({position})</DisplayString> <DisplayString>{map_}</DisplayString>
</Type>
<Type Name="toml::v2::table">
<DisplayString>{map}</DisplayString>
<Expand> <Expand>
<!-- Modified from std::map visualizer in VS 2019 stl.natvis --> <!-- Modified from std::map visualizer in VS 2019 stl.natvis -->
<TreeItems> <TreeItems>
<Size>map._Mypair._Myval2._Myval2._Mysize</Size> <Size>map_._Mypair._Myval2._Myval2._Mysize</Size>
<HeadPointer>map._Mypair._Myval2._Myval2._Myhead-&gt;_Parent</HeadPointer> <HeadPointer>map_._Mypair._Myval2._Myval2._Myhead-&gt;_Parent</HeadPointer>
<LeftPointer>_Left</LeftPointer> <LeftPointer>_Left</LeftPointer>
<RightPointer>_Right</RightPointer> <RightPointer>_Right</RightPointer>
<ValueNode Condition="_Isnil == 0" Name="[{_Myval.first,s8}]">*_Myval.second</ValueNode> <ValueNode Condition="_Isnil == 0" Name="[{_Myval.first,s8}]">*_Myval.second</ValueNode>
@ -108,31 +105,31 @@
</Expand> </Expand>
</Type> </Type>
<Type Name="toml::v2::array"> <Type Name="toml::v3::array">
<DisplayString>{elements}</DisplayString> <DisplayString>{elems_}</DisplayString>
<Expand> <Expand>
<!-- Modified from std::vector visualizer in VS 2019 stl.natvis --> <!-- Modified from std::vector visualizer in VS 2019 stl.natvis -->
<IndexListItems> <IndexListItems>
<Size>elements._Mypair._Myval2._Mylast - elements._Mypair._Myval2._Myfirst</Size> <Size>elems_._Mypair._Myval2._Mylast - elems_._Mypair._Myval2._Myfirst</Size>
<ValueNode>*elements._Mypair._Myval2._Myfirst[$i]</ValueNode> <ValueNode>*elems_._Mypair._Myval2._Myfirst[$i]</ValueNode>
</IndexListItems> </IndexListItems>
</Expand> </Expand>
</Type> </Type>
<Type Name="toml::v2::noex::parse_error"> <Type Name="toml::v3::noex::parse_error">
<DisplayString>line {source_.begin.line}: {description_,s8b}</DisplayString> <DisplayString>line {source_.begin.line}: {description_,s8b}</DisplayString>
</Type> </Type>
<Type Name="toml::v2::ex::parse_error"> <Type Name="toml::v3::ex::parse_error">
<DisplayString>line {source_.begin.line}: {_Data._What,s8b}</DisplayString> <DisplayString>line {source_.begin.line}: {_Data._What,s8b}</DisplayString>
</Type> </Type>
<Type Name="toml::v2::noex::parse_result"> <Type Name="toml::v3::noex::parse_result">
<DisplayString Condition="!err_">{*reinterpret_cast&lt;toml::v2::table*&gt;(&amp;storage_.bytes)}</DisplayString> <DisplayString Condition="!err_">{*reinterpret_cast&lt;toml::v3::table*&gt;(&amp;storage_.bytes)}</DisplayString>
<DisplayString Condition="err_">{*reinterpret_cast&lt;toml::v2::noex::parse_error*&gt;(&amp;storage_.bytes)}</DisplayString> <DisplayString Condition="err_">{*reinterpret_cast&lt;toml::v3::noex::parse_error*&gt;(&amp;storage_.bytes)}</DisplayString>
<Expand> <Expand>
<Item Name="[table]" Condition="!err_">*reinterpret_cast&lt;toml::v2::table*&gt;(&amp;storage_.bytes)</Item> <Item Name="[table]" Condition="!err_">*reinterpret_cast&lt;toml::v3::table*&gt;(&amp;storage_.bytes)</Item>
<Item Name="[error]" Condition="err_">*reinterpret_cast&lt;toml::v2::noex::parse_error*&gt;(&amp;storage_.bytes)</Item> <Item Name="[error]" Condition="err_">*reinterpret_cast&lt;toml::v3::noex::parse_error*&gt;(&amp;storage_.bytes)</Item>
</Expand> </Expand>
</Type> </Type>

View File

@ -82,6 +82,10 @@
<None Include=".clang-format" /> <None Include=".clang-format" />
<None Include=".editorconfig" /> <None Include=".editorconfig" />
<None Include=".gitattributes" /> <None Include=".gitattributes" />
<None Include=".github\ISSUE_TEMPLATE\bug_report.md" />
<None Include=".github\ISSUE_TEMPLATE\config.yml" />
<None Include=".github\ISSUE_TEMPLATE\feature_request.md" />
<None Include=".github\pull_request_template.md" />
<None Include=".gitignore" /> <None Include=".gitignore" />
<None Include=".runsettings" /> <None Include=".runsettings" />
<None Include="CODE_OF_CONDUCT.md" /> <None Include="CODE_OF_CONDUCT.md" />

View File

@ -183,6 +183,18 @@
<None Include="include\toml++\impl\node_view_extern.inl"> <None Include="include\toml++\impl\node_view_extern.inl">
<Filter>include\impl</Filter> <Filter>include\impl</Filter>
</None> </None>
<None Include=".github\pull_request_template.md">
<Filter>.github</Filter>
</None>
<None Include=".github\ISSUE_TEMPLATE\bug_report.md">
<Filter>.github</Filter>
</None>
<None Include=".github\ISSUE_TEMPLATE\config.yml">
<Filter>.github</Filter>
</None>
<None Include=".github\ISSUE_TEMPLATE\feature_request.md">
<Filter>.github</Filter>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include=".circleci"> <Filter Include=".circleci">
@ -206,6 +218,9 @@
<Filter Include="include\impl"> <Filter Include="include\impl">
<UniqueIdentifier>{4e42aaa3-98cd-4678-9c1c-ffa3eaf519d7}</UniqueIdentifier> <UniqueIdentifier>{4e42aaa3-98cd-4678-9c1c-ffa3eaf519d7}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include=".github">
<UniqueIdentifier>{e3ab5e86-e053-48a6-9fee-f6442a63aaa6}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Natvis Include="toml++.natvis" /> <Natvis Include="toml++.natvis" />

337
toml.hpp

File diff suppressed because it is too large Load Diff

View File

@ -78,30 +78,29 @@ def main():
# strip various things: # strip various things:
if 1: if 1:
for i in range(3):
# trailing whitespace # trailing whitespace
toml_h = re.sub('([^ \t])[ \t]+\n', r'\1\n', toml_h) toml_h = re.sub('([^ \t])[ \t]+\n', r'\1\n', toml_h)
# explicit 'strip this' blocks # explicit 'strip this' blocks
toml_h = re.sub(r'(?:\n[ \t]*)?//[#!][ \t]*[{][{].*?//[#!][ \t]*[}][}].*?\n', '\n', toml_h, flags=re.S) toml_h = re.sub(r'(?:\n[ \t]*)?//[#!][ \t]*[{][{].*?//[#!][ \t]*[}][}].*?\n', '\n', toml_h, flags=re.S)
# spdx license identifiers # spdx license identifiers
toml_h = re.sub(r'^\s*//\s*SPDX-License-Identifier:.+?$', '', toml_h, 0, re.I | re.M) toml_h = re.sub(r'^\s*//\s*SPDX-License-Identifier:.+?$', '', toml_h, 0, re.I | re.M)
# double blank lines
toml_h = re.sub('\n(?:[ \t]*\n[ \t]*)+\n', '\n\n', toml_h)
# magic comments # magic comments
blank_line = r'(?:[ \t]*\n)' blank_line = r'(?:[ \t]*\n)'
comment_line = r'(?:[ \t]*//(?:[/#!<]| ?(?:---|===|\^\^\^|vvv))[^\n]*\n)' comment_line = r'(?:[ \t]*//(?:[/#!<]| ?(?:---|===|\^\^\^|vvv))[^\n]*\n)'
toml_h = re.sub(rf'\n{comment_line}{blank_line}+{comment_line}', '\n', toml_h) toml_h = re.sub(rf'\n{comment_line}{blank_line}+{comment_line}', '\n', toml_h)
toml_h = re.sub(rf'([{{,])\s*\n(?:{comment_line}|{blank_line})+', r'\1\n', toml_h) toml_h = re.sub(rf'([{{,])\s*\n(?:{comment_line}|{blank_line})+', r'\1\n', toml_h)
toml_h = re.sub(rf'{comment_line}+', '\n', toml_h) toml_h = re.sub(rf'{comment_line}+', '\n', toml_h)
# trailing whitespace
toml_h = re.sub('([^ \t])[ \t]+\n', r'\1\n', toml_h)
# enable warnings -> disable warnings
toml_h = re.sub('(TOML_ENABLE_WARNINGS;)\n[ \t\n]*\n(TOML_DISABLE_WARNINGS;)', r'', toml_h)
# blank lines between consecutive TOML_DISABLE_XXXXX_WARNINGS statements
toml_h = re.sub('(TOML_(?:PUSH|DISABLE_[A-Z_]+?)WARNINGS;)\n[ \t\n]*\n(TOML_DISABLE_[A-Z_]+?WARNINGS;)', r'\1\n\2', toml_h)
# blank lines between consecutive #includes
toml_h = re.sub('[#]\s*include\s*<(.+?)>\n[ \t\n]*\n[#]\s*include\s*<(.+?)>', r'#include <\1>\n#include <\2>', toml_h)
# double blank lines
toml_h = re.sub('\n(?:[ \t]*\n[ \t]*)+\n', '\n\n', toml_h)
# weird spacing edge case between } and pp directives # weird spacing edge case between } and pp directives
toml_h = re.sub('\n[}]\n#', r'\n}\n\n#', toml_h, re.S) toml_h = re.sub('\n[}]\n#', r'\n}\n\n#', toml_h, re.S)
# enable warnings -> disable warnings
toml_h = re.sub('(TOML_ENABLE_WARNINGS;)\n[ \t\n]*\n(TOML_DISABLE_WARNINGS;)', r'', toml_h)
# blank lines between consecutive TOML_XXXXX_WARNINGS statements
toml_h = re.sub('(TOML_[A-Z_]+?_WARNINGS;)\n[ \t\n]*\n(TOML_[A-Z_]+?_WARNINGS;)', r'\1\n\2', toml_h)
# blank lines between consecutive #includes
toml_h = re.sub('[#]\s*include\s*<(.+?)>\n[ \t\n]*\n[#]\s*include\s*<(.+?)>', r'#include <\1>\n#include <\2>', toml_h)
# blank lines following opening brackets or a comma # blank lines following opening brackets or a comma
toml_h = re.sub(r'([^@][({,])\n\n', r'\1\n', toml_h) toml_h = re.sub(r'([^@][({,])\n\n', r'\1\n', toml_h)
# blank lines preceeding closing brackets # blank lines preceeding closing brackets