diff options
| author | Amlal El Mahrouss <amlal@nekernel.org> | 2026-03-08 15:50:45 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-08 15:50:45 +0100 |
| commit | 386b6ba6702aaf121a8667b68fba86385dad68ed (patch) | |
| tree | 985c7eda4fafa827eaad88b6b469b0baba791817 /vendor/toml++/impl/forward_declarations.hpp | |
| parent | 7a469801ecb55fcde0199d4e41b1cec3a17dcb05 (diff) | |
| parent | ddb1cbc831b6d13b985d91022f01e955e24ae871 (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/forward_declarations.hpp')
| -rw-r--r-- | vendor/toml++/impl/forward_declarations.hpp | 1786 |
1 files changed, 851 insertions, 935 deletions
diff --git a/vendor/toml++/impl/forward_declarations.hpp b/vendor/toml++/impl/forward_declarations.hpp index 386a9e0..b755855 100644 --- a/vendor/toml++/impl/forward_declarations.hpp +++ b/vendor/toml++/impl/forward_declarations.hpp @@ -1,38 +1,43 @@ -//# 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 "std_string.hpp" #include "std_new.hpp" +#include "std_string.hpp" TOML_DISABLE_WARNINGS; -#include <cstdint> -#include <cstddef> -#include <cstring> #include <cfloat> #include <climits> #include <cmath> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <iosfwd> #include <limits> #include <memory> -#include <iosfwd> #include <type_traits> TOML_ENABLE_WARNINGS; #include "header_start.hpp" -//#--------------------------------------------------------------------------------------------------------------------- -//# ENVIRONMENT GROUND-TRUTHS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # ENVIRONMENT GROUND-TRUTHS +// #--------------------------------------------------------------------------------------------------------------------- /// \cond #ifndef TOML_DISABLE_ENVIRONMENT_CHECKS -#define TOML_ENV_MESSAGE \ - "If you're seeing this error it's because you're building toml++ for an environment that doesn't conform to " \ - "one of the 'ground truths' assumed by the library. Essentially this just means that I don't have the " \ - "resources to test on more platforms, but I wish I did! You can try disabling the checks by defining " \ - "TOML_DISABLE_ENVIRONMENT_CHECKS, but your mileage may vary. Please consider filing an issue at " \ - "https://github.com/marzer/tomlplusplus/issues to help me improve support for your target environment. " \ - "Thanks!" +#define TOML_ENV_MESSAGE \ + "If you're seeing this error it's because you're building toml++ for an environment that " \ + "doesn't conform to " \ + "one of the 'ground truths' assumed by the library. Essentially this just means that I don't " \ + "have the " \ + "resources to test on more platforms, but I wish I did! You can try disabling the checks by " \ + "defining " \ + "TOML_DISABLE_ENVIRONMENT_CHECKS, but your mileage may vary. Please consider filing an issue " \ + "at " \ + "https://github.com/marzer/tomlplusplus/issues to help me improve support for your target " \ + "environment. " \ + "Thanks!" static_assert(CHAR_BIT == 8, TOML_ENV_MESSAGE); #ifdef FLT_RADIX @@ -46,83 +51,81 @@ static_assert(std::numeric_limits<double>::digits10 == 15, TOML_ENV_MESSAGE); static_assert(std::numeric_limits<double>::radix == 2, TOML_ENV_MESSAGE); #undef TOML_ENV_MESSAGE -#endif // !TOML_DISABLE_ENVIRONMENT_CHECKS +#endif // !TOML_DISABLE_ENVIRONMENT_CHECKS /// \endcond -//#--------------------------------------------------------------------------------------------------------------------- -//# UNDOCUMENTED TYPEDEFS AND FORWARD DECLARATIONS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # UNDOCUMENTED TYPEDEFS AND FORWARD DECLARATIONS +// #--------------------------------------------------------------------------------------------------------------------- /// \cond // undocumented forward declarations are hidden from doxygen because they fuck it up =/ -namespace toml // non-abi namespace; this is not an error -{ - using ::std::size_t; - using ::std::intptr_t; - using ::std::uintptr_t; - using ::std::ptrdiff_t; - using ::std::nullptr_t; - using ::std::int8_t; - using ::std::int16_t; - using ::std::int32_t; - using ::std::int64_t; - using ::std::uint8_t; - using ::std::uint16_t; - using ::std::uint32_t; - using ::std::uint64_t; - using ::std::uint_least32_t; - using ::std::uint_least64_t; -} - -TOML_NAMESPACE_START +namespace toml // non-abi namespace; this is not an error { - struct date; - struct time; - struct time_offset; - - TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt); - struct date_time; - TOML_ABI_NAMESPACE_END; - - struct source_position; - struct source_region; - - class node; - template <typename> - class node_view; - - class key; - class array; - class table; - template <typename> - class value; - - class path; - - class toml_formatter; - class json_formatter; - class yaml_formatter; - - TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex); +using ::std::int16_t; +using ::std::int32_t; +using ::std::int64_t; +using ::std::int8_t; +using ::std::intptr_t; +using ::std::nullptr_t; +using ::std::ptrdiff_t; +using ::std::size_t; +using ::std::uint16_t; +using ::std::uint32_t; +using ::std::uint64_t; +using ::std::uint8_t; +using ::std::uint_least32_t; +using ::std::uint_least64_t; +using ::std::uintptr_t; +} // namespace toml + +TOML_NAMESPACE_START { + struct date; + struct time; + struct time_offset; + + TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt); + struct date_time; + TOML_ABI_NAMESPACE_END; + + struct source_position; + struct source_region; + + class node; + template <typename> + class node_view; + + class key; + class array; + class table; + template <typename> + class value; + + class path; + + class toml_formatter; + class json_formatter; + class yaml_formatter; + + TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, ex, noex); #if TOML_EXCEPTIONS - using parse_result = table; + using parse_result = table; #else - class parse_result; + class parse_result; #endif - TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS + TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS } TOML_NAMESPACE_END; -TOML_IMPL_NAMESPACE_START -{ - using node_ptr = std::unique_ptr<node>; +TOML_IMPL_NAMESPACE_START { + using node_ptr = std::unique_ptr<node>; - TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, impl_ex, impl_noex); - class parser; - TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS + TOML_ABI_NAMESPACE_BOOL(TOML_EXCEPTIONS, impl_ex, impl_noex); + class parser; + TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS - // clang-format off + // clang-format off inline constexpr std::string_view control_char_escapes[] = { @@ -174,7 +177,7 @@ TOML_IMPL_NAMESPACE_START "date-time"sv }; - // clang-format on + // clang-format on } TOML_IMPL_NAMESPACE_END; @@ -190,906 +193,819 @@ TOML_IMPL_NAMESPACE_END; /// \endcond -//#--------------------------------------------------------------------------------------------------------------------- -//# DOCUMENTED TYPEDEFS AND FORWARD DECLARATIONS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # DOCUMENTED TYPEDEFS AND FORWARD DECLARATIONS +// #--------------------------------------------------------------------------------------------------------------------- /// \brief The root namespace for all toml++ functions and types. -namespace toml -{ -} +namespace toml {} -TOML_NAMESPACE_START // abi namespace +TOML_NAMESPACE_START // abi namespace { - /// \brief Convenience literal operators for working with toml++. - /// - /// \detail This namespace exists so you can safely hoist the toml++ literal operators into another scope - /// without dragging in everything from the toml namespace: \cpp - /// - /// #include <toml++/toml.hpp> - /// using namespace toml::literals; - /// - /// int main() - /// { - /// toml::table tbl = "vals = [1, 2, 3]"_toml; - /// - /// // ... do stuff with the table generated by the "_toml" literal ... - /// - /// return 0; - /// } - /// \ecpp - /// - inline namespace literals - { - } - - /// \brief TOML node type identifiers. - enum class TOML_CLOSED_ENUM node_type : uint8_t - { - none, ///< Not-a-node. - table, ///< The node is a toml::table. - array, ///< The node is a toml::array. - string, ///< The node is a toml::value<std::string>. - integer, ///< The node is a toml::value<int64_t>. - floating_point, ///< The node is a toml::value<double>. - boolean, ///< The node is a toml::value<bool>. - date, ///< The node is a toml::value<date>. - time, ///< The node is a toml::value<time>. - date_time ///< The node is a toml::value<date_time>. - }; - - /// \brief Pretty-prints the value of a node_type to a stream. - /// - /// \detail \cpp - /// auto arr = toml::array{ 1, 2.0, "3", false }; - /// for (size_t i = 0; i < arr.size() i++) - /// std::cout << "Element ["sv << i << "] is: "sv << arr[i].type() << "\n"; - /// \ecpp - /// - /// \out - /// Element [0] is: integer - /// Element [1] is: floating-point - /// Element [2] is: string - /// Element [3] is: boolean - /// \eout - template <typename Char> - inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, node_type rhs) - { - const auto str = impl::node_type_friendly_names[static_cast<std::underlying_type_t<node_type>>(rhs)]; - using str_char_t = decltype(str)::value_type; - if constexpr (std::is_same_v<Char, str_char_t>) - return lhs << str; - else - { - if constexpr (sizeof(Char) == sizeof(str_char_t)) - return lhs << std::basic_string_view<Char>{ reinterpret_cast<const Char*>(str.data()), str.length() }; - else - return lhs << str.data(); - } - } - - /// \brief Metadata associated with TOML values. - enum class TOML_OPEN_FLAGS_ENUM value_flags : uint16_t // being an "OPEN" flags enum is not an error - { - /// \brief None. - none, - - /// \brief Format integer values as binary. - format_as_binary = 1, - - /// \brief Format integer values as octal. - format_as_octal = 2, - - /// \brief Format integer values as hexadecimal. - format_as_hexadecimal = 3, - }; - TOML_MAKE_FLAGS(value_flags); - - /// \brief Special #toml::value_flags constant used for array + table insert functions to specify that any value - /// nodes being copied should not have their flags property overridden by the inserting function's `flags` argument. - inline constexpr value_flags preserve_source_value_flags = - POXY_IMPLEMENTATION_DETAIL(value_flags{ static_cast<std::underlying_type_t<value_flags>>(-1) }); - - /// \brief Format flags for modifying how TOML data is printed to streams. - /// - /// \note Formatters may disregard/override any of these flags according to the requirements of their - /// output target (e.g. #toml::json_formatter will always apply quotes to dates and times). - enum class TOML_CLOSED_FLAGS_ENUM format_flags : uint64_t - { - /// \brief None. - none, - - /// \brief Dates and times will be emitted as quoted strings. - quote_dates_and_times = (1ull << 0), - - /// \brief Infinities and NaNs will be emitted as quoted strings. - quote_infinities_and_nans = (1ull << 1), - - /// \brief Strings will be emitted as single-quoted literal strings where possible. - allow_literal_strings = (1ull << 2), - - /// \brief Strings containing newlines will be emitted as triple-quoted 'multi-line' strings where possible. - allow_multi_line_strings = (1ull << 3), - - /// \brief Allow real tab characters in string literals (as opposed to the escaped form `\t`). - allow_real_tabs_in_strings = (1ull << 4), - - /// \brief Allow non-ASCII characters in strings (as opposed to their escaped form, e.g. `\u00DA`). - allow_unicode_strings = (1ull << 5), - - /// \brief Allow integers with #value_flags::format_as_binary to be emitted as binary. - allow_binary_integers = (1ull << 6), - - /// \brief Allow integers with #value_flags::format_as_octal to be emitted as octal. - allow_octal_integers = (1ull << 7), - - /// \brief Allow integers with #value_flags::format_as_hexadecimal to be emitted as hexadecimal. - allow_hexadecimal_integers = (1ull << 8), - - /// \brief Apply indentation to tables nested within other tables/arrays. - indent_sub_tables = (1ull << 9), - - /// \brief Apply indentation to array elements when the array is forced to wrap over multiple lines. - indent_array_elements = (1ull << 10), - - /// \brief Combination mask of all indentation-enabling flags. - indentation = indent_sub_tables | indent_array_elements, - - /// \brief Emit floating-point values with relaxed (human-friendly) precision. - /// \warning Setting this flag may cause serialized documents to no longer round-trip correctly - /// since floats might have a less precise value upon being written out than they did when being - /// read in. Use this flag at your own risk. - relaxed_float_precision = (1ull << 11), - - /// \brief Avoids the use of whitespace around key-value pairs. - terse_key_value_pairs = (1ull << 12), - }; - TOML_MAKE_FLAGS(format_flags); - - /// \brief Helper class for suppressing move-construction in single-argument array constructors. - /// - /// \detail \cpp - /// // desired result: [ [ 42 ] ] - /// auto bad = toml::array{ toml::array{ 42 } }; - /// auto good = toml::array{ toml::inserter{ toml::array{ 42 } } }; - /// std::cout << "bad: " << bad << "\n"; - /// std::cout << "good:" << good << "\n"; - /// \ecpp - /// \out - /// bad: [ 42 ] - /// good: [ [ 42 ] ] - /// \eout - /// - /// \see toml::array - template <typename T> - struct TOML_TRIVIAL_ABI inserter - { - static_assert(std::is_reference_v<T>); - - T value; - }; - template <typename T> - inserter(T&&) -> inserter<T&&>; - template <typename T> - inserter(T&) -> inserter<T&>; - - /// \brief The 'default' formatter used by TOML objects when they are printed to a stream. - /// \detail This is an alias for #toml::toml_formatter. - using default_formatter = toml_formatter; + /// \brief Convenience literal operators for working with toml++. + /// + /// \detail This namespace exists so you can safely hoist the toml++ literal operators into + /// another scope without dragging in everything from the toml namespace: \cpp + /// + /// #include <toml++/toml.hpp> + /// using namespace toml::literals; + /// + /// int main() + /// { + /// toml::table tbl = "vals = [1, 2, 3]"_toml; + /// + /// // ... do stuff with the table generated by the "_toml" literal ... + /// + /// return 0; + /// } + /// \ecpp + /// + inline namespace literals {} + + /// \brief TOML node type identifiers. + enum class TOML_CLOSED_ENUM node_type : uint8_t { + none, ///< Not-a-node. + table, ///< The node is a toml::table. + array, ///< The node is a toml::array. + string, ///< The node is a toml::value<std::string>. + integer, ///< The node is a toml::value<int64_t>. + floating_point, ///< The node is a toml::value<double>. + boolean, ///< The node is a toml::value<bool>. + date, ///< The node is a toml::value<date>. + time, ///< The node is a toml::value<time>. + date_time ///< The node is a toml::value<date_time>. + }; + + /// \brief Pretty-prints the value of a node_type to a stream. + /// + /// \detail \cpp + /// auto arr = toml::array{ 1, 2.0, "3", false }; + /// for (size_t i = 0; i < arr.size() i++) + /// std::cout << "Element ["sv << i << "] is: "sv << arr[i].type() << "\n"; + /// \ecpp + /// + /// \out + /// Element [0] is: integer + /// Element [1] is: floating-point + /// Element [2] is: string + /// Element [3] is: boolean + /// \eout + template <typename Char> + inline std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& lhs, node_type rhs) { + const auto str = + impl::node_type_friendly_names[static_cast<std::underlying_type_t<node_type>>(rhs)]; + using str_char_t = decltype(str)::value_type; + if constexpr (std::is_same_v<Char, str_char_t>) + return lhs << str; + else { + if constexpr (sizeof(Char) == sizeof(str_char_t)) + return lhs << std::basic_string_view<Char>{reinterpret_cast<const Char*>(str.data()), + str.length()}; + else + return lhs << str.data(); + } + } + + /// \brief Metadata associated with TOML values. + enum class TOML_OPEN_FLAGS_ENUM + value_flags : uint16_t // being an "OPEN" flags enum is not an error + { + /// \brief None. + none, + + /// \brief Format integer values as binary. + format_as_binary = 1, + + /// \brief Format integer values as octal. + format_as_octal = 2, + + /// \brief Format integer values as hexadecimal. + format_as_hexadecimal = 3, + }; + TOML_MAKE_FLAGS(value_flags); + + /// \brief Special #toml::value_flags constant used for array + table insert functions to specify + /// that any value nodes being copied should not have their flags property overridden by the + /// inserting function's `flags` argument. + inline constexpr value_flags preserve_source_value_flags = + POXY_IMPLEMENTATION_DETAIL(value_flags{static_cast<std::underlying_type_t<value_flags>>(-1)}); + + /// \brief Format flags for modifying how TOML data is printed to streams. + /// + /// \note Formatters may disregard/override any of these flags according to the requirements of + /// their + /// output target (e.g. #toml::json_formatter will always apply quotes to dates and times). + enum class TOML_CLOSED_FLAGS_ENUM format_flags : uint64_t { + /// \brief None. + none, + + /// \brief Dates and times will be emitted as quoted strings. + quote_dates_and_times = (1ull << 0), + + /// \brief Infinities and NaNs will be emitted as quoted strings. + quote_infinities_and_nans = (1ull << 1), + + /// \brief Strings will be emitted as single-quoted literal strings where possible. + allow_literal_strings = (1ull << 2), + + /// \brief Strings containing newlines will be emitted as triple-quoted 'multi-line' strings + /// where possible. + allow_multi_line_strings = (1ull << 3), + + /// \brief Allow real tab characters in string literals (as opposed to the escaped form `\t`). + allow_real_tabs_in_strings = (1ull << 4), + + /// \brief Allow non-ASCII characters in strings (as opposed to their escaped form, e.g. + /// `\u00DA`). + allow_unicode_strings = (1ull << 5), + + /// \brief Allow integers with #value_flags::format_as_binary to be emitted as binary. + allow_binary_integers = (1ull << 6), + + /// \brief Allow integers with #value_flags::format_as_octal to be emitted as octal. + allow_octal_integers = (1ull << 7), + + /// \brief Allow integers with #value_flags::format_as_hexadecimal to be emitted as hexadecimal. + allow_hexadecimal_integers = (1ull << 8), + + /// \brief Apply indentation to tables nested within other tables/arrays. + indent_sub_tables = (1ull << 9), + + /// \brief Apply indentation to array elements when the array is forced to wrap over multiple + /// lines. + indent_array_elements = (1ull << 10), + + /// \brief Combination mask of all indentation-enabling flags. + indentation = indent_sub_tables | indent_array_elements, + + /// \brief Emit floating-point values with relaxed (human-friendly) precision. + /// \warning Setting this flag may cause serialized documents to no longer round-trip correctly + /// since floats might have a less precise value upon being written out than they did when + ///being read in. Use this flag at your own risk. + relaxed_float_precision = (1ull << 11), + + /// \brief Avoids the use of whitespace around key-value pairs. + terse_key_value_pairs = (1ull << 12), + }; + TOML_MAKE_FLAGS(format_flags); + + /// \brief Helper class for suppressing move-construction in single-argument array constructors. + /// + /// \detail \cpp + /// // desired result: [ [ 42 ] ] + /// auto bad = toml::array{ toml::array{ 42 } }; + /// auto good = toml::array{ toml::inserter{ toml::array{ 42 } } }; + /// std::cout << "bad: " << bad << "\n"; + /// std::cout << "good:" << good << "\n"; + /// \ecpp + /// \out + /// bad: [ 42 ] + /// good: [ [ 42 ] ] + /// \eout + /// + /// \see toml::array + template <typename T> + struct TOML_TRIVIAL_ABI inserter { + static_assert(std::is_reference_v<T>); + + T value; + }; + template <typename T> + inserter(T&&) -> inserter<T&&>; + template <typename T> + inserter(T&) -> inserter<T&>; + + /// \brief The 'default' formatter used by TOML objects when they are printed to a stream. + /// \detail This is an alias for #toml::toml_formatter. + using default_formatter = toml_formatter; } TOML_NAMESPACE_END; -//#--------------------------------------------------------------------------------------------------------------------- -//# METAFUNCTIONS & TYPE TRAITS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # METAFUNCTIONS & TYPE TRAITS +// #--------------------------------------------------------------------------------------------------------------------- /// \cond -TOML_IMPL_NAMESPACE_START -{ - template <typename T> - using remove_cvref = std::remove_cv_t<std::remove_reference_t<T>>; +TOML_IMPL_NAMESPACE_START { + template <typename T> + using remove_cvref = std::remove_cv_t<std::remove_reference_t<T>>; - template <typename... T> - using common_signed_type = std::common_type_t<std::make_signed_t<T>...>; + template <typename... T> + using common_signed_type = std::common_type_t<std::make_signed_t<T>...>; - template <typename T, typename... U> - inline constexpr bool is_one_of = (false || ... || std::is_same_v<T, U>); + template <typename T, typename... U> + inline constexpr bool is_one_of = (false || ... || std::is_same_v<T, U>); - template <typename... T> - inline constexpr bool all_integral = (std::is_integral_v<T> && ...); + template <typename... T> + inline constexpr bool all_integral = (std::is_integral_v<T> && ...); - template <typename T> - inline constexpr bool is_cvref = std::is_reference_v<T> || std::is_const_v<T> || std::is_volatile_v<T>; + template <typename T> + inline constexpr bool is_cvref = + std::is_reference_v<T> || std::is_const_v<T> || std::is_volatile_v<T>; - template <typename T> - inline constexpr bool is_wide_string = - is_one_of<std::decay_t<T>, const wchar_t*, wchar_t*, std::wstring_view, std::wstring>; + template <typename T> + inline constexpr bool is_wide_string = + is_one_of<std::decay_t<T>, const wchar_t*, wchar_t*, std::wstring_view, std::wstring>; - template <typename T> - inline constexpr bool value_retrieval_is_nothrow = !std::is_same_v<remove_cvref<T>, std::string> + template <typename T> + inline constexpr bool value_retrieval_is_nothrow = + !std::is_same_v<remove_cvref<T>, std::string> #if TOML_HAS_CHAR8 - && !std::is_same_v<remove_cvref<T>, std::u8string> + && !std::is_same_v<remove_cvref<T>, std::u8string> #endif - && !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...> - inline constexpr bool always_false = false; - - template <typename T, typename... U> - inline constexpr bool first_is_same = false; - template <typename T, typename... U> - inline constexpr bool first_is_same<T, T, U...> = true; - - template <typename T, bool = std::is_enum_v<T>> - struct underlying_type_ - { - using type = std::underlying_type_t<T>; - }; - template <typename T> - struct underlying_type_<T, false> - { - using type = T; - }; - template <typename T> - using underlying_type = typename underlying_type_<T>::type; - - // general value traits - // (as they relate to their equivalent native TOML type) - struct default_value_traits - { - using native_type = void; - static constexpr bool is_native = false; - static constexpr bool is_losslessly_convertible_to_native = false; - static constexpr bool can_represent_native = false; - static constexpr bool can_partially_represent_native = false; - static constexpr auto type = node_type::none; - }; - - template <typename T> - struct value_traits; - - template <typename T, bool = std::is_enum_v<T>> - struct value_traits_base_selector - { - static_assert(!is_cvref<T>); - - using type = default_value_traits; - }; - template <typename T> - struct value_traits_base_selector<T, true> - { - static_assert(!is_cvref<T>); - - using type = value_traits<underlying_type<T>>; - }; - - template <typename T> - struct value_traits : value_traits_base_selector<T>::type - {}; - 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> - {}; - - // integer value_traits specializations - standard types - template <typename T> - struct integer_limits - { - static constexpr T min = T{ (std::numeric_limits<underlying_type<T>>::min)() }; - static constexpr T max = T{ (std::numeric_limits<underlying_type<T>>::max)() }; - }; - template <typename T> - struct integer_traits_base : integer_limits<T> - { - using native_type = int64_t; - static constexpr bool is_native = std::is_same_v<underlying_type<T>, native_type>; - static constexpr bool is_signed = static_cast<underlying_type<T>>(-1) < underlying_type<T>{}; - static constexpr auto type = node_type::integer; - static constexpr bool can_partially_represent_native = true; - }; - template <typename T> - struct unsigned_integer_traits : integer_traits_base<T> - { - static constexpr bool is_losslessly_convertible_to_native = - integer_limits<underlying_type<T>>::max <= 9223372036854775807ULL; - static constexpr bool can_represent_native = false; - }; - template <typename T> - struct signed_integer_traits : integer_traits_base<T> - { - using native_type = int64_t; - static constexpr bool is_losslessly_convertible_to_native = - integer_limits<underlying_type<T>>::min >= (-9223372036854775807LL - 1LL) - && integer_limits<underlying_type<T>>::max <= 9223372036854775807LL; - static constexpr bool can_represent_native = - integer_limits<underlying_type<T>>::min <= (-9223372036854775807LL - 1LL) - && integer_limits<underlying_type<T>>::max >= 9223372036854775807LL; - }; - template <typename T, bool S = integer_traits_base<T>::is_signed> - struct integer_traits : signed_integer_traits<T> - {}; - template <typename T> - struct integer_traits<T, false> : unsigned_integer_traits<T> - {}; - template <> - struct value_traits<signed char> : integer_traits<signed char> - {}; - template <> - struct value_traits<unsigned char> : integer_traits<unsigned char> - {}; - template <> - struct value_traits<signed short> : integer_traits<signed short> - {}; - template <> - struct value_traits<unsigned short> : integer_traits<unsigned short> - {}; - template <> - struct value_traits<signed int> : integer_traits<signed int> - {}; - template <> - struct value_traits<unsigned int> : integer_traits<unsigned int> - {}; - template <> - struct value_traits<signed long> : integer_traits<signed long> - {}; - template <> - struct value_traits<unsigned long> : integer_traits<unsigned long> - {}; - template <> - struct value_traits<signed long long> : integer_traits<signed long long> - {}; - template <> - struct value_traits<unsigned long long> : integer_traits<unsigned long long> - {}; - static_assert(value_traits<int64_t>::is_native); - static_assert(value_traits<int64_t>::is_signed); - static_assert(value_traits<int64_t>::is_losslessly_convertible_to_native); - static_assert(value_traits<int64_t>::can_represent_native); - static_assert(value_traits<int64_t>::can_partially_represent_native); - - // integer value_traits specializations - non-standard types + && !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...> + inline constexpr bool always_false = false; + + template <typename T, typename... U> + inline constexpr bool first_is_same = false; + template <typename T, typename... U> + inline constexpr bool first_is_same<T, T, U...> = true; + + template <typename T, bool = std::is_enum_v<T>> + struct underlying_type_ { + using type = std::underlying_type_t<T>; + }; + template <typename T> + struct underlying_type_<T, false> { + using type = T; + }; + template <typename T> + using underlying_type = typename underlying_type_<T>::type; + + // general value traits + // (as they relate to their equivalent native TOML type) + struct default_value_traits { + using native_type = void; + static constexpr bool is_native = false; + static constexpr bool is_losslessly_convertible_to_native = false; + static constexpr bool can_represent_native = false; + static constexpr bool can_partially_represent_native = false; + static constexpr auto type = node_type::none; + }; + + template <typename T> + struct value_traits; + + template <typename T, bool = std::is_enum_v<T>> + struct value_traits_base_selector { + static_assert(!is_cvref<T>); + + using type = default_value_traits; + }; + template <typename T> + struct value_traits_base_selector<T, true> { + static_assert(!is_cvref<T>); + + using type = value_traits<underlying_type<T>>; + }; + + template <typename T> + struct value_traits : value_traits_base_selector<T>::type {}; + 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> {}; + + // integer value_traits specializations - standard types + template <typename T> + struct integer_limits { + static constexpr T min = T{(std::numeric_limits<underlying_type<T>>::min)()}; + static constexpr T max = T{(std::numeric_limits<underlying_type<T>>::max)()}; + }; + template <typename T> + struct integer_traits_base : integer_limits<T> { + using native_type = int64_t; + static constexpr bool is_native = std::is_same_v<underlying_type<T>, native_type>; + static constexpr bool is_signed = static_cast<underlying_type<T>>(-1) < underlying_type<T>{}; + static constexpr auto type = node_type::integer; + static constexpr bool can_partially_represent_native = true; + }; + template <typename T> + struct unsigned_integer_traits : integer_traits_base<T> { + static constexpr bool is_losslessly_convertible_to_native = + integer_limits<underlying_type<T>>::max <= 9223372036854775807ULL; + static constexpr bool can_represent_native = false; + }; + template <typename T> + struct signed_integer_traits : integer_traits_base<T> { + using native_type = int64_t; + static constexpr bool is_losslessly_convertible_to_native = + integer_limits<underlying_type<T>>::min >= (-9223372036854775807LL - 1LL) && + integer_limits<underlying_type<T>>::max <= 9223372036854775807LL; + static constexpr bool can_represent_native = + integer_limits<underlying_type<T>>::min <= (-9223372036854775807LL - 1LL) && + integer_limits<underlying_type<T>>::max >= 9223372036854775807LL; + }; + template <typename T, bool S = integer_traits_base<T>::is_signed> + struct integer_traits : signed_integer_traits<T> {}; + template <typename T> + struct integer_traits<T, false> : unsigned_integer_traits<T> {}; + template <> + struct value_traits<signed char> : integer_traits<signed char> {}; + template <> + struct value_traits<unsigned char> : integer_traits<unsigned char> {}; + template <> + struct value_traits<signed short> : integer_traits<signed short> {}; + template <> + struct value_traits<unsigned short> : integer_traits<unsigned short> {}; + template <> + struct value_traits<signed int> : integer_traits<signed int> {}; + template <> + struct value_traits<unsigned int> : integer_traits<unsigned int> {}; + template <> + struct value_traits<signed long> : integer_traits<signed long> {}; + template <> + struct value_traits<unsigned long> : integer_traits<unsigned long> {}; + template <> + struct value_traits<signed long long> : integer_traits<signed long long> {}; + template <> + struct value_traits<unsigned long long> : integer_traits<unsigned long long> {}; + static_assert(value_traits<int64_t>::is_native); + static_assert(value_traits<int64_t>::is_signed); + static_assert(value_traits<int64_t>::is_losslessly_convertible_to_native); + static_assert(value_traits<int64_t>::can_represent_native); + static_assert(value_traits<int64_t>::can_partially_represent_native); + + // integer value_traits specializations - non-standard types #ifdef TOML_INT128 - template <> - struct integer_limits<TOML_INT128> - { - static constexpr TOML_INT128 max = - static_cast<TOML_INT128>((TOML_UINT128{ 1u } << ((__SIZEOF_INT128__ * CHAR_BIT) - 1)) - 1); - static constexpr TOML_INT128 min = -max - TOML_INT128{ 1 }; - }; - template <> - struct integer_limits<TOML_UINT128> - { - static constexpr TOML_UINT128 min = TOML_UINT128{}; - static constexpr TOML_UINT128 max = (2u * static_cast<TOML_UINT128>(integer_limits<TOML_INT128>::max)) + 1u; - }; - template <> - struct value_traits<TOML_INT128> : integer_traits<TOML_INT128> - {}; - template <> - struct value_traits<TOML_UINT128> : integer_traits<TOML_UINT128> - {}; + template <> + struct integer_limits<TOML_INT128> { + static constexpr TOML_INT128 max = + static_cast<TOML_INT128>((TOML_UINT128{1u} << ((__SIZEOF_INT128__ * CHAR_BIT) - 1)) - 1); + static constexpr TOML_INT128 min = -max - TOML_INT128{1}; + }; + template <> + struct integer_limits<TOML_UINT128> { + static constexpr TOML_UINT128 min = TOML_UINT128{}; + static constexpr TOML_UINT128 max = + (2u * static_cast<TOML_UINT128>(integer_limits<TOML_INT128>::max)) + 1u; + }; + template <> + struct value_traits<TOML_INT128> : integer_traits<TOML_INT128> {}; + template <> + struct value_traits<TOML_UINT128> : integer_traits<TOML_UINT128> {}; #endif #ifdef TOML_SMALL_INT_TYPE - template <> - struct value_traits<TOML_SMALL_INT_TYPE> : signed_integer_traits<TOML_SMALL_INT_TYPE> - {}; + template <> + struct value_traits<TOML_SMALL_INT_TYPE> : signed_integer_traits<TOML_SMALL_INT_TYPE> {}; #endif - // floating-point traits base - template <typename T, int MantissaDigits, int DecimalDigits> - struct float_traits_base - { - static constexpr auto type = node_type::floating_point; - using native_type = double; - static constexpr bool is_native = std::is_same_v<T, native_type>; - static constexpr bool is_signed = true; - - static constexpr int bits = static_cast<int>(sizeof(T) * CHAR_BIT); - static constexpr int digits = MantissaDigits; - static constexpr int digits10 = DecimalDigits; - - static constexpr bool is_losslessly_convertible_to_native = bits <= 64 // - && digits <= 53 // DBL_MANT_DIG - && digits10 <= 15; // DBL_DIG - - static constexpr bool can_represent_native = digits >= 53 // DBL_MANT_DIG - && digits10 >= 15; // DBL_DIG - - static constexpr bool can_partially_represent_native = digits > 0 && digits10 > 0; - }; - template <typename T> - struct float_traits : float_traits_base<T, std::numeric_limits<T>::digits, std::numeric_limits<T>::digits10> - {}; + // floating-point traits base + template <typename T, int MantissaDigits, int DecimalDigits> + struct float_traits_base { + static constexpr auto type = node_type::floating_point; + using native_type = double; + static constexpr bool is_native = std::is_same_v<T, native_type>; + static constexpr bool is_signed = true; + + static constexpr int bits = static_cast<int>(sizeof(T) * CHAR_BIT); + static constexpr int digits = MantissaDigits; + static constexpr int digits10 = DecimalDigits; + + static constexpr bool is_losslessly_convertible_to_native = bits <= 64 // + && digits <= 53 // DBL_MANT_DIG + && digits10 <= 15; // DBL_DIG + + static constexpr bool can_represent_native = digits >= 53 // DBL_MANT_DIG + && digits10 >= 15; // DBL_DIG + + static constexpr bool can_partially_represent_native = digits > 0 && digits10 > 0; + }; + template <typename T> + struct float_traits + : float_traits_base<T, std::numeric_limits<T>::digits, std::numeric_limits<T>::digits10> {}; #if TOML_ENABLE_FLOAT16 - template <> - struct float_traits<_Float16> : float_traits_base<_Float16, __FLT16_MANT_DIG__, __FLT16_DIG__> - {}; + template <> + struct float_traits<_Float16> : float_traits_base<_Float16, __FLT16_MANT_DIG__, __FLT16_DIG__> {}; #endif #ifdef TOML_FLOAT128 - template <> - struct float_traits<TOML_FLOAT128> : float_traits_base<TOML_FLOAT128, __FLT128_MANT_DIG__, __FLT128_DIG__> - {}; + template <> + struct float_traits<TOML_FLOAT128> + : float_traits_base<TOML_FLOAT128, __FLT128_MANT_DIG__, __FLT128_DIG__> {}; #endif - // floating-point traits - template <> - struct value_traits<float> : float_traits<float> - {}; - template <> - struct value_traits<double> : float_traits<double> - {}; - template <> - struct value_traits<long double> : float_traits<long double> - {}; + // floating-point traits + template <> + struct value_traits<float> : float_traits<float> {}; + template <> + struct value_traits<double> : float_traits<double> {}; + template <> + struct value_traits<long double> : float_traits<long double> {}; #if TOML_ENABLE_FLOAT16 - template <> - struct value_traits<_Float16> : float_traits<_Float16> - {}; + template <> + struct value_traits<_Float16> : float_traits<_Float16> {}; #endif #ifdef TOML_FLOAT128 - template <> - struct value_traits<TOML_FLOAT128> : float_traits<TOML_FLOAT128> - {}; + template <> + struct value_traits<TOML_FLOAT128> : float_traits<TOML_FLOAT128> {}; #endif #ifdef TOML_SMALL_FLOAT_TYPE - template <> - struct value_traits<TOML_SMALL_FLOAT_TYPE> : float_traits<TOML_SMALL_FLOAT_TYPE> - {}; + template <> + struct value_traits<TOML_SMALL_FLOAT_TYPE> : float_traits<TOML_SMALL_FLOAT_TYPE> {}; #endif - static_assert(value_traits<double>::is_native); - static_assert(value_traits<double>::is_losslessly_convertible_to_native); - static_assert(value_traits<double>::can_represent_native); - static_assert(value_traits<double>::can_partially_represent_native); - - // string value_traits specializations - char-based strings - template <typename T> - struct string_traits - { - using native_type = std::string; - static constexpr bool is_native = std::is_same_v<T, native_type>; - static constexpr bool is_losslessly_convertible_to_native = true; - static constexpr bool can_represent_native = - !std::is_array_v<T> && (!std::is_pointer_v<T> || std::is_const_v<std::remove_pointer_t<T>>); - static constexpr bool can_partially_represent_native = can_represent_native; - static constexpr auto type = node_type::string; - }; - template <> - struct value_traits<std::string> : string_traits<std::string> - {}; - template <> - struct value_traits<std::string_view> : string_traits<std::string_view> - {}; - template <> - struct value_traits<const char*> : string_traits<const char*> - {}; - template <size_t N> - struct value_traits<const char[N]> : string_traits<const char[N]> - {}; - template <> - struct value_traits<char*> : string_traits<char*> - {}; - template <size_t N> - struct value_traits<char[N]> : string_traits<char[N]> - {}; - - // string value_traits specializations - char8_t-based strings + static_assert(value_traits<double>::is_native); + static_assert(value_traits<double>::is_losslessly_convertible_to_native); + static_assert(value_traits<double>::can_represent_native); + static_assert(value_traits<double>::can_partially_represent_native); + + // string value_traits specializations - char-based strings + template <typename T> + struct string_traits { + using native_type = std::string; + static constexpr bool is_native = std::is_same_v<T, native_type>; + static constexpr bool is_losslessly_convertible_to_native = true; + static constexpr bool can_represent_native = + !std::is_array_v<T> && (!std::is_pointer_v<T> || std::is_const_v<std::remove_pointer_t<T>>); + static constexpr bool can_partially_represent_native = can_represent_native; + static constexpr auto type = node_type::string; + }; + template <> + struct value_traits<std::string> : string_traits<std::string> {}; + template <> + struct value_traits<std::string_view> : string_traits<std::string_view> {}; + template <> + struct value_traits<const char*> : string_traits<const char*> {}; + template <size_t N> + struct value_traits<const char[N]> : string_traits<const char[N]> {}; + template <> + struct value_traits<char*> : string_traits<char*> {}; + template <size_t N> + struct value_traits<char[N]> : string_traits<char[N]> {}; + + // string value_traits specializations - char8_t-based strings #if TOML_HAS_CHAR8 - template <> - struct value_traits<std::u8string> : string_traits<std::u8string> - {}; - template <> - struct value_traits<std::u8string_view> : string_traits<std::u8string_view> - {}; - template <> - struct value_traits<const char8_t*> : string_traits<const char8_t*> - {}; - template <size_t N> - struct value_traits<const char8_t[N]> : string_traits<const char8_t[N]> - {}; - template <> - struct value_traits<char8_t*> : string_traits<char8_t*> - {}; - template <size_t N> - struct value_traits<char8_t[N]> : string_traits<char8_t[N]> - {}; + template <> + struct value_traits<std::u8string> : string_traits<std::u8string> {}; + template <> + struct value_traits<std::u8string_view> : string_traits<std::u8string_view> {}; + template <> + struct value_traits<const char8_t*> : string_traits<const char8_t*> {}; + template <size_t N> + struct value_traits<const char8_t[N]> : string_traits<const char8_t[N]> {}; + template <> + struct value_traits<char8_t*> : string_traits<char8_t*> {}; + template <size_t N> + struct value_traits<char8_t[N]> : string_traits<char8_t[N]> {}; #endif - // string value_traits specializations - wchar_t-based strings on Windows + // string value_traits specializations - wchar_t-based strings on Windows #if TOML_ENABLE_WINDOWS_COMPAT - template <typename T> - struct wstring_traits - { - using native_type = std::string; - static constexpr bool is_native = false; - static constexpr bool is_losslessly_convertible_to_native = true; // narrow - static constexpr bool can_represent_native = std::is_same_v<T, std::wstring>; // widen - static constexpr bool can_partially_represent_native = can_represent_native; - static constexpr auto type = node_type::string; - }; - template <> - struct value_traits<std::wstring> : wstring_traits<std::wstring> - {}; - template <> - struct value_traits<std::wstring_view> : wstring_traits<std::wstring_view> - {}; - template <> - struct value_traits<const wchar_t*> : wstring_traits<const wchar_t*> - {}; - template <size_t N> - struct value_traits<const wchar_t[N]> : wstring_traits<const wchar_t[N]> - {}; - template <> - struct value_traits<wchar_t*> : wstring_traits<wchar_t*> - {}; - template <size_t N> - struct value_traits<wchar_t[N]> : wstring_traits<wchar_t[N]> - {}; + template <typename T> + struct wstring_traits { + using native_type = std::string; + static constexpr bool is_native = false; + static constexpr bool is_losslessly_convertible_to_native = true; // narrow + static constexpr bool can_represent_native = std::is_same_v<T, std::wstring>; // widen + static constexpr bool can_partially_represent_native = can_represent_native; + static constexpr auto type = node_type::string; + }; + template <> + struct value_traits<std::wstring> : wstring_traits<std::wstring> {}; + template <> + struct value_traits<std::wstring_view> : wstring_traits<std::wstring_view> {}; + template <> + struct value_traits<const wchar_t*> : wstring_traits<const wchar_t*> {}; + template <size_t N> + struct value_traits<const wchar_t[N]> : wstring_traits<const wchar_t[N]> {}; + template <> + struct value_traits<wchar_t*> : wstring_traits<wchar_t*> {}; + template <size_t N> + struct value_traits<wchar_t[N]> : wstring_traits<wchar_t[N]> {}; #endif - // other 'native' value_traits specializations - template <typename T, node_type NodeType> - struct native_value_traits - { - using native_type = T; - static constexpr bool is_native = true; - static constexpr bool is_losslessly_convertible_to_native = true; - static constexpr bool can_represent_native = true; - static constexpr bool can_partially_represent_native = true; - static constexpr auto type = NodeType; - }; - template <> - struct value_traits<bool> : native_value_traits<bool, node_type::boolean> - {}; - template <> - struct value_traits<date> : native_value_traits<date, node_type::date> - {}; - template <> - struct value_traits<time> : native_value_traits<time, node_type::time> - {}; - template <> - struct value_traits<date_time> : native_value_traits<date_time, node_type::date_time> - {}; - - // native value category queries - template <typename T> - using native_type_of = typename value_traits<T>::native_type; - template <typename T> - inline constexpr bool is_native = value_traits<T>::is_native; - template <typename T> - inline constexpr bool can_represent_native = value_traits<T>::can_represent_native; - template <typename T> - inline constexpr bool can_partially_represent_native = value_traits<T>::can_partially_represent_native; - template <typename T> - inline constexpr bool is_losslessly_convertible_to_native = value_traits<T>::is_losslessly_convertible_to_native; - template <typename T, typename... U> - inline constexpr bool is_natively_one_of = is_one_of<native_type_of<T>, U...>; - - // native value types => nodes - template <typename T> - struct node_wrapper - { - 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> - { - using type = value<std::string>; - }; - template <> - struct node_wrapper<int64_t> - { - using type = value<int64_t>; - }; - template <> - struct node_wrapper<double> - { - using type = value<double>; - }; - template <> - struct node_wrapper<bool> - { - using type = value<bool>; - }; - template <> - struct node_wrapper<date> - { - using type = value<date>; - }; - template <> - struct node_wrapper<time> - { - using type = value<time>; - }; - template <> - struct node_wrapper<date_time> - { - using type = value<date_time>; - }; - template <typename T> - using wrap_node = typename node_wrapper<std::remove_reference_t<T>>::type; - - // nodes => native value types - template <typename T> - struct node_unwrapper - { - using type = T; - }; - template <typename T> - struct node_unwrapper<value<T>> - { - using type = T; - }; - template <typename T> - 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 - { - static constexpr auto value = value_traits<T>::type; - }; - template <> - struct node_type_getter<table> - { - static constexpr auto value = node_type::table; - }; - template <> - struct node_type_getter<array> - { - static constexpr auto value = node_type::array; - }; - template <> - struct node_type_getter<void> - { - static constexpr auto value = node_type::none; - }; - template <typename T> - inline constexpr node_type node_type_of = node_type_getter<unwrap_node<remove_cvref<T>>>::value; - - template <typename T, typename ConvertFrom> - inline constexpr bool is_constructible_or_convertible = std::is_constructible_v<T, ConvertFrom> // - || std::is_convertible_v<ConvertFrom, T>; + // other 'native' value_traits specializations + template <typename T, node_type NodeType> + struct native_value_traits { + using native_type = T; + static constexpr bool is_native = true; + static constexpr bool is_losslessly_convertible_to_native = true; + static constexpr bool can_represent_native = true; + static constexpr bool can_partially_represent_native = true; + static constexpr auto type = NodeType; + }; + template <> + struct value_traits<bool> : native_value_traits<bool, node_type::boolean> {}; + template <> + struct value_traits<date> : native_value_traits<date, node_type::date> {}; + template <> + struct value_traits<time> : native_value_traits<time, node_type::time> {}; + template <> + struct value_traits<date_time> : native_value_traits<date_time, node_type::date_time> {}; + + // native value category queries + template <typename T> + using native_type_of = typename value_traits<T>::native_type; + template <typename T> + inline constexpr bool is_native = value_traits<T>::is_native; + template <typename T> + inline constexpr bool can_represent_native = value_traits<T>::can_represent_native; + template <typename T> + inline constexpr bool can_partially_represent_native = + value_traits<T>::can_partially_represent_native; + template <typename T> + inline constexpr bool is_losslessly_convertible_to_native = + value_traits<T>::is_losslessly_convertible_to_native; + template <typename T, typename... U> + inline constexpr bool is_natively_one_of = is_one_of<native_type_of<T>, U...>; + + // native value types => nodes + template <typename T> + struct node_wrapper { + 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> { + using type = value<std::string>; + }; + template <> + struct node_wrapper<int64_t> { + using type = value<int64_t>; + }; + template <> + struct node_wrapper<double> { + using type = value<double>; + }; + template <> + struct node_wrapper<bool> { + using type = value<bool>; + }; + template <> + struct node_wrapper<date> { + using type = value<date>; + }; + template <> + struct node_wrapper<time> { + using type = value<time>; + }; + template <> + struct node_wrapper<date_time> { + using type = value<date_time>; + }; + template <typename T> + using wrap_node = typename node_wrapper<std::remove_reference_t<T>>::type; + + // nodes => native value types + template <typename T> + struct node_unwrapper { + using type = T; + }; + template <typename T> + struct node_unwrapper<value<T>> { + using type = T; + }; + template <typename T> + 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 { + static constexpr auto value = value_traits<T>::type; + }; + template <> + struct node_type_getter<table> { + static constexpr auto value = node_type::table; + }; + template <> + struct node_type_getter<array> { + static constexpr auto value = node_type::array; + }; + template <> + struct node_type_getter<void> { + static constexpr auto value = node_type::none; + }; + template <typename T> + inline constexpr node_type node_type_of = node_type_getter<unwrap_node<remove_cvref<T>>>::value; + + template <typename T, typename ConvertFrom> + inline constexpr bool is_constructible_or_convertible = + std::is_constructible_v<T, ConvertFrom> // + || std::is_convertible_v<ConvertFrom, T>; } TOML_IMPL_NAMESPACE_END; /// \endcond -TOML_NAMESPACE_START -{ - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::table. - template <typename T> - inline constexpr bool is_table = std::is_same_v<impl::remove_cvref<T>, table>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::array. - template <typename T> - inline constexpr bool is_array = std::is_same_v<impl::remove_cvref<T>, array>; - - /// \brief Metafunction for determining if a type satisfies either toml::is_table or toml::is_array. - template <typename T> - inline constexpr bool is_container = is_table<T> || is_array<T>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a std::string or toml::value<std::string>. - template <typename T> - inline constexpr bool is_string = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<std::string>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a int64_t or toml::value<int64_t>. - template <typename T> - inline constexpr bool is_integer = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<int64_t>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a double or toml::value<double>. - template <typename T> - inline constexpr bool is_floating_point = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<double>>; - - /// \brief Metafunction for determining if a type satisfies either toml::is_integer or toml::is_floating_point. - template <typename T> - inline constexpr bool is_number = is_integer<T> || is_floating_point<T>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a bool or toml::value<bool>. - template <typename T> - inline constexpr bool is_boolean = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<bool>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::date or toml::value<date>. - template <typename T> - inline constexpr bool is_date = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<date>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::time or toml::value<time>. - template <typename T> - inline constexpr bool is_time = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<time>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::date_time or toml::value<date_time>. - template <typename T> - inline constexpr bool is_date_time = std::is_same_v< // - impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // - value<date_time>>; - - /// \brief Metafunction for determining if a type satisfies any of toml::is_date, toml::is_time or toml::is_date_time. - template <typename T> - inline constexpr bool is_chronological = is_date<T> || is_time<T> || is_date_time<T>; - - /// \brief Metafunction for determining if a type is, or is a reference to, any of the toml value types. Excludes tables and arrays. - template <typename T> - inline constexpr bool is_value = is_string<T> || is_number<T> || is_boolean<T> || is_chronological<T>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::node (or one of its subclasses). - template <typename T> - inline constexpr bool is_node = std::is_same_v<toml::node, impl::remove_cvref<T>> // - || std::is_base_of_v<toml::node, impl::remove_cvref<T>>; - - /// \brief Metafunction for determining if a type is, or is a reference to, a toml::node_view. - template <typename T> - inline constexpr bool is_node_view = impl::is_one_of<impl::remove_cvref<T>, node_view<node>, node_view<const node>>; +TOML_NAMESPACE_START { + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::table. + template <typename T> + inline constexpr bool is_table = std::is_same_v<impl::remove_cvref<T>, table>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::array. + template <typename T> + inline constexpr bool is_array = std::is_same_v<impl::remove_cvref<T>, array>; + + /// \brief Metafunction for determining if a type satisfies either toml::is_table or + /// toml::is_array. + template <typename T> + inline constexpr bool is_container = is_table<T> || is_array<T>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a std::string or + /// toml::value<std::string>. + template <typename T> + inline constexpr bool is_string = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<std::string>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a int64_t or + /// toml::value<int64_t>. + template <typename T> + inline constexpr bool is_integer = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<int64_t>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a double or + /// toml::value<double>. + template <typename T> + inline constexpr bool is_floating_point = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<double>>; + + /// \brief Metafunction for determining if a type satisfies either toml::is_integer or + /// toml::is_floating_point. + template <typename T> + inline constexpr bool is_number = is_integer<T> || is_floating_point<T>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a bool or + /// toml::value<bool>. + template <typename T> + inline constexpr bool is_boolean = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<bool>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::date or + /// toml::value<date>. + template <typename T> + inline constexpr bool is_date = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<date>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::time or + /// toml::value<time>. + template <typename T> + inline constexpr bool is_time = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<time>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::date_time or + /// toml::value<date_time>. + template <typename T> + inline constexpr bool is_date_time = std::is_same_v< // + impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, // + value<date_time>>; + + /// \brief Metafunction for determining if a type satisfies any of toml::is_date, toml::is_time + /// or toml::is_date_time. + template <typename T> + inline constexpr bool is_chronological = is_date<T> || is_time<T> || is_date_time<T>; + + /// \brief Metafunction for determining if a type is, or is a reference to, any of the toml value + /// types. Excludes tables and arrays. + template <typename T> + inline constexpr bool is_value = + is_string<T> || is_number<T> || is_boolean<T> || is_chronological<T>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::node (or one + /// of its subclasses). + template <typename T> + inline constexpr bool is_node = std::is_same_v<toml::node, impl::remove_cvref<T>> // + || std::is_base_of_v<toml::node, impl::remove_cvref<T>>; + + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::node_view. + template <typename T> + inline constexpr bool is_node_view = + impl::is_one_of<impl::remove_cvref<T>, node_view<node>, node_view<const node>>; } TOML_NAMESPACE_END; -//#--------------------------------------------------------------------------------------------------------------------- -//# INTERNAL HELPERS -//#--------------------------------------------------------------------------------------------------------------------- +// #--------------------------------------------------------------------------------------------------------------------- +// # INTERNAL HELPERS +// #--------------------------------------------------------------------------------------------------------------------- /// \cond -TOML_IMPL_NAMESPACE_START -{ - template <typename T> - TOML_CONST_INLINE_GETTER - constexpr std::underlying_type_t<T> unwrap_enum(T val) noexcept - { - return static_cast<std::underlying_type_t<T>>(val); - } - - // Q: "why not use std::fpclassify?" - // A: Because it gets broken by -ffast-math and friends - enum class TOML_CLOSED_ENUM fp_class : unsigned - { - ok, - neg_inf, - pos_inf, - nan - }; - - TOML_PURE_GETTER - inline fp_class fpclassify(const double& val) noexcept - { - static_assert(sizeof(uint64_t) == sizeof(double)); - - static constexpr uint64_t sign = 0b1000000000000000000000000000000000000000000000000000000000000000ull; - static constexpr uint64_t exponent = 0b0111111111110000000000000000000000000000000000000000000000000000ull; - static constexpr uint64_t mantissa = 0b0000000000001111111111111111111111111111111111111111111111111111ull; - - uint64_t val_bits; - std::memcpy(&val_bits, &val, sizeof(val)); - if ((val_bits & exponent) != exponent) - return fp_class::ok; - if ((val_bits & mantissa)) - return fp_class::nan; - return (val_bits & sign) ? fp_class::neg_inf : fp_class::pos_inf; - } - - // Q: "why not use std::find and std::min?" - // A: Because <algorithm> is _huge_ and these would be the only things I used from it. - // I don't want to impose such a heavy compile-time burden on users. - - template <typename Iterator, typename T> - TOML_PURE_GETTER - inline auto find(Iterator start, Iterator end, const T& needle) noexcept // - ->decltype(&(*start)) - { - for (; start != end; start++) - if (*start == needle) - return &(*start); - return nullptr; - } - - template <typename T> - TOML_PURE_INLINE_GETTER - constexpr const T& min(const T& a, const T& b) noexcept // - { - return a < b ? a : b; - } +TOML_IMPL_NAMESPACE_START { + template <typename T> + TOML_CONST_INLINE_GETTER constexpr std::underlying_type_t<T> unwrap_enum(T val) noexcept { + return static_cast<std::underlying_type_t<T>>(val); + } + + // Q: "why not use std::fpclassify?" + // A: Because it gets broken by -ffast-math and friends + enum class TOML_CLOSED_ENUM fp_class : unsigned { ok, neg_inf, pos_inf, nan }; + + TOML_PURE_GETTER + inline fp_class fpclassify(const double& val) noexcept { + static_assert(sizeof(uint64_t) == sizeof(double)); + + static constexpr uint64_t sign = + 0b1000000000000000000000000000000000000000000000000000000000000000ull; + static constexpr uint64_t exponent = + 0b0111111111110000000000000000000000000000000000000000000000000000ull; + static constexpr uint64_t mantissa = + 0b0000000000001111111111111111111111111111111111111111111111111111ull; + + uint64_t val_bits; + std::memcpy(&val_bits, &val, sizeof(val)); + if ((val_bits & exponent) != exponent) return fp_class::ok; + if ((val_bits & mantissa)) return fp_class::nan; + return (val_bits & sign) ? fp_class::neg_inf : fp_class::pos_inf; + } + + // Q: "why not use std::find and std::min?" + // A: Because <algorithm> is _huge_ and these would be the only things I used from it. + // I don't want to impose such a heavy compile-time burden on users. + + template <typename Iterator, typename T> + TOML_PURE_GETTER inline auto find(Iterator start, Iterator end, const T& needle) noexcept // + -> decltype(&(*start)) { + for (; start != end; start++) + if (*start == needle) return &(*start); + return nullptr; + } + + template <typename T> + TOML_PURE_INLINE_GETTER constexpr const T& min(const T& a, const T& b) noexcept // + { + return a < b ? a : b; + } } TOML_IMPL_NAMESPACE_END; /// \endcond |
