summaryrefslogtreecommitdiffhomepage
path: root/vendor/toml++/impl/value.hpp
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2026-03-08 15:50:45 +0100
committerGitHub <noreply@github.com>2026-03-08 15:50:45 +0100
commit386b6ba6702aaf121a8667b68fba86385dad68ed (patch)
tree985c7eda4fafa827eaad88b6b469b0baba791817 /vendor/toml++/impl/value.hpp
parent7a469801ecb55fcde0199d4e41b1cec3a17dcb05 (diff)
parentddb1cbc831b6d13b985d91022f01e955e24ae871 (diff)
Merge pull request #25 from ne-foss-org/nebuild-patches-deref
[CHORE] Patching TOML manifest parser to avoid null deref.
Diffstat (limited to 'vendor/toml++/impl/value.hpp')
-rw-r--r--vendor/toml++/impl/value.hpp1964
1 files changed, 859 insertions, 1105 deletions
diff --git a/vendor/toml++/impl/value.hpp b/vendor/toml++/impl/value.hpp
index 6fb35dc..964e90d 100644
--- a/vendor/toml++/impl/value.hpp
+++ b/vendor/toml++/impl/value.hpp
@@ -1,14 +1,14 @@
-//# This file is a part of toml++ and is subject to the the terms of the MIT license.
-//# Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
-//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
-// SPDX-License-Identifier: MIT
+// # This file is a part of toml++ and is subject to the the terms of the MIT license.
+// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
+// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
+// SPDX-License-Identifier: MIT
#pragma once
#include "date_time.hpp"
+#include "header_start.hpp"
#include "node.hpp"
#include "print_to_stream.hpp"
#include "std_utility.hpp"
-#include "header_start.hpp"
TOML_DISABLE_ARITHMETIC_WARNINGS;
/// \cond
@@ -74,1136 +74,892 @@ TOML_DISABLE_ARITHMETIC_WARNINGS;
/// \endcond
/// \cond
-TOML_IMPL_NAMESPACE_START
-{
- template <typename T, typename...>
- struct native_value_maker
- {
- template <typename... Args>
- TOML_NODISCARD
- static T make(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args&&...>)
- {
- if constexpr (std::is_aggregate_v<T>)
- return T{ static_cast<Args&&>(args)... };
- else
- return T(static_cast<Args&&>(args)...);
- }
- };
-
- template <typename T>
- struct native_value_maker<T, T>
- {
- template <typename U>
- TOML_NODISCARD
- TOML_ALWAYS_INLINE
- static U&& make(U&& val) noexcept
- {
- return static_cast<U&&>(val);
- }
- };
+TOML_IMPL_NAMESPACE_START {
+ template <typename T, typename...>
+ struct native_value_maker {
+ template <typename... Args>
+ TOML_NODISCARD static T make(Args&&... args) noexcept(
+ std::is_nothrow_constructible_v<T, Args&&...>) {
+ if constexpr (std::is_aggregate_v<T>)
+ return T{static_cast<Args&&>(args)...};
+ else
+ return T(static_cast<Args&&>(args)...);
+ }
+ };
+
+ template <typename T>
+ struct native_value_maker<T, T> {
+ template <typename U>
+ TOML_NODISCARD TOML_ALWAYS_INLINE static U&& make(U&& val) noexcept {
+ return static_cast<U&&>(val);
+ }
+ };
#if TOML_HAS_CHAR8 || TOML_ENABLE_WINDOWS_COMPAT
- struct string_maker
- {
- template <typename T>
- TOML_NODISCARD
- static std::string make(T&& arg)
- {
- using arg_type = std::decay_t<T>;
+ struct string_maker {
+ template <typename T>
+ TOML_NODISCARD static std::string make(T&& arg) {
+ using arg_type = std::decay_t<T>;
#if TOML_HAS_CHAR8
- 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)));
- }
- 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());
- }
+ 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)));
+ }
+ 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
#if TOML_ENABLE_WINDOWS_COMPAT
- if constexpr (is_wide_string<arg_type>)
- {
- return narrow(static_cast<T&&>(arg));
- }
+ if constexpr (is_wide_string<arg_type>) {
+ return narrow(static_cast<T&&>(arg));
+ }
#endif
- }
- };
+ }
+ };
#if TOML_HAS_CHAR8
- template <>
- struct native_value_maker<std::string, char8_t*> : string_maker
- {};
- template <>
- struct native_value_maker<std::string, const char8_t*> : string_maker
- {};
- template <>
- struct native_value_maker<std::string, std::u8string> : string_maker
- {};
- template <>
- struct native_value_maker<std::string, std::u8string_view> : string_maker
- {};
-#endif // TOML_HAS_CHAR8
+ template <>
+ struct native_value_maker<std::string, char8_t*> : string_maker {};
+ template <>
+ struct native_value_maker<std::string, const char8_t*> : string_maker {};
+ template <>
+ struct native_value_maker<std::string, std::u8string> : string_maker {};
+ template <>
+ struct native_value_maker<std::string, std::u8string_view> : string_maker {};
+#endif // TOML_HAS_CHAR8
#if TOML_ENABLE_WINDOWS_COMPAT
- template <>
- struct native_value_maker<std::string, wchar_t*> : string_maker
- {};
- template <>
- struct native_value_maker<std::string, const wchar_t*> : string_maker
- {};
- template <>
- struct native_value_maker<std::string, std::wstring> : string_maker
- {};
- template <>
- struct native_value_maker<std::string, std::wstring_view> : string_maker
- {};
-#endif // TOML_ENABLE_WINDOWS_COMPAT
-
-#endif // TOML_HAS_CHAR8 || TOML_ENABLE_WINDOWS_COMPAT
-
- template <typename T>
- TOML_CONST_GETTER
- inline optional<T> node_integer_cast(int64_t val) noexcept
- {
- static_assert(node_type_of<T> == node_type::integer);
- static_assert(!is_cvref<T>);
-
- using traits = value_traits<T>;
- if constexpr (!traits::is_signed)
- {
- if constexpr ((sizeof(T) * CHAR_BIT) < 63) // 63 bits == int64_max
- {
- using common_t = decltype(int64_t{} + T{});
- if (val < int64_t{} || static_cast<common_t>(val) > static_cast<common_t>(traits::max))
- return {};
- }
- else
- {
- if (val < int64_t{})
- return {};
- }
- }
- else
- {
- if (val < traits::min || val > traits::max)
- return {};
- }
- return { static_cast<T>(val) };
- }
-
- template <typename...>
- struct value_variadic_ctor_allowed : std::true_type
- {};
-
- template <typename T, typename... Args>
- struct value_variadic_ctor_allowed<value<T>, value<T>, Args...> : std::false_type
- {};
+ template <>
+ struct native_value_maker<std::string, wchar_t*> : string_maker {};
+ template <>
+ struct native_value_maker<std::string, const wchar_t*> : string_maker {};
+ template <>
+ struct native_value_maker<std::string, std::wstring> : string_maker {};
+ template <>
+ struct native_value_maker<std::string, std::wstring_view> : string_maker {};
+#endif // TOML_ENABLE_WINDOWS_COMPAT
+
+#endif // TOML_HAS_CHAR8 || TOML_ENABLE_WINDOWS_COMPAT
+
+ template <typename T>
+ TOML_CONST_GETTER inline optional<T> node_integer_cast(int64_t val) noexcept {
+ static_assert(node_type_of<T> == node_type::integer);
+ static_assert(!is_cvref<T>);
+
+ using traits = value_traits<T>;
+ if constexpr (!traits::is_signed) {
+ if constexpr ((sizeof(T) * CHAR_BIT) < 63) // 63 bits == int64_max
+ {
+ using common_t = decltype(int64_t{} + T{});
+ if (val < int64_t{} || static_cast<common_t>(val) > static_cast<common_t>(traits::max))
+ return {};
+ } else {
+ if (val < int64_t{}) return {};
+ }
+ } else {
+ if (val < traits::min || val > traits::max) return {};
+ }
+ return {static_cast<T>(val)};
+ }
+
+ template <typename...>
+ struct value_variadic_ctor_allowed : std::true_type {};
+
+ template <typename T, typename... Args>
+ struct value_variadic_ctor_allowed<value<T>, value<T>, Args...> : std::false_type {};
}
TOML_IMPL_NAMESPACE_END;
/// \endcond
-TOML_NAMESPACE_START
-{
- /// \brief A TOML value.
- ///
- /// \tparam ValueType The value's native TOML data type. Can be one of:
- /// - std::string
- /// - toml::date
- /// - toml::time
- /// - toml::date_time
- /// - int64_t
- /// - double
- /// - bool
- template <typename ValueType>
- class value : public node
- {
- static_assert(impl::is_native<ValueType> && !impl::is_cvref<ValueType>,
- "A toml::value<> must model one of the native TOML value types:" TOML_SA_NATIVE_VALUE_TYPE_LIST);
-
- private:
- /// \cond
-
- friend class TOML_PARSER_TYPENAME;
-
- template <typename T, typename U>
- TOML_CONST_INLINE_GETTER
- static auto as_value([[maybe_unused]] U* ptr) noexcept
- {
- if constexpr (std::is_same_v<value_type, T>)
- return ptr;
- else
- return nullptr;
- }
-
- ValueType val_;
- value_flags flags_ = value_flags::none;
-
- /// \endcond
-
- public:
- /// \brief The value's underlying data type.
- using value_type = ValueType;
-
- /// \brief A type alias for 'value arguments'.
- /// \details This differs according to the value's type argument:
- /// - ints, floats, booleans: `value_type`
- /// - strings: `string_view`
- /// - everything else: `const value_type&`
- using value_arg = POXY_IMPLEMENTATION_DETAIL(
- std::conditional_t<
- std::is_same_v<value_type, std::string>,
- std::string_view,
- std::conditional_t<impl::is_one_of<value_type, double, int64_t, bool>, value_type, const value_type&>>);
-
- /// \brief Constructs a toml value.
- ///
- /// \tparam Args Constructor argument types.
- /// \param args Arguments to forward to the internal value's constructor.
- TOML_HIDDEN_CONSTRAINT(
- (impl::value_variadic_ctor_allowed<value<ValueType>, impl::remove_cvref<Args>...>::value),
- typename... Args)
- TOML_NODISCARD_CTOR
- explicit value(Args&&... args) noexcept(noexcept(value_type(
- impl::native_value_maker<value_type, std::decay_t<Args>...>::make(static_cast<Args&&>(args)...))))
- : val_(impl::native_value_maker<value_type, std::decay_t<Args>...>::make(static_cast<Args&&>(args)...))
- {
+TOML_NAMESPACE_START {
+ /// \brief A TOML value.
+ ///
+ /// \tparam ValueType The value's native TOML data type. Can be one of:
+ /// - std::string
+ /// - toml::date
+ /// - toml::time
+ /// - toml::date_time
+ /// - int64_t
+ /// - double
+ /// - bool
+ template <typename ValueType>
+ class value : public node {
+ static_assert(impl::is_native<ValueType> && !impl::is_cvref<ValueType>,
+ "A toml::value<> must model one of the native TOML value "
+ "types:" TOML_SA_NATIVE_VALUE_TYPE_LIST);
+
+ private:
+ /// \cond
+
+ friend class TOML_PARSER_TYPENAME;
+
+ template <typename T, typename U>
+ TOML_CONST_INLINE_GETTER static auto as_value([[maybe_unused]] U* ptr) noexcept {
+ if constexpr (std::is_same_v<value_type, T>)
+ return ptr;
+ else
+ return nullptr;
+ }
+
+ ValueType val_;
+ value_flags flags_ = value_flags::none;
+
+ /// \endcond
+
+ public:
+ /// \brief The value's underlying data type.
+ using value_type = ValueType;
+
+ /// \brief A type alias for 'value arguments'.
+ /// \details This differs according to the value's type argument:
+ /// - ints, floats, booleans: `value_type`
+ /// - strings: `string_view`
+ /// - everything else: `const value_type&`
+ using value_arg = POXY_IMPLEMENTATION_DETAIL(
+ std::conditional_t<std::is_same_v<value_type, std::string>, std::string_view,
+ std::conditional_t<impl::is_one_of<value_type, double, int64_t, bool>,
+ value_type, const value_type&>>);
+
+ /// \brief Constructs a toml value.
+ ///
+ /// \tparam Args Constructor argument types.
+ /// \param args Arguments to forward to the internal value's constructor.
+ TOML_HIDDEN_CONSTRAINT(
+ (impl::value_variadic_ctor_allowed<value<ValueType>, impl::remove_cvref<Args>...>::value),
+ typename... Args)
+ TOML_NODISCARD_CTOR
+ explicit value(Args&&... args) noexcept(
+ noexcept(value_type(impl::native_value_maker<value_type, std::decay_t<Args>...>::make(
+ static_cast<Args&&>(args)...))))
+ : val_(impl::native_value_maker<value_type, std::decay_t<Args>...>::make(
+ static_cast<Args&&>(args)...)) {
#if TOML_LIFETIME_HOOKS
- TOML_VALUE_CREATED;
+ TOML_VALUE_CREATED;
#endif
- }
-
- /// \brief Copy constructor.
- TOML_NODISCARD_CTOR
- value(const value& other) noexcept //
- : node(other),
- val_{ other.val_ },
- flags_{ other.flags_ }
- {
+ }
+
+ /// \brief Copy constructor.
+ TOML_NODISCARD_CTOR
+ value(const value& other) noexcept //
+ : node(other), val_{other.val_}, flags_{other.flags_} {
#if TOML_LIFETIME_HOOKS
- TOML_VALUE_CREATED;
+ TOML_VALUE_CREATED;
#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 }
- {
+ }
+
+ /// \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;
+ TOML_VALUE_CREATED;
#endif
- }
-
- /// \brief Move constructor.
- TOML_NODISCARD_CTOR
- value(value&& other) noexcept //
- : node(std::move(other)),
- val_{ std::move(other.val_) },
- flags_{ std::exchange(other.flags_, value_flags{}) }
- {
+ }
+
+ /// \brief Move constructor.
+ TOML_NODISCARD_CTOR
+ value(value&& other) noexcept //
+ : node(std::move(other)),
+ val_{std::move(other.val_)},
+ flags_{std::exchange(other.flags_, value_flags{})} {
#if TOML_LIFETIME_HOOKS
- TOML_VALUE_CREATED;
+ TOML_VALUE_CREATED;
#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 }
- {
+ }
+
+ /// \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;
+ TOML_VALUE_CREATED;
#endif
- other.flags_ = {};
- }
-
- /// \brief Copy-assignment operator.
- value& operator=(const value& rhs) noexcept
- {
- node::operator=(rhs);
- val_ = rhs.val_;
- flags_ = rhs.flags_;
- return *this;
- }
-
- /// \brief Move-assignment operator.
- value& operator=(value&& rhs) noexcept
- {
- if (&rhs != this)
- {
- node::operator=(std::move(rhs));
- val_ = std::move(rhs.val_);
- flags_ = std::exchange(rhs.flags_, value_flags{});
- }
- return *this;
- }
+ other.flags_ = {};
+ }
+
+ /// \brief Copy-assignment operator.
+ value& operator=(const value& rhs) noexcept {
+ node::operator=(rhs);
+ val_ = rhs.val_;
+ flags_ = rhs.flags_;
+ return *this;
+ }
+
+ /// \brief Move-assignment operator.
+ value& operator=(value&& rhs) noexcept {
+ if (&rhs != this) {
+ node::operator=(std::move(rhs));
+ val_ = std::move(rhs.val_);
+ flags_ = std::exchange(rhs.flags_, value_flags{});
+ }
+ return *this;
+ }
#if TOML_LIFETIME_HOOKS
- ~value() noexcept
- {
- TOML_VALUE_DESTROYED;
- }
+ ~value() noexcept { TOML_VALUE_DESTROYED; }
#endif
- /// \name Type checks
- /// @{
-
- /// \brief Returns the value's node type identifier.
- ///
- /// \returns One of:
- /// - node_type::string
- /// - node_type::integer
- /// - node_type::floating_point
- /// - node_type::boolean
- /// - node_type::date
- /// - node_type::time
- /// - node_type::date_time
- TOML_CONST_INLINE_GETTER
- node_type type() const noexcept final
- {
- return impl::node_type_of<value_type>;
- }
-
- TOML_PURE_GETTER
- bool is_homogeneous(node_type ntype) const noexcept final
- {
- return ntype == node_type::none || ntype == impl::node_type_of<value_type>;
- }
-
- TOML_PURE_GETTER
- bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final
- {
- if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
- {
- first_nonmatch = this;
- return false;
- }
- return true;
- }
-
- TOML_PURE_GETTER
- bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final
- {
- if (ntype != node_type::none && ntype != impl::node_type_of<value_type>)
- {
- first_nonmatch = this;
- return false;
- }
- return true;
- }
-
- /// \cond
- template <typename ElemType = void>
- TOML_PURE_GETTER
- bool is_homogeneous() const noexcept
- {
- using type = impl::remove_cvref<impl::unwrap_node<ElemType>>;
- static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>,
- "The template type argument of value::is_homogeneous() must be void or one "
- "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
-
- if constexpr (std::is_void_v<type>)
- return true;
- else
- return impl::node_type_of<type> == impl::node_type_of<value_type>;
- }
- /// \endcond
-
- /// \brief Returns `false`.
- TOML_CONST_INLINE_GETTER
- bool is_table() const noexcept final
- {
- return false;
- }
-
- /// \brief Returns `false`.
- TOML_CONST_INLINE_GETTER
- bool is_array() const noexcept final
- {
- return false;
- }
-
- /// \brief Returns `false`.
- TOML_CONST_INLINE_GETTER
- bool is_array_of_tables() const noexcept final
- {
- return false;
- }
-
- /// \brief Returns `true`.
- TOML_CONST_INLINE_GETTER
- bool is_value() const noexcept final
- {
- return true;
- }
-
- /// \brief Returns `true` if the #value_type is std::string.
- TOML_CONST_INLINE_GETTER
- bool is_string() const noexcept final
- {
- return std::is_same_v<value_type, std::string>;
- }
-
- /// \brief Returns `true` if the #value_type is int64_t.
- TOML_CONST_INLINE_GETTER
- bool is_integer() const noexcept final
- {
- return std::is_same_v<value_type, int64_t>;
- }
-
- /// \brief Returns `true` if the #value_type is `double`.
- TOML_CONST_INLINE_GETTER
- bool is_floating_point() const noexcept final
- {
- return std::is_same_v<value_type, double>;
- }
-
- /// \brief Returns `true` if the #value_type is int64_t or `double`.
- TOML_CONST_INLINE_GETTER
- bool is_number() const noexcept final
- {
- return impl::is_one_of<value_type, int64_t, double>;
- }
-
- /// \brief Returns `true` if the #value_type is `bool`.
- TOML_CONST_INLINE_GETTER
- bool is_boolean() const noexcept final
- {
- return std::is_same_v<value_type, bool>;
- }
-
- /// \brief Returns `true` if the #value_type is toml::date.
- TOML_CONST_INLINE_GETTER
- bool is_date() const noexcept final
- {
- return std::is_same_v<value_type, date>;
- }
-
- /// \brief Returns `true` if the #value_type is toml::time.
- TOML_CONST_INLINE_GETTER
- bool is_time() const noexcept final
- {
- return std::is_same_v<value_type, time>;
- }
-
- /// \brief Returns `true` if the #value_type is toml_date_time.
- TOML_CONST_INLINE_GETTER
- bool is_date_time() const noexcept final
- {
- return std::is_same_v<value_type, date_time>;
- }
-
- /// @}
-
- /// \name Type casts
- /// @{
-
- /// \brief Returns `nullptr`.
- TOML_CONST_INLINE_GETTER
- table* as_table() noexcept final
- {
- return nullptr;
- }
-
- /// \brief Returns `nullptr`.
- TOML_CONST_INLINE_GETTER
- array* as_array() noexcept final
- {
- return nullptr;
- }
-
- /// \brief Returns a pointer to the value if it is a value<std::string>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- value<std::string>* as_string() noexcept final
- {
- return as_value<std::string>(this);
- }
-
- /// \brief Returns a pointer to the value if it is a value<int64_t>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- value<int64_t>* as_integer() noexcept final
- {
- return as_value<int64_t>(this);
- }
-
- /// \brief Returns a pointer to the value if it is a value<double>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- value<double>* as_floating_point() noexcept final
- {
- return as_value<double>(this);
- }
-
- /// \brief Returns a pointer to the value if it is a value<bool>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- value<bool>* as_boolean() noexcept final
- {
- return as_value<bool>(this);
- }
-
- /// \brief Returns a pointer to the value if it is a value<date>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- value<date>* as_date() noexcept final
- {
- return as_value<date>(this);
- }
-
- /// \brief Returns a pointer to the value if it is a value<time>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- value<time>* as_time() noexcept final
- {
- return as_value<time>(this);
- }
-
- /// \brief Returns a pointer to the value if it is a value<date_time>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- value<date_time>* as_date_time() noexcept final
- {
- return as_value<date_time>(this);
- }
-
- /// \brief Returns `nullptr`.
- TOML_CONST_INLINE_GETTER
- const table* as_table() const noexcept final
- {
- return nullptr;
- }
-
- /// \brief Returns `nullptr`.
- TOML_CONST_INLINE_GETTER
- const array* as_array() const noexcept final
- {
- return nullptr;
- }
-
- /// \brief Returns a const-qualified pointer to the value if it is a value<std::string>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- const value<std::string>* as_string() const noexcept final
- {
- return as_value<std::string>(this);
- }
-
- /// \brief Returns a const-qualified pointer to the value if it is a value<int64_t>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- const value<int64_t>* as_integer() const noexcept final
- {
- return as_value<int64_t>(this);
- }
-
- /// \brief Returns a const-qualified pointer to the value if it is a value<double>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- const value<double>* as_floating_point() const noexcept final
- {
- return as_value<double>(this);
- }
-
- /// \brief Returns a const-qualified pointer to the value if it is a value<bool>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- const value<bool>* as_boolean() const noexcept final
- {
- return as_value<bool>(this);
- }
-
- /// \brief Returns a const-qualified pointer to the value if it is a value<date>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- const value<date>* as_date() const noexcept final
- {
- return as_value<date>(this);
- }
-
- /// \brief Returns a const-qualified pointer to the value if it is a value<time>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- const value<time>* as_time() const noexcept final
- {
- return as_value<time>(this);
- }
-
- /// \brief Returns a const-qualified pointer to the value if it is a value<date_time>, otherwise `nullptr`.
- TOML_CONST_INLINE_GETTER
- const value<date_time>* as_date_time() const noexcept final
- {
- return as_value<date_time>(this);
- }
-
- /// @}
-
- /// \name Value retrieval
- /// @{
-
- /// \brief Returns a reference to the underlying value.
- TOML_PURE_INLINE_GETTER
- value_type& get() & noexcept
- {
- return val_;
- }
-
- /// \brief Returns a reference to the underlying value (rvalue overload).
- TOML_PURE_INLINE_GETTER
- value_type&& get() && noexcept
- {
- return static_cast<value_type&&>(val_);
- }
-
- /// \brief Returns a reference to the underlying value (const overload).
- TOML_PURE_INLINE_GETTER
- const value_type& get() const& noexcept
- {
- 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
- {
- return val_;
- }
-
- /// \brief Returns a reference to the underlying value (rvalue overload).
- TOML_PURE_INLINE_GETTER
- value_type&& operator*() && noexcept
- {
- return static_cast<value_type&&>(val_);
- }
-
- /// \brief Returns a reference to the underlying value (const overload).
- TOML_PURE_INLINE_GETTER
- const value_type& operator*() const& noexcept
- {
- 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
- {
- return val_;
- }
-
- /// \brief Returns a reference to the underlying value (rvalue overload).
- TOML_PURE_INLINE_GETTER
- explicit operator value_type&&() && noexcept
- {
- return static_cast<value_type&&>(val_);
- }
-
- /// \brief Returns a reference to the underlying value (const overload).
- TOML_PURE_INLINE_GETTER
- explicit operator const value_type&() const& noexcept
- {
- 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.
- TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type)
- TOML_PURE_INLINE_GETTER
- value_type* operator->() noexcept
- {
- return &val_;
- }
-
- /// \brief Returns a pointer to the underlying value (const overload).
- ///
- /// \availability This operator is only available when #value_type is a class/struct.
- TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type)
- TOML_PURE_INLINE_GETTER
- const value_type* operator->() const noexcept
- {
- return &val_;
- }
-
- /// @}
-
- /// \name Metadata
- /// @{
-
- /// \brief Returns the metadata flags associated with this value.
- TOML_NODISCARD
- value_flags flags() const noexcept
- {
- return flags_;
- }
-
- /// \brief Sets the metadata flags associated with this value.
- /// \returns A reference to the value object.
- value& flags(value_flags new_flags) noexcept
- {
- flags_ = new_flags;
- return *this;
- }
-
- /// @}
-
- /// \brief Value-assignment operator.
- value& operator=(value_arg rhs) noexcept
- {
- if constexpr (std::is_same_v<value_type, std::string>)
- val_.assign(rhs);
- else
- val_ = rhs;
- return *this;
- }
-
- TOML_CONSTRAINED_TEMPLATE((std::is_same_v<T, std::string>), typename T = value_type)
- value& operator=(std::string&& rhs) noexcept
- {
- val_ = std::move(rhs);
- return *this;
- }
-
- /// \name Equality and Comparison
- /// @{
-
- /// \brief Value equality operator.
- TOML_PURE_GETTER
- friend bool operator==(const value& lhs, value_arg rhs) noexcept
- {
- if constexpr (std::is_same_v<value_type, double>)
- {
- const auto lhs_nan = impl::fpclassify(lhs.val_) == impl::fp_class::nan;
- const auto rhs_nan = impl::fpclassify(rhs) == impl::fp_class::nan;
- if (lhs_nan != rhs_nan)
- return false;
- if (lhs_nan)
- return true;
- }
- return lhs.val_ == rhs;
- }
- TOML_ASYMMETRICAL_EQUALITY_OPS(const value&, value_arg, );
-
- /// \brief Value less-than operator.
- TOML_PURE_GETTER
- friend bool operator<(const value& lhs, value_arg rhs) noexcept
- {
- return lhs.val_ < rhs;
- }
-
- /// \brief Value less-than operator.
- TOML_PURE_GETTER
- friend bool operator<(value_arg lhs, const value& rhs) noexcept
- {
- return lhs < rhs.val_;
- }
-
- /// \brief Value less-than-or-equal-to operator.
- TOML_PURE_GETTER
- friend bool operator<=(const value& lhs, value_arg rhs) noexcept
- {
- return lhs.val_ <= rhs;
- }
-
- /// \brief Value less-than-or-equal-to operator.
- TOML_PURE_GETTER
- friend bool operator<=(value_arg lhs, const value& rhs) noexcept
- {
- return lhs <= rhs.val_;
- }
-
- /// \brief Value greater-than operator.
- TOML_PURE_GETTER
- friend bool operator>(const value& lhs, value_arg rhs) noexcept
- {
- return lhs.val_ > rhs;
- }
-
- /// \brief Value greater-than operator.
- TOML_PURE_GETTER
- friend bool operator>(value_arg lhs, const value& rhs) noexcept
- {
- return lhs > rhs.val_;
- }
-
- /// \brief Value greater-than-or-equal-to operator.
- TOML_PURE_GETTER
- friend bool operator>=(const value& lhs, value_arg rhs) noexcept
- {
- return lhs.val_ >= rhs;
- }
-
- /// \brief Value greater-than-or-equal-to operator.
- TOML_PURE_GETTER
- friend bool operator>=(value_arg lhs, const value& rhs) noexcept
- {
- return lhs >= rhs.val_;
- }
-
- /// \brief Equality operator.
- ///
- /// \param lhs The LHS value.
- /// \param rhs The RHS value.
- ///
- /// \returns True if the values were of the same type and contained the same value.
- template <typename T>
- TOML_PURE_GETTER
- friend bool operator==(const value& lhs, const value<T>& rhs) noexcept
- {
- if constexpr (std::is_same_v<value_type, T>)
- return lhs == rhs.val_; // calls asymmetrical value-equality operator defined above
- else
- return false;
- }
-
- /// \brief Inequality operator.
- ///
- /// \param lhs The LHS value.
- /// \param rhs The RHS value.
- ///
- /// \returns True if the values were not of the same type, or did not contain the same value.
- template <typename T>
- TOML_PURE_INLINE_GETTER
- friend bool operator!=(const value& lhs, const value<T>& rhs) noexcept
- {
- return !(lhs == rhs);
- }
-
- /// \brief Less-than operator.
- ///
- /// \param lhs The LHS toml::value.
- /// \param rhs The RHS toml::value.
- ///
- /// \returns \conditional_return{Same value types}
- /// `lhs.get() < rhs.get()`
- /// \conditional_return{Different value types}
- /// `lhs.type() < rhs.type()`
- template <typename T>
- TOML_PURE_GETTER
- friend bool operator<(const value& lhs, const value<T>& rhs) noexcept
- {
- if constexpr (std::is_same_v<value_type, T>)
- return lhs.val_ < rhs.val_;
- else
- return impl::node_type_of<value_type> < impl::node_type_of<T>;
- }
-
- /// \brief Less-than-or-equal-to operator.
- ///
- /// \param lhs The LHS toml::value.
- /// \param rhs The RHS toml::value.
- ///
- /// \returns \conditional_return{Same value types}
- /// `lhs.get() <= rhs.get()`
- /// \conditional_return{Different value types}
- /// `lhs.type() <= rhs.type()`
- template <typename T>
- TOML_PURE_GETTER
- friend bool operator<=(const value& lhs, const value<T>& rhs) noexcept
- {
- if constexpr (std::is_same_v<value_type, T>)
- return lhs.val_ <= rhs.val_;
- else
- return impl::node_type_of<value_type> <= impl::node_type_of<T>;
- }
-
- /// \brief Greater-than operator.
- ///
- /// \param lhs The LHS toml::value.
- /// \param rhs The RHS toml::value.
- ///
- /// \returns \conditional_return{Same value types}
- /// `lhs.get() > rhs.get()`
- /// \conditional_return{Different value types}
- /// `lhs.type() > rhs.type()`
- template <typename T>
- TOML_PURE_GETTER
- friend bool operator>(const value& lhs, const value<T>& rhs) noexcept
- {
- if constexpr (std::is_same_v<value_type, T>)
- return lhs.val_ > rhs.val_;
- else
- return impl::node_type_of<value_type> > impl::node_type_of<T>;
- }
-
- /// \brief Greater-than-or-equal-to operator.
- ///
- /// \param lhs The LHS toml::value.
- /// \param rhs The RHS toml::value.
- ///
- /// \returns \conditional_return{Same value types}
- /// `lhs.get() >= rhs.get()`
- /// \conditional_return{Different value types}
- /// `lhs.type() >= rhs.type()`
- template <typename T>
- TOML_PURE_GETTER
- friend bool operator>=(const value& lhs, const value<T>& rhs) noexcept
- {
- if constexpr (std::is_same_v<value_type, T>)
- return lhs.val_ >= rhs.val_;
- else
- return impl::node_type_of<value_type> >= impl::node_type_of<T>;
- }
-
- /// @}
+ /// \name Type checks
+ /// @{
+
+ /// \brief Returns the value's node type identifier.
+ ///
+ /// \returns One of:
+ /// - node_type::string
+ /// - node_type::integer
+ /// - node_type::floating_point
+ /// - node_type::boolean
+ /// - node_type::date
+ /// - node_type::time
+ /// - node_type::date_time
+ TOML_CONST_INLINE_GETTER
+ node_type type() const noexcept final { return impl::node_type_of<value_type>; }
+
+ TOML_PURE_GETTER
+ bool is_homogeneous(node_type ntype) const noexcept final {
+ return ntype == node_type::none || ntype == impl::node_type_of<value_type>;
+ }
+
+ TOML_PURE_GETTER
+ bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final {
+ if (ntype != node_type::none && ntype != impl::node_type_of<value_type>) {
+ first_nonmatch = this;
+ return false;
+ }
+ return true;
+ }
+
+ TOML_PURE_GETTER
+ bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final {
+ if (ntype != node_type::none && ntype != impl::node_type_of<value_type>) {
+ first_nonmatch = this;
+ return false;
+ }
+ return true;
+ }
+
+ /// \cond
+ template <typename ElemType = void>
+ TOML_PURE_GETTER bool is_homogeneous() const noexcept {
+ using type = impl::remove_cvref<impl::unwrap_node<ElemType>>;
+ static_assert(std::is_void_v<type> || toml::is_value<type> || toml::is_container<type>,
+ "The template type argument of value::is_homogeneous() must be void or one "
+ "of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
+
+ if constexpr (std::is_void_v<type>)
+ return true;
+ else
+ return impl::node_type_of<type> == impl::node_type_of<value_type>;
+ }
+ /// \endcond
+
+ /// \brief Returns `false`.
+ TOML_CONST_INLINE_GETTER
+ bool is_table() const noexcept final { return false; }
+
+ /// \brief Returns `false`.
+ TOML_CONST_INLINE_GETTER
+ bool is_array() const noexcept final { return false; }
+
+ /// \brief Returns `false`.
+ TOML_CONST_INLINE_GETTER
+ bool is_array_of_tables() const noexcept final { return false; }
+
+ /// \brief Returns `true`.
+ TOML_CONST_INLINE_GETTER
+ bool is_value() const noexcept final { return true; }
+
+ /// \brief Returns `true` if the #value_type is std::string.
+ TOML_CONST_INLINE_GETTER
+ bool is_string() const noexcept final { return std::is_same_v<value_type, std::string>; }
+
+ /// \brief Returns `true` if the #value_type is int64_t.
+ TOML_CONST_INLINE_GETTER
+ bool is_integer() const noexcept final { return std::is_same_v<value_type, int64_t>; }
+
+ /// \brief Returns `true` if the #value_type is `double`.
+ TOML_CONST_INLINE_GETTER
+ bool is_floating_point() const noexcept final { return std::is_same_v<value_type, double>; }
+
+ /// \brief Returns `true` if the #value_type is int64_t or `double`.
+ TOML_CONST_INLINE_GETTER
+ bool is_number() const noexcept final { return impl::is_one_of<value_type, int64_t, double>; }
+
+ /// \brief Returns `true` if the #value_type is `bool`.
+ TOML_CONST_INLINE_GETTER
+ bool is_boolean() const noexcept final { return std::is_same_v<value_type, bool>; }
+
+ /// \brief Returns `true` if the #value_type is toml::date.
+ TOML_CONST_INLINE_GETTER
+ bool is_date() const noexcept final { return std::is_same_v<value_type, date>; }
+
+ /// \brief Returns `true` if the #value_type is toml::time.
+ TOML_CONST_INLINE_GETTER
+ bool is_time() const noexcept final { return std::is_same_v<value_type, time>; }
+
+ /// \brief Returns `true` if the #value_type is toml_date_time.
+ TOML_CONST_INLINE_GETTER
+ bool is_date_time() const noexcept final { return std::is_same_v<value_type, date_time>; }
+
+ /// @}
+
+ /// \name Type casts
+ /// @{
+
+ /// \brief Returns `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ table* as_table() noexcept final { return nullptr; }
+
+ /// \brief Returns `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ array* as_array() noexcept final { return nullptr; }
+
+ /// \brief Returns a pointer to the value if it is a value<std::string>, otherwise `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ value<std::string>* as_string() noexcept final { return as_value<std::string>(this); }
+
+ /// \brief Returns a pointer to the value if it is a value<int64_t>, otherwise `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ value<int64_t>* as_integer() noexcept final { return as_value<int64_t>(this); }
+
+ /// \brief Returns a pointer to the value if it is a value<double>, otherwise `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ value<double>* as_floating_point() noexcept final { return as_value<double>(this); }
+
+ /// \brief Returns a pointer to the value if it is a value<bool>, otherwise `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ value<bool>* as_boolean() noexcept final { return as_value<bool>(this); }
+
+ /// \brief Returns a pointer to the value if it is a value<date>, otherwise `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ value<date>* as_date() noexcept final { return as_value<date>(this); }
+
+ /// \brief Returns a pointer to the value if it is a value<time>, otherwise `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ value<time>* as_time() noexcept final { return as_value<time>(this); }
+
+ /// \brief Returns a pointer to the value if it is a value<date_time>, otherwise `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ value<date_time>* as_date_time() noexcept final { return as_value<date_time>(this); }
+
+ /// \brief Returns `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ const table* as_table() const noexcept final { return nullptr; }
+
+ /// \brief Returns `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ const array* as_array() const noexcept final { return nullptr; }
+
+ /// \brief Returns a const-qualified pointer to the value if it is a value<std::string>,
+ /// otherwise `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ const value<std::string>* as_string() const noexcept final {
+ return as_value<std::string>(this);
+ }
+
+ /// \brief Returns a const-qualified pointer to the value if it is a value<int64_t>, otherwise
+ /// `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ const value<int64_t>* as_integer() const noexcept final { return as_value<int64_t>(this); }
+
+ /// \brief Returns a const-qualified pointer to the value if it is a value<double>, otherwise
+ /// `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ const value<double>* as_floating_point() const noexcept final { return as_value<double>(this); }
+
+ /// \brief Returns a const-qualified pointer to the value if it is a value<bool>, otherwise
+ /// `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ const value<bool>* as_boolean() const noexcept final { return as_value<bool>(this); }
+
+ /// \brief Returns a const-qualified pointer to the value if it is a value<date>, otherwise
+ /// `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ const value<date>* as_date() const noexcept final { return as_value<date>(this); }
+
+ /// \brief Returns a const-qualified pointer to the value if it is a value<time>, otherwise
+ /// `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ const value<time>* as_time() const noexcept final { return as_value<time>(this); }
+
+ /// \brief Returns a const-qualified pointer to the value if it is a value<date_time>, otherwise
+ /// `nullptr`.
+ TOML_CONST_INLINE_GETTER
+ const value<date_time>* as_date_time() const noexcept final {
+ return as_value<date_time>(this);
+ }
+
+ /// @}
+
+ /// \name Value retrieval
+ /// @{
+
+ /// \brief Returns a reference to the underlying value.
+ TOML_PURE_INLINE_GETTER
+ value_type& get() & noexcept { return val_; }
+
+ /// \brief Returns a reference to the underlying value (rvalue overload).
+ TOML_PURE_INLINE_GETTER
+ value_type&& get() && noexcept { return static_cast<value_type&&>(val_); }
+
+ /// \brief Returns a reference to the underlying value (const overload).
+ TOML_PURE_INLINE_GETTER
+ const value_type& get() const& noexcept { 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 { return val_; }
+
+ /// \brief Returns a reference to the underlying value (rvalue overload).
+ TOML_PURE_INLINE_GETTER
+ value_type&& operator*() && noexcept { return static_cast<value_type&&>(val_); }
+
+ /// \brief Returns a reference to the underlying value (const overload).
+ TOML_PURE_INLINE_GETTER
+ const value_type& operator*() const& noexcept { 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 { return val_; }
+
+ /// \brief Returns a reference to the underlying value (rvalue overload).
+ TOML_PURE_INLINE_GETTER
+ explicit operator value_type&&() && noexcept { return static_cast<value_type&&>(val_); }
+
+ /// \brief Returns a reference to the underlying value (const overload).
+ TOML_PURE_INLINE_GETTER
+ explicit operator const value_type&() const& noexcept { 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.
+ TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type)
+ TOML_PURE_INLINE_GETTER
+ value_type* operator->() noexcept { return &val_; }
+
+ /// \brief Returns a pointer to the underlying value (const overload).
+ ///
+ /// \availability This operator is only available when #value_type is a class/struct.
+ TOML_HIDDEN_CONSTRAINT(std::is_class_v<T>, typename T = value_type)
+ TOML_PURE_INLINE_GETTER
+ const value_type* operator->() const noexcept { return &val_; }
+
+ /// @}
+
+ /// \name Metadata
+ /// @{
+
+ /// \brief Returns the metadata flags associated with this value.
+ TOML_NODISCARD
+ value_flags flags() const noexcept { return flags_; }
+
+ /// \brief Sets the metadata flags associated with this value.
+ /// \returns A reference to the value object.
+ value& flags(value_flags new_flags) noexcept {
+ flags_ = new_flags;
+ return *this;
+ }
+
+ /// @}
+
+ /// \brief Value-assignment operator.
+ value& operator=(value_arg rhs) noexcept {
+ if constexpr (std::is_same_v<value_type, std::string>)
+ val_.assign(rhs);
+ else
+ val_ = rhs;
+ return *this;
+ }
+
+ TOML_CONSTRAINED_TEMPLATE((std::is_same_v<T, std::string>), typename T = value_type)
+ value& operator=(std::string&& rhs) noexcept {
+ val_ = std::move(rhs);
+ return *this;
+ }
+
+ /// \name Equality and Comparison
+ /// @{
+
+ /// \brief Value equality operator.
+ TOML_PURE_GETTER
+ friend bool operator==(const value& lhs, value_arg rhs) noexcept {
+ if constexpr (std::is_same_v<value_type, double>) {
+ const auto lhs_nan = impl::fpclassify(lhs.val_) == impl::fp_class::nan;
+ const auto rhs_nan = impl::fpclassify(rhs) == impl::fp_class::nan;
+ if (lhs_nan != rhs_nan) return false;
+ if (lhs_nan) return true;
+ }
+ return lhs.val_ == rhs;
+ }
+ TOML_ASYMMETRICAL_EQUALITY_OPS(const value&, value_arg, );
+
+ /// \brief Value less-than operator.
+ TOML_PURE_GETTER
+ friend bool operator<(const value& lhs, value_arg rhs) noexcept { return lhs.val_ < rhs; }
+
+ /// \brief Value less-than operator.
+ TOML_PURE_GETTER
+ friend bool operator<(value_arg lhs, const value& rhs) noexcept { return lhs < rhs.val_; }
+
+ /// \brief Value less-than-or-equal-to operator.
+ TOML_PURE_GETTER
+ friend bool operator<=(const value& lhs, value_arg rhs) noexcept { return lhs.val_ <= rhs; }
+
+ /// \brief Value less-than-or-equal-to operator.
+ TOML_PURE_GETTER
+ friend bool operator<=(value_arg lhs, const value& rhs) noexcept { return lhs <= rhs.val_; }
+
+ /// \brief Value greater-than operator.
+ TOML_PURE_GETTER
+ friend bool operator>(const value& lhs, value_arg rhs) noexcept { return lhs.val_ > rhs; }
+
+ /// \brief Value greater-than operator.
+ TOML_PURE_GETTER
+ friend bool operator>(value_arg lhs, const value& rhs) noexcept { return lhs > rhs.val_; }
+
+ /// \brief Value greater-than-or-equal-to operator.
+ TOML_PURE_GETTER
+ friend bool operator>=(const value& lhs, value_arg rhs) noexcept { return lhs.val_ >= rhs; }
+
+ /// \brief Value greater-than-or-equal-to operator.
+ TOML_PURE_GETTER
+ friend bool operator>=(value_arg lhs, const value& rhs) noexcept { return lhs >= rhs.val_; }
+
+ /// \brief Equality operator.
+ ///
+ /// \param lhs The LHS value.
+ /// \param rhs The RHS value.
+ ///
+ /// \returns True if the values were of the same type and contained the same value.
+ template <typename T>
+ TOML_PURE_GETTER friend bool operator==(const value& lhs, const value<T>& rhs) noexcept {
+ if constexpr (std::is_same_v<value_type, T>)
+ return lhs == rhs.val_; // calls asymmetrical value-equality operator defined above
+ else
+ return false;
+ }
+
+ /// \brief Inequality operator.
+ ///
+ /// \param lhs The LHS value.
+ /// \param rhs The RHS value.
+ ///
+ /// \returns True if the values were not of the same type, or did not contain the same value.
+ template <typename T>
+ TOML_PURE_INLINE_GETTER friend bool operator!=(const value& lhs, const value<T>& rhs) noexcept {
+ return !(lhs == rhs);
+ }
+
+ /// \brief Less-than operator.
+ ///
+ /// \param lhs The LHS toml::value.
+ /// \param rhs The RHS toml::value.
+ ///
+ /// \returns \conditional_return{Same value types}
+ /// `lhs.get() < rhs.get()`
+ /// \conditional_return{Different value types}
+ /// `lhs.type() < rhs.type()`
+ template <typename T>
+ TOML_PURE_GETTER friend bool operator<(const value& lhs, const value<T>& rhs) noexcept {
+ if constexpr (std::is_same_v<value_type, T>)
+ return lhs.val_ < rhs.val_;
+ else
+ return impl::node_type_of<value_type> < impl::node_type_of<T>;
+ }
+
+ /// \brief Less-than-or-equal-to operator.
+ ///
+ /// \param lhs The LHS toml::value.
+ /// \param rhs The RHS toml::value.
+ ///
+ /// \returns \conditional_return{Same value types}
+ /// `lhs.get() <= rhs.get()`
+ /// \conditional_return{Different value types}
+ /// `lhs.type() <= rhs.type()`
+ template <typename T>
+ TOML_PURE_GETTER friend bool operator<=(const value& lhs, const value<T>& rhs) noexcept {
+ if constexpr (std::is_same_v<value_type, T>)
+ return lhs.val_ <= rhs.val_;
+ else
+ return impl::node_type_of<value_type> <= impl::node_type_of<T>;
+ }
+
+ /// \brief Greater-than operator.
+ ///
+ /// \param lhs The LHS toml::value.
+ /// \param rhs The RHS toml::value.
+ ///
+ /// \returns \conditional_return{Same value types}
+ /// `lhs.get() > rhs.get()`
+ /// \conditional_return{Different value types}
+ /// `lhs.type() > rhs.type()`
+ template <typename T>
+ TOML_PURE_GETTER friend bool operator>(const value& lhs, const value<T>& rhs) noexcept {
+ if constexpr (std::is_same_v<value_type, T>)
+ return lhs.val_ > rhs.val_;
+ else
+ return impl::node_type_of<value_type> > impl::node_type_of<T>;
+ }
+
+ /// \brief Greater-than-or-equal-to operator.
+ ///
+ /// \param lhs The LHS toml::value.
+ /// \param rhs The RHS toml::value.
+ ///
+ /// \returns \conditional_return{Same value types}
+ /// `lhs.get() >= rhs.get()`
+ /// \conditional_return{Different value types}
+ /// `lhs.type() >= rhs.type()`
+ template <typename T>
+ TOML_PURE_GETTER friend bool operator>=(const value& lhs, const value<T>& rhs) noexcept {
+ if constexpr (std::is_same_v<value_type, T>)
+ return lhs.val_ >= rhs.val_;
+ else
+ return impl::node_type_of<value_type> >= impl::node_type_of<T>;
+ }
+
+ /// @}
#if TOML_ENABLE_FORMATTERS
- /// \brief Prints the value out to a stream as formatted TOML.
- ///
- /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
- friend std::ostream& operator<<(std::ostream& lhs, const value& rhs)
- {
- impl::print_to_stream(lhs, rhs);
- return lhs;
- }
+ /// \brief Prints the value out to a stream as formatted TOML.
+ ///
+ /// \availability This operator is only available when #TOML_ENABLE_FORMATTERS is enabled.
+ friend std::ostream& operator<<(std::ostream& lhs, const value& rhs) {
+ impl::print_to_stream(lhs, rhs);
+ return lhs;
+ }
#endif
- };
-
- /// \cond
-
- template <typename T>
- value(T) -> value<impl::native_type_of<impl::remove_cvref<T>>>;
- template <typename T>
- value(T, value_flags) -> value<impl::native_type_of<impl::remove_cvref<T>>>;
-
- template <typename T>
- TOML_NODISCARD
- inline decltype(auto) node::get_value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>)
- {
- using namespace impl;
-
- static_assert(node_type_of<T> != node_type::none);
- static_assert(node_type_of<T> != node_type::table);
- static_assert(node_type_of<T> != node_type::array);
- static_assert(is_native<T> || can_represent_native<T>);
- static_assert(!is_cvref<T>);
- TOML_ASSERT(this->type() == node_type_of<T>);
-
- if constexpr (node_type_of<T> == node_type::string)
- {
- const auto& str = *ref_cast<std::string>();
- if constexpr (std::is_same_v<T, std::string>)
- return str;
- else if constexpr (std::is_same_v<T, std::string_view>)
- return T{ str };
- else if constexpr (std::is_same_v<T, const char*>)
- return str.c_str();
-
- else if constexpr (std::is_same_v<T, std::wstring>)
- {
+ };
+
+ /// \cond
+
+ template <typename T>
+ value(T) -> value<impl::native_type_of<impl::remove_cvref<T>>>;
+ template <typename T>
+ value(T, value_flags) -> value<impl::native_type_of<impl::remove_cvref<T>>>;
+
+ template <typename T>
+ TOML_NODISCARD inline decltype(auto) node::get_value_exact()
+ const noexcept(impl::value_retrieval_is_nothrow<T>) {
+ using namespace impl;
+
+ static_assert(node_type_of<T> != node_type::none);
+ static_assert(node_type_of<T> != node_type::table);
+ static_assert(node_type_of<T> != node_type::array);
+ static_assert(is_native<T> || can_represent_native<T>);
+ static_assert(!is_cvref<T>);
+ TOML_ASSERT(this->type() == node_type_of<T>);
+
+ if constexpr (node_type_of<T> == node_type::string) {
+ const auto& str = *ref_cast<std::string>();
+ if constexpr (std::is_same_v<T, std::string>)
+ return str;
+ else if constexpr (std::is_same_v<T, std::string_view>)
+ return T{str};
+ else if constexpr (std::is_same_v<T, const char*>)
+ return str.c_str();
+
+ else if constexpr (std::is_same_v<T, std::wstring>) {
#if TOML_ENABLE_WINDOWS_COMPAT
- return widen(str);
+ return widen(str);
#else
- static_assert(always_false<T>, "Evaluated unreachable branch!");
+ static_assert(always_false<T>, "Evaluated unreachable branch!");
#endif
- }
+ }
#if TOML_HAS_CHAR8
- // char -> char8_t (potentially unsafe - the feature is 'experimental'!)
- else if constexpr (is_one_of<T, std::u8string, std::u8string_view>)
- return T(reinterpret_cast<const char8_t*>(str.c_str()), str.length());
- else if constexpr (std::is_same_v<T, const char8_t*>)
- return reinterpret_cast<const char8_t*>(str.c_str());
- else
- static_assert(always_false<T>, "Evaluated unreachable branch!");
+ // char -> char8_t (potentially unsafe - the feature is 'experimental'!)
+ else if constexpr (is_one_of<T, std::u8string, std::u8string_view>)
+ return T(reinterpret_cast<const char8_t*>(str.c_str()), str.length());
+ else if constexpr (std::is_same_v<T, const char8_t*>)
+ return reinterpret_cast<const char8_t*>(str.c_str());
+ else
+ static_assert(always_false<T>, "Evaluated unreachable branch!");
#endif
- }
- else
- return static_cast<T>(*ref_cast<native_type_of<T>>());
- }
-
- template <typename T>
- TOML_NODISCARD
- inline optional<T> node::value_exact() const noexcept(impl::value_retrieval_is_nothrow<T>)
- {
- using namespace impl;
-
- static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
- "Retrieving values as wide-character strings with node::value_exact() is only "
- "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
-
- static_assert((is_native<T> || can_represent_native<T>)&&!is_cvref<T>,
- TOML_SA_VALUE_EXACT_FUNC_MESSAGE("return type of node::value_exact()"));
-
- // prevent additional compiler error spam when the static_assert fails by gating behind if constexpr
- if constexpr ((is_native<T> || can_represent_native<T>)&&!is_cvref<T>)
- {
- if (type() == node_type_of<T>)
- return { this->get_value_exact<T>() };
- else
- return {};
- }
- }
-
- template <typename T>
- TOML_NODISCARD
- inline optional<T> node::value() const noexcept(impl::value_retrieval_is_nothrow<T>)
- {
- using namespace impl;
-
- static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
- "Retrieving values as wide-character strings with node::value() is only "
- "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
- static_assert((is_native<T> || can_represent_native<T> || can_partially_represent_native<T>)&&!is_cvref<T>,
- TOML_SA_VALUE_FUNC_MESSAGE("return type of node::value()"));
-
- // when asking for strings, dates, times and date_times there's no 'fuzzy' conversion
- // semantics to be mindful of so the exact retrieval is enough.
- if constexpr (is_natively_one_of<T, std::string, time, date, date_time>)
- {
- if (type() == node_type_of<T>)
- return { this->get_value_exact<T>() };
- else
- return {};
- }
-
- // everything else requires a bit of logicking.
- else
- {
- switch (type())
- {
- // int -> *
- case node_type::integer:
- {
- // int -> int
- if constexpr (is_natively_one_of<T, int64_t>)
- {
- if constexpr (is_native<T> || can_represent_native<T>)
- return static_cast<T>(*ref_cast<int64_t>());
- else
- return node_integer_cast<T>(*ref_cast<int64_t>());
- }
-
- // int -> float
- else if constexpr (is_natively_one_of<T, double>)
- {
- const int64_t val = *ref_cast<int64_t>();
- if constexpr (std::numeric_limits<T>::digits < 64)
- {
- constexpr auto largest_whole_float = (int64_t{ 1 } << std::numeric_limits<T>::digits);
- if (val < -largest_whole_float || val > largest_whole_float)
- return {};
- }
- return static_cast<T>(val);
- }
-
- // int -> bool
- else if constexpr (is_natively_one_of<T, bool>)
- return static_cast<bool>(*ref_cast<int64_t>());
-
- // int -> anything else
- else
- return {};
- }
-
- // float -> *
- case node_type::floating_point:
- {
- // float -> float
- if constexpr (is_natively_one_of<T, double>)
- {
- if constexpr (is_native<T> || can_represent_native<T>)
- return { static_cast<T>(*ref_cast<double>()) };
- else
- {
- const double val = *ref_cast<double>();
- if (impl::fpclassify(val) == fp_class::ok
- && (val < (std::numeric_limits<T>::lowest)() || val > (std::numeric_limits<T>::max)()))
- return {};
- return { static_cast<T>(val) };
- }
- }
-
- // float -> int
- else if constexpr (is_natively_one_of<T, int64_t>)
- {
- const double val = *ref_cast<double>();
- if (impl::fpclassify(val) == fp_class::ok
- && static_cast<double>(static_cast<int64_t>(val)) == val)
- return node_integer_cast<T>(static_cast<int64_t>(val));
- else
- return {};
- }
-
- // float -> anything else
- else
- return {};
- }
-
- // bool -> *
- case node_type::boolean:
- {
- // bool -> bool
- if constexpr (is_natively_one_of<T, bool>)
- return { *ref_cast<bool>() };
-
- // bool -> int
- else if constexpr (is_natively_one_of<T, int64_t>)
- return { static_cast<T>(*ref_cast<bool>()) };
-
- // bool -> anything else
- else
- return {};
- }
- }
-
- // non-values, or 'exact' types covered above
- return {};
- }
- }
-
- template <typename T>
- TOML_NODISCARD
- inline auto node::value_or(T && default_value) const noexcept(impl::value_retrieval_is_nothrow<T>)
- {
- using namespace impl;
-
- static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
- "Retrieving values as wide-character strings with node::value_or() is only "
- "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
-
- if constexpr (is_wide_string<T>)
- {
+ } else
+ return static_cast<T>(*ref_cast<native_type_of<T>>());
+ }
+
+ template <typename T>
+ TOML_NODISCARD inline optional<T> node::value_exact()
+ const noexcept(impl::value_retrieval_is_nothrow<T>) {
+ using namespace impl;
+
+ static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
+ "Retrieving values as wide-character strings with node::value_exact() is only "
+ "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
+
+ static_assert((is_native<T> || can_represent_native<T>) && !is_cvref<T>,
+ TOML_SA_VALUE_EXACT_FUNC_MESSAGE("return type of node::value_exact()"));
+
+ // prevent additional compiler error spam when the static_assert fails by gating behind if
+ // constexpr
+ if constexpr ((is_native<T> || can_represent_native<T>) && !is_cvref<T>) {
+ if (type() == node_type_of<T>)
+ return {this->get_value_exact<T>()};
+ else
+ return {};
+ }
+ }
+
+ template <typename T>
+ TOML_NODISCARD inline optional<T> node::value()
+ const noexcept(impl::value_retrieval_is_nothrow<T>) {
+ using namespace impl;
+
+ static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
+ "Retrieving values as wide-character strings with node::value() is only "
+ "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
+ static_assert((is_native<T> || can_represent_native<T> || can_partially_represent_native<T>) &&
+ !is_cvref<T>,
+ TOML_SA_VALUE_FUNC_MESSAGE("return type of node::value()"));
+
+ // when asking for strings, dates, times and date_times there's no 'fuzzy' conversion
+ // semantics to be mindful of so the exact retrieval is enough.
+ if constexpr (is_natively_one_of<T, std::string, time, date, date_time>) {
+ if (type() == node_type_of<T>)
+ return {this->get_value_exact<T>()};
+ else
+ return {};
+ }
+
+ // everything else requires a bit of logicking.
+ else {
+ switch (type()) {
+ // int -> *
+ case node_type::integer: {
+ // int -> int
+ if constexpr (is_natively_one_of<T, int64_t>) {
+ if constexpr (is_native<T> || can_represent_native<T>)
+ return static_cast<T>(*ref_cast<int64_t>());
+ else
+ return node_integer_cast<T>(*ref_cast<int64_t>());
+ }
+
+ // int -> float
+ else if constexpr (is_natively_one_of<T, double>) {
+ const int64_t val = *ref_cast<int64_t>();
+ if constexpr (std::numeric_limits<T>::digits < 64) {
+ constexpr auto largest_whole_float = (int64_t{1} << std::numeric_limits<T>::digits);
+ if (val < -largest_whole_float || val > largest_whole_float) return {};
+ }
+ return static_cast<T>(val);
+ }
+
+ // int -> bool
+ else if constexpr (is_natively_one_of<T, bool>)
+ return static_cast<bool>(*ref_cast<int64_t>());
+
+ // int -> anything else
+ else
+ return {};
+ }
+
+ // float -> *
+ case node_type::floating_point: {
+ // float -> float
+ if constexpr (is_natively_one_of<T, double>) {
+ if constexpr (is_native<T> || can_represent_native<T>)
+ return {static_cast<T>(*ref_cast<double>())};
+ else {
+ const double val = *ref_cast<double>();
+ if (impl::fpclassify(val) == fp_class::ok &&
+ (val < (std::numeric_limits<T>::lowest)() ||
+ val > (std::numeric_limits<T>::max)()))
+ return {};
+ return {static_cast<T>(val)};
+ }
+ }
+
+ // float -> int
+ else if constexpr (is_natively_one_of<T, int64_t>) {
+ const double val = *ref_cast<double>();
+ if (impl::fpclassify(val) == fp_class::ok &&
+ static_cast<double>(static_cast<int64_t>(val)) == val)
+ return node_integer_cast<T>(static_cast<int64_t>(val));
+ else
+ return {};
+ }
+
+ // float -> anything else
+ else
+ return {};
+ }
+
+ // bool -> *
+ case node_type::boolean: {
+ // bool -> bool
+ if constexpr (is_natively_one_of<T, bool>) return {*ref_cast<bool>()};
+
+ // bool -> int
+ else if constexpr (is_natively_one_of<T, int64_t>)
+ return {static_cast<T>(*ref_cast<bool>())};
+
+ // bool -> anything else
+ else
+ return {};
+ }
+ }
+
+ // non-values, or 'exact' types covered above
+ return {};
+ }
+ }
+
+ template <typename T>
+ TOML_NODISCARD inline auto node::value_or(T && default_value)
+ const noexcept(impl::value_retrieval_is_nothrow<T>) {
+ using namespace impl;
+
+ static_assert(!is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
+ "Retrieving values as wide-character strings with node::value_or() is only "
+ "supported on Windows with TOML_ENABLE_WINDOWS_COMPAT enabled.");
+
+ if constexpr (is_wide_string<T>) {
#if TOML_ENABLE_WINDOWS_COMPAT
- if (type() == node_type::string)
- return widen(*ref_cast<std::string>());
- return std::wstring{ static_cast<T&&>(default_value) };
+ if (type() == node_type::string) return widen(*ref_cast<std::string>());
+ return std::wstring{static_cast<T&&>(default_value)};
#else
- static_assert(always_false<T>, "Evaluated unreachable branch!");
+ static_assert(always_false<T>, "Evaluated unreachable branch!");
#endif
- }
- else
- {
- using value_type =
- std::conditional_t<std::is_pointer_v<std::decay_t<T>>,
- std::add_pointer_t<std::add_const_t<std::remove_pointer_t<std::decay_t<T>>>>,
- std::decay_t<T>>;
- using traits = value_traits<value_type>;
+ } else {
+ using value_type = std::conditional_t<
+ std::is_pointer_v<std::decay_t<T>>,
+ std::add_pointer_t<std::add_const_t<std::remove_pointer_t<std::decay_t<T>>>>,
+ std::decay_t<T>>;
+ using traits = value_traits<value_type>;
- // clang-format off
+ // clang-format off
static_assert(
traits::is_native || traits::can_represent_native || traits::can_partially_represent_native,
@@ -1243,27 +999,25 @@ TOML_NAMESPACE_START
TOML_SA_LIST_END
);
- // clang-format on
-
- // prevent additional compiler error spam when the static_assert fails by gating behind if constexpr
- if constexpr (traits::is_native || traits::can_represent_native || traits::can_partially_represent_native)
- {
- if constexpr (traits::is_native)
- {
- if (type() == node_type_of<value_type>)
- return *ref_cast<typename traits::native_type>();
- }
- if (auto val = this->value<value_type>())
- return *val;
- if constexpr (std::is_pointer_v<value_type>)
- return value_type{ default_value };
- else
- return static_cast<T&&>(default_value);
- }
- }
- }
-
- /// \endcond
+ // clang-format on
+
+ // prevent additional compiler error spam when the static_assert fails by gating behind if
+ // constexpr
+ if constexpr (traits::is_native || traits::can_represent_native ||
+ traits::can_partially_represent_native) {
+ if constexpr (traits::is_native) {
+ if (type() == node_type_of<value_type>) return *ref_cast<typename traits::native_type>();
+ }
+ if (auto val = this->value<value_type>()) return *val;
+ if constexpr (std::is_pointer_v<value_type>)
+ return value_type{default_value};
+ else
+ return static_cast<T&&>(default_value);
+ }
+ }
+ }
+
+ /// \endcond
}
TOML_NAMESPACE_END;