From fd07301baefa08f7b2bdfabf1e71c5e263b94e73 Mon Sep 17 00:00:00 2001 From: Mark Gillard Date: Sat, 25 Jul 2020 20:37:30 +0300 Subject: [PATCH] improved support for __fp16, _Float16 and __float128 also: - fixed a bunch of doxygen parsing issues - added `#define` leak detection to the single-header script - renamed `TOML_ALL_INLINE` to `TOML_HEADER_ONLY` (the old one still works too) - simplified abi namespace definitions --- README.md | 4 +- docs/Doxyfile | 69 +- docs/main_page.dox | 6 +- examples/utf8_console.h | 14 +- include/toml++/toml.h | 117 +- include/toml++/toml_array.h | 19 +- include/toml++/toml_array.hpp | 7 +- include/toml++/toml_common.h | 1198 ++++++----- include/toml++/toml_date_time.h | 15 +- include/toml++/toml_default_formatter.h | 51 +- include/toml++/toml_default_formatter.hpp | 22 +- include/toml++/toml_formatter.h | 17 +- include/toml++/toml_instantiations.hpp | 18 +- include/toml++/toml_json_formatter.h | 16 +- include/toml++/toml_json_formatter.hpp | 7 +- include/toml++/toml_node.h | 12 +- include/toml++/toml_node.hpp | 7 +- include/toml++/toml_node_view.h | 16 +- include/toml++/toml_parse_error.h | 11 +- include/toml++/toml_parser.h | 43 +- include/toml++/toml_parser.hpp | 21 +- include/toml++/toml_preprocessor.h | 369 ++-- include/toml++/toml_print_to_stream.h | 20 +- include/toml++/toml_table.h | 19 +- include/toml++/toml_table.hpp | 7 +- include/toml++/toml_utf8.h | 10 +- include/toml++/toml_utf8_generated.h | 16 +- include/toml++/toml_utf8_streams.h | 7 +- include/toml++/toml_utf8_streams.hpp | 7 +- include/toml++/toml_value.h | 40 +- include/toml++/toml_version.h | 2 +- meson.build | 2 +- python/generate_documentation.py | 7 + python/generate_single_header.py | 61 +- python/generate_unicode_functions.py | 16 +- python/generate_windows_test_targets.py | 97 +- tests/impl_toml.cpp | 81 +- tests/meson.build | 135 +- tests/settings.h | 22 +- tests/unicode_generated.cpp | 4 +- toml.hpp | 1894 +++++++++-------- vs/tests/test_debug_x64.vcxproj | 97 + vs/tests/test_debug_x64_cpplatest.vcxproj | 97 + .../test_debug_x64_cpplatest_noexcept.vcxproj | 97 + ...debug_x64_cpplatest_noexcept_unrel.vcxproj | 97 + .../test_debug_x64_cpplatest_unrel.vcxproj | 97 + vs/tests/test_debug_x64_noexcept.vcxproj | 97 + .../test_debug_x64_noexcept_unrel.vcxproj | 97 + vs/tests/test_debug_x64_unrel.vcxproj | 97 + vs/tests/test_debug_x86.vcxproj | 97 + vs/tests/test_debug_x86_cpplatest.vcxproj | 97 + .../test_debug_x86_cpplatest_noexcept.vcxproj | 97 + ...debug_x86_cpplatest_noexcept_unrel.vcxproj | 97 + .../test_debug_x86_cpplatest_unrel.vcxproj | 97 + vs/tests/test_debug_x86_noexcept.vcxproj | 97 + .../test_debug_x86_noexcept_unrel.vcxproj | 97 + vs/tests/test_debug_x86_unrel.vcxproj | 97 + .../test_release_x64.vcxproj} | 76 +- .../test_release_x64_cpplatest.vcxproj} | 76 +- ...st_release_x64_cpplatest_noexcept.vcxproj} | 76 +- ...ease_x64_cpplatest_noexcept_unrel.vcxproj} | 76 +- .../test_release_x64_cpplatest_unrel.vcxproj} | 76 +- .../test_release_x64_noexcept.vcxproj} | 76 +- .../test_release_x64_noexcept_unrel.vcxproj} | 76 +- .../test_release_x64_unrel.vcxproj} | 76 +- .../test_release_x86.vcxproj} | 76 +- .../test_release_x86_cpplatest.vcxproj} | 76 +- ...st_release_x86_cpplatest_noexcept.vcxproj} | 76 +- ...ease_x86_cpplatest_noexcept_unrel.vcxproj} | 76 +- .../test_release_x86_cpplatest_unrel.vcxproj} | 76 +- .../test_release_x86_noexcept.vcxproj} | 76 +- .../test_release_x86_noexcept_unrel.vcxproj} | 76 +- .../test_release_x86_unrel.vcxproj} | 76 +- vs/toml++.sln | 304 ++- 74 files changed, 4792 insertions(+), 2786 deletions(-) create mode 100644 vs/tests/test_debug_x64.vcxproj create mode 100644 vs/tests/test_debug_x64_cpplatest.vcxproj create mode 100644 vs/tests/test_debug_x64_cpplatest_noexcept.vcxproj create mode 100644 vs/tests/test_debug_x64_cpplatest_noexcept_unrel.vcxproj create mode 100644 vs/tests/test_debug_x64_cpplatest_unrel.vcxproj create mode 100644 vs/tests/test_debug_x64_noexcept.vcxproj create mode 100644 vs/tests/test_debug_x64_noexcept_unrel.vcxproj create mode 100644 vs/tests/test_debug_x64_unrel.vcxproj create mode 100644 vs/tests/test_debug_x86.vcxproj create mode 100644 vs/tests/test_debug_x86_cpplatest.vcxproj create mode 100644 vs/tests/test_debug_x86_cpplatest_noexcept.vcxproj create mode 100644 vs/tests/test_debug_x86_cpplatest_noexcept_unrel.vcxproj create mode 100644 vs/tests/test_debug_x86_cpplatest_unrel.vcxproj create mode 100644 vs/tests/test_debug_x86_noexcept.vcxproj create mode 100644 vs/tests/test_debug_x86_noexcept_unrel.vcxproj create mode 100644 vs/tests/test_debug_x86_unrel.vcxproj rename vs/{test_x64.vcxproj => tests/test_release_x64.vcxproj} (52%) rename vs/{test_x64_cpplatest.vcxproj => tests/test_release_x64_cpplatest.vcxproj} (52%) rename vs/{test_x64_cpplatest_noexcept.vcxproj => tests/test_release_x64_cpplatest_noexcept.vcxproj} (52%) rename vs/{test_x64_cpplatest_unrel_noexcept.vcxproj => tests/test_release_x64_cpplatest_noexcept_unrel.vcxproj} (52%) rename vs/{test_x64_cpplatest_unrel.vcxproj => tests/test_release_x64_cpplatest_unrel.vcxproj} (52%) rename vs/{test_x64_noexcept.vcxproj => tests/test_release_x64_noexcept.vcxproj} (52%) rename vs/{test_x64_unrel_noexcept.vcxproj => tests/test_release_x64_noexcept_unrel.vcxproj} (52%) rename vs/{test_x64_unrel.vcxproj => tests/test_release_x64_unrel.vcxproj} (52%) rename vs/{test_x86.vcxproj => tests/test_release_x86.vcxproj} (52%) rename vs/{test_x86_cpplatest.vcxproj => tests/test_release_x86_cpplatest.vcxproj} (52%) rename vs/{test_x86_cpplatest_noexcept.vcxproj => tests/test_release_x86_cpplatest_noexcept.vcxproj} (52%) rename vs/{test_x86_cpplatest_unrel_noexcept.vcxproj => tests/test_release_x86_cpplatest_noexcept_unrel.vcxproj} (52%) rename vs/{test_x86_cpplatest_unrel.vcxproj => tests/test_release_x86_cpplatest_unrel.vcxproj} (52%) rename vs/{test_x86_noexcept.vcxproj => tests/test_release_x86_noexcept.vcxproj} (52%) rename vs/{test_x86_unrel_noexcept.vcxproj => tests/test_release_x86_noexcept_unrel.vcxproj} (52%) rename vs/{test_x86_unrel.vcxproj => tests/test_release_x86_unrel.vcxproj} (52%) diff --git a/README.md b/README.md index f3e6631..36bbc72 100644 --- a/README.md +++ b/README.md @@ -115,12 +115,12 @@ won't need to mess with these at all, but if you do, set them before including t | Option | Type | Default | Description | |----------------------------|:--------------:|-----------------------------------|----------------------------------------------------------------------------------------------------------------------| -| `TOML_ALL_INLINE` | boolean | `1` | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library). | +| `TOML_HEADER_ONLY` | boolean | `1` | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library). | | `TOML_API` | define | undefined | API annotation to add to public symbols (e.g. `__declspec(dllexport)` on Windows). | | `TOML_ASSERT(expr)` | function macro | `assert(expr)`
(or undefined) | Sets the assert function used by the library. | | `TOML_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. | | `TOML_EXCEPTIONS` | boolean | per your compiler's settings | Sets whether the library uses exceptions. | -| `TOML_IMPLEMENTATION` | define | undefined | Define this to enable compilation of the library's implementation. Meaningless if `TOML_ALL_INLINE` is `1`. | +| `TOML_IMPLEMENTATION` | define | undefined | Define this to enable compilation of the library's implementation. Meaningless if `TOML_HEADER_ONLY` is `1`. | | `TOML_LARGE_FILES` | boolean | `0` | Uses 32-bit integers for line and column indices (instead of 16-bit). | | `TOML_OPTIONAL_TYPE` | type name | undefined | Overrides the `optional` type used by the library if you need [something better than std::optional]. | | `TOML_PARSER` | boolean | `1` | Disable this to prevent inclusion of the parser-related parts of the library if you don't need them. | diff --git a/docs/Doxyfile b/docs/Doxyfile index b3d84e1..f70b1b5 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -309,32 +309,49 @@ EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = NO INCLUDE_PATH = INCLUDE_FILE_PATTERNS = -PREDEFINED = DOXYGEN=1 \ - NDEBUG=1 \ - __cplusplus=201703L \ - __has_include(x)=0 \ - __has_attribute(x)=0 \ - __cpp_lib_char8_t=201811L \ - TOML_ALWAYS_INLINE=inline \ - TOML_MAY_THROW= \ - TOML_NODISCARD_CTOR= \ - TOML_EXTERNAL_LINKAGE= \ - TOML_API= \ - TOML_ABI_NAMESPACE_START(...)= \ - TOML_ABI_NAMESPACE_BOOL(...)= \ - TOML_ABI_NAMESPACE_END= \ - TOML_ATTR(...)= \ - TOML_PUSH_WARNINGS= \ - TOML_DISABLE_SWITCH_WARNINGS= \ - TOML_DISABLE_INIT_WARNINGS= \ - TOML_DISABLE_MISC_WARNINGS= \ - TOML_DISABLE_PADDING_WARNINGS= \ - TOML_DISABLE_ARITHMETIC_WARNINGS= \ - TOML_DISABLE_SHADOW_WARNINGS= \ - TOML_DISABLE_SUGGEST_WARNINGS= \ - TOML_DISABLE_ALL_WARNINGS= \ - TOML_POP_WARNINGS= \ - TOML_ASYMMETRICAL_EQUALITY_OPS(...)= +PREDEFINED = \ + "DOXYGEN=1" \ + "NDEBUG=1" \ + "__cplusplus=201703L" \ + "__has_include(...)=0" \ + "__has_attribute(...)=0" \ + "__cpp_lib_char8_t=201811L" \ + "TOML_DISABLE_ENVIRONMENT_CHECKS=" \ + "TOML_ALWAYS_INLINE=inline" \ + "TOML_MAY_THROW=" \ + "TOML_NODISCARD_CTOR=" \ + "TOML_EXTERNAL_LINKAGE=" \ + "TOML_API=" \ + "TOML_ATTR(...)=" \ + "TOML_PUSH_WARNINGS=" \ + "TOML_DISABLE_SWITCH_WARNINGS=" \ + "TOML_DISABLE_INIT_WARNINGS=" \ + "TOML_DISABLE_MISC_WARNINGS=" \ + "TOML_DISABLE_PADDING_WARNINGS=" \ + "TOML_DISABLE_ARITHMETIC_WARNINGS=" \ + "TOML_DISABLE_SHADOW_WARNINGS=" \ + "TOML_DISABLE_SUGGEST_WARNINGS=" \ + "TOML_DISABLE_ALL_WARNINGS=" \ + "TOML_POP_WARNINGS=" \ + "TOML_ASYMMETRICAL_EQUALITY_OPS(...)=" \ + "TOML_NAMESPACE_START=namespace toml" \ + "TOML_NAMESPACE_END=" \ + "TOML_NAMESPACE=toml" \ + "TOML_ABI_NAMESPACE_START(...)=" \ + "TOML_ABI_NAMESPACE_BOOL(...)=" \ + "TOML_ABI_NAMESPACE_END=" \ + "TOML_IMPL_NAMESPACE_START=namespace toml { namespace impl" \ + "TOML_IMPL_NAMESPACE_END=} }" \ + "TOML_ANON_NAMESPACE_START=namespace" \ + "TOML_ANON_NAMESPACE_END=" \ + "TOML_ANON_NAMESPACE=" \ + "TOML_USING_ANON_NAMESPACE=(void)0" \ + "TOML_EXTERNAL_LINKAGE=" \ + "TOML_TRIVIAL_ABI=" \ + "TOML_EMPTY_BASES=" \ + "TOML_INTERFACE" \ + "TOML_SIMPLE_STATIC_ASSERT_MESSAGES=1" \ + "TOML_INTERNAL_LINKAGE=static" EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- diff --git a/docs/main_page.dox b/docs/main_page.dox index 8cd1657..2867f04 100644 --- a/docs/main_page.dox +++ b/docs/main_page.dox @@ -59,7 +59,7 @@ /// \m_class{m-note m-warning} /// /// \parblock -///

Don't forget [code]#include <fstream>[/code]!

+///

Don't forget [code]\#include <fstream>[/code]!

/// Not everyone who uses the library is going to work directly from files, so not everybody is forced to pay /// the compilation overhead of including ``. You need to explicitly include it if you're going to be calling /// toml::parse_file(). @@ -383,14 +383,14 @@ /// a large number of translation units. You can counter this by disabling 'all inline' mode and explicitly controlling /// where the library's implementation is compiled. /// -/// Step 1: Set \ref TOML_ALL_INLINE to [code]0[/code] before including toml++ +/// Step 1: Set \ref TOML_HEADER_ONLY to [code]0[/code] before including toml++ /// /// This must be the same everywhere, so either set it as a global `#define` in your build system, or /// do it manually before including toml++ in some global header that's used everywhere in your project: /// \cpp /// // global_header_that_includes_toml++.h /// -/// #define TOML_ALL_INLINE 0 +/// #define TOML_HEADER_ONLY 0 /// #include /// \ecpp /// diff --git a/examples/utf8_console.h b/examples/utf8_console.h index 2ac7ee4..7d330d4 100644 --- a/examples/utf8_console.h +++ b/examples/utf8_console.h @@ -8,11 +8,11 @@ #include #endif - inline void init_utf8_console() noexcept - { - #ifdef _WIN32 - SetConsoleOutputCP(65001); //CP_UTF8 - #endif +inline void init_utf8_console() noexcept +{ + #ifdef _WIN32 + SetConsoleOutputCP(65001); //CP_UTF8 + #endif - std::cout << std::boolalpha; - } + std::cout << std::boolalpha; +} diff --git a/include/toml++/toml.h b/include/toml++/toml.h index 979f7ed..e1e6d78 100644 --- a/include/toml++/toml.h +++ b/include/toml++/toml.h @@ -43,81 +43,96 @@ #include "toml_parser.hpp" #endif // TOML_PARSER -#if !TOML_ALL_INLINE +#if !TOML_HEADER_ONLY #include "toml_instantiations.hpp" -#endif // !TOML_ALL_INLINE +#endif // !TOML_HEADER_ONLY #endif // TOML_IMPLEMENTATION // macro hygiene #if TOML_UNDEF_MACROS - #undef TOML_INT_CHARCONV - #undef TOML_FLOAT_CHARCONV + #undef TOML_ABI_NAMESPACES + #undef TOML_ABI_NAMESPACE_BOOL + #undef TOML_ABI_NAMESPACE_END + #undef TOML_ABI_NAMESPACE_START + #undef TOML_ALWAYS_INLINE + #undef TOML_ANON_NAMESPACE + #undef TOML_ANON_NAMESPACE_END + #undef TOML_ANON_NAMESPACE_START + #undef TOML_ARM + #undef TOML_ASSERT + #undef TOML_ASSUME + #undef TOML_ASYMMETRICAL_EQUALITY_OPS #undef TOML_ATTR - #undef TOML_PUSH_WARNINGS - #undef TOML_DISABLE_SWITCH_WARNINGS + #undef TOML_CLANG + #undef TOML_COMPILER_EXCEPTIONS + #undef TOML_CONCAT + #undef TOML_CONCAT_1 + #undef TOML_CONSTEVAL + #undef TOML_CPP + #undef TOML_DISABLE_ALL_WARNINGS + #undef TOML_DISABLE_ARITHMETIC_WARNINGS #undef TOML_DISABLE_INIT_WARNINGS #undef TOML_DISABLE_MISC_WARNINGS #undef TOML_DISABLE_PADDING_WARNINGS - #undef TOML_DISABLE_ARITHMETIC_WARNINGS #undef TOML_DISABLE_SHADOW_WARNINGS #undef TOML_DISABLE_SUGGEST_WARNINGS - #undef TOML_DISABLE_ALL_WARNINGS - #undef TOML_POP_WARNINGS - #undef TOML_ALWAYS_INLINE - #undef TOML_NEVER_INLINE - #undef TOML_ASSUME - #undef TOML_UNREACHABLE - #undef TOML_INTERFACE + #undef TOML_DISABLE_SWITCH_WARNINGS #undef TOML_EMPTY_BASES - #undef TOML_CPP - #undef TOML_MAY_THROW - #undef TOML_NO_DEFAULT_CASE - #undef TOML_CONSTEVAL - #undef TOML_LIKELY - #undef TOML_UNLIKELY - #undef TOML_NODISCARD_CTOR - #undef TOML_MAKE_VERSION + #undef TOML_EVAL_BOOL_0 + #undef TOML_EVAL_BOOL_1 + #undef TOML_EXTERNAL_LINKAGE + #undef TOML_FLOAT128 + #undef TOML_FLOAT16 + #undef TOML_FLOAT_CHARCONV + #undef TOML_FP16 + #undef TOML_GCC + #undef TOML_HAS_CUSTOM_OPTIONAL_TYPE + #undef TOML_HAS_INCLUDE + #undef TOML_ICC + #undef TOML_IMPLEMENTATION + #undef TOML_IMPL_NAMESPACE_END + #undef TOML_IMPL_NAMESPACE_START + #undef TOML_INT128 + #undef TOML_INTELLISENSE + #undef TOML_INTERFACE + #undef TOML_INTERNAL_LINKAGE + #undef TOML_INT_CHARCONV + #undef TOML_LANG_AT_LEAST #undef TOML_LANG_EFFECTIVE_VERSION #undef TOML_LANG_HIGHER_THAN - #undef TOML_LANG_AT_LEAST #undef TOML_LANG_UNRELEASED - #undef TOML_UNDEF_MACROS - #undef TOML_RELOPS_REORDERING - #undef TOML_ASYMMETRICAL_EQUALITY_OPS - #undef TOML_ALL_INLINE - #undef TOML_IMPLEMENTATION - #undef TOML_EXTERNAL_LINKAGE - #undef TOML_INTERNAL_LINKAGE - #undef TOML_ANONYMOUS_NAMESPACE - #undef TOML_ANONYMOUS_NAMESPACE_END - #undef TOML_COMPILER_EXCEPTIONS - #undef TOML_TRIVIAL_ABI - #undef TOML_ABI_NAMESPACES - #undef TOML_ABI_NAMESPACE_START - #undef TOML_ABI_NAMESPACE_VERSION - #undef TOML_ABI_NAMESPACE_BOOL - #undef TOML_ABI_NAMESPACE_END - #undef TOML_PARSER_TYPENAME #undef TOML_LAUNDER - #undef TOML_CONCAT_1 - #undef TOML_CONCAT - #undef TOML_EVAL_BOOL_1 - #undef TOML_EVAL_BOOL_0 - #undef TOML_HAS_CUSTOM_OPTIONAL_TYPE - #undef TOML_IMPL_NAMESPACE_START - #undef TOML_IMPL_NAMESPACE_END - #undef TOML_SIMPLE_STATIC_ASSERT_MESSAGES - #undef TOML_SA_NEWLINE - #undef TOML_SA_LIST_SEP + #undef TOML_LIKELY + #undef TOML_MAKE_VERSION + #undef TOML_MAY_THROW + #undef TOML_MSVC + #undef TOML_NAMESPACE + #undef TOML_NAMESPACE_END + #undef TOML_NAMESPACE_START + #undef TOML_NEVER_INLINE + #undef TOML_NODISCARD_CTOR + #undef TOML_NO_DEFAULT_CASE + #undef TOML_PARSER_TYPENAME + #undef TOML_POP_WARNINGS + #undef TOML_PUSH_WARNINGS + #undef TOML_RELOPS_REORDERING #undef TOML_SA_LIST_BEG + #undef TOML_SA_LIST_CAP #undef TOML_SA_LIST_END #undef TOML_SA_LIST_NEW #undef TOML_SA_LIST_NXT - #undef TOML_SA_LIST_CAP + #undef TOML_SA_LIST_SEP #undef TOML_SA_NATIVE_VALUE_TYPE_LIST + #undef TOML_SA_NEWLINE #undef TOML_SA_NODE_TYPE_LIST #undef TOML_SA_UNWRAPPED_NODE_TYPE_LIST + #undef TOML_SIMPLE_STATIC_ASSERT_MESSAGES + #undef TOML_TRIVIAL_ABI + #undef TOML_UINT128 + #undef TOML_UNLIKELY + #undef TOML_UNREACHABLE + #undef TOML_USING_ANON_NAMESPACE #endif //# {{ diff --git a/include/toml++/toml_array.h b/include/toml++/toml_array.h index 0d29e7e..07d77c2 100644 --- a/include/toml++/toml_array.h +++ b/include/toml++/toml_array.h @@ -9,10 +9,8 @@ TOML_PUSH_WARNINGS TOML_DISABLE_MISC_WARNINGS -namespace toml +TOML_IMPL_NAMESPACE_START { - TOML_IMPL_NAMESPACE_START - template class TOML_TRIVIAL_ABI array_iterator final { @@ -222,19 +220,11 @@ namespace toml { return make_node(std::move(val.value)); } - - TOML_IMPL_NAMESPACE_END } +TOML_IMPL_NAMESPACE_END -namespace toml +TOML_NAMESPACE_START { - TOML_ABI_NAMESPACE_VERSION - - [[nodiscard]] TOML_API bool operator == (const array& lhs, const array& rhs) noexcept; - [[nodiscard]] TOML_API bool operator != (const array& lhs, const array& rhs) noexcept; - template - std::basic_ostream& operator << (std::basic_ostream&, const array&); - /// \brief A RandomAccessIterator for iterating over nodes in a toml::array. using array_iterator = impl::array_iterator; @@ -997,8 +987,7 @@ namespace toml template friend std::basic_ostream& operator << (std::basic_ostream&, const array&); }; - - TOML_ABI_NAMESPACE_END // version } +TOML_NAMESPACE_END TOML_POP_WARNINGS //TOML_DISABLE_MISC_WARNINGS diff --git a/include/toml++/toml_array.hpp b/include/toml++/toml_array.hpp index f0f4166..df03ff4 100644 --- a/include/toml++/toml_array.hpp +++ b/include/toml++/toml_array.hpp @@ -17,10 +17,8 @@ TOML_PUSH_WARNINGS TOML_DISABLE_SUGGEST_WARNINGS TOML_DISABLE_PADDING_WARNINGS -namespace toml +TOML_NAMESPACE_START { - TOML_ABI_NAMESPACE_VERSION - TOML_EXTERNAL_LINKAGE void array::preinsertion_resize(size_t idx, size_t count) noexcept { @@ -257,9 +255,8 @@ namespace toml { return is_homogeneous(node_type::table); } - - TOML_ABI_NAMESPACE_END // version } +TOML_NAMESPACE_END TOML_POP_WARNINGS // TOML_DISABLE_SUGGEST_WARNINGS, TOML_DISABLE_PADDING_WARNINGS diff --git a/include/toml++/toml_common.h b/include/toml++/toml_common.h index 11bd908..58ab1dc 100644 --- a/include/toml++/toml_common.h +++ b/include/toml++/toml_common.h @@ -6,16 +6,15 @@ #pragma once #include "toml_preprocessor.h" -////////// INCLUDES +//#==================================================================================================================== +//# INCLUDES +//#==================================================================================================================== TOML_PUSH_WARNINGS TOML_DISABLE_ALL_WARNINGS - -#if __has_include() - #include -#endif #include -#include //memcpy, memset +#include +#include #include #include #include @@ -28,7 +27,9 @@ TOML_DISABLE_ALL_WARNINGS #if !TOML_HAS_CUSTOM_OPTIONAL_TYPE #include #endif - +#if TOML_HAS_INCLUDE() + #include +#endif TOML_POP_WARNINGS #ifdef __cpp_lib_launder @@ -37,85 +38,221 @@ TOML_POP_WARNINGS #define TOML_LAUNDER(x) x #endif -////////// ENVIRONMENT GROUND-TRUTHS +//#==================================================================================================================== +//# ENVIRONMENT GROUND-TRUTHS +//#==================================================================================================================== -static_assert(CHAR_BIT == 8); -static_assert(FLT_RADIX == 2); -static_assert('A' == 65); -static_assert(sizeof(double) == 8); -static_assert(std::numeric_limits::is_iec559); -static_assert(std::numeric_limits::digits == 53); -static_assert(std::numeric_limits::digits10 == 15); -static_assert(std::numeric_limits::max_digits10 == 17); +#ifndef DOXYGEN +#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 esoteric 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!" -////////// FORWARD DECLARATIONS & TYPEDEFS +static_assert(CHAR_BIT == 8, TOML_ENV_MESSAGE); +static_assert(FLT_RADIX == 2, TOML_ENV_MESSAGE); +static_assert('A' == 65, TOML_ENV_MESSAGE); +static_assert(sizeof(double) == 8, TOML_ENV_MESSAGE); +static_assert(std::numeric_limits::is_iec559, TOML_ENV_MESSAGE); +static_assert(std::numeric_limits::digits == 53, TOML_ENV_MESSAGE); +static_assert(std::numeric_limits::digits10 == 15, TOML_ENV_MESSAGE); + +#undef TOML_ENV_MESSAGE +#endif // !TOML_DISABLE_ENVIRONMENT_CHECKS +#endif // !DOXYGEN + +//#==================================================================================================================== +//# UNDOCUMENTED TYPEDEFS AND FORWARD DECLARATIONS +//#==================================================================================================================== + +#ifndef DOXYGEN // undocumented forward declarations are hidden from doxygen because they fuck it up =/ TOML_PUSH_WARNINGS TOML_DISABLE_PADDING_WARNINGS -TOML_DISABLE_SHADOW_WARNINGS -/// \brief The root namespace for all toml++ functions and types. -namespace toml { TOML_ABI_NAMESPACE_VERSION TOML_ABI_NAMESPACE_END } - -#if TOML_WINDOWS_COMPAT -namespace toml +namespace toml // non-abi namespace; this is not an error { - TOML_IMPL_NAMESPACE_START - - [[nodiscard]] TOML_API std::string narrow(std::wstring_view) noexcept; - [[nodiscard]] TOML_API std::wstring widen(std::string_view) noexcept; - #ifdef __cpp_lib_char8_t - [[nodiscard]] TOML_API std::wstring widen(std::u8string_view) noexcept; - #endif - - TOML_IMPL_NAMESPACE_END -} -#endif // TOML_WINDOWS_COMPAT - -namespace toml -{ - TOML_ABI_NAMESPACE_VERSION - using namespace std::string_literals; using namespace std::string_view_literals; - using size_t = std::size_t; - using ptrdiff_t = std::ptrdiff_t; - - [[nodiscard]] - TOML_ATTR(const) - TOML_ALWAYS_INLINE - TOML_CONSTEVAL size_t operator"" _sz(unsigned long long n) noexcept - { - return static_cast(n); - } + 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; // legacy typedefs using string_char = char; using string = std::string; using string_view = std::string_view; +} - #if !TOML_DOXYGEN - - // foward declarations are hidden from doxygen - // because they fuck it up =/ +TOML_NAMESPACE_START // abi namespace +{ 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 + class node; class array; class table; + template class node_view; template class value; template class default_formatter; template class json_formatter; - TOML_ABI_NAMESPACE_BOOL(TOML_HAS_CUSTOM_OPTIONAL_TYPE, custopt, stdopt) + [[nodiscard]] TOML_API bool operator == (const array& lhs, const array& rhs) noexcept; + [[nodiscard]] TOML_API bool operator != (const array& lhs, const array& rhs) noexcept; + [[nodiscard]] TOML_API bool operator == (const table& lhs, const table& rhs) noexcept; + [[nodiscard]] TOML_API bool operator != (const table& lhs, const table& rhs) noexcept; - struct date_time; + template + std::basic_ostream& operator << (std::basic_ostream&, const array&); + template + std::basic_ostream& operator << (std::basic_ostream&, const value&); + template + std::basic_ostream& operator << (std::basic_ostream&, const table&); + template + std::basic_ostream& operator << (std::basic_ostream&, default_formatter&); + template + std::basic_ostream& operator << (std::basic_ostream&, default_formatter&&); + template + std::basic_ostream& operator << (std::basic_ostream&, json_formatter&); + template + std::basic_ostream& operator << (std::basic_ostream&, json_formatter&&); + template + inline std::basic_ostream& operator << (std::basic_ostream&, const node_view&); - TOML_ABI_NAMESPACE_END // TOML_HAS_CUSTOM_OPTIONAL_TYPE + namespace impl + { + template + using string_map = std::map>; // heterogeneous lookup - #endif // !TOML_DOXYGEN + template + using remove_cvref_t = std::remove_cv_t>; + + //template + //struct is_one_of_ : std::integral_constant)> {}; + + template + inline constexpr bool is_one_of = (false || ... || std::is_same_v); + + template + inline constexpr bool is_cvref = std::is_reference_v || std::is_const_v || std::is_volatile_v; + + template + inline constexpr bool is_wide_string = is_one_of< + std::decay_t, + const wchar_t*, + wchar_t*, + std::wstring_view, + std::wstring + >; + + template + inline constexpr bool dependent_false = false; + + #define TOML_P2S_DECL(Type) \ + template \ + inline void print_to_stream(Type, std::basic_ostream&) + TOML_P2S_DECL(int8_t); + TOML_P2S_DECL(int16_t); + TOML_P2S_DECL(int32_t); + TOML_P2S_DECL(int64_t); + TOML_P2S_DECL(uint8_t); + TOML_P2S_DECL(uint16_t); + TOML_P2S_DECL(uint32_t); + TOML_P2S_DECL(uint64_t); + TOML_P2S_DECL(float); + TOML_P2S_DECL(const date&); + TOML_P2S_DECL(const time&); + TOML_P2S_DECL(time_offset); + TOML_P2S_DECL(const date_time&); + #undef TOML_P2S_DECL + + #if TOML_WINDOWS_COMPAT + [[nodiscard]] TOML_API std::string narrow(std::wstring_view) noexcept; + [[nodiscard]] TOML_API std::wstring widen(std::string_view) noexcept; + #ifdef __cpp_lib_char8_t + [[nodiscard]] TOML_API std::wstring widen(std::u8string_view) noexcept; + #endif + #endif // TOML_WINDOWS_COMPAT + + #if TOML_ABI_NAMESPACES + #if TOML_EXCEPTIONS + TOML_ABI_NAMESPACE_START(ex) + #define TOML_PARSER_TYPENAME TOML_NAMESPACE::impl::ex::parser + #else + TOML_ABI_NAMESPACE_START(noex) + #define TOML_PARSER_TYPENAME TOML_NAMESPACE::impl::noex::parser + #endif + #else + #define TOML_PARSER_TYPENAME TOML_NAMESPACE::impl::parser + #endif + class parser; + TOML_ABI_NAMESPACE_END // TOML_EXCEPTIONS + } +} +TOML_NAMESPACE_END + +TOML_POP_WARNINGS // TOML_DISABLE_PADDING_WARNINGS + +#endif // !DOXYGEN + +//#==================================================================================================================== +//# TYPEDEFS AND FORWARD DECLARATIONS +//#==================================================================================================================== + +/// \brief The root namespace for all toml++ functions and types. +namespace toml { } + +TOML_NAMESPACE_START // abi namespace +{ + /// \brief Convenience literal operators for working with toml++. + /// + /// \detail This namespace exists so you can safely hoist the UDL operators into another scope + /// without dragging in everything in the toml namespace: \cpp + /// + /// #include + /// using namespace toml::literals; + /// + /// int main() + /// { + /// auto tbl = "vals = [1, 2, 3]"_toml; + /// + /// // ... do stuff with the table generated by the "_toml" UDL ... + /// + /// return 0; + /// } + /// \ecpp + /// + inline namespace literals {} + + #if TOML_HAS_CUSTOM_OPTIONAL_TYPE + template + using optional = TOML_OPTIONAL_TYPE; + #else + /// \brief The 'optional' type used throughout the library. + /// + /// \remarks By default this will be an alias for std::optional, but you can change the optional type + /// used by the library by defining #TOML_OPTIONAL_TYPE. + template + using optional = std::optional; + #endif /// \brief TOML node type identifiers. enum class node_type : uint8_t @@ -132,25 +269,454 @@ namespace toml date_time ///< The node is a toml::value. }; - #if TOML_HAS_CUSTOM_OPTIONAL_TYPE - - template - using optional = TOML_OPTIONAL_TYPE; - - #else - - /// \brief The 'optional' type used throughout the library. - /// - /// \remarks By default this will be a simple alias for std::optional, but you can change the optional type - /// used by the library by defining #TOML_OPTIONAL_TYPE. - template - using optional = std::optional; - - #endif - /// \brief A pointer to a shared string resource containing a source path. using source_path_ptr = std::shared_ptr; + /// \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 << std::endl; + /// std::cout << "good:" << good << std::endl; + /// \ecpp + /// + /// \out + /// bad: [ 42 ] + /// good: [ [ 42 ] ] + /// \eout + /// + /// \see toml::array + template + struct TOML_TRIVIAL_ABI inserter + { + T&& value; + }; + template inserter(T&&) -> inserter; +} +TOML_NAMESPACE_END + +//#==================================================================================================================== +//# VALUE AND NODE TRAITS +//#==================================================================================================================== + +TOML_IMPL_NAMESPACE_START +{ + // general value traits + // (as they relate to their equivalent native TOML type) + template + struct 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 struct value_traits : value_traits {}; + template struct value_traits : value_traits {}; + template struct value_traits : value_traits {}; + template struct value_traits : value_traits {}; + template struct value_traits : value_traits {}; + + + // integer value traits + template + struct integer_value_limits + { + static constexpr auto min = (std::numeric_limits::min)(); + static constexpr auto max = (std::numeric_limits::max)(); + }; + template + struct integer_value_traits_base : integer_value_limits + { + using native_type = int64_t; + static constexpr bool is_native = std::is_same_v; + static constexpr bool is_signed = static_cast(-1) < T{}; // for impls not specializing std::is_signed + static constexpr auto type = node_type::integer; + static constexpr bool can_partially_represent_native = true; + }; + template + struct unsigned_integer_value_traits : integer_value_traits_base + { + static constexpr bool is_losslessly_convertible_to_native + = integer_value_limits::max <= 9223372036854775807ULL; + static constexpr bool can_represent_native = false; + + }; + template + struct signed_integer_value_traits : integer_value_traits_base + { + using native_type = int64_t; + static constexpr bool is_losslessly_convertible_to_native + = integer_value_limits::min >= (-9223372036854775807LL - 1LL) + && integer_value_limits::max <= 9223372036854775807LL; + static constexpr bool can_represent_native + = integer_value_limits::min <= (-9223372036854775807LL - 1LL) + && integer_value_limits::max >= 9223372036854775807LL; + }; + template ::is_signed> + struct integer_value_traits : signed_integer_value_traits {}; + template + struct integer_value_traits : unsigned_integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + #ifdef TOML_INT128 + template <> + struct integer_value_limits + { + static constexpr TOML_INT128 max = static_cast( + (TOML_UINT128{ 1u } << ((__SIZEOF_INT128__ * CHAR_BIT) - 1)) - 1 + ); + static constexpr TOML_INT128 min = -max - TOML_INT128{ 1 }; + }; + template <> + struct integer_value_limits + { + static constexpr TOML_UINT128 min = TOML_UINT128{}; + static constexpr TOML_UINT128 max = (2u * static_cast(integer_value_limits::max)) + 1u; + }; + template <> struct value_traits : integer_value_traits {}; + template <> struct value_traits : integer_value_traits {}; + #endif + #ifdef TOML_SMALL_INT_TYPE + template <> struct value_traits : signed_integer_value_traits {}; + #endif + static_assert(value_traits::is_native); + static_assert(value_traits::is_signed); + static_assert(value_traits::is_losslessly_convertible_to_native); + static_assert(value_traits::can_represent_native); + static_assert(value_traits::can_partially_represent_native); + + // float value traits + template + struct float_value_limits + { + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + }; + template + struct float_value_traits : float_value_limits + { + using native_type = double; + static constexpr bool is_native = std::is_same_v; + static constexpr bool is_signed = true; + static constexpr bool is_losslessly_convertible_to_native + = float_value_limits::is_iec559 + && float_value_limits::digits <= 53 + && float_value_limits::digits10 <= 15; + static constexpr bool can_represent_native + = float_value_limits::is_iec559 + && float_value_limits::digits >= 53 // DBL_MANT_DIG + && float_value_limits::digits10 >= 15; // DBL_DIG + static constexpr bool can_partially_represent_native //32-bit float values + = float_value_limits::is_iec559 + && float_value_limits::digits >= 24 + && float_value_limits::digits10 >= 6; + static constexpr auto type = node_type::floating_point; + }; + template <> struct value_traits : float_value_traits {}; + template <> struct value_traits : float_value_traits {}; + template <> struct value_traits : float_value_traits {}; + template + struct extended_float_value_limits + { + static constexpr bool is_iec559 = true; + static constexpr int digits = mant_dig; + static constexpr int digits10 = dig; + }; + #ifdef TOML_FP16 + template <> struct float_value_limits : extended_float_value_limits<__FLT16_MANT_DIG__, __FLT16_DIG__> {}; + template <> struct value_traits : float_value_traits {}; + #endif + #ifdef TOML_FLOAT16 + template <> struct float_value_limits : extended_float_value_limits<__FLT16_MANT_DIG__, __FLT16_DIG__> {}; + template <> struct value_traits : float_value_traits {}; + #endif + #ifdef TOML_FLOAT128 + template <> struct float_value_limits : extended_float_value_limits<__FLT128_MANT_DIG__, __FLT128_DIG__> {}; + template <> struct value_traits : float_value_traits {}; + #endif + #ifdef TOML_SMALL_FLOAT_TYPE + template <> struct value_traits : float_value_traits {}; + #endif + static_assert(value_traits::is_native); + static_assert(value_traits::is_losslessly_convertible_to_native); + static_assert(value_traits::can_represent_native); + static_assert(value_traits::can_partially_represent_native); + + // string value traits + template + struct string_value_traits + { + using native_type = std::string; + static constexpr bool is_native = std::is_same_v; + static constexpr bool is_losslessly_convertible_to_native = true; + static constexpr bool can_represent_native + = !std::is_array_v + && (!std::is_pointer_v || std::is_const_v>); + static constexpr bool can_partially_represent_native = can_represent_native; + static constexpr auto type = node_type::string; + }; + template <> struct value_traits : string_value_traits {}; + template <> struct value_traits : string_value_traits {}; + template <> struct value_traits : string_value_traits {}; + template struct value_traits : string_value_traits {}; + template <> struct value_traits : string_value_traits {}; + template struct value_traits : string_value_traits {}; + #ifdef __cpp_lib_char8_t + template <> struct value_traits : string_value_traits {}; + template <> struct value_traits : string_value_traits {}; + template <> struct value_traits : string_value_traits {}; + template struct value_traits : string_value_traits {}; + template <> struct value_traits : string_value_traits {}; + template struct value_traits : string_value_traits {}; + #endif + #if TOML_WINDOWS_COMPAT + template + struct wstring_value_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; //widen + static constexpr bool can_partially_represent_native = can_represent_native; + static constexpr auto type = node_type::string; + }; + template <> struct value_traits : wstring_value_traits {}; + template <> struct value_traits : wstring_value_traits {}; + template <> struct value_traits : wstring_value_traits {}; + template struct value_traits : wstring_value_traits {}; + template <> struct value_traits : wstring_value_traits {}; + template struct value_traits : wstring_value_traits {}; + #endif + + // other native value traits + template + 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 : native_value_traits {}; + template <> struct value_traits : native_value_traits {}; + template <> struct value_traits