diff --git a/README.md b/README.md index 5bf48c10..7d8768c5 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,13 @@ [![GitHub](https://img.shields.io/github/license/marzer/tomlplusplus)](https://github.com/marzer/tomlplusplus/blob/master/LICENSE) `toml++` is a header-only toml parser and serializer for C++17, C++20 and whatever comes after. - - Fully [TOML v0.5.0]-compliant - - Modern C++17 (with some C++20 features where supported) + - [TOML v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md), plus support for some + unreleased TOML features (these are optional) + - C++17 (plus some C++20 features where available, e.g. experimental support for char8_t strings) - Proper UTF-8 handling (incl. BOM) - Works with or without exceptions - Doesn't require RTTI - First-class support for serializing to JSON - - Supports a number of 'unreleased' TOML features (optional)
diff --git a/include/toml++/toml.h b/include/toml++/toml.h index c40c04c9..ae64f801 100644 --- a/include/toml++/toml.h +++ b/include/toml++/toml.h @@ -53,7 +53,10 @@ #undef TOML_DOXYGEN #undef TOML_RELOPS_REORDERING #undef TOML_ASYMMETRICAL_EQUALITY_OPS + #undef TOML_INLINE_NS_EX #undef TOML_START + #undef TOML_START_2 + #undef TOML_START_1 #undef TOML_END #undef TOML_IMPL_START #undef TOML_IMPL_END @@ -61,33 +64,47 @@ /// \mainpage toml++ /// -/// This is the home of toml++, a header-only [TOML](https://github.com/toml-lang/toml) parser and serializer for C++17 and later. +/// This is the home of toml++, a header-only [TOML](https://github.com/toml-lang/toml) parser and serializer for C++17 +/// and later. /// /// \tableofcontents /// /////////////////////////////////////////////////////////////////////// /// /// \section mainpage-features Features -/// - C++17 (plus some C++20 features where supported, e.g. char8_t strings) +/// - [TOML v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md), plus support for some +/// unreleased TOML features (these are optional) +/// - C++17 (plus some C++20 features where available, e.g. experimental support for char8_t strings) /// - Proper UTF-8 handling (incl. BOM) /// - Works with or without exceptions /// - Doesn't require RTTI /// - First-class support for serializing to JSON -/// - Fully [TOML v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md)-compliant -/// - Supports a number of 'unreleased' TOML features (optional; these can be disabled) /// /////////////////////////////////////////////////////////////////////// /// /// \section mainpage-adding-lib Adding toml++ to your project -/// Clone [the repository](https://github.com/marzer/tomlplusplus/) from GitHub. It's header-only so there's not much you have to do after that, -/// other than some very minor (optional) configuration. See the [README](https://github.com/marzer/tomlplusplus/blob/master/README.md) for more info. +/// It's header-only library so really all you have to do is clone +/// [the repository](https://github.com/marzer/tomlplusplus/) from GitHub and set your include paths. +/// There's some minor configuration you can do to customize some basic library functionality, but that's totally +/// optional. See the [README](https://github.com/marzer/tomlplusplus/blob/master/README.md) for more info. +/// +///
+///

On Linkers and the One-Definition-Rule

+///

Header-only libraries are great for minimal setup, but can cause ODR violations and complex linker errors +/// in situations where multiple modules include them separately, each with different versions, configuration options, +/// exception handling modes, et cetera.

+///

`toml++` attempts to combat this problem by nesting everything inside an additional inline namespace that +/// changes according to the library's major version and the compiler's exception-handling mode.

+///
/// /////////////////////////////////////////////////////////////////////// /// /// \section mainpage-api-documentation API Documentation -/// You're looking at it! Browse the docs using the links at the top of the page. You can search from anywhere by pressing the TAB key. +/// You're looking at it! Browse the docs using the links at the top of the page. +/// You can search from anywhere by pressing the TAB key. /// -/// toml++ is still pretty hot off the presses so there's going to be some omissions, typos and general sparseness throughout the docs. +/// toml++ is still pretty hot off the presses so there's going to be some omissions, +/// typos and general sparseness throughout the docs. /// If you spot something or have a suggestion, please [let me know](https://github.com/marzer/tomlplusplus/issues)! /// /////////////////////////////////////////////////////////////////////// @@ -99,7 +116,8 @@ /// \subsection mainpage-example-parsing-files Parsing TOML files /// toml++ works whether you have exceptions enabled or not. For the most part the usage is the same, /// the main difference being how parsing errors are reported to the caller. When exceptions are enabled -/// a toml::parse_error is thrown directly from the site of the error: +/// a successful call to a parsing function simply returns a toml::table, whereas a failed call sees a toml::parse_error +/// thrown directly from the site of the error: /// \cpp /// #include /// #include //required for parse_file() @@ -129,7 +147,7 @@ /// /// \ecpp /// -/// When exceptions are disabled parsing methods return a toml::parse_result and it is up to the caller +/// When exceptions are disabled parsing functions return a toml::parse_result instead and it is up to the caller /// to check if parsing has been successful by examining the return value: /// \cpp /// #include @@ -341,9 +359,13 @@ /// /// \section mainpage-license License /// -/// toml++ is licensed under the terms of the MIT license - see [LICENSE](https://github.com/marzer/tomlplusplus/blob/master/LICENSE). +/// toml++ is licensed under the terms of the MIT license - see +/// [LICENSE](https://github.com/marzer/tomlplusplus/blob/master/LICENSE). /// -/// UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's 'Flexible and Economical UTF - 8 Decoder', which is also subject -/// to the terms of the MIT license - see [LICENSE-utf8-decoder](https://github.com/marzer/tomlplusplus/blob/master/LICENSE-utf8-decoder). +/// UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's +/// 'Flexible and Economical UTF - 8 Decoder', which is also subject to the terms of the MIT license - see +/// [LICENSE-utf8-decoder](https://github.com/marzer/tomlplusplus/blob/master/LICENSE-utf8-decoder). /// +/// \remark Note that if you're using the single-header version of the library you don't need to distribute these files; +/// their contents is included in the preamble at the top of the file. /// diff --git a/include/toml++/toml_common.h b/include/toml++/toml_common.h index 52c164fc..777ef7f5 100644 --- a/include/toml++/toml_common.h +++ b/include/toml++/toml_common.h @@ -229,17 +229,6 @@ __VA_ARGS__ [[nodiscard]] friend bool operator != (RHS rhs, LHS lhs) noexcept { return !(lhs == rhs); } #endif -#if !TOML_DOXYGEN - #if TOML_EXCEPTIONS - #define TOML_START namespace toml { inline namespace wex - #else - #define TOML_START namespace toml { inline namespace woex - #endif - #define TOML_END } -#endif -#define TOML_IMPL_START TOML_START { namespace impl -#define TOML_IMPL_END } TOML_END - #include "toml_version.h" #define TOML_MAKE_VERSION(maj, min, rev) \ @@ -262,6 +251,22 @@ #define TOML_LANG_EXACTLY(maj, min, rev) \ (TOML_LANG_EFFECTIVE_VERSION == TOML_MAKE_VERSION(maj, min, rev)) +#if !TOML_DOXYGEN + + #if TOML_EXCEPTIONS + #define TOML_INLINE_NS_EX + #else + #define TOML_INLINE_NS_EX _noex + #endif + + #define TOML_START_2(VER, ARG1, ARG2) namespace toml { inline namespace v##VER##ARG1##ARG2 + #define TOML_START_1(VER, ARG1, ARG2) TOML_START_2(VER, ARG1, ARG2) + #define TOML_START TOML_START_1(TOML_LIB_MAJOR,TOML_INLINE_NS_EX,) + #define TOML_END } + +#endif +#define TOML_IMPL_START TOML_START { namespace impl +#define TOML_IMPL_END } TOML_END ////////// INCLUDES diff --git a/include/toml++/toml_node_view.h b/include/toml++/toml_node_view.h index ad81dba8..e5f7ce1b 100644 --- a/include/toml++/toml_node_view.h +++ b/include/toml++/toml_node_view.h @@ -35,17 +35,18 @@ TOML_START /// /// tbl["products"][0]["keywords"].as_array()->push_back("heavy"); /// std::cout << tbl["products"][0]["keywords"] << std::endl; - /// std::cout << "has third product: "sv << !!tbl["products"][2] << std::endl; - /// std::cout << tbl["products"][2] << std::endl; // no-op - /// - /// \ecpp + /// std::cout << "has product[2]: "sv << !!tbl["products"][2] << std::endl; + /// std::cout << "product[2]: "sv << tbl["products"][2] << std::endl; + /// \ecpp /// /// \out /// "my hardware store" /// "Hammer" /// [ "hammer", "construction", "build" ] + /// "build" /// [ "hammer", "construction", "build", "heavy" ] - /// has third product: false + /// has product[2]: false + /// product[2]: /// \eout template class node_view final diff --git a/include/toml++/toml_value.h b/include/toml++/toml_value.h index 743d5b06..c786764d 100644 --- a/include/toml++/toml_value.h +++ b/include/toml++/toml_value.h @@ -42,6 +42,17 @@ TOML_START /// \brief The value's underlying data type. using value_type = T; + /// \brief A type alias for 'value arguments'. + /// \details This differs according to the value's type argument: + /// - ints, floats, booleans: `value_type` + /// - strings: `string_view` + /// - everything else: `const value_type&` + using value_arg = std::conditional_t< + std::is_same_v, + string_view, + std::conditional_t, T, const T&> + >; + /// \brief Constructs a toml value. /// /// \tparam U Constructor argument types. @@ -167,19 +178,8 @@ TOML_START return lhs; } - /// \brief A type alias for 'value arguments'. - /// \details This differs according to the value's type argument: - /// - ints, floats, booleans: `value_type` - /// - strings: `string_view` - /// - everything else: `const value_type&` - using value_arg_t = std::conditional_t< - std::is_same_v, - string_view, - std::conditional_t, T, const T&> - >; - /// \brief Value-assignment operator. - value& operator= (value_arg_t rhs) noexcept + value& operator= (value_arg rhs) noexcept { if constexpr (std::is_same_v) val_.assign(rhs); @@ -196,26 +196,26 @@ TOML_START } /// \brief Value equality operator. - [[nodiscard]] friend bool operator == (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ == rhs; } - TOML_ASYMMETRICAL_EQUALITY_OPS(const value&, value_arg_t, ) + [[nodiscard]] friend bool operator == (const value& lhs, value_arg rhs) noexcept { return lhs.val_ == rhs; } + TOML_ASYMMETRICAL_EQUALITY_OPS(const value&, value_arg, ) /// \brief Value less-than operator. - [[nodiscard]] friend bool operator < (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ < rhs; } + [[nodiscard]] friend bool operator < (const value& lhs, value_arg rhs) noexcept { return lhs.val_ < rhs; } /// \brief Value less-than operator. - [[nodiscard]] friend bool operator < (value_arg_t lhs, const value& rhs) noexcept { return lhs < rhs.val_; } + [[nodiscard]] friend bool operator < (value_arg lhs, const value& rhs) noexcept { return lhs < rhs.val_; } /// \brief Value less-than-or-equal-to operator. - [[nodiscard]] friend bool operator <= (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ <= rhs; } + [[nodiscard]] friend bool operator <= (const value& lhs, value_arg rhs) noexcept { return lhs.val_ <= rhs; } /// \brief Value less-than-or-equal-to operator. - [[nodiscard]] friend bool operator <= (value_arg_t lhs, const value& rhs) noexcept { return lhs <= rhs.val_; } + [[nodiscard]] friend bool operator <= (value_arg lhs, const value& rhs) noexcept { return lhs <= rhs.val_; } /// \brief Value greater-than operator. - [[nodiscard]] friend bool operator > (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ > rhs; } + [[nodiscard]] friend bool operator > (const value& lhs, value_arg rhs) noexcept { return lhs.val_ > rhs; } /// \brief Value greater-than operator. - [[nodiscard]] friend bool operator > (value_arg_t lhs, const value& rhs) noexcept { return lhs > rhs.val_; } + [[nodiscard]] friend bool operator > (value_arg lhs, const value& rhs) noexcept { return lhs > rhs.val_; } /// \brief Value greater-than-or-equal-to operator. - [[nodiscard]] friend bool operator >= (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ >= rhs; } + [[nodiscard]] friend bool operator >= (const value& lhs, value_arg rhs) noexcept { return lhs.val_ >= rhs; } /// \brief Value greater-than-or-equal-to operator. - [[nodiscard]] friend bool operator >= (value_arg_t lhs, const value& rhs) noexcept { return lhs >= rhs.val_; } + [[nodiscard]] friend bool operator >= (value_arg lhs, const value& rhs) noexcept { return lhs >= rhs.val_; } /// \brief Equality operator. /// diff --git a/toml.hpp b/toml.hpp index cbf6abe9..1c2151e6 100644 --- a/toml.hpp +++ b/toml.hpp @@ -293,17 +293,6 @@ __VA_ARGS__ [[nodiscard]] friend bool operator != (RHS rhs, LHS lhs) noexcept { return !(lhs == rhs); } #endif -#if !TOML_DOXYGEN - #if TOML_EXCEPTIONS - #define TOML_START namespace toml { inline namespace wex - #else - #define TOML_START namespace toml { inline namespace woex - #endif - #define TOML_END } -#endif -#define TOML_IMPL_START TOML_START { namespace impl -#define TOML_IMPL_END } TOML_END - #define TOML_LIB_MAJOR 0 #define TOML_LIB_MINOR 2 #define TOML_LIB_PATCH 0 @@ -332,6 +321,23 @@ #define TOML_LANG_EXACTLY(maj, min, rev) \ (TOML_LANG_EFFECTIVE_VERSION == TOML_MAKE_VERSION(maj, min, rev)) +#if !TOML_DOXYGEN + + #if TOML_EXCEPTIONS + #define TOML_INLINE_NS_EX + #else + #define TOML_INLINE_NS_EX _noex + #endif + + #define TOML_START_2(VER, ARG1, ARG2) namespace toml { inline namespace v##VER##ARG1##ARG2 + #define TOML_START_1(VER, ARG1, ARG2) TOML_START_2(VER, ARG1, ARG2) + #define TOML_START TOML_START_1(TOML_LIB_MAJOR,TOML_INLINE_NS_EX,) + #define TOML_END } + +#endif +#define TOML_IMPL_START TOML_START { namespace impl +#define TOML_IMPL_END } TOML_END + TOML_PUSH_WARNINGS TOML_DISABLE_ALL_WARNINGS @@ -1680,6 +1686,11 @@ TOML_START public: using value_type = T; + using value_arg = std::conditional_t< + std::is_same_v, + string_view, + std::conditional_t, T, const T&> + >; template TOML_NODISCARD_CTOR @@ -1757,13 +1768,7 @@ TOML_START return lhs; } - using value_arg_t = std::conditional_t< - std::is_same_v, - string_view, - std::conditional_t, T, const T&> - >; - - value& operator= (value_arg_t rhs) noexcept + value& operator= (value_arg rhs) noexcept { if constexpr (std::is_same_v) val_.assign(rhs); @@ -1779,16 +1784,16 @@ TOML_START return *this; } - [[nodiscard]] friend bool operator == (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ == rhs; } - TOML_ASYMMETRICAL_EQUALITY_OPS(const value&, value_arg_t, ) - [[nodiscard]] friend bool operator < (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ < rhs; } - [[nodiscard]] friend bool operator < (value_arg_t lhs, const value& rhs) noexcept { return lhs < rhs.val_; } - [[nodiscard]] friend bool operator <= (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ <= rhs; } - [[nodiscard]] friend bool operator <= (value_arg_t lhs, const value& rhs) noexcept { return lhs <= rhs.val_; } - [[nodiscard]] friend bool operator > (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ > rhs; } - [[nodiscard]] friend bool operator > (value_arg_t lhs, const value& rhs) noexcept { return lhs > rhs.val_; } - [[nodiscard]] friend bool operator >= (const value& lhs, value_arg_t rhs) noexcept { return lhs.val_ >= rhs; } - [[nodiscard]] friend bool operator >= (value_arg_t lhs, const value& rhs) noexcept { return lhs >= rhs.val_; } + [[nodiscard]] friend bool operator == (const value& lhs, value_arg rhs) noexcept { return lhs.val_ == rhs; } + TOML_ASYMMETRICAL_EQUALITY_OPS(const value&, value_arg, ) + [[nodiscard]] friend bool operator < (const value& lhs, value_arg rhs) noexcept { return lhs.val_ < rhs; } + [[nodiscard]] friend bool operator < (value_arg lhs, const value& rhs) noexcept { return lhs < rhs.val_; } + [[nodiscard]] friend bool operator <= (const value& lhs, value_arg rhs) noexcept { return lhs.val_ <= rhs; } + [[nodiscard]] friend bool operator <= (value_arg lhs, const value& rhs) noexcept { return lhs <= rhs.val_; } + [[nodiscard]] friend bool operator > (const value& lhs, value_arg rhs) noexcept { return lhs.val_ > rhs; } + [[nodiscard]] friend bool operator > (value_arg lhs, const value& rhs) noexcept { return lhs > rhs.val_; } + [[nodiscard]] friend bool operator >= (const value& lhs, value_arg rhs) noexcept { return lhs.val_ >= rhs; } + [[nodiscard]] friend bool operator >= (value_arg lhs, const value& rhs) noexcept { return lhs >= rhs.val_; } template [[nodiscard]] friend bool operator == (const value& lhs, const value& rhs) noexcept @@ -8562,7 +8567,10 @@ TOML_END #undef TOML_DOXYGEN #undef TOML_RELOPS_REORDERING #undef TOML_ASYMMETRICAL_EQUALITY_OPS + #undef TOML_INLINE_NS_EX #undef TOML_START + #undef TOML_START_2 + #undef TOML_START_1 #undef TOML_END #undef TOML_IMPL_START #undef TOML_IMPL_END