mirror of
https://github.com/marzer/tomlplusplus.git
synced 2024-09-04 14:09:11 +00:00
fixed strong exception guarantee edge-cases
also: - added `value` copy+move constructor overloads with flags override `table::ref()` now supports explicit ref categories and cv-qualifiers
This commit is contained in:
parent
32df34add2
commit
9066ac7d01
@ -22,8 +22,8 @@ code changes at callsites or in build systems are indicated with ⚠️.
|
||||
|
||||
#### Fixes:
|
||||
- ⚠️ fixed incorrect `noexcept` specifications on many functions
|
||||
- ⚠️ fixed `toml::table` init-list constructor requiring double-brackets
|
||||
- fixed `toml::json_formatter` not formatting inf and nan incorrectly
|
||||
- fixed `toml::table` init-list constructor requiring double-brackets
|
||||
- fixed `TOML_API` + extern templates causing linker errors in some circumstances
|
||||
- fixed an illegal table redefinition edge case (#112) (@python36)
|
||||
- fixed documentation issues
|
||||
@ -32,6 +32,7 @@ code changes at callsites or in build systems are indicated with ⚠️.
|
||||
- fixed missing `#include <utility>`
|
||||
- fixed missing `TOML_API` on interfaces
|
||||
- fixed parser not correctly round-tripping the format of binary and octal integers in some cases
|
||||
- fixed strong exception guarantee edge-cases in `toml::table` and `toml::array`
|
||||
|
||||
#### Additions:
|
||||
- added `operator->` to `toml::value` for class types
|
||||
@ -52,6 +53,7 @@ code changes at callsites or in build systems are indicated with ⚠️.
|
||||
- added `toml::table::emplace_hint()` (same semantics as `std::map::emplace_hint()`)
|
||||
- added `toml::table::lower_bound()` (same semantics as `std::map::lower_bound()`)
|
||||
- added `toml::table::prune()`
|
||||
- added `toml::value` copy+move constructor overloads with flags override
|
||||
- added `toml::yaml_formatter`
|
||||
- added `TOML_ENABLE_FORMATTERS` option
|
||||
- added clang's enum annotation attributes to all enums
|
||||
@ -70,6 +72,7 @@ code changes at callsites or in build systems are indicated with ⚠️.
|
||||
- ⚠️ renamed `TOML_PARSER` option to `TOML_ENABLE_PARSER` (`TOML_PARSER` will continue to work but is deprecated)
|
||||
- ⚠️ renamed `TOML_UNRELEASED_FEATURES` to `TOML_ENABLE_UNRELEASED_FEATURES` (`TOML_UNRELEASED_FEATURES` will continue to work but is deprecated)
|
||||
- ⚠️ renamed `TOML_WINDOWS_COMPAT` to `TOML_ENABLE_WINDOWS_COMPAT` (`TOML_WINDOWS_COMPAT` will continue to work but is deprecated)
|
||||
- `toml::table::ref()` now supports explicit ref categories and cv-qualifiers
|
||||
- applied clang-format to all the things 🎉️
|
||||
- improved performance of parser
|
||||
- made date/time constructors accept any integral types
|
||||
|
@ -21,31 +21,31 @@ TOML_IMPL_NAMESPACE_START
|
||||
template <bool>
|
||||
friend class array_iterator;
|
||||
|
||||
using raw_mutable_iterator = std::vector<node_ptr>::iterator;
|
||||
using raw_const_iterator = std::vector<node_ptr>::const_iterator;
|
||||
using raw_iterator = std::conditional_t<IsConst, raw_const_iterator, raw_mutable_iterator>;
|
||||
using mutable_vector_iterator = std::vector<node_ptr>::iterator;
|
||||
using const_vector_iterator = std::vector<node_ptr>::const_iterator;
|
||||
using vector_iterator = std::conditional_t<IsConst, const_vector_iterator, mutable_vector_iterator>;
|
||||
|
||||
mutable raw_iterator iter_;
|
||||
mutable vector_iterator iter_;
|
||||
|
||||
public:
|
||||
using value_type = std::conditional_t<IsConst, const node, node>;
|
||||
using reference = value_type&;
|
||||
using pointer = value_type*;
|
||||
using difference_type = ptrdiff_t;
|
||||
using iterator_category = typename std::iterator_traits<raw_iterator>::iterator_category;
|
||||
using iterator_category = typename std::iterator_traits<vector_iterator>::iterator_category;
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
array_iterator() noexcept = default;
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
array_iterator(raw_mutable_iterator raw) noexcept //
|
||||
: iter_{ raw }
|
||||
array_iterator(mutable_vector_iterator iter) noexcept //
|
||||
: iter_{ iter }
|
||||
{}
|
||||
|
||||
TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst)
|
||||
TOML_NODISCARD_CTOR
|
||||
array_iterator(raw_const_iterator raw) noexcept //
|
||||
: iter_{ raw }
|
||||
array_iterator(const_vector_iterator iter) noexcept //
|
||||
: iter_{ iter }
|
||||
{}
|
||||
|
||||
TOML_CONSTRAINED_TEMPLATE(C, bool C = IsConst)
|
||||
@ -98,7 +98,14 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
TOML_PURE_INLINE_GETTER
|
||||
operator const raw_iterator&() const noexcept
|
||||
operator const vector_iterator&() const noexcept
|
||||
{
|
||||
return iter_;
|
||||
}
|
||||
|
||||
TOML_CONSTRAINED_TEMPLATE(!C, bool C = IsConst)
|
||||
TOML_PURE_INLINE_GETTER
|
||||
operator const const_vector_iterator() const noexcept
|
||||
{
|
||||
return iter_;
|
||||
}
|
||||
@ -181,6 +188,17 @@ TOML_IMPL_NAMESPACE_START
|
||||
return *(iter_ + idx)->get();
|
||||
}
|
||||
};
|
||||
|
||||
struct array_init_elem
|
||||
{
|
||||
mutable node_ptr value;
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD_CTOR
|
||||
array_init_elem(T&& val, value_flags flags = preserve_source_value_flags) //
|
||||
: value{ make_node(static_cast<T&&>(val), flags) }
|
||||
{}
|
||||
};
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
@ -235,7 +253,6 @@ TOML_NAMESPACE_START
|
||||
/// arr.emplace_back<std::string>("ten");
|
||||
/// arr.emplace_back<toml::array>(11, 12.0);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -249,11 +266,29 @@ TOML_NAMESPACE_START
|
||||
private:
|
||||
/// \cond
|
||||
|
||||
std::vector<impl::node_ptr> elems_;
|
||||
using vector_type = std::vector<impl::node_ptr>;
|
||||
using vector_iterator = typename vector_type::iterator;
|
||||
using const_vector_iterator = typename vector_type::const_iterator;
|
||||
vector_type elems_;
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
TOML_API
|
||||
array(const impl::array_init_elem*, const impl::array_init_elem*);
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
array(std::false_type, std::initializer_list<impl::array_init_elem> elems) //
|
||||
: array{ elems.begin(), elems.end() }
|
||||
{}
|
||||
|
||||
TOML_API
|
||||
void preinsertion_resize(size_t idx, size_t count);
|
||||
|
||||
TOML_API
|
||||
void insert_at_back(impl::node_ptr&&);
|
||||
|
||||
TOML_API
|
||||
vector_iterator insert_at(const_vector_iterator, impl::node_ptr&&);
|
||||
|
||||
template <typename T>
|
||||
void emplace_back_if_not_empty_view(T&& val, value_flags flags)
|
||||
{
|
||||
@ -262,7 +297,7 @@ TOML_NAMESPACE_START
|
||||
if (!val)
|
||||
return;
|
||||
}
|
||||
elems_.emplace_back(impl::make_node(static_cast<T&&>(val), flags));
|
||||
insert_at_back(impl::make_node(static_cast<T&&>(val), flags));
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
@ -271,6 +306,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
TOML_API
|
||||
void flatten_child(array&& child, size_t& dest_index) noexcept;
|
||||
|
||||
/// \endcond
|
||||
|
||||
public:
|
||||
@ -316,14 +352,6 @@ TOML_NAMESPACE_START
|
||||
TOML_API
|
||||
array(array&& other) noexcept;
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
TOML_API
|
||||
array& operator=(const array&);
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
TOML_API
|
||||
array& operator=(array&& rhs) noexcept;
|
||||
|
||||
/// \brief Constructs an array with one or more initial elements.
|
||||
///
|
||||
/// \detail \cpp
|
||||
@ -361,18 +389,18 @@ TOML_NAMESPACE_START
|
||||
typename... ElemTypes)
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit array(ElemType&& val, ElemTypes&&... vals)
|
||||
{
|
||||
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), preserve_source_value_flags), ...);
|
||||
}
|
||||
: array{ std::false_type{},
|
||||
std::initializer_list<impl::array_init_elem>{ static_cast<ElemType&&>(val),
|
||||
static_cast<ElemTypes&&>(vals)... } }
|
||||
{}
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
#endif
|
||||
}
|
||||
/// \brief Copy-assignment operator.
|
||||
TOML_API
|
||||
array& operator=(const array&);
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
TOML_API
|
||||
array& operator=(array&& rhs) noexcept;
|
||||
|
||||
/// \name Type checks
|
||||
/// @{
|
||||
@ -401,13 +429,13 @@ TOML_NAMESPACE_START
|
||||
TOML_PURE_GETTER
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
static_assert(
|
||||
std::is_void_v<
|
||||
type> || ((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>),
|
||||
"The template type argument of array::is_homogeneous() must be void or one "
|
||||
"of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
return is_homogeneous(impl::node_type_of<type>);
|
||||
using unwrapped_type = impl::unwrap_node<impl::remove_cvref<ElemType>>;
|
||||
static_assert(std::is_void_v<unwrapped_type> //
|
||||
|| (impl::is_native<unwrapped_type> || impl::is_one_of<unwrapped_type, table, array>),
|
||||
"The template type argument of array::is_homogeneous() must be void or one "
|
||||
"of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
return is_homogeneous(impl::node_type_of<unwrapped_type>);
|
||||
}
|
||||
/// \endcond
|
||||
|
||||
@ -628,7 +656,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Array operations
|
||||
/// \name Value retrieval
|
||||
/// @{
|
||||
|
||||
/// \brief Gets a pointer to the element at a specific index.
|
||||
@ -640,7 +668,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << "element [2] exists: "sv << !!arr.get(2) << "\n";
|
||||
/// if (toml::node* val = arr.get(0))
|
||||
/// std::cout << "element [0] is an "sv << val->type() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -676,7 +703,6 @@ TOML_NAMESPACE_START
|
||||
/// auto arr = toml::array{ 42, "is the meaning of life, apparently."sv };
|
||||
/// if (toml::value<int64_t>* val = arr.get_as<int64_t>(0))
|
||||
/// std::cout << "element [0] is an integer with value "sv << *val << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -763,6 +789,11 @@ TOML_NAMESPACE_START
|
||||
return *elems_.back();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Iterators
|
||||
/// @{
|
||||
|
||||
/// \brief Returns an iterator to the first element.
|
||||
TOML_NODISCARD
|
||||
iterator begin() noexcept
|
||||
@ -805,6 +836,11 @@ TOML_NAMESPACE_START
|
||||
return elems_.cend();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Size and Capacity
|
||||
/// @{
|
||||
|
||||
/// \brief Returns true if the array is empty.
|
||||
TOML_NODISCARD
|
||||
bool empty() const noexcept
|
||||
@ -819,18 +855,6 @@ TOML_NAMESPACE_START
|
||||
return elems_.size();
|
||||
}
|
||||
|
||||
/// \brief Reserves internal storage capacity up to a pre-determined number of elements.
|
||||
void reserve(size_t new_capacity)
|
||||
{
|
||||
elems_.reserve(new_capacity);
|
||||
}
|
||||
|
||||
/// \brief Removes all elements from the array.
|
||||
void clear() noexcept
|
||||
{
|
||||
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
|
||||
@ -845,12 +869,205 @@ TOML_NAMESPACE_START
|
||||
return elems_.capacity();
|
||||
}
|
||||
|
||||
/// \brief Reserves internal storage capacity up to a pre-determined number of elements.
|
||||
TOML_API
|
||||
void reserve(size_t new_capacity);
|
||||
|
||||
/// \brief Requests the removal of any unused internal storage capacity.
|
||||
void shrink_to_fit()
|
||||
TOML_API
|
||||
void shrink_to_fit();
|
||||
|
||||
/// \brief Shrinks the array to the given size.
|
||||
///
|
||||
/// \detail \godbolt{rxEzK5}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.truncate(5); // no-op
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.truncate(1);
|
||||
/// std::cout << arr << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1]
|
||||
/// \eout
|
||||
///
|
||||
/// \remarks Does nothing if the requested size is larger than or equal to the current size.
|
||||
TOML_API
|
||||
void truncate(size_t new_size);
|
||||
|
||||
/// \brief Resizes the array.
|
||||
///
|
||||
/// \detail \godbolt{W5zqx3}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.resize(6, 42);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.resize(2, 0);
|
||||
/// std::cout << arr << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1, 2, 3, 42, 42, 42 ]
|
||||
/// [ 1, 2 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam ElemType toml::node, toml::table, toml::array, or a native TOML value type
|
||||
/// (or a type promotable to one).
|
||||
///
|
||||
/// \param new_size The number of elements the array will have after resizing.
|
||||
/// \param default_init_val The node or value used to initialize new elements if the array needs to grow.
|
||||
/// \param default_init_flags Value flags to apply to new values created if new elements are created by growing.
|
||||
template <typename ElemType>
|
||||
void resize(size_t new_size,
|
||||
ElemType&& default_init_val,
|
||||
value_flags default_init_flags = preserve_source_value_flags)
|
||||
{
|
||||
elems_.shrink_to_fit();
|
||||
static_assert(!is_node_view<ElemType>,
|
||||
"The default element type argument to toml::array::resize may not be toml::node_view.");
|
||||
|
||||
if (!new_size)
|
||||
clear();
|
||||
else if (new_size > elems_.size())
|
||||
insert(cend(), new_size - elems_.size(), static_cast<ElemType&&>(default_init_val), default_init_flags);
|
||||
else
|
||||
truncate(new_size);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Erasure
|
||||
/// @{
|
||||
|
||||
/// \brief Removes the specified element from the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.erase(arr.cbegin() + 1);
|
||||
/// std::cout << arr << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1, 3 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \param pos Iterator to the element being erased.
|
||||
///
|
||||
/// \returns Iterator to the first element immediately following the removed element.
|
||||
TOML_API
|
||||
iterator erase(const_iterator pos) noexcept;
|
||||
|
||||
/// \brief Removes the elements in the range [first, last) from the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, "bad", "karma" 2 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.erase(arr.cbegin() + 1, arr.cbegin() + 3);
|
||||
/// std::cout << arr << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 'bad', 'karma', 3 ]
|
||||
/// [ 1, 3 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \param first Iterator to the first element being erased.
|
||||
/// \param last Iterator to the one-past-the-last element being erased.
|
||||
///
|
||||
/// \returns Iterator to the first element immediately following the last removed element.
|
||||
TOML_API
|
||||
iterator erase(const_iterator first, const_iterator last) noexcept;
|
||||
|
||||
/// \brief Flattens this array, recursively hoisting the contents of child arrays up into itself.
|
||||
///
|
||||
/// \detail \cpp
|
||||
///
|
||||
/// auto arr = toml::array{ 1, 2, toml::array{ 3, 4, toml::array{ 5 } }, 6, toml::array{} };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.flatten();
|
||||
/// std::cout << arr << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, [ 3, 4, [ 5 ] ], 6, [] ]
|
||||
/// [ 1, 2, 3, 4, 5, 6 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \remarks Arrays inside child tables are not flattened.
|
||||
///
|
||||
/// \returns A reference to the array.
|
||||
TOML_API
|
||||
array& flatten() &;
|
||||
|
||||
/// \brief Flattens this array, recursively hoisting the contents of child arrays up into itself (rvalue overload).
|
||||
///
|
||||
/// \returns An rvalue reference to the array.
|
||||
array&& flatten() &&
|
||||
{
|
||||
return static_cast<toml::array&&>(this->flatten());
|
||||
}
|
||||
|
||||
/// \brief Removes empty child arrays and tables.
|
||||
///
|
||||
/// \detail \cpp
|
||||
///
|
||||
/// auto arr = toml::array{ 1, 2, toml::array{ }, toml::array{ 3, toml::array{ } }, 4 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.prune(true);
|
||||
/// std::cout << arr << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, [], [ 3, [] ], 4 ]
|
||||
/// [ 1, 2, [ 3 ], 4 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \param recursive Should child arrays and tables themselves be pruned?
|
||||
///
|
||||
/// \returns A reference to the array.
|
||||
TOML_API
|
||||
array& prune(bool recursive = true) & noexcept;
|
||||
|
||||
/// \brief Removes empty child arrays and tables (rvalue overload).
|
||||
///
|
||||
/// \param recursive Should child arrays and tables themselves be pruned?
|
||||
///
|
||||
/// \returns An rvalue reference to the array.
|
||||
array&& prune(bool recursive = true) && noexcept
|
||||
{
|
||||
return static_cast<toml::array&&>(this->prune(recursive));
|
||||
}
|
||||
|
||||
/// \brief Removes the last element from the array.
|
||||
TOML_API
|
||||
void pop_back() noexcept;
|
||||
|
||||
/// \brief Removes all elements from the array.
|
||||
TOML_API
|
||||
void clear() noexcept;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Insertion and Emplacement
|
||||
/// @{
|
||||
|
||||
/// \brief Inserts a new element at a specific position in the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
@ -858,7 +1075,6 @@ TOML_NAMESPACE_START
|
||||
/// arr.insert(arr.cbegin() + 1, "two");
|
||||
/// arr.insert(arr.cend(), toml::array{ 4, 5 });
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -873,10 +1089,10 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \returns \conditional_return{Valid input}
|
||||
/// An iterator to the newly-inserted element.
|
||||
/// \conditional_return{Input is an empty toml::node_view}
|
||||
/// \conditional_return{Input is a null toml::node_view}
|
||||
/// end()
|
||||
///
|
||||
/// \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 a null 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 = preserve_source_value_flags)
|
||||
@ -886,7 +1102,7 @@ TOML_NAMESPACE_START
|
||||
if (!val)
|
||||
return end();
|
||||
}
|
||||
return elems_.emplace(pos, impl::make_node(static_cast<ElemType&&>(val), flags));
|
||||
return insert_at(pos, impl::make_node(static_cast<ElemType&&>(val), flags));
|
||||
}
|
||||
|
||||
/// \brief Repeatedly inserts a new element starting at a specific position in the array.
|
||||
@ -898,7 +1114,6 @@ TOML_NAMESPACE_START
|
||||
/// };
|
||||
/// arr.insert(arr.cbegin() + 1, 3, "honk");
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -922,10 +1137,10 @@ TOML_NAMESPACE_START
|
||||
/// An iterator to the newly-inserted element.
|
||||
/// \conditional_return{count == 0}
|
||||
/// A copy of pos
|
||||
/// \conditional_return{Input is an empty toml::node_view}
|
||||
/// \conditional_return{Input is a null toml::node_view}
|
||||
/// end()
|
||||
///
|
||||
/// \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 a null 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,
|
||||
@ -969,7 +1184,7 @@ TOML_NAMESPACE_START
|
||||
/// An iterator to the first newly-inserted element.
|
||||
/// \conditional_return{first >= last}
|
||||
/// A copy of pos
|
||||
/// \conditional_return{All objects in the range were empty toml::node_views}
|
||||
/// \conditional_return{All objects in the range were null toml::node_views}
|
||||
/// A copy of pos
|
||||
template <typename Iter>
|
||||
iterator insert(const_iterator pos, Iter first, Iter last, value_flags flags = preserve_source_value_flags)
|
||||
@ -1020,7 +1235,7 @@ TOML_NAMESPACE_START
|
||||
/// An iterator to the first newly-inserted element.
|
||||
/// \conditional_return{Input list is empty}
|
||||
/// A copy of pos
|
||||
/// \conditional_return{All objects in the list were empty toml::node_views}
|
||||
/// \conditional_return{All objects in the list were null toml::node_views}
|
||||
/// A copy of pos
|
||||
template <typename ElemType>
|
||||
iterator insert(const_iterator pos,
|
||||
@ -1038,7 +1253,6 @@ TOML_NAMESPACE_START
|
||||
/// //add a string using std::string's substring constructor
|
||||
/// arr.emplace<std::string>(arr.cbegin() + 1, "this is not a drill"sv, 14, 5);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -1061,7 +1275,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 elems_.emplace(pos, new impl::wrap_node<type>{ static_cast<Args&&>(args)... });
|
||||
return insert_at(pos, impl::node_ptr{ new impl::wrap_node<type>{ static_cast<Args&&>(args)... } });
|
||||
}
|
||||
|
||||
/// \brief Replaces the element at a specific position in the array with a different value.
|
||||
@ -1086,10 +1300,10 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \returns \conditional_return{Valid input}
|
||||
/// An iterator to the replaced element.
|
||||
/// \conditional_return{Input is an empty toml::node_view}
|
||||
/// \conditional_return{Input is a null toml::node_view}
|
||||
/// end()
|
||||
///
|
||||
/// \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 a null toml::node_view,
|
||||
/// because no replacement can take place. This is the only circumstance in which this can occur.
|
||||
template <typename ElemType>
|
||||
iterator replace(const_iterator pos, ElemType&& val, value_flags flags = preserve_source_value_flags)
|
||||
@ -1107,128 +1321,6 @@ TOML_NAMESPACE_START
|
||||
return it;
|
||||
}
|
||||
|
||||
/// \brief Removes the specified element from the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.erase(arr.cbegin() + 1);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1, 3 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \param pos Iterator to the element being erased.
|
||||
///
|
||||
/// \returns Iterator to the first element immediately following the removed element.
|
||||
iterator erase(const_iterator pos) noexcept
|
||||
{
|
||||
return elems_.erase(pos);
|
||||
}
|
||||
|
||||
/// \brief Removes the elements in the range [first, last) from the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
/// auto arr = toml::array{ 1, "bad", "karma" 2 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.erase(arr.cbegin() + 1, arr.cbegin() + 3);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 'bad', 'karma', 3 ]
|
||||
/// [ 1, 3 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \param first Iterator to the first element being erased.
|
||||
/// \param last Iterator to the one-past-the-last element being erased.
|
||||
///
|
||||
/// \returns Iterator to the first element immediately following the last removed element.
|
||||
iterator erase(const_iterator first, const_iterator last) noexcept
|
||||
{
|
||||
return elems_.erase(first, last);
|
||||
}
|
||||
|
||||
/// \brief Resizes the array.
|
||||
///
|
||||
/// \detail \godbolt{W5zqx3}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.resize(6, 42);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.resize(2, 0);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1, 2, 3, 42, 42, 42 ]
|
||||
/// [ 1, 2 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam ElemType toml::node, toml::table, toml::array, or a native TOML value type
|
||||
/// (or a type promotable to one).
|
||||
///
|
||||
/// \param new_size The number of elements the array will have after resizing.
|
||||
/// \param default_init_val The node or value used to initialize new elements if the array needs to grow.
|
||||
/// \param default_init_flags Value flags to apply to new values created if new elements are created by growing.
|
||||
template <typename ElemType>
|
||||
void resize(size_t new_size,
|
||||
ElemType&& default_init_val,
|
||||
value_flags default_init_flags = preserve_source_value_flags)
|
||||
{
|
||||
static_assert(!is_node_view<ElemType>,
|
||||
"The default element type argument to toml::array::resize may not be toml::node_view.");
|
||||
|
||||
if (!new_size)
|
||||
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), default_init_flags);
|
||||
}
|
||||
|
||||
/// \brief Shrinks the array to the given size.
|
||||
///
|
||||
/// \detail \godbolt{rxEzK5}
|
||||
///
|
||||
/// \cpp
|
||||
/// auto arr = toml::array{ 1, 2, 3 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.truncate(5); // no-op
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.truncate(1);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1, 2, 3 ]
|
||||
/// [ 1]
|
||||
/// \eout
|
||||
///
|
||||
/// \remarks Does nothing if the requested size is larger than or equal to the current size.
|
||||
void truncate(size_t new_size)
|
||||
{
|
||||
if (new_size < elems_.size())
|
||||
elems_.resize(new_size);
|
||||
}
|
||||
|
||||
/// \brief Appends a new element to the end of the array.
|
||||
///
|
||||
/// \detail \cpp
|
||||
@ -1237,7 +1329,6 @@ TOML_NAMESPACE_START
|
||||
/// arr.push_back(4.0);
|
||||
/// arr.push_back(toml::array{ 5, "six"sv });
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -1248,7 +1339,7 @@ TOML_NAMESPACE_START
|
||||
/// \param val The node or value being added.
|
||||
/// \param flags Value flags to apply to new values.
|
||||
///
|
||||
/// \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 a null toml::node_view.
|
||||
/// This is the only circumstance in which this can occur.
|
||||
template <typename ElemType>
|
||||
void push_back(ElemType&& val, value_flags flags = preserve_source_value_flags)
|
||||
@ -1262,7 +1353,6 @@ TOML_NAMESPACE_START
|
||||
/// auto arr = toml::array{ 1, 2 };
|
||||
/// arr.emplace_back<toml::array>(3, "four"sv);
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -1296,86 +1386,17 @@ TOML_NAMESPACE_START
|
||||
|
||||
if constexpr (moving_node_ptr)
|
||||
{
|
||||
elems_.emplace_back(static_cast<ElemArgs&&>(args)...);
|
||||
insert_at_back(static_cast<ElemArgs&&>(args)...);
|
||||
return *elems_.back();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto nde = new impl::wrap_node<unwrapped_type>{ static_cast<ElemArgs&&>(args)... };
|
||||
elems_.emplace_back(nde);
|
||||
return *nde;
|
||||
auto ptr = new impl::wrap_node<unwrapped_type>{ static_cast<ElemArgs&&>(args)... };
|
||||
insert_at_back(impl::node_ptr{ ptr });
|
||||
return *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Removes the last element from the array.
|
||||
void pop_back() noexcept
|
||||
{
|
||||
elems_.pop_back();
|
||||
}
|
||||
|
||||
/// \brief Flattens this array, recursively hoisting the contents of child arrays up into itself.
|
||||
///
|
||||
/// \detail \cpp
|
||||
///
|
||||
/// auto arr = toml::array{ 1, 2, toml::array{ 3, 4, toml::array{ 5 } }, 6, toml::array{} };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.flatten();
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, [ 3, 4, [ 5 ] ], 6, [] ]
|
||||
/// [ 1, 2, 3, 4, 5, 6 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \remarks Arrays inside child tables are not flattened.
|
||||
///
|
||||
/// \returns A reference to the array.
|
||||
TOML_API
|
||||
array& flatten() &;
|
||||
|
||||
/// \brief Flattens this array, recursively hoisting the contents of child arrays up into itself (rvalue overload).
|
||||
///
|
||||
/// \returns An rvalue reference to the array.
|
||||
array&& flatten() &&
|
||||
{
|
||||
return static_cast<toml::array&&>(this->flatten());
|
||||
}
|
||||
|
||||
/// \brief Removes empty child arrays and tables.
|
||||
///
|
||||
/// \detail \cpp
|
||||
///
|
||||
/// auto arr = toml::array{ 1, 2, toml::array{ }, toml::array{ 3, toml::array{ } }, 4 };
|
||||
/// std::cout << arr << "\n";
|
||||
///
|
||||
/// arr.prune();
|
||||
/// std::cout << arr << "\n";
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// [ 1, 2, [], [ 3, [] ], 4 ]
|
||||
/// [ 1, 2, [ 3 ], 4 ]
|
||||
/// \eout
|
||||
///
|
||||
/// \param recursive Should child arrays and tables themselves be pruned?
|
||||
///
|
||||
/// \returns A reference to the array.
|
||||
TOML_API
|
||||
array& prune(bool recursive = true) & noexcept;
|
||||
|
||||
/// \brief Removes empty child arrays and tables (rvalue overload).
|
||||
///
|
||||
/// \param recursive Should child arrays and tables themselves be pruned?
|
||||
///
|
||||
/// \returns An rvalue reference to the array.
|
||||
array&& prune(bool recursive = true) && noexcept
|
||||
{
|
||||
return static_cast<toml::array&&>(this->prune(recursive));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
private:
|
||||
|
@ -16,6 +16,37 @@
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(const impl::array_init_elem* b, const impl::array_init_elem* e)
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
|
||||
TOML_ASSERT_ASSUME(b);
|
||||
TOML_ASSERT_ASSUME(e);
|
||||
TOML_ASSERT_ASSUME(b <= e);
|
||||
|
||||
if TOML_UNLIKELY(b == e)
|
||||
return;
|
||||
|
||||
size_t cap{};
|
||||
for (auto it = b; it != e; it++)
|
||||
{
|
||||
if (it->value)
|
||||
cap++;
|
||||
}
|
||||
if TOML_UNLIKELY(!cap)
|
||||
return;
|
||||
|
||||
elems_.reserve(cap);
|
||||
for (; b != e; b++)
|
||||
{
|
||||
if (b->value)
|
||||
elems_.push_back(std::move(b->value));
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(const array& other) //
|
||||
: node(other)
|
||||
@ -32,7 +63,7 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array && other) noexcept //
|
||||
: node(std::move(other)),
|
||||
elems_{ std::move(other.elems_) }
|
||||
elems_(std::move(other.elems_))
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_ARRAY_CREATED;
|
||||
@ -68,7 +99,7 @@ TOML_NAMESPACE_START
|
||||
void array::preinsertion_resize(size_t idx, size_t count)
|
||||
{
|
||||
TOML_ASSERT(idx <= elems_.size());
|
||||
TOML_ASSERT(count >= 1u);
|
||||
TOML_ASSERT_ASSUME(count >= 1u);
|
||||
const auto old_size = elems_.size();
|
||||
const auto new_size = old_size + count;
|
||||
const auto inserting_at_end = idx == old_size;
|
||||
@ -80,6 +111,18 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::insert_at_back(impl::node_ptr && elem)
|
||||
{
|
||||
elems_.push_back(std::move(elem));
|
||||
}
|
||||
|
||||
TOML_API
|
||||
array::vector_iterator array::insert_at(const_vector_iterator pos, impl::node_ptr && elem)
|
||||
{
|
||||
return elems_.insert(pos, std::move(elem));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::is_homogeneous(node_type ntype) const noexcept
|
||||
{
|
||||
@ -136,34 +179,41 @@ TOML_NAMESPACE_START
|
||||
#else
|
||||
|
||||
auto n = get(index);
|
||||
TOML_ASSERT(n && "element index not found in array!");
|
||||
TOML_ASSERT_ASSUME(n && "element index not found in array!");
|
||||
return *n;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::equal(const array& lhs, const array& rhs) noexcept
|
||||
void array::reserve(size_t new_capacity)
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.elems_.size() != rhs.elems_.size())
|
||||
return false;
|
||||
for (size_t i = 0, e = lhs.elems_.size(); i < e; 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;
|
||||
elems_.reserve(new_capacity);
|
||||
}
|
||||
|
||||
const bool equal = lhs.elems_[i]->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::shrink_to_fit()
|
||||
{
|
||||
elems_.shrink_to_fit();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::truncate(size_t new_size)
|
||||
{
|
||||
if (new_size < elems_.size())
|
||||
elems_.resize(new_size);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator pos) noexcept
|
||||
{
|
||||
return elems_.erase(pos);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::iterator array::erase(const_iterator first, const_iterator last) noexcept
|
||||
{
|
||||
return elems_.erase(first, last);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -270,6 +320,42 @@ TOML_NAMESPACE_START
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::pop_back() noexcept
|
||||
{
|
||||
elems_.pop_back();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::clear() noexcept
|
||||
{
|
||||
elems_.clear();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool array::equal(const array& lhs, const array& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.elems_.size() != rhs.elems_.size())
|
||||
return false;
|
||||
for (size_t i = 0, e = lhs.elems_.size(); i < e; 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.elems_[i]->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
|
@ -229,7 +229,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << toml::time_offset{ -2, 30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ -2, -30 } << "\n";
|
||||
/// std::cout << toml::time_offset{ 0, 0 } << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
|
@ -37,7 +37,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
constants_{ &constants },
|
||||
config_{ config }
|
||||
{
|
||||
TOML_ASSERT(source_ != nullptr);
|
||||
TOML_ASSERT_ASSUME(source_);
|
||||
|
||||
config_.flags = (config_.flags | constants_->mandatory_flags) & ~constants_->ignored_flags;
|
||||
|
||||
|
@ -395,6 +395,62 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
&& !is_wide_string<T>;
|
||||
|
||||
template <typename, typename>
|
||||
struct copy_ref_;
|
||||
template <typename Dest, typename Src>
|
||||
using copy_ref = typename copy_ref_<Dest, Src>::type;
|
||||
|
||||
template <typename Dest, typename Src>
|
||||
struct copy_ref_
|
||||
{
|
||||
using type = Dest;
|
||||
};
|
||||
|
||||
template <typename Dest, typename Src>
|
||||
struct copy_ref_<Dest, Src&>
|
||||
{
|
||||
using type = std::add_lvalue_reference_t<Dest>;
|
||||
};
|
||||
|
||||
template <typename Dest, typename Src>
|
||||
struct copy_ref_<Dest, Src&&>
|
||||
{
|
||||
using type = std::add_rvalue_reference_t<Dest>;
|
||||
};
|
||||
|
||||
template <typename, typename>
|
||||
struct copy_cv_;
|
||||
template <typename Dest, typename Src>
|
||||
using copy_cv = typename copy_cv_<Dest, Src>::type;
|
||||
|
||||
template <typename Dest, typename Src>
|
||||
struct copy_cv_
|
||||
{
|
||||
using type = Dest;
|
||||
};
|
||||
|
||||
template <typename Dest, typename Src>
|
||||
struct copy_cv_<Dest, const Src>
|
||||
{
|
||||
using type = std::add_const_t<Dest>;
|
||||
};
|
||||
|
||||
template <typename Dest, typename Src>
|
||||
struct copy_cv_<Dest, volatile Src>
|
||||
{
|
||||
using type = std::add_volatile_t<Dest>;
|
||||
};
|
||||
|
||||
template <typename Dest, typename Src>
|
||||
struct copy_cv_<Dest, const volatile Src>
|
||||
{
|
||||
using type = std::add_cv_t<Dest>;
|
||||
};
|
||||
|
||||
template <typename Dest, typename Src>
|
||||
using copy_cvref =
|
||||
copy_ref<copy_ref<copy_cv<std::remove_reference_t<Dest>, std::remove_reference_t<Src>>, Dest>, Src>;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool dependent_false = false;
|
||||
|
||||
@ -416,21 +472,21 @@ TOML_IMPL_NAMESPACE_START
|
||||
static constexpr auto type = node_type::none;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct value_traits<const T> : value_traits<T>
|
||||
{};
|
||||
template <typename T>
|
||||
struct value_traits<volatile T> : value_traits<T>
|
||||
{};
|
||||
template <typename T>
|
||||
struct value_traits<const volatile T> : value_traits<T>
|
||||
{};
|
||||
template <typename T>
|
||||
struct value_traits<T&> : value_traits<T>
|
||||
{};
|
||||
template <typename T>
|
||||
struct value_traits<T&&> : value_traits<T>
|
||||
{};
|
||||
template <typename T>
|
||||
struct value_traits<T* const> : value_traits<T*>
|
||||
{};
|
||||
template <typename T>
|
||||
struct value_traits<T* volatile> : value_traits<T*>
|
||||
{};
|
||||
template <typename T>
|
||||
struct value_traits<T* const volatile> : value_traits<T*>
|
||||
{};
|
||||
|
||||
// integer value_traits specializations - standard types
|
||||
template <typename T>
|
||||
@ -747,6 +803,21 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
template <typename T>
|
||||
struct node_wrapper<const T>
|
||||
{
|
||||
using type = std::add_const_t<typename node_wrapper<T>::type>;
|
||||
};
|
||||
template <typename T>
|
||||
struct node_wrapper<volatile T>
|
||||
{
|
||||
using type = std::add_volatile_t<typename node_wrapper<T>::type>;
|
||||
};
|
||||
template <typename T>
|
||||
struct node_wrapper<const volatile T>
|
||||
{
|
||||
using type = std::add_const_t<std::add_volatile_t<typename node_wrapper<T>::type>>;
|
||||
};
|
||||
template <>
|
||||
struct node_wrapper<std::string>
|
||||
{
|
||||
@ -783,7 +854,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
using type = value<date_time>;
|
||||
};
|
||||
template <typename T>
|
||||
using wrap_node = typename node_wrapper<T>::type;
|
||||
using wrap_node = typename node_wrapper<std::remove_reference_t<T>>::type;
|
||||
|
||||
// nodes => native value types
|
||||
template <typename T>
|
||||
@ -797,7 +868,22 @@ TOML_IMPL_NAMESPACE_START
|
||||
using type = T;
|
||||
};
|
||||
template <typename T>
|
||||
using unwrap_node = typename node_unwrapper<T>::type;
|
||||
struct node_unwrapper<const value<T>>
|
||||
{
|
||||
using type = std::add_const_t<T>;
|
||||
};
|
||||
template <typename T>
|
||||
struct node_unwrapper<volatile value<T>>
|
||||
{
|
||||
using type = std::add_volatile_t<T>;
|
||||
};
|
||||
template <typename T>
|
||||
struct node_unwrapper<const volatile value<T>>
|
||||
{
|
||||
using type = std::add_volatile_t<std::add_const_t<T>>;
|
||||
};
|
||||
template <typename T>
|
||||
using unwrap_node = typename node_unwrapper<std::remove_reference_t<T>>::type;
|
||||
|
||||
template <typename T>
|
||||
struct node_type_getter
|
||||
|
@ -36,39 +36,46 @@ TOML_NAMESPACE_START
|
||||
|
||||
public:
|
||||
/// \brief Default constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
key() noexcept = default;
|
||||
|
||||
/// \brief Constructs a key from a string view and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::string_view k, source_region&& src = {}) //
|
||||
: key_{ k },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a string view and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::string_view k, const source_region& src) //
|
||||
: key_{ k },
|
||||
source_{ src }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a string and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::string&& k, source_region&& src = {}) noexcept //
|
||||
: key_{ std::move(k) },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a string and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::string&& k, const source_region& src) noexcept //
|
||||
: key_{ std::move(k) },
|
||||
source_{ src }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a c-string and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(const char* k, source_region&& src = {}) //
|
||||
: key_{ k },
|
||||
source_{ std::move(src) }
|
||||
{}
|
||||
|
||||
/// \brief Constructs a key from a c-string view and source region.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(const char* k, const source_region& src) //
|
||||
: key_{ k },
|
||||
source_{ src }
|
||||
@ -79,6 +86,7 @@ TOML_NAMESPACE_START
|
||||
/// \brief Constructs a key from a wide string view and source region.
|
||||
///
|
||||
/// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::wstring_view k, source_region&& src = {}) //
|
||||
: key_{ impl::narrow(k) },
|
||||
source_{ std::move(src) }
|
||||
@ -87,6 +95,7 @@ TOML_NAMESPACE_START
|
||||
/// \brief Constructs a key from a wide string and source region.
|
||||
///
|
||||
/// \availability This constructor is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit key(std::wstring_view k, const source_region& src) //
|
||||
: key_{ impl::narrow(k) },
|
||||
source_{ src }
|
||||
|
@ -22,7 +22,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
// arrays + tables - invoke copy/move ctor
|
||||
if constexpr (is_one_of<unwrapped_type, array, table>)
|
||||
{
|
||||
return new unwrapped_type{ static_cast<T&&>(val) };
|
||||
return new unwrapped_type(static_cast<T&&>(val));
|
||||
}
|
||||
|
||||
// values
|
||||
|
@ -27,20 +27,41 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
decltype(auto) get_value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>);
|
||||
|
||||
template <typename T, typename N>
|
||||
using ref_type_ = std::conditional_t< //
|
||||
std::is_reference_v<T>, //
|
||||
impl::copy_ref<impl::copy_cv<impl::unwrap_node<T>, std::remove_reference_t<N>>, T>, //
|
||||
impl::copy_cvref<impl::unwrap_node<T>, N> //
|
||||
>;
|
||||
|
||||
template <typename T, typename N>
|
||||
using ref_type = std::conditional_t< //
|
||||
std::is_reference_v<N>, //
|
||||
ref_type_<T, N>, //
|
||||
ref_type_<T, std::add_lvalue_reference_t<N>> //
|
||||
>;
|
||||
|
||||
template <typename T, typename N>
|
||||
TOML_PURE_GETTER
|
||||
static decltype(auto) do_ref(N&& n) noexcept
|
||||
static ref_type<T, N&&> do_ref(N&& n) noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
|
||||
using unwrapped_type = impl::unwrap_node<T>;
|
||||
static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
|
||||
"The template type argument of node::ref() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
TOML_ASSERT(
|
||||
n.template is<T>()
|
||||
&& "template type argument T provided to toml::node::ref() didn't match the node's actual type");
|
||||
if constexpr (impl::is_native<type>)
|
||||
return static_cast<N&&>(n).template ref_cast<type>().get();
|
||||
|
||||
TOML_ASSERT_ASSUME(
|
||||
n.template is<unwrapped_type>()
|
||||
&& "template type argument provided to toml::node::ref() didn't match the node's actual type");
|
||||
|
||||
using node_ref = std::remove_volatile_t<std::remove_reference_t<N>>&;
|
||||
using val_type = std::remove_volatile_t<unwrapped_type>;
|
||||
using out_ref = ref_type<T, N&&>;
|
||||
static_assert(std::is_reference_v<out_ref>);
|
||||
|
||||
if constexpr (toml::is_value<unwrapped_type>)
|
||||
return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>().get());
|
||||
else
|
||||
return static_cast<N&&>(n).template ref_cast<type>();
|
||||
return static_cast<out_ref>(const_cast<node_ref>(n).template ref_cast<val_type>());
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -58,29 +79,55 @@ TOML_NAMESPACE_START
|
||||
TOML_API
|
||||
node& operator=(node&&) noexcept;
|
||||
|
||||
template <typename T, typename N>
|
||||
using ref_cast_type_ = std::conditional_t< //
|
||||
std::is_reference_v<T>, //
|
||||
impl::copy_ref<impl::copy_cv<impl::wrap_node<T>, std::remove_reference_t<N>>, T>, //
|
||||
impl::copy_cvref<impl::wrap_node<T>, N> //
|
||||
>;
|
||||
|
||||
template <typename T, typename N>
|
||||
using ref_cast_type = std::conditional_t< //
|
||||
std::is_reference_v<N>, //
|
||||
ref_cast_type_<T, N>, //
|
||||
ref_cast_type_<T, std::add_lvalue_reference_t<N>> //
|
||||
>;
|
||||
|
||||
template <typename T>
|
||||
TOML_PURE_INLINE_GETTER
|
||||
impl::wrap_node<T>& ref_cast() & noexcept
|
||||
ref_cast_type<T, node&> ref_cast() & noexcept
|
||||
{
|
||||
return *reinterpret_cast<impl::wrap_node<T>*>(this);
|
||||
using out_ref = ref_cast_type<T, node&>;
|
||||
using out_type = std::remove_reference_t<out_ref>;
|
||||
return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_PURE_INLINE_GETTER
|
||||
impl::wrap_node<T>&& ref_cast() && noexcept
|
||||
ref_cast_type<T, node&&> ref_cast() && noexcept
|
||||
{
|
||||
return std::move(*reinterpret_cast<impl::wrap_node<T>*>(this));
|
||||
using out_ref = ref_cast_type<T, node&&>;
|
||||
using out_type = std::remove_reference_t<out_ref>;
|
||||
return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const impl::wrap_node<T>& ref_cast() const& noexcept
|
||||
ref_cast_type<T, const node&> ref_cast() const& noexcept
|
||||
{
|
||||
return *reinterpret_cast<const impl::wrap_node<T>*>(this);
|
||||
using out_ref = ref_cast_type<T, const node&>;
|
||||
using out_type = std::remove_reference_t<out_ref>;
|
||||
return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
|
||||
}
|
||||
|
||||
template <typename N, typename T>
|
||||
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
|
||||
template <typename T>
|
||||
TOML_PURE_INLINE_GETTER
|
||||
ref_cast_type<T, const node&&> ref_cast() const&& noexcept
|
||||
{
|
||||
using out_ref = ref_cast_type<T, const node&&>;
|
||||
using out_type = std::remove_reference_t<out_ref>;
|
||||
return static_cast<out_ref>(*reinterpret_cast<out_type*>(this));
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
||||
@ -137,7 +184,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << "all floats: "sv << arr.is_homogeneous(toml::node_type::floating_point) << "\n";
|
||||
/// std::cout << "all arrays: "sv << arr.is_homogeneous(toml::node_type::array) << "\n";
|
||||
/// std::cout << "all ints: "sv << arr.is_homogeneous(toml::node_type::integer) << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -167,7 +213,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << "all doubles: "sv << arr.is_homogeneous<double>() << "\n";
|
||||
/// std::cout << "all arrays: "sv << arr.is_homogeneous<toml::array>() << "\n";
|
||||
/// std::cout << "all integers: "sv << arr.is_homogeneous<int64_t>() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -190,13 +235,13 @@ TOML_NAMESPACE_START
|
||||
TOML_PURE_GETTER
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<ElemType>;
|
||||
static_assert(
|
||||
std::is_void_v<
|
||||
type> || ((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>),
|
||||
"The template type argument of node::is_homogeneous() must be void or one "
|
||||
"of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
return is_homogeneous(impl::node_type_of<type>);
|
||||
using unwrapped_type = impl::unwrap_node<impl::remove_cvref<ElemType>>;
|
||||
static_assert(std::is_void_v<unwrapped_type> //
|
||||
|| (toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>),
|
||||
"The template type argument of node::is_homogeneous() must be void or one "
|
||||
"of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
return is_homogeneous(impl::node_type_of<unwrapped_type>);
|
||||
}
|
||||
|
||||
/// \brief Returns the node's type identifier.
|
||||
@ -260,27 +305,27 @@ TOML_NAMESPACE_START
|
||||
TOML_PURE_INLINE_GETTER
|
||||
bool is() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
|
||||
using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
|
||||
static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
|
||||
"The template type argument of node::is() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
if constexpr (std::is_same_v<type, table>)
|
||||
if constexpr (std::is_same_v<unwrapped_type, table>)
|
||||
return is_table();
|
||||
else if constexpr (std::is_same_v<type, array>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, array>)
|
||||
return is_array();
|
||||
else if constexpr (std::is_same_v<type, std::string>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, std::string>)
|
||||
return is_string();
|
||||
else if constexpr (std::is_same_v<type, int64_t>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
|
||||
return is_integer();
|
||||
else if constexpr (std::is_same_v<type, double>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, double>)
|
||||
return is_floating_point();
|
||||
else if constexpr (std::is_same_v<type, bool>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, bool>)
|
||||
return is_boolean();
|
||||
else if constexpr (std::is_same_v<type, date>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date>)
|
||||
return is_date();
|
||||
else if constexpr (std::is_same_v<type, time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, time>)
|
||||
return is_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date_time>)
|
||||
return is_date_time();
|
||||
}
|
||||
|
||||
@ -376,7 +421,6 @@ TOML_NAMESPACE_START
|
||||
/// toml::value<int64_t>* int_value2 = node->as<toml::value<int64_t>>();
|
||||
/// if (int_value2)
|
||||
/// std::cout << "Node is a value<int64_t>\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam T The node type or TOML value type to cast to.
|
||||
@ -386,27 +430,27 @@ TOML_NAMESPACE_START
|
||||
TOML_PURE_INLINE_GETTER
|
||||
impl::wrap_node<T>* as() noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
|
||||
using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
|
||||
static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
|
||||
"The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
if constexpr (std::is_same_v<type, table>)
|
||||
if constexpr (std::is_same_v<unwrapped_type, table>)
|
||||
return as_table();
|
||||
else if constexpr (std::is_same_v<type, array>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, array>)
|
||||
return as_array();
|
||||
else if constexpr (std::is_same_v<type, std::string>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, std::string>)
|
||||
return as_string();
|
||||
else if constexpr (std::is_same_v<type, int64_t>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
|
||||
return as_integer();
|
||||
else if constexpr (std::is_same_v<type, double>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, double>)
|
||||
return as_floating_point();
|
||||
else if constexpr (std::is_same_v<type, bool>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, bool>)
|
||||
return as_boolean();
|
||||
else if constexpr (std::is_same_v<type, date>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date>)
|
||||
return as_date();
|
||||
else if constexpr (std::is_same_v<type, time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, time>)
|
||||
return as_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date_time>)
|
||||
return as_date_time();
|
||||
}
|
||||
|
||||
@ -415,27 +459,27 @@ TOML_NAMESPACE_START
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const impl::wrap_node<T>* as() const noexcept
|
||||
{
|
||||
using type = impl::unwrap_node<T>;
|
||||
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
|
||||
using unwrapped_type = impl::unwrap_node<impl::remove_cvref<T>>;
|
||||
static_assert(toml::is_value<unwrapped_type> || toml::is_container<unwrapped_type>,
|
||||
"The template type argument of node::as() must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
|
||||
|
||||
if constexpr (std::is_same_v<type, table>)
|
||||
if constexpr (std::is_same_v<unwrapped_type, table>)
|
||||
return as_table();
|
||||
else if constexpr (std::is_same_v<type, array>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, array>)
|
||||
return as_array();
|
||||
else if constexpr (std::is_same_v<type, std::string>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, std::string>)
|
||||
return as_string();
|
||||
else if constexpr (std::is_same_v<type, int64_t>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, int64_t>)
|
||||
return as_integer();
|
||||
else if constexpr (std::is_same_v<type, double>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, double>)
|
||||
return as_floating_point();
|
||||
else if constexpr (std::is_same_v<type, bool>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, bool>)
|
||||
return as_boolean();
|
||||
else if constexpr (std::is_same_v<type, date>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date>)
|
||||
return as_date();
|
||||
else if constexpr (std::is_same_v<type, time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, time>)
|
||||
return as_time();
|
||||
else if constexpr (std::is_same_v<type, date_time>)
|
||||
else if constexpr (std::is_same_v<unwrapped_type, date_time>)
|
||||
return as_date_time();
|
||||
}
|
||||
|
||||
@ -621,6 +665,23 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// \brief Gets a raw reference to a value node's underlying data.
|
||||
///
|
||||
/// \note Providing explicit ref qualifiers acts as an explicit ref-category cast. Providing
|
||||
/// explicit cv-ref qualifiers 'merges' them with whatever the cv qualification of the node is. Examples:
|
||||
/// | node | T | return type |
|
||||
/// |-------------|------------------------|------------------------------|
|
||||
/// | node& | std::string | std::string& |
|
||||
/// | node& | std::string& | std::string& |
|
||||
/// | node& | std::string&& | std::string&& |
|
||||
/// | node&& | std::string | std::string&& |
|
||||
/// | node&& | std::string& | std::string& |
|
||||
/// | node&& | std::string&& | std::string&& |
|
||||
/// | const node& | std::string | const std::string& |
|
||||
/// | const node& | std::string& | const std::string& |
|
||||
/// | const node& | std::string&& | const std::string&& |
|
||||
/// | const node& | volatile std::string | const volatile std::string& |
|
||||
/// | const node& | volatile std::string& | const volatile std::string& |
|
||||
/// | const node& | volatile std::string&& | const volatile std::string&& |
|
||||
///
|
||||
/// \warning This function is dangerous if used carelessly and **WILL** break your code if the
|
||||
/// chosen value type doesn't match the node's actual type. In debug builds an assertion
|
||||
/// will fire when invalid accesses are attempted: \cpp
|
||||
@ -632,7 +693,6 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// int64_t& min_ref = tbl.get("min")->ref<int64_t>(); // matching type
|
||||
/// double& max_ref = tbl.get("max")->ref<double>(); // mismatched type, hits assert()
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam T One of the TOML value types.
|
||||
@ -640,7 +700,7 @@ TOML_NAMESPACE_START
|
||||
/// \returns A reference to the underlying data.
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
impl::unwrap_node<T>& ref() & noexcept
|
||||
decltype(auto) ref() & noexcept
|
||||
{
|
||||
return do_ref<T>(*this);
|
||||
}
|
||||
@ -648,7 +708,7 @@ TOML_NAMESPACE_START
|
||||
/// \brief Gets a raw reference to a value node's underlying data (rvalue overload).
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
impl::unwrap_node<T>&& ref() && noexcept
|
||||
decltype(auto) ref() && noexcept
|
||||
{
|
||||
return do_ref<T>(std::move(*this));
|
||||
}
|
||||
@ -656,11 +716,19 @@ TOML_NAMESPACE_START
|
||||
/// \brief Gets a raw reference to a value node's underlying data (const lvalue overload).
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
const impl::unwrap_node<T>& ref() const& noexcept
|
||||
decltype(auto) ref() const& noexcept
|
||||
{
|
||||
return do_ref<T>(*this);
|
||||
}
|
||||
|
||||
/// \brief Gets a raw reference to a value node's underlying data (const rvalue overload).
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
decltype(auto) ref() const&& noexcept
|
||||
{
|
||||
return do_ref<T>(std::move(*this));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Metadata
|
||||
@ -681,7 +749,7 @@ TOML_NAMESPACE_START
|
||||
// clang-format off
|
||||
|
||||
template <typename Func, typename N, typename T>
|
||||
static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<N, T>>;
|
||||
static constexpr bool can_visit = std::is_invocable_v<Func, ref_cast_type<T, N>>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
static constexpr bool can_visit_any =
|
||||
@ -710,7 +778,7 @@ TOML_NAMESPACE_START
|
||||
template <typename Func, typename N, typename T>
|
||||
static constexpr bool visit_is_nothrow_one =
|
||||
!can_visit<Func, N, T>
|
||||
|| std::is_nothrow_invocable_v<Func, ref_cast_type<N, T>>;
|
||||
|| std::is_nothrow_invocable_v<Func, ref_cast_type<T, N>>;
|
||||
|
||||
template <typename Func, typename N>
|
||||
static constexpr bool visit_is_nothrow =
|
||||
@ -729,7 +797,7 @@ TOML_NAMESPACE_START
|
||||
template <typename Func, typename N, typename T, bool = can_visit<Func, N, T>>
|
||||
struct visit_return_type_
|
||||
{
|
||||
using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<N, T>>()));
|
||||
using type = decltype(std::declval<Func>()(std::declval<ref_cast_type<T, N>>()));
|
||||
};
|
||||
template <typename Func, typename N, typename T>
|
||||
struct visit_return_type_<Func, N, T, false>
|
||||
@ -856,7 +924,6 @@ TOML_NAMESPACE_START
|
||||
/// else
|
||||
/// throw std::exception{ "Expected string or integer" };
|
||||
/// });
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam Func A callable type invocable with one or more of the
|
||||
@ -888,6 +955,13 @@ TOML_NAMESPACE_START
|
||||
return do_visit(*this, static_cast<Func&&>(visitor));
|
||||
}
|
||||
|
||||
/// \brief Invokes a visitor on the node based on the node's concrete type (const rvalue overload).
|
||||
template <typename Func>
|
||||
decltype(auto) visit(Func&& visitor) const&& noexcept(visit_is_nothrow<Func&&, const node&&>)
|
||||
{
|
||||
return do_visit(static_cast<const node&&>(*this), static_cast<Func&&>(visitor));
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Node views
|
||||
|
@ -225,7 +225,7 @@ TOML_NAMESPACE_START
|
||||
TOML_PURE_GETTER
|
||||
bool is() const noexcept
|
||||
{
|
||||
return node_ ? node_->template is<T>() : false;
|
||||
return node_ ? node_->template is<impl::unwrap_node<impl::remove_cvref<T>>>() : false;
|
||||
}
|
||||
|
||||
/// \brief Checks if the viewed node contains values/elements of only one type.
|
||||
@ -276,7 +276,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << "all floats: "sv << cfg["arr"].is_homogeneous(toml::node_type::floating_point) << "\n";
|
||||
/// std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous(toml::node_type::array) << "\n";
|
||||
/// std::cout << "all ints: "sv << cfg["arr"].is_homogeneous(toml::node_type::integer) << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -308,7 +307,6 @@ TOML_NAMESPACE_START
|
||||
/// std::cout << "all doubles: "sv << cfg["arr"].is_homogeneous<double>() << "\n";
|
||||
/// std::cout << "all arrays: "sv << cfg["arr"].is_homogeneous<toml::array>() << "\n";
|
||||
/// std::cout << "all integers: "sv << cfg["arr"].is_homogeneous<int64_t>() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -330,7 +328,7 @@ TOML_NAMESPACE_START
|
||||
TOML_PURE_GETTER
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
return node_ ? node_->template is_homogeneous<impl::unwrap_node<ElemType>>() : false;
|
||||
return node_ ? node_->template is_homogeneous<impl::unwrap_node<impl::remove_cvref<ElemType>>>() : false;
|
||||
}
|
||||
|
||||
/// @}
|
||||
@ -347,70 +345,70 @@ TOML_NAMESPACE_START
|
||||
/// \see toml::node::as()
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
auto as() const noexcept
|
||||
auto* as() const noexcept
|
||||
{
|
||||
return node_ ? node_->template as<T>() : nullptr;
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::table, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto as_table() const noexcept
|
||||
auto* as_table() const noexcept
|
||||
{
|
||||
return as<table>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::array, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto as_array() const noexcept
|
||||
auto* as_array() const noexcept
|
||||
{
|
||||
return as<array>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<string>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto as_string() const noexcept
|
||||
auto* as_string() const noexcept
|
||||
{
|
||||
return as<std::string>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<int64_t>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto as_integer() const noexcept
|
||||
auto* as_integer() const noexcept
|
||||
{
|
||||
return as<int64_t>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<double>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto as_floating_point() const noexcept
|
||||
auto* as_floating_point() const noexcept
|
||||
{
|
||||
return as<double>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<bool>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto as_boolean() const noexcept
|
||||
auto* as_boolean() const noexcept
|
||||
{
|
||||
return as<bool>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<date>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto as_date() const noexcept
|
||||
auto* as_date() const noexcept
|
||||
{
|
||||
return as<date>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<time>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto as_time() const noexcept
|
||||
auto* as_time() const noexcept
|
||||
{
|
||||
return as<time>();
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the viewed node as a toml::value<date_time>, if it is one.
|
||||
TOML_PURE_GETTER
|
||||
auto as_date_time() const noexcept
|
||||
auto* as_date_time() const noexcept
|
||||
{
|
||||
return as<date_time>();
|
||||
}
|
||||
@ -528,6 +526,17 @@ TOML_NAMESPACE_START
|
||||
|
||||
/// \brief Gets a raw reference to the viewed node's underlying data.
|
||||
///
|
||||
/// /// \note Providing explicit ref qualifiers acts as an explicit ref-category cast. Providing
|
||||
/// explicit cv-ref qualifiers 'merges' them with whatever the cv qualification of the viewed node is. Examples:
|
||||
/// | node | T | return type |
|
||||
/// |-------------|------------------------|------------------------------|
|
||||
/// | node | std::string | std::string& |
|
||||
/// | node | std::string& | std::string& |
|
||||
/// | node | std::string&& | std::string&& |
|
||||
/// | const node | volatile std::string | const volatile std::string& |
|
||||
/// | const node | volatile std::string& | const volatile std::string& |
|
||||
/// | const node | volatile std::string&& | const volatile std::string&& |
|
||||
///
|
||||
/// \warning This function is dangerous if used carelessly and **WILL** break your code if the
|
||||
/// node_view didn't reference a node, or the chosen value type doesn't match the node's
|
||||
/// actual type. In debug builds an assertion will fire when invalid accesses are attempted: \cpp
|
||||
@ -540,7 +549,6 @@ TOML_NAMESPACE_START
|
||||
/// int64_t& min_ref = tbl["min"].ref<int64_t>(); // matching type
|
||||
/// double& max_ref = tbl["max"].ref<double>(); // mismatched type, hits assert()
|
||||
/// int64_t& foo_ref = tbl["foo"].ref<int64_t>(); // nonexistent key, hits assert()
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \tparam T One of the TOML value types.
|
||||
@ -550,8 +558,8 @@ TOML_NAMESPACE_START
|
||||
TOML_PURE_INLINE_GETTER
|
||||
decltype(auto) ref() const noexcept
|
||||
{
|
||||
TOML_ASSERT(node_ && "toml::node_view::ref() called on a node_view that did not reference a node");
|
||||
return node_->template ref<impl::unwrap_node<T>>();
|
||||
TOML_ASSERT_ASSUME(node_ && "toml::node_view::ref() called on a node_view that did not reference a node");
|
||||
return node_->template ref<T>();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
@ -35,7 +35,6 @@ TOML_NAMESPACE_START
|
||||
/// do_stuff_with_a_table(result); //implicitly converts to table&
|
||||
/// else
|
||||
/// std::cerr << "Parse failed:\n"sv << result.error() << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -114,7 +113,7 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
toml::table& table() & noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
TOML_ASSERT_ASSUME(!err_);
|
||||
return *get_as<toml::table>(storage_);
|
||||
}
|
||||
|
||||
@ -122,7 +121,7 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
toml::table&& table() && noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
TOML_ASSERT_ASSUME(!err_);
|
||||
return static_cast<toml::table&&>(*get_as<toml::table>(storage_));
|
||||
}
|
||||
|
||||
@ -130,7 +129,7 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
const toml::table& table() const& noexcept
|
||||
{
|
||||
TOML_ASSERT(!err_);
|
||||
TOML_ASSERT_ASSUME(!err_);
|
||||
return *get_as<const toml::table>(storage_);
|
||||
}
|
||||
|
||||
@ -138,7 +137,7 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
parse_error& error() & noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
TOML_ASSERT_ASSUME(err_);
|
||||
return *get_as<parse_error>(storage_);
|
||||
}
|
||||
|
||||
@ -146,7 +145,7 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
parse_error&& error() && noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
TOML_ASSERT_ASSUME(err_);
|
||||
return static_cast<parse_error&&>(*get_as<parse_error>(storage_));
|
||||
}
|
||||
|
||||
@ -154,7 +153,7 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
const parse_error& error() const& noexcept
|
||||
{
|
||||
TOML_ASSERT(err_);
|
||||
TOML_ASSERT_ASSUME(err_);
|
||||
return *get_as<const parse_error>(storage_);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("a = 3"sv);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -45,7 +44,6 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("a = 3"sv, "foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -91,7 +89,6 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse(u8"a = 3"sv);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -116,7 +113,6 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse(u8"a = 3"sv, "foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -166,7 +162,6 @@ TOML_NAMESPACE_START
|
||||
/// \detail \cpp
|
||||
/// auto tbl = toml::parse("a = 3"sv, L"foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -196,7 +191,6 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// auto tbl = toml::parse(ss);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -277,7 +271,6 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// auto tbl = toml::parse(ss);
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -305,7 +298,6 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// auto tbl = toml::parse(ss, "foo.toml");
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -338,7 +330,6 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// auto tbl = "a = 3"_toml;
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
@ -367,7 +358,6 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// auto tbl = u8"a = 3"_toml;
|
||||
/// std::cout << tbl["a"] << "\n";
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
|
@ -41,12 +41,6 @@ TOML_ENABLE_WARNINGS;
|
||||
//# UTF8 STREAMS
|
||||
//#---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define assert_or_assume(cond) TOML_ASSUME(cond)
|
||||
#else
|
||||
#define assert_or_assume(cond) TOML_ASSERT(cond)
|
||||
#endif
|
||||
|
||||
TOML_ANON_NAMESPACE_START
|
||||
{
|
||||
template <typename T>
|
||||
@ -158,7 +152,7 @@ TOML_ANON_NAMESPACE_START
|
||||
TOML_ATTR(nonnull)
|
||||
size_t operator()(void* dest, size_t num) noexcept
|
||||
{
|
||||
assert_or_assume(!eof());
|
||||
TOML_ASSERT_ASSUME(!eof());
|
||||
|
||||
num = impl::min(position_ + num, source_.length()) - position_;
|
||||
std::memcpy(dest, source_.data() + position_, num);
|
||||
@ -271,8 +265,8 @@ TOML_ANON_NAMESPACE_START
|
||||
|
||||
#if TOML_EXCEPTIONS
|
||||
#define utf8_reader_error(...) throw parse_error(__VA_ARGS__)
|
||||
#define utf8_reader_return_after_error(...) (void)0
|
||||
#define utf8_reader_error_check(...) (void)0
|
||||
#define utf8_reader_return_after_error(...) static_assert(true)
|
||||
#define utf8_reader_error_check(...) static_assert(true)
|
||||
#else
|
||||
#define utf8_reader_error(...) err_.emplace(__VA_ARGS__)
|
||||
#define utf8_reader_return_after_error(...) return __VA_ARGS__
|
||||
@ -366,7 +360,7 @@ TOML_ANON_NAMESPACE_START
|
||||
return false;
|
||||
}
|
||||
|
||||
assert_or_assume(raw_bytes_read);
|
||||
TOML_ASSERT_ASSUME(raw_bytes_read);
|
||||
std::memset(&codepoints_, 0, sizeof(codepoints_));
|
||||
|
||||
// helper for calculating decoded codepoint line+cols
|
||||
@ -453,7 +447,7 @@ TOML_ANON_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
assert_or_assume(codepoints_.count);
|
||||
TOML_ASSERT_ASSUME(codepoints_.count);
|
||||
calc_positions();
|
||||
|
||||
// handle general I/O errors
|
||||
@ -501,11 +495,11 @@ TOML_ANON_NAMESPACE_START
|
||||
if TOML_UNLIKELY(!stream_ || !read_next_block())
|
||||
return nullptr;
|
||||
|
||||
assert_or_assume(!codepoints_.current);
|
||||
TOML_ASSERT_ASSUME(!codepoints_.current);
|
||||
}
|
||||
assert_or_assume(codepoints_.count);
|
||||
assert_or_assume(codepoints_.count <= block_capacity);
|
||||
assert_or_assume(codepoints_.current < codepoints_.count);
|
||||
TOML_ASSERT_ASSUME(codepoints_.count);
|
||||
TOML_ASSERT_ASSUME(codepoints_.count <= block_capacity);
|
||||
TOML_ASSERT_ASSUME(codepoints_.current < codepoints_.count);
|
||||
|
||||
return &codepoints_.buffer[codepoints_.current++];
|
||||
}
|
||||
@ -537,7 +531,7 @@ TOML_ANON_NAMESPACE_START
|
||||
utf8_reader(std::basic_istream<Char>&, std::string &&) -> utf8_reader<std::basic_istream<Char>>;
|
||||
|
||||
#if TOML_EXCEPTIONS
|
||||
#define utf8_buffered_reader_error_check(...) (void)0
|
||||
#define utf8_buffered_reader_error_check(...) static_assert(true)
|
||||
#else
|
||||
#define utf8_buffered_reader_error_check(...) \
|
||||
do \
|
||||
@ -621,8 +615,8 @@ TOML_ANON_NAMESPACE_START
|
||||
{
|
||||
utf8_buffered_reader_error_check({});
|
||||
|
||||
assert_or_assume(history_.count);
|
||||
assert_or_assume(negative_offset_ + count <= history_.count);
|
||||
TOML_ASSERT_ASSUME(history_.count);
|
||||
TOML_ASSERT_ASSUME(negative_offset_ + count <= history_.count);
|
||||
|
||||
negative_offset_ += count;
|
||||
|
||||
@ -869,11 +863,7 @@ TOML_ANON_NAMESPACE_START
|
||||
parse_scope& operator=(const parse_scope&) = delete;
|
||||
parse_scope& operator=(parse_scope&&) = delete;
|
||||
};
|
||||
#define push_parse_scope_2(scope, line) \
|
||||
parse_scope ps_##line \
|
||||
{ \
|
||||
current_scope, scope \
|
||||
}
|
||||
#define push_parse_scope_2(scope, line) parse_scope ps_##line(current_scope, scope)
|
||||
#define push_parse_scope_1(scope, line) push_parse_scope_2(scope, line)
|
||||
#define push_parse_scope(scope) push_parse_scope_1(scope, __LINE__)
|
||||
|
||||
@ -965,7 +955,7 @@ TOML_ANON_NAMESPACE_END;
|
||||
// of toml++.
|
||||
|
||||
#define is_eof() !cp
|
||||
#define assert_not_eof() assert_or_assume(cp != nullptr)
|
||||
#define assert_not_eof() TOML_ASSERT_ASSUME(cp != nullptr)
|
||||
#define return_if_eof(...) \
|
||||
do \
|
||||
{ \
|
||||
@ -1126,7 +1116,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
void go_back(size_t count = 1) noexcept
|
||||
{
|
||||
return_if_error();
|
||||
assert_or_assume(count);
|
||||
TOML_ASSERT_ASSUME(count);
|
||||
|
||||
cp = reader.step_back(count);
|
||||
prev_pos = cp->position;
|
||||
@ -1290,8 +1280,8 @@ TOML_IMPL_NAMESPACE_START
|
||||
bool consume_digit_sequence(T* digits, size_t len)
|
||||
{
|
||||
return_if_error({});
|
||||
assert_or_assume(digits);
|
||||
assert_or_assume(len);
|
||||
TOML_ASSERT_ASSUME(digits);
|
||||
TOML_ASSERT_ASSUME(len);
|
||||
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
@ -1310,8 +1300,8 @@ TOML_IMPL_NAMESPACE_START
|
||||
size_t consume_variable_length_digit_sequence(T* buffer, size_t max_len)
|
||||
{
|
||||
return_if_error({});
|
||||
assert_or_assume(buffer);
|
||||
assert_or_assume(max_len);
|
||||
TOML_ASSERT_ASSUME(buffer);
|
||||
TOML_ASSERT_ASSUME(max_len);
|
||||
|
||||
size_t i = {};
|
||||
for (; i < max_len; i++)
|
||||
@ -1331,7 +1321,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(*cp == U'"');
|
||||
TOML_ASSERT_ASSUME(*cp == U'"');
|
||||
push_parse_scope("string"sv);
|
||||
|
||||
// skip the '"'
|
||||
@ -1557,7 +1547,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(*cp == U'\'');
|
||||
TOML_ASSERT_ASSUME(*cp == U'\'');
|
||||
push_parse_scope("literal string"sv);
|
||||
|
||||
// skip the delimiter
|
||||
@ -1661,7 +1651,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_string_delimiter(*cp));
|
||||
TOML_ASSERT_ASSUME(is_string_delimiter(*cp));
|
||||
push_parse_scope("string"sv);
|
||||
|
||||
// get the first three characters to determine the string type
|
||||
@ -1705,7 +1695,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_bare_key_character(*cp));
|
||||
TOML_ASSERT_ASSUME(is_bare_key_character(*cp));
|
||||
|
||||
string_buffer.clear();
|
||||
|
||||
@ -1727,7 +1717,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_match(*cp, U't', U'f', U'T', U'F'));
|
||||
TOML_ASSERT_ASSUME(is_match(*cp, U't', U'f', U'T', U'F'));
|
||||
push_parse_scope("boolean"sv);
|
||||
|
||||
start_recording(true);
|
||||
@ -1752,7 +1742,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_match(*cp, U'i', U'n', U'I', U'N', U'+', U'-'));
|
||||
TOML_ASSERT_ASSUME(is_match(*cp, U'i', U'n', U'I', U'N', U'+', U'-'));
|
||||
push_parse_scope("floating-point"sv);
|
||||
|
||||
start_recording(true);
|
||||
@ -1782,7 +1772,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_match(*cp, U'+', U'-', U'.') || is_decimal_digit(*cp));
|
||||
TOML_ASSERT_ASSUME(is_match(*cp, U'+', U'-', U'.') || is_decimal_digit(*cp));
|
||||
push_parse_scope("floating-point"sv);
|
||||
|
||||
// sign
|
||||
@ -1938,7 +1928,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_match(*cp, U'0', U'+', U'-'));
|
||||
TOML_ASSERT_ASSUME(is_match(*cp, U'0', U'+', U'-'));
|
||||
push_parse_scope("hexadecimal floating-point"sv);
|
||||
|
||||
#if TOML_LANG_UNRELEASED // toml/issues/562 (hexfloats)
|
||||
@ -2235,7 +2225,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_decimal_digit(*cp));
|
||||
TOML_ASSERT_ASSUME(is_decimal_digit(*cp));
|
||||
push_parse_scope("date"sv);
|
||||
|
||||
// "YYYY"
|
||||
@ -2290,7 +2280,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_decimal_digit(*cp));
|
||||
TOML_ASSERT_ASSUME(is_decimal_digit(*cp));
|
||||
push_parse_scope("time"sv);
|
||||
|
||||
static constexpr size_t max_digits = 9;
|
||||
@ -2382,7 +2372,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_decimal_digit(*cp));
|
||||
TOML_ASSERT_ASSUME(is_decimal_digit(*cp));
|
||||
push_parse_scope("date-time"sv);
|
||||
|
||||
// "YYYY-MM-DD"
|
||||
@ -2459,8 +2449,8 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(!is_control_character(*cp));
|
||||
assert_or_assume(*cp != U'_');
|
||||
TOML_ASSERT_ASSUME(!is_control_character(*cp));
|
||||
TOML_ASSERT_ASSUME(*cp != U'_');
|
||||
|
||||
switch (cp->value)
|
||||
{
|
||||
@ -2501,7 +2491,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(!is_value_terminator(*cp));
|
||||
TOML_ASSERT_ASSUME(!is_value_terminator(*cp));
|
||||
push_parse_scope("value"sv);
|
||||
|
||||
const parse_depth_counter depth_counter{ nested_values };
|
||||
@ -2525,8 +2515,8 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
do
|
||||
{
|
||||
assert_or_assume(!is_control_character(*cp));
|
||||
assert_or_assume(*cp != U'_');
|
||||
TOML_ASSERT_ASSUME(!is_control_character(*cp));
|
||||
TOML_ASSERT_ASSUME(*cp != U'_');
|
||||
|
||||
// detect the value type and parse accordingly,
|
||||
// starting with value types that can be detected
|
||||
@ -2584,7 +2574,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
if (is_eof())
|
||||
return;
|
||||
assert_or_assume(!is_value_terminator(*cp));
|
||||
TOML_ASSERT_ASSUME(!is_value_terminator(*cp));
|
||||
|
||||
do
|
||||
{
|
||||
@ -2596,7 +2586,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
add_trait(has_digits);
|
||||
else if (is_ascii_letter(c))
|
||||
{
|
||||
assert_or_assume((c >= U'a' && c <= U'z') || (c >= U'A' && c <= U'Z'));
|
||||
TOML_ASSERT_ASSUME((c >= U'a' && c <= U'z') || (c >= U'A' && c <= U'Z'));
|
||||
switch (static_cast<char32_t>(c | 32u))
|
||||
{
|
||||
case U'b':
|
||||
@ -2633,7 +2623,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
else if (c <= U':')
|
||||
{
|
||||
assert_or_assume(c < U'0' || c > U'9');
|
||||
TOML_ASSERT_ASSUME(c < U'0' || c > U'9');
|
||||
switch (c)
|
||||
{
|
||||
case U'+': add_trait(has_plus); break;
|
||||
@ -2715,7 +2705,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
// now things that can be identified from two or more characters
|
||||
return_if_error({});
|
||||
assert_or_assume(char_count >= 2u);
|
||||
TOML_ASSERT_ASSUME(char_count >= 2u);
|
||||
|
||||
// do some 'fuzzy matching' where there's no ambiguity, since that allows the specific
|
||||
// typed parse functions to take over and show better diagnostics if there's an issue
|
||||
@ -2978,7 +2968,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_bare_key_character(*cp) || is_string_delimiter(*cp));
|
||||
TOML_ASSERT_ASSUME(is_bare_key_character(*cp) || is_string_delimiter(*cp));
|
||||
push_parse_scope("key"sv);
|
||||
|
||||
key_buffer.clear();
|
||||
@ -3065,7 +3055,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(*cp == U'[');
|
||||
TOML_ASSERT_ASSUME(*cp == U'[');
|
||||
push_parse_scope("table header"sv);
|
||||
|
||||
const source_position header_begin_pos = cp->position;
|
||||
@ -3267,7 +3257,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(is_string_delimiter(*cp) || is_bare_key_character(*cp));
|
||||
TOML_ASSERT_ASSUME(is_string_delimiter(*cp) || is_bare_key_character(*cp));
|
||||
push_parse_scope("key-value pair"sv);
|
||||
|
||||
// read the key into the key buffer
|
||||
@ -3425,7 +3415,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
auto end = nde.source_.end;
|
||||
for (auto&& [k, v] : tbl)
|
||||
{
|
||||
(void)k;
|
||||
TOML_UNUSED(k);
|
||||
update_region_ends(v);
|
||||
if (end < v.source_.end)
|
||||
end = v.source_.end;
|
||||
@ -3493,7 +3483,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(*cp == U'[');
|
||||
TOML_ASSERT_ASSUME(*cp == U'[');
|
||||
push_parse_scope("array"sv);
|
||||
|
||||
// skip opening '['
|
||||
@ -3558,7 +3548,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
return_if_error({});
|
||||
assert_not_eof();
|
||||
assert_or_assume(*cp == U'{');
|
||||
TOML_ASSERT_ASSUME(*cp == U'{');
|
||||
push_parse_scope("inline table"sv);
|
||||
|
||||
// skip opening '{'
|
||||
@ -3645,11 +3635,8 @@ TOML_IMPL_NAMESPACE_END;
|
||||
#undef TOML_RETURNS_BY_THROWING
|
||||
#undef advance_and_return_if_error
|
||||
#undef advance_and_return_if_error_or_eof
|
||||
#undef assert_or_assume
|
||||
#undef assert_not_eof
|
||||
#undef assert_not_error
|
||||
#undef bdigit_msk
|
||||
#undef bzero_msk
|
||||
#undef is_eof
|
||||
#undef is_error
|
||||
#undef parse_error_break
|
||||
@ -3663,7 +3650,6 @@ TOML_IMPL_NAMESPACE_END;
|
||||
#undef set_error_and_return
|
||||
#undef set_error_and_return_default
|
||||
#undef set_error_and_return_if_eof
|
||||
#undef signs_msk
|
||||
#undef utf8_buffered_reader_error_check
|
||||
#undef utf8_reader_error
|
||||
#undef utf8_reader_error_check
|
||||
|
@ -101,7 +101,7 @@
|
||||
|
||||
#define TOML_ENABLE_WARNINGS TOML_POP_WARNINGS
|
||||
|
||||
#define TOML_ASSUME(cond) __builtin_assume(cond)
|
||||
#define TOML_ASSUME(expr) __builtin_assume(expr)
|
||||
#define TOML_UNREACHABLE __builtin_unreachable()
|
||||
#define TOML_ATTR(...) __attribute__((__VA_ARGS__))
|
||||
#if defined(_MSC_VER) // msvc compat mode
|
||||
@ -235,7 +235,7 @@
|
||||
#define TOML_ALWAYS_INLINE __forceinline
|
||||
#endif
|
||||
#define TOML_NEVER_INLINE __declspec(noinline)
|
||||
#define TOML_ASSUME(cond) __assume(cond)
|
||||
#define TOML_ASSUME(expr) __assume(expr)
|
||||
#define TOML_UNREACHABLE __assume(0)
|
||||
#define TOML_ABSTRACT_BASE __declspec(novtable)
|
||||
#define TOML_EMPTY_BASES __declspec(empty_bases)
|
||||
@ -588,11 +588,11 @@
|
||||
#endif
|
||||
|
||||
#ifndef TOML_ASSUME
|
||||
#define TOML_ASSUME(cond) (void)0
|
||||
#define TOML_ASSUME(expr) static_assert(true)
|
||||
#endif
|
||||
|
||||
#ifndef TOML_UNREACHABLE
|
||||
#define TOML_UNREACHABLE TOML_ASSERT(false)
|
||||
#define TOML_UNREACHABLE TOML_ASSUME(false)
|
||||
#endif
|
||||
|
||||
#ifndef TOML_FLAGS_ENUM
|
||||
@ -743,6 +743,8 @@
|
||||
#define TOML_CONST_INLINE_GETTER TOML_NODISCARD TOML_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#define TOML_UNUSED(...) static_cast<void>(__VA_ARGS__)
|
||||
|
||||
//======================================================================================================================
|
||||
// SFINAE
|
||||
//======================================================================================================================
|
||||
@ -871,18 +873,23 @@
|
||||
//# ASSERT
|
||||
//#====================================================================================================================
|
||||
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#ifndef TOML_ASSERT
|
||||
#ifdef NDEBUG
|
||||
#define TOML_ASSERT(expr) static_cast<void>(0)
|
||||
#else
|
||||
#ifndef assert
|
||||
#include <cassert>
|
||||
#endif
|
||||
#define TOML_ASSERT(expr) assert(expr)
|
||||
#endif
|
||||
#ifdef NDEBUG
|
||||
#undef TOML_ASSERT
|
||||
#define TOML_ASSERT(expr) static_assert(true)
|
||||
#endif
|
||||
#ifndef TOML_ASSERT
|
||||
#ifndef assert
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#include <cassert>
|
||||
TOML_ENABLE_WARNINGS;
|
||||
#endif
|
||||
#define TOML_ASSERT(expr) assert(expr)
|
||||
#endif
|
||||
#ifdef NDEBUG
|
||||
#define TOML_ASSERT_ASSUME(expr) TOML_ASSUME(expr)
|
||||
#else
|
||||
#define TOML_ASSERT_ASSUME(expr) TOML_ASSERT(expr)
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
|
||||
//#====================================================================================================================
|
||||
//# STATIC ASSERT MESSAGE FORMATTING
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,17 @@ TOML_NAMESPACE_START
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(const impl::table_init_pair* b, const impl::table_init_pair* e)
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
|
||||
TOML_ASSERT_ASSUME(b);
|
||||
TOML_ASSERT_ASSUME(e);
|
||||
TOML_ASSERT_ASSUME(b <= e);
|
||||
|
||||
if TOML_UNLIKELY(b == e)
|
||||
return;
|
||||
|
||||
for (; b != e; b++)
|
||||
{
|
||||
if (!b->value) // empty node_views
|
||||
@ -27,10 +38,6 @@ TOML_NAMESPACE_START
|
||||
|
||||
map_.insert_or_assign(std::move(b->key), std::move(b->value));
|
||||
}
|
||||
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_TABLE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -94,7 +101,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
for (auto&& [k, v] : map_)
|
||||
{
|
||||
static_cast<void>(k);
|
||||
TOML_UNUSED(k);
|
||||
if (v->type() != ntype)
|
||||
return false;
|
||||
}
|
||||
@ -114,7 +121,7 @@ TOML_NAMESPACE_START
|
||||
ntype = map_.cbegin()->second->type();
|
||||
for (const auto& [k, v] : map_)
|
||||
{
|
||||
static_cast<void>(k);
|
||||
TOML_UNUSED(k);
|
||||
if (v->type() != ntype)
|
||||
{
|
||||
first_nonmatch = v.get();
|
||||
@ -158,7 +165,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
#else
|
||||
|
||||
TOML_ASSERT(n && "key not found in table!");
|
||||
TOML_ASSERT_ASSUME(n && "key not found in table!");
|
||||
|
||||
#endif
|
||||
|
||||
@ -166,43 +173,44 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::equal(const table& lhs, const table& rhs) noexcept
|
||||
table::map_iterator table::get_lower_bound(std::string_view key) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.map_.size() != rhs.map_.size())
|
||||
return false;
|
||||
return map_.lower_bound(key);
|
||||
}
|
||||
|
||||
for (auto l = lhs.map_.begin(), r = rhs.map_.begin(), e = lhs.map_.end(); l != e; l++, r++)
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::find(std::string_view key) noexcept
|
||||
{
|
||||
return map_.find(key);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::const_iterator table::find(std::string_view key) const noexcept
|
||||
{
|
||||
return map_.find(key);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::map_iterator table::erase(const_map_iterator pos) noexcept
|
||||
{
|
||||
return map_.erase(pos);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::map_iterator table::erase(const_map_iterator begin, const_map_iterator end) noexcept
|
||||
{
|
||||
return map_.erase(begin, end);
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
size_t table::erase(std::string_view key) noexcept
|
||||
{
|
||||
if (auto it = map_.find(key); it != map_.end())
|
||||
{
|
||||
if (l->first != r->first)
|
||||
return false;
|
||||
|
||||
const auto lhs_type = l->second->type();
|
||||
const node& rhs_ = *r->second;
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = l->second->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
map_.erase(it);
|
||||
return size_t{ 1 };
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::iterator table::lower_bound(std::string_view key) noexcept
|
||||
{
|
||||
return iterator{ map_.lower_bound(key) };
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::const_iterator table::lower_bound(std::string_view key) const noexcept
|
||||
{
|
||||
return const_iterator{ map_.lower_bound(key) };
|
||||
return size_t{};
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
@ -240,6 +248,46 @@ TOML_NAMESPACE_START
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void table::clear() noexcept
|
||||
{
|
||||
map_.clear();
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::map_iterator table::insert_with_hint(const_iterator hint, key && k, impl::node_ptr && v)
|
||||
{
|
||||
return map_.emplace_hint(hint, std::move(k), std::move(v));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
bool table::equal(const table& lhs, const table& rhs) noexcept
|
||||
{
|
||||
if (&lhs == &rhs)
|
||||
return true;
|
||||
if (lhs.map_.size() != rhs.map_.size())
|
||||
return false;
|
||||
|
||||
for (auto l = lhs.map_.begin(), r = rhs.map_.begin(), e = lhs.map_.end(); l != e; l++, r++)
|
||||
{
|
||||
if (l->first != r->first)
|
||||
return false;
|
||||
|
||||
const auto lhs_type = l->second->type();
|
||||
const node& rhs_ = *r->second;
|
||||
const auto rhs_type = rhs_.type();
|
||||
if (lhs_type != rhs_type)
|
||||
return false;
|
||||
|
||||
const bool equal = l->second->visit(
|
||||
[&](const auto& lhs_) noexcept
|
||||
{ return lhs_ == *reinterpret_cast<std::remove_reference_t<decltype(lhs_)>*>(&rhs_); });
|
||||
if (!equal)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
|
@ -288,7 +288,7 @@ TOML_NAMESPACE_START
|
||||
size_t child_table_array_count{};
|
||||
for (auto&& [child_k, child_v] : child_tbl)
|
||||
{
|
||||
(void)child_k;
|
||||
TOML_UNUSED(child_k);
|
||||
const auto child_type = child_v.type();
|
||||
TOML_ASSUME(child_type != node_type::none);
|
||||
switch (child_type)
|
||||
|
@ -938,7 +938,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
constexpr void operator()(uint8_t byte) noexcept
|
||||
{
|
||||
TOML_ASSERT(!error());
|
||||
TOML_ASSERT_ASSUME(!error());
|
||||
|
||||
const auto type = state_table[byte];
|
||||
|
||||
|
@ -82,7 +82,10 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
static T make(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args&&...>)
|
||||
{
|
||||
return T(static_cast<Args&&>(args)...);
|
||||
if constexpr (std::is_aggregate_v<T>)
|
||||
return T{ static_cast<Args&&>(args)... };
|
||||
else
|
||||
return T(static_cast<Args&&>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
@ -106,18 +109,25 @@ TOML_IMPL_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
static std::string make(T&& arg) noexcept
|
||||
{
|
||||
using arg_type = std::decay_t<T>;
|
||||
#if TOML_HAS_CHAR8
|
||||
if constexpr (is_one_of<std::decay_t<T>, char8_t*, const char8_t*>)
|
||||
if constexpr (is_one_of<arg_type, char8_t*, const char8_t*>)
|
||||
{
|
||||
return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg)));
|
||||
else if constexpr (is_one_of<remove_cvref<T>, std::u8string, std::u8string_view>)
|
||||
}
|
||||
if constexpr (is_one_of<arg_type, std::u8string, std::u8string_view>)
|
||||
{
|
||||
return std::string(reinterpret_cast<const char*>(static_cast<const char8_t*>(arg.data())),
|
||||
arg.length());
|
||||
#endif // TOML_HAS_CHAR8
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
if constexpr (is_wide_string<T>)
|
||||
if constexpr (is_wide_string<arg_type>)
|
||||
{
|
||||
return narrow(static_cast<T&&>(arg));
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@ -266,6 +276,18 @@ TOML_NAMESPACE_START
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Copy constructor with flags override.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(const value& other, value_flags flags) noexcept //
|
||||
: node(other),
|
||||
val_{ other.val_ },
|
||||
flags_{ flags == preserve_source_value_flags ? other.flags_ : flags }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_VALUE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(value&& other) noexcept //
|
||||
@ -278,6 +300,18 @@ TOML_NAMESPACE_START
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Move constructor with flags override.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(value&& other, value_flags flags) noexcept //
|
||||
: node(std::move(other)),
|
||||
val_{ std::move(other.val_) },
|
||||
flags_{ flags == preserve_source_value_flags ? other.flags_ : flags }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_VALUE_CREATED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
value& operator=(const value& rhs) noexcept
|
||||
{
|
||||
@ -614,6 +648,13 @@ TOML_NAMESPACE_START
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const rvalue overload).
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type&& get() const&& noexcept
|
||||
{
|
||||
return static_cast<const value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
value_type& operator*() & noexcept
|
||||
@ -635,6 +676,13 @@ TOML_NAMESPACE_START
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const rvalue overload).
|
||||
TOML_PURE_INLINE_GETTER
|
||||
const value_type&& operator*() const&& noexcept
|
||||
{
|
||||
return static_cast<const value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator value_type&() & noexcept
|
||||
@ -656,6 +704,13 @@ TOML_NAMESPACE_START
|
||||
return val_;
|
||||
}
|
||||
|
||||
/// \brief Returns a reference to the underlying value (const rvalue overload).
|
||||
TOML_PURE_INLINE_GETTER
|
||||
explicit operator const value_type&&() && noexcept
|
||||
{
|
||||
return static_cast<const value_type&&>(val_);
|
||||
}
|
||||
|
||||
/// \brief Returns a pointer to the underlying value.
|
||||
///
|
||||
/// \availability This operator is only available when #value_type is a class/struct.
|
||||
|
@ -77,6 +77,7 @@ TOML_POP_WARNINGS;
|
||||
#undef TOML_ANON_NAMESPACE_START
|
||||
#undef TOML_ARM
|
||||
#undef TOML_ASSERT
|
||||
#undef TOML_ASSERT_ASSUME
|
||||
#undef TOML_ASSUME
|
||||
#undef TOML_ASYMMETRICAL_EQUALITY_OPS
|
||||
#undef TOML_ATTR
|
||||
@ -172,6 +173,7 @@ TOML_POP_WARNINGS;
|
||||
#undef TOML_UINT128
|
||||
#undef TOML_UNLIKELY
|
||||
#undef TOML_UNREACHABLE
|
||||
#undef TOML_UNUSED
|
||||
#endif
|
||||
|
||||
#endif // TOMLPLUSPLUS_H
|
||||
|
@ -303,25 +303,115 @@ namespace toml
|
||||
CHECK_INSERTED_AS(TOML_FLOAT16, value<double>);
|
||||
#endif
|
||||
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<double>()), double&>);
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<double>()), double&&>);
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<double>()), const double&>);
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<value<double>>()), double&>);
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<value<double>>()), double&&>);
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<value<double>>()), const double&>);
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<table>()), table&>);
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<table>()), table&&>);
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<table>()), const table&>);
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<array>()), array&>);
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<array>()), array&&>);
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<array>()), const array&>);
|
||||
#define CHECK_NODE_REF_TYPE(T) \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<T>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<volatile T>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<T&>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<volatile T&>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<T&&>()), T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<volatile T&&>()), volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&>().ref<const volatile T&&>()), const volatile T&&>); \
|
||||
\
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<T>()), T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const T>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<volatile T>()), volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const volatile T>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<T&>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<volatile T&>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<T&&>()), T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<volatile T&&>()), volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node&&>().ref<const volatile T&&>()), const volatile T&&>); \
|
||||
\
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<volatile T&&>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&>().ref<const volatile T&&>()), const volatile T&&>); \
|
||||
\
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<T>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const T>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<volatile T>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const volatile T>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<volatile T&&>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<const node&&>().ref<const volatile T&&>()), const volatile T&&>)
|
||||
|
||||
CHECK_NODE_REF_TYPE(table);
|
||||
CHECK_NODE_REF_TYPE(array);
|
||||
CHECK_NODE_REF_TYPE(std::string);
|
||||
CHECK_NODE_REF_TYPE(int64_t);
|
||||
CHECK_NODE_REF_TYPE(double);
|
||||
CHECK_NODE_REF_TYPE(bool);
|
||||
CHECK_NODE_REF_TYPE(date);
|
||||
CHECK_NODE_REF_TYPE(time);
|
||||
CHECK_NODE_REF_TYPE(date_time);
|
||||
|
||||
#define CHECK_NODE_VIEW_REF_TYPE(T) \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<T>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<volatile T>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<T&>()), T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<volatile T&>()), volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<T&&>()), T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<volatile T&&>()), volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<const volatile T&&>()), const volatile T&&>)
|
||||
|
||||
CHECK_NODE_VIEW_REF_TYPE(table);
|
||||
CHECK_NODE_VIEW_REF_TYPE(array);
|
||||
CHECK_NODE_VIEW_REF_TYPE(std::string);
|
||||
CHECK_NODE_VIEW_REF_TYPE(int64_t);
|
||||
CHECK_NODE_VIEW_REF_TYPE(double);
|
||||
CHECK_NODE_VIEW_REF_TYPE(bool);
|
||||
CHECK_NODE_VIEW_REF_TYPE(date);
|
||||
CHECK_NODE_VIEW_REF_TYPE(time);
|
||||
CHECK_NODE_VIEW_REF_TYPE(date_time);
|
||||
|
||||
#define CHECK_CONST_NODE_VIEW_REF_TYPE(T) \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const T>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const volatile T>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const T&>()), const T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const volatile T&>()), const volatile T&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const T&&>()), const T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<volatile T&&>()), const volatile T&&>); \
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<const volatile T&&>()), const volatile T&&>)
|
||||
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(table);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(array);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(std::string);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(int64_t);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(double);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(bool);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(date);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(time);
|
||||
CHECK_CONST_NODE_VIEW_REF_TYPE(date_time);
|
||||
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<double>()), double&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<double>()), const double&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<value<double>>()), double&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<value<double>>()), const double&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<table>()), table&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<table>()), const table&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<node>>().ref<array>()), array&>);
|
||||
static_assert(is_same_v<decltype(declval<node_view<const node>>().ref<array>()), const array&>);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user