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.
Please DO NOT delete this template and roll your own!
Please don't delete this template and roll your own!
Thanks for contributing!
-->

View File

@ -9,7 +9,7 @@ assignees: marzer
<!--
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!
-->

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:
- The single-header file `toml.hpp` is generated by a script; make your changes in the files in
`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
(Visual Studio 2019). All three is a bonus.
- Your changes should compile warning-free on at least one of:
- 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).
<br>

View File

@ -249,7 +249,7 @@ TOML_NAMESPACE_START
/// \cond
friend class TOML_PARSER_TYPENAME;
std::vector<std::unique_ptr<node>> elements;
std::vector<std::unique_ptr<node>> elems_;
TOML_API
void preinsertion_resize(size_t idx, size_t count);
@ -262,7 +262,7 @@ TOML_NAMESPACE_START
if (!val)
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
@ -363,11 +363,11 @@ TOML_NAMESPACE_START
TOML_NODISCARD_CTOR
explicit array(ElemType&& val, ElemTypes&&... vals)
{
elements.reserve(sizeof...(ElemTypes) + 1u);
emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), value_flags::none);
elems_.reserve(sizeof...(ElemTypes) + 1u);
emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), preserve_source_value_flags);
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
@ -442,130 +442,130 @@ TOML_NAMESPACE_START
TOML_NODISCARD
node& operator[](size_t index) noexcept
{
return *elements[index];
return *elems_[index];
}
/// \brief Gets a reference to the element at a specific index.
TOML_NODISCARD
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.
TOML_NODISCARD
node& front() noexcept
{
return *elements.front();
return *elems_.front();
}
/// \brief Returns a reference to the first element in the array.
TOML_NODISCARD
const node& front() const noexcept
{
return *elements.front();
return *elems_.front();
}
/// \brief Returns a reference to the last element in the array.
TOML_NODISCARD
node& back() noexcept
{
return *elements.back();
return *elems_.back();
}
/// \brief Returns a reference to the last element in the array.
TOML_NODISCARD
const node& back() const noexcept
{
return *elements.back();
return *elems_.back();
}
/// \brief Returns an iterator to the first element.
TOML_NODISCARD
iterator begin() noexcept
{
return { elements.begin() };
return { elems_.begin() };
}
/// \brief Returns an iterator to the first element.
TOML_NODISCARD
const_iterator begin() const noexcept
{
return { elements.cbegin() };
return { elems_.cbegin() };
}
/// \brief Returns an iterator to the first element.
TOML_NODISCARD
const_iterator cbegin() const noexcept
{
return { elements.cbegin() };
return { elems_.cbegin() };
}
/// \brief Returns an iterator to one-past-the-last element.
TOML_NODISCARD
iterator end() noexcept
{
return { elements.end() };
return { elems_.end() };
}
/// \brief Returns an iterator to one-past-the-last element.
TOML_NODISCARD
const_iterator end() const noexcept
{
return { elements.cend() };
return { elems_.cend() };
}
/// \brief Returns an iterator to one-past-the-last element.
TOML_NODISCARD
const_iterator cend() const noexcept
{
return { elements.cend() };
return { elems_.cend() };
}
/// \brief Returns true if the array is empty.
TOML_NODISCARD
bool empty() const noexcept
{
return elements.empty();
return elems_.empty();
}
/// \brief Returns the number of elements in the array.
TOML_NODISCARD
size_t size() const noexcept
{
return elements.size();
return elems_.size();
}
/// \brief Reserves internal storage capacity up to a pre-determined number of elements.
void reserve(size_t new_capacity)
{
elements.reserve(new_capacity);
elems_.reserve(new_capacity);
}
/// \brief Removes all elements from the array.
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.
TOML_NODISCARD
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.
TOML_NODISCARD
size_t capacity() const noexcept
{
return elements.capacity();
return elems_.capacity();
}
/// \brief Requests the removal of any unused internal storage capacity.
void shrink_to_fit()
{
elements.shrink_to_fit();
elems_.shrink_to_fit();
}
/// \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 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}
/// An iterator to the newly-inserted element.
/// \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,
/// because no insertion can take place. This is the only circumstance in which this can occur.
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 (!val)
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.
@ -638,9 +635,6 @@ TOML_NAMESPACE_START
/// \param val The node or value being inserted.
/// \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}
/// An iterator to the newly-inserted element.
/// \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,
/// because no insertion can take place. This is the only circumstance in which this can occur.
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>)
{
@ -660,19 +657,19 @@ TOML_NAMESPACE_START
}
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);
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);
size_t i = start_idx;
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
elements[i].reset(impl::make_node(static_cast<ElemType&&>(val), flags));
return { elements.begin() + static_cast<ptrdiff_t>(start_idx) };
elems_[i].reset(impl::make_node(static_cast<ElemType&&>(val), flags));
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 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}
/// An iterator to the first newly-inserted element.
/// \conditional_return{first >= last}
@ -695,11 +689,11 @@ TOML_NAMESPACE_START
/// \conditional_return{All objects in the range were empty toml::node_views}
/// A copy of pos
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);
if (distance <= 0)
return { elements.begin() + (pos.raw_ - elements.cbegin()) };
return { elems_.begin() + (pos.raw_ - elems_.cbegin()) };
else
{
auto count = distance;
@ -710,9 +704,9 @@ TOML_NAMESPACE_START
if (!(*it))
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));
size_t i = start_idx;
for (auto it = first; it != last; it++)
@ -723,11 +717,11 @@ TOML_NAMESPACE_START
continue;
}
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
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 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}
/// An iterator to the first newly-inserted element.
/// \conditional_return{Input list is empty}
@ -751,7 +742,7 @@ TOML_NAMESPACE_START
template <typename ElemType>
iterator insert(const_iterator pos,
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);
}
@ -787,7 +778,7 @@ TOML_NAMESPACE_START
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 { 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.
@ -811,7 +802,7 @@ TOML_NAMESPACE_START
/// \returns Iterator to the first element immediately following the removed element.
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.
@ -836,7 +827,7 @@ TOML_NAMESPACE_START
/// \returns Iterator to the first element immediately following the last removed element.
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.
@ -873,11 +864,11 @@ TOML_NAMESPACE_START
"The default element type argument to toml::array::resize may not be toml::node_view.");
if (!new_size)
elements.clear();
else if (new_size < elements.size())
elements.resize(new_size);
else if (new_size > elements.size())
insert(cend(), new_size - elements.size(), static_cast<ElemType&&>(default_init_val));
elems_.clear();
else if (new_size < elems_.size())
elems_.resize(new_size);
else if (new_size > elems_.size())
insert(cend(), new_size - elems_.size(), static_cast<ElemType&&>(default_init_val));
}
/// \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.
void truncate(size_t new_size)
{
if (new_size < elements.size())
elements.resize(new_size);
if (new_size < elems_.size())
elems_.resize(new_size);
}
/// \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 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.
/// This is the only circumstance in which this can occur.
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);
}
@ -968,14 +956,14 @@ TOML_NAMESPACE_START
"Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
auto nde = new impl::wrap_node<type>{ static_cast<Args&&>(args)... };
elements.emplace_back(nde);
elems_.emplace_back(nde);
return *nde;
}
/// \brief Removes the last element from the array.
void pop_back() noexcept
{
elements.pop_back();
elems_.pop_back();
}
/// \brief Gets the element at a specific index.
@ -1003,7 +991,7 @@ TOML_NAMESPACE_START
TOML_NODISCARD
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).
@ -1014,7 +1002,7 @@ TOML_NAMESPACE_START
TOML_NODISCARD
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.

View File

@ -46,9 +46,9 @@ TOML_NAMESPACE_START
array::array(const array& other) //
: node(other)
{
elements.reserve(other.elements.size());
elems_.reserve(other.elems_.size());
for (const auto& elem : other)
elements.emplace_back(impl::make_node(elem));
elems_.emplace_back(impl::make_node(elem));
#if TOML_LIFETIME_HOOKS
TOML_ARRAY_CREATED;
@ -58,7 +58,7 @@ TOML_NAMESPACE_START
TOML_EXTERNAL_LINKAGE
array::array(array && other) noexcept //
: node(std::move(other)),
elements{ std::move(other.elements) }
elems_{ std::move(other.elems_) }
{
#if TOML_LIFETIME_HOOKS
TOML_ARRAY_CREATED;
@ -71,10 +71,10 @@ TOML_NAMESPACE_START
if (&rhs != this)
{
node::operator=(rhs);
elements.clear();
elements.reserve(rhs.elements.size());
elems_.clear();
elems_.reserve(rhs.elems_.size());
for (const auto& elem : rhs)
elements.emplace_back(impl::make_node(elem));
elems_.emplace_back(impl::make_node(elem));
}
return *this;
}
@ -85,7 +85,7 @@ TOML_NAMESPACE_START
if (&rhs != this)
{
node::operator=(std::move(rhs));
elements = std::move(rhs.elements);
elems_ = std::move(rhs.elems_);
}
return *this;
}
@ -93,29 +93,29 @@ TOML_NAMESPACE_START
TOML_EXTERNAL_LINKAGE
void array::preinsertion_resize(size_t idx, size_t count)
{
TOML_ASSERT(idx <= elements.size());
TOML_ASSERT(idx <= elems_.size());
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 inserting_at_end = idx == old_size;
elements.resize(new_size);
elems_.resize(new_size);
if (!inserting_at_end)
{
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
bool array::is_homogeneous(node_type ntype) const noexcept
{
if (elements.empty())
if (elems_.empty())
return false;
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)
return false;
@ -125,13 +125,13 @@ TOML_NAMESPACE_START
TOML_EXTERNAL_LINKAGE
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
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
@ -139,17 +139,17 @@ TOML_NAMESPACE_START
{
if (&lhs == &rhs)
return true;
if (lhs.elements.size() != rhs.elements.size())
if (lhs.elems_.size() != rhs.elems_.size())
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 node& rhs_ = *rhs.elements[i];
const auto lhs_type = lhs.elems_[i]->type();
const node& rhs_ = *rhs.elems_[i];
const auto rhs_type = rhs_.type();
if (lhs_type != rhs_type)
return false;
const bool equal = lhs.elements[i]->visit(
const bool equal = lhs.elems_[i]->visit(
[&](const auto& lhs_) noexcept
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
if (!equal)
@ -162,9 +162,9 @@ TOML_NAMESPACE_START
size_t array::total_leaf_count() const noexcept
{
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 };
}
return leaves;
@ -175,29 +175,29 @@ TOML_NAMESPACE_START
{
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)
{
array& arr = *reinterpret_cast<array*>(child.elements[i].get());
array& arr = *reinterpret_cast<array*>(child.elems_[i].get());
if (!arr.empty())
flatten_child(std::move(arr), dest_index);
}
else
elements[dest_index++] = std::move(child.elements[i]);
elems_[dest_index++] = std::move(child.elems_[i]);
}
}
TOML_EXTERNAL_LINKAGE
array& array::flatten()&
{
if (elements.empty())
if (elems_.empty())
return *this;
bool requires_flattening = false;
size_t size_after_flattening = elements.size();
for (size_t i = elements.size(); i-- > 0u;)
size_t size_after_flattening = elems_.size();
for (size_t i = elems_.size(); i-- > 0u;)
{
auto arr = elements[i]->as_array();
auto arr = elems_[i]->as_array();
if (!arr)
continue;
size_after_flattening--; // discount the array itself
@ -208,25 +208,25 @@ TOML_NAMESPACE_START
size_after_flattening += leaf_count;
}
else
elements.erase(elements.cbegin() + static_cast<ptrdiff_t>(i));
elems_.erase(elems_.cbegin() + static_cast<ptrdiff_t>(i));
}
if (!requires_flattening)
return *this;
elements.reserve(size_after_flattening);
elems_.reserve(size_after_flattening);
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)
{
i++;
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();
if (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);
/// \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.
///
/// \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
{
template <typename T>
TOML_NODISCARD
TOML_ATTR(const)
TOML_ALWAYS_INLINE
TOML_CONST_INLINE_GETTER
constexpr std::underlying_type_t<T> unwrap_enum(T val) noexcept
{
return static_cast<std::underlying_type_t<T>>(val);
@ -886,8 +889,7 @@ TOML_IMPL_NAMESPACE_START
nan
};
TOML_NODISCARD
TOML_ATTR(pure)
TOML_PURE_GETTER
inline fp_class fpclassify(const double& val) noexcept
{
static_assert(sizeof(uint64_t) == sizeof(double));
@ -897,7 +899,7 @@ TOML_IMPL_NAMESPACE_START
static constexpr uint64_t mantissa = 0b0000000000001111111111111111111111111111111111111111111111111111ull;
uint64_t val_bits;
memcpy(&val_bits, &val, sizeof(val));
std::memcpy(&val_bits, &val, sizeof(val));
if ((val_bits & exponent) != exponent)
return fp_class::ok;
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.
// I don't want to impose such a heavy compile-time burden on users.
template <typename Iterator, typename T>
TOML_NODISCARD
TOML_PURE_GETTER
inline auto find(Iterator start, Iterator end, const T& needle) noexcept //
->decltype(&(*start))
{

View File

@ -4,5 +4,3 @@
#endif
//# }}
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>)
{
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
@ -63,17 +58,18 @@ TOML_IMPL_NAMESPACE_START
}
else
out = new value_type{ static_cast<T&&>(val) };
out->flags(flags);
}
if (flags != preserve_source_value_flags)
out->flags(flags);
return out;
}
}
template <typename T>
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>>;
if constexpr (std::is_same_v<type, node> || is_node_view<type>)
@ -96,7 +92,7 @@ TOML_IMPL_NAMESPACE_START
template <typename T>
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);
}

View File

@ -81,22 +81,19 @@ TOML_ANON_NAMESPACE_START
position_ += 3u;
}
TOML_NODISCARD
TOML_ALWAYS_INLINE
TOML_PURE_INLINE_GETTER
constexpr bool eof() const noexcept
{
return position_ >= source_.length();
}
TOML_NODISCARD
TOML_ALWAYS_INLINE
TOML_PURE_INLINE_GETTER
constexpr bool peek_eof() const noexcept
{
return eof();
}
TOML_NODISCARD
TOML_ALWAYS_INLINE
TOML_CONST_INLINE_GETTER
constexpr bool error() const noexcept
{
return false;
@ -138,14 +135,12 @@ TOML_ANON_NAMESPACE_START
}
TOML_NODISCARD
TOML_ALWAYS_INLINE
bool eof() const noexcept
{
return source_->eof();
}
TOML_NODISCARD
TOML_ALWAYS_INLINE
bool peek_eof() const
{
using stream_traits = typename std::remove_pointer_t<decltype(source_)>::traits_type;
@ -153,7 +148,6 @@ TOML_ANON_NAMESPACE_START
}
TOML_NODISCARD
TOML_ALWAYS_INLINE
bool error() const noexcept
{
return !(*source_);
@ -175,21 +169,19 @@ TOML_ANON_NAMESPACE_START
char bytes[4];
source_position position;
TOML_NODISCARD
TOML_PURE_GETTER
std::string_view as_view() const noexcept
{
return bytes[3] ? std::string_view{ bytes, 4u } : std::string_view{ bytes };
}
TOML_NODISCARD
TOML_ATTR(pure)
TOML_PURE_GETTER
constexpr operator const char32_t&() const noexcept
{
return value;
}
TOML_NODISCARD
TOML_ATTR(pure)
TOML_PURE_GETTER
constexpr const char32_t& operator*() const noexcept
{
return value;
@ -3025,9 +3017,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>().elements.empty());
TOML_ASSERT(child->ref_cast<array>().elements.back()->is_table());
parent = &child->ref_cast<array>().elements.back()->ref_cast<table>();
TOML_ASSERT(!child->ref_cast<array>().elems_.empty());
TOML_ASSERT(child->ref_cast<array>().elems_.back()->is_table());
parent = &child->ref_cast<array>().elems_.back()->ref_cast<table>();
}
else
{
@ -3060,9 +3052,9 @@ TOML_IMPL_NAMESPACE_START
table_arrays.push_back(tab_arr);
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
tab_arr->elements.emplace_back(new table{});
tab_arr->elements.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elements.back()->ref_cast<table>();
tab_arr->elems_.emplace_back(new table{});
tab_arr->elems_.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elems_.back()->ref_cast<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>()))
{
auto tab_arr = &matching_node->ref_cast<array>();
tab_arr->elements.emplace_back(new table{});
tab_arr->elements.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elements.back()->ref_cast<table>();
tab_arr->elems_.emplace_back(new table{});
tab_arr->elems_.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elems_.back()->ref_cast<table>();
}
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 end = nde.source_.end;
for (auto& v : arr.elements)
for (auto& v : arr.elems_)
{
update_region_ends(*v);
if (end < v->source_.end)
@ -3328,7 +3320,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
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
{
none,

View File

@ -159,21 +159,21 @@ TOML_IMPL_NAMESPACE_START
template <typename V>
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) },
value{ make_node(static_cast<V&&>(v), flags) }
{}
template <typename V>
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 },
value{ make_node(static_cast<V&&>(v), flags) }
{}
template <typename V>
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 },
value{ make_node(static_cast<V&&>(v), flags) }
{}
@ -182,21 +182,21 @@ TOML_IMPL_NAMESPACE_START
template <typename V>
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) },
value{ make_node(static_cast<V&&>(v), flags) }
{}
template <typename V>
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) },
value{ make_node(static_cast<V&&>(v), flags) }
{}
template <typename V>
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 }) },
value{ make_node(static_cast<V&&>(v), flags) }
{}
@ -652,9 +652,6 @@ TOML_NAMESPACE_START
/// \param val The new value to insert.
/// \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}
/// <ul>
/// <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>),
typename KeyType,
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(
!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 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
/// key-value pair covered by the iterator range, so any values with keys already found in the
/// table will not be replaced.
TOML_CONSTRAINED_TEMPLATE((!std::is_convertible_v<Iter, std::string_view> && !impl::is_wide_string<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)
return;
@ -803,9 +799,6 @@ TOML_NAMESPACE_START
/// \param val The value to insert/assign.
/// \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}
/// <ul>
/// <li>An iterator to the value's position
@ -820,7 +813,7 @@ TOML_NAMESPACE_START
template <typename KeyType, typename ValueType>
std::pair<iterator, bool> insert_or_assign(KeyType&& key,
ValueType&& val,
value_flags flags = value_flags::none)
value_flags flags = preserve_source_value_flags)
{
static_assert(
!impl::is_wide_string<KeyType> || TOML_WINDOWS_COMPAT,

View File

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

View File

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

View File

@ -82,6 +82,10 @@
<None Include=".clang-format" />
<None Include=".editorconfig" />
<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=".runsettings" />
<None Include="CODE_OF_CONDUCT.md" />

View File

@ -183,6 +183,18 @@
<None Include="include\toml++\impl\node_view_extern.inl">
<Filter>include\impl</Filter>
</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>
<Filter Include=".circleci">
@ -206,6 +218,9 @@
<Filter Include="include\impl">
<UniqueIdentifier>{4e42aaa3-98cd-4678-9c1c-ffa3eaf519d7}</UniqueIdentifier>
</Filter>
<Filter Include=".github">
<UniqueIdentifier>{e3ab5e86-e053-48a6-9fee-f6442a63aaa6}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Natvis Include="toml++.natvis" />

337
toml.hpp

File diff suppressed because it is too large Load Diff

View File

@ -78,34 +78,33 @@ def main():
# strip various things:
if 1:
# trailing whitespace
toml_h = re.sub('([^ \t])[ \t]+\n', r'\1\n', toml_h)
# explicit 'strip this' blocks
toml_h = re.sub(r'(?:\n[ \t]*)?//[#!][ \t]*[{][{].*?//[#!][ \t]*[}][}].*?\n', '\n', toml_h, flags=re.S)
# spdx license identifiers
toml_h = re.sub(r'^\s*//\s*SPDX-License-Identifier:.+?$', '', toml_h, 0, re.I | re.M)
# magic comments
blank_line = r'(?:[ \t]*\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'([{{,])\s*\n(?:{comment_line}|{blank_line})+', r'\1\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
toml_h = re.sub('\n[}]\n#', r'\n}\n\n#', toml_h, re.S)
# blank lines following opening brackets or a comma
toml_h = re.sub(r'([^@][({,])\n\n', r'\1\n', toml_h)
# blank lines preceeding closing brackets
toml_h = re.sub(r'\n\n([ \t]*[})])', r'\n\1', toml_h)
for i in range(3):
# trailing whitespace
toml_h = re.sub('([^ \t])[ \t]+\n', r'\1\n', toml_h)
# explicit 'strip this' blocks
toml_h = re.sub(r'(?:\n[ \t]*)?//[#!][ \t]*[{][{].*?//[#!][ \t]*[}][}].*?\n', '\n', toml_h, flags=re.S)
# spdx license identifiers
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
blank_line = r'(?:[ \t]*\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'([{{,])\s*\n(?:{comment_line}|{blank_line})+', r'\1\n', toml_h)
toml_h = re.sub(rf'{comment_line}+', '\n', toml_h)
# weird spacing edge case between } and pp directives
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
toml_h = re.sub(r'([^@][({,])\n\n', r'\1\n', toml_h)
# blank lines preceeding closing brackets
toml_h = re.sub(r'\n\n([ \t]*[})])', r'\n\1', toml_h)
# ensure only one trailing newline
toml_h = toml_h.strip() + '\n'