From 358ac66669ebf303d505cbefdcf0037a703627b9 Mon Sep 17 00:00:00 2001 From: Mark Gillard Date: Fri, 3 Apr 2020 16:33:02 +0300 Subject: [PATCH] added operator[], begin(), end() to parse_result in noexcept-mode also: - added note about `#include ` requirements README - added tests for parse_result - added array and table iterators to the toml namespace --- README.md | 9 +- include/toml++/toml.h | 12 ++- include/toml++/toml_array.h | 14 ++- include/toml++/toml_default_formatter.h | 10 +- include/toml++/toml_default_formatter_impl.h | 2 +- include/toml++/toml_json_formatter.h | 2 +- include/toml++/toml_node_view.h | 6 +- include/toml++/toml_parser.h | 73 ++++++++++++- include/toml++/toml_table.h | 14 ++- python/generate_single_header.py | 6 +- tests/manipulating_parse_result.cpp | 107 +++++++++++++++++++ toml.hpp | 80 +++++++++++--- vs/test_char.vcxproj | 1 + vs/test_char8.vcxproj | 3 +- vs/test_char8_noexcept.vcxproj | 3 +- vs/test_char8_strict.vcxproj | 3 +- vs/test_char8_strict_noexcept.vcxproj | 3 +- vs/test_char_noexcept.vcxproj | 25 ++--- vs/test_char_strict.vcxproj | 3 +- vs/test_char_strict_noexcept.vcxproj | 3 +- vs/test_x86_char.vcxproj | 1 + vs/test_x86_char8.vcxproj | 1 + vs/test_x86_char8_noexcept.vcxproj | 1 + vs/test_x86_char8_strict.vcxproj | 1 + vs/test_x86_char8_strict_noexcept.vcxproj | 1 + vs/test_x86_char_noexcept.vcxproj | 1 + vs/test_x86_char_strict.vcxproj | 1 + vs/test_x86_char_strict_noexcept.vcxproj | 1 + 28 files changed, 326 insertions(+), 61 deletions(-) create mode 100644 tests/manipulating_parse_result.cpp diff --git a/README.md b/README.md index a5b38e8..6a912ed 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ cpp = 17 ``` Reading it in C++ is easy with `toml++`: ```cpp +#include +#include //required for toml::parse_file() + auto config = toml::parse_file( "configuration.toml" ); // get key-value pairs @@ -48,7 +51,7 @@ config.insert_or_assign("alternatives", toml::array{ }); // iterate & visit over the data -for (auto [k, v] : config) +for (auto&& [k, v] : config) { v.visit([](auto& node) noexcept { @@ -176,8 +179,8 @@ though you're welcome to reach out via other means. In order of likely response [char8_t]: https://en.cppreference.com/w/cpp/keyword/char8_t [TOML master]: https://github.com/toml-lang/toml/blob/master/README.md [TOML issues list]: https://github.com/toml-lang/toml/issues -[TOML v1.0.0-rc.1]: https://github.com/toml-lang/toml/blob/master/README.md -[v1.0.0-rc.1]: https://github.com/toml-lang/toml/blob/master/README.md +[TOML v1.0.0-rc.1]: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md +[v1.0.0-rc.1]: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md [CONTRIBUTING]: ./CONTRIBUTING.md [LICENSE]: ./LICENSE [Flexible and Economical UTF-8 Decoder]: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ diff --git a/include/toml++/toml.h b/include/toml++/toml.h index dbf7b78..601c844 100644 --- a/include/toml++/toml.h +++ b/include/toml++/toml.h @@ -86,8 +86,8 @@ /////////////////////////////////////////////////////////////////////// /// /// \section mainpage-features Features -/// - [TOML v1.0.0-rc.1](https://github.com/toml-lang/toml/blob/master/README.md), plus optional support for some -/// unreleased TOML features +/// - [TOML v1.0.0-rc.1](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md), +/// plus optional support for some unreleased TOML features /// - 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 @@ -252,6 +252,8 @@ /// ... exactly as above, but twice /// \eout /// +/// The error-handling semantics are the same as for toml::parse_file. +/// /// \see toml::parse() /// /////////////////////////////////// @@ -347,7 +349,7 @@ /// auto tbl = toml::table{{ /// { "lib", "toml++" }, /// { "cpp", toml::array{ 17, 20, "and beyond" } }, -/// { "toml", toml::array{ "1.0.0", "and beyond" } }, +/// { "toml", toml::array{ "1.0.0-rc.1", "and beyond" } }, /// { "repo", "https://github.com/marzer/tomlplusplus/" }, /// { "author", toml::table{{ /// { "name", "Mark Gillard" }, @@ -374,7 +376,7 @@ /// cpp = [17, 20, "and beyond"] /// lib = "toml++" /// repo = "https://github.com/marzer/tomlplusplus/" -/// toml = ["1.0.0", "and beyond"] +/// toml = ["1.0.0-rc.1", "and beyond"] /// /// [author] /// github = "https://github.com/marzer" @@ -397,7 +399,7 @@ /// "lib" : "toml++", /// "repo" : "https://github.com/marzer/tomlplusplus/", /// "toml" : [ -/// "1.0.0", +/// "1.0.0-rc.1", /// "and beyond" /// ] /// } diff --git a/include/toml++/toml_array.h b/include/toml++/toml_array.h index 480372f..2a02d80 100644 --- a/include/toml++/toml_array.h +++ b/include/toml++/toml_array.h @@ -186,6 +186,12 @@ namespace toml 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; + + /// \brief A RandomAccessIterator for iterating over const nodes in a toml::array. + using const_array_iterator = impl::array_iterator; + /// \brief A TOML array. /// /// \detail The interface of this type is modeled after std::vector, with some @@ -242,10 +248,10 @@ namespace toml using reference = node&; using const_reference = const node&; - /// \brief A RandomAccessIterator for iterating over the nodes in an array. - using iterator = impl::array_iterator; - /// \brief A const RandomAccessIterator for iterating over the nodes in an array. - using const_iterator = impl::array_iterator; + /// \brief A RandomAccessIterator for iterating over nodes in a toml::array. + using iterator = array_iterator; + /// \brief A RandomAccessIterator for iterating over const nodes in a toml::array. + using const_iterator = const_array_iterator; /// \brief Default constructor. TOML_NODISCARD_CTOR diff --git a/include/toml++/toml_default_formatter.h b/include/toml++/toml_default_formatter.h index 2bd6b3b..1a33007 100644 --- a/include/toml++/toml_default_formatter.h +++ b/include/toml++/toml_default_formatter.h @@ -175,7 +175,7 @@ namespace toml }; //values, arrays, and inline tables/table arrays - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { const auto type = v.type(); if ((type == node_type::table && !reinterpret_cast(&v)->is_inline()) @@ -196,7 +196,7 @@ namespace toml } //non-inline tables - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { const auto type = v.type(); if (type != node_type::table || reinterpret_cast(&v)->is_inline()) @@ -208,7 +208,7 @@ namespace toml size_t child_value_count{}; //includes inline tables and non-table arrays size_t child_table_count{}; size_t child_table_array_count{}; - for (auto [child_k, child_v] : child_tbl) + for (auto&& [child_k, child_v] : child_tbl) { const auto child_type = child_v.type(); switch (child_type) @@ -258,7 +258,7 @@ namespace toml } //table arrays - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { if (!is_non_inline_array_of_tables(v)) continue; @@ -345,7 +345,7 @@ namespace toml impl::print_to_stream("{ "sv, base::stream()); bool first = false; - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { if (first) impl::print_to_stream(", "sv, base::stream()); diff --git a/include/toml++/toml_default_formatter_impl.h b/include/toml++/toml_default_formatter_impl.h index d9352b2..e841981 100644 --- a/include/toml++/toml_default_formatter_impl.h +++ b/include/toml++/toml_default_formatter_impl.h @@ -72,7 +72,7 @@ namespace toml::impl if (n.empty()) return 2_sz; // "{}" size_t weight = 3_sz; // "{ }" - for (auto [k, v] : n) + for (auto&& [k, v] : n) weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", " return weight; } diff --git a/include/toml++/toml_json_formatter.h b/include/toml++/toml_json_formatter.h index 144319c..e4afca7 100644 --- a/include/toml++/toml_json_formatter.h +++ b/include/toml++/toml_json_formatter.h @@ -131,7 +131,7 @@ namespace toml impl::print_to_stream('{', base::stream()); base::increase_indent(); bool first = false; - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { if (first) impl::print_to_stream(", "sv, base::stream()); diff --git a/include/toml++/toml_node_view.h b/include/toml++/toml_node_view.h index f2ea8f4..4463be3 100644 --- a/include/toml++/toml_node_view.h +++ b/include/toml++/toml_node_view.h @@ -65,7 +65,7 @@ namespace toml friend class toml::table; template friend class toml::node_view; - mutable viewed_type* node_; + mutable viewed_type* node_ = nullptr; TOML_NODISCARD_CTOR node_view(viewed_type* node) noexcept @@ -78,6 +78,10 @@ namespace toml public: + /// \brief Constructs an empty node view. + TOML_NODISCARD_CTOR + node_view() noexcept = default; + /// \brief Returns true if the view references a node. [[nodiscard]] explicit operator bool() const noexcept { return node_ != nullptr; } /// \brief Returns the node that's being referenced by the view. diff --git a/include/toml++/toml_parser.h b/include/toml++/toml_parser.h index b59dd9d..8ebf4ed 100644 --- a/include/toml++/toml_parser.h +++ b/include/toml++/toml_parser.h @@ -36,6 +36,11 @@ namespace toml /// (error occurred at line 1, column 13 of 'config.toml') /// \eout /// + /// Getting node_views (`operator[]`) and using the iterator accessor functions (`begin(), end()` etc.) are + /// unconditionally safe; when parsing fails these just return 'empty' values. A ranged-for loop on a failed + /// parse_result is also safe since `begin()` and `end()` return the same iterator and will not lead to any + /// dereferences and iterations. + /// /// \attention This type only exists when exceptions are not enabled. /// Otherwise parse_result is just an alias for toml::table: \cpp /// #if TOML_EXCEPTIONS @@ -63,6 +68,12 @@ namespace toml public: + /// \brief A BidirectionalIterator for iterating over key-value pairs in a wrapped toml::table. + using iterator = table_iterator; + + /// \brief A BidirectionalIterator for iterating over const key-value pairs in a wrapped toml::table. + using const_iterator = const_table_iterator; + /// \brief Returns true if parsing succeeeded. [[nodiscard]] bool succeeded() const noexcept { return !is_err; } /// \brief Returns true if parsing failed. @@ -136,7 +147,6 @@ namespace toml ::new (&storage) parse_error{ std::move(err) }; } - /// \brief Move constructor. TOML_NODISCARD_CTOR parse_result(parse_result&& res) noexcept @@ -175,6 +185,67 @@ namespace toml { destroy(); } + + /// \brief Gets a node_view for the selected key-value pair in the wrapped table. + /// + /// \param key The key used for the lookup. + /// + /// \returns A view of the value at the given key if parsing was successful and a matching key existed, + /// or an empty node view. + /// + /// \see toml::node_view + [[nodiscard]] node_view operator[] (string_view key) noexcept + { + return is_err ? node_view{} : get()[key]; + } + + /// \brief Gets a node_view for the selected key-value pair in the wrapped table (const overload). + [[nodiscard]] node_view operator[] (string_view key) const noexcept + { + return is_err ? node_view{} : get()[key]; + } + + /// \brief Returns an iterator to the first key-value pair in the wrapped table. + /// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed. + [[nodiscard]] table_iterator begin() noexcept + { + return is_err ? table_iterator{} : get().begin(); + } + + /// \brief Returns an iterator to the first key-value pair in the wrapped table. + /// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed. + [[nodiscard]] const_table_iterator begin() const noexcept + { + return is_err ? const_table_iterator{} : get().begin(); + } + + /// \brief Returns an iterator to the first key-value pair in the wrapped table. + /// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed. + [[nodiscard]] const_table_iterator cbegin() const noexcept + { + return is_err ? const_table_iterator{} : get().cbegin(); + } + + /// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table. + /// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed. + [[nodiscard]] table_iterator end() noexcept + { + return is_err ? table_iterator{} : get().end(); + } + + /// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table. + /// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed. + [[nodiscard]] const_table_iterator end() const noexcept + { + return is_err ? const_table_iterator{} : get().end(); + } + + /// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table. + /// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed. + [[nodiscard]] const_table_iterator cend() const noexcept + { + return is_err ? const_table_iterator{} : get().cend(); + } }; #if TOML_ABI_NAMESPACES diff --git a/include/toml++/toml_table.h b/include/toml++/toml_table.h index d19b566..bd93933 100644 --- a/include/toml++/toml_table.h +++ b/include/toml++/toml_table.h @@ -122,6 +122,12 @@ namespace toml template std::basic_ostream& operator << (std::basic_ostream&, const table&); + /// \brief A BidirectionalIterator for iterating over key-value pairs in a toml::table. + using table_iterator = impl::table_iterator; + + /// \brief A BidirectionalIterator for iterating over const key-value pairs in a toml::table. + using const_table_iterator = impl::table_iterator; + /// \brief A TOML table. /// /// \remarks The interface of this type is modeled after std::map, with some @@ -141,10 +147,10 @@ namespace toml public: - /// \brief A BidirectionalIterator for iterating over the key-value pairs in a table. - using iterator = impl::table_iterator; - /// \brief A const BidirectionalIterator for iterating over the key-value pairs in a table. - using const_iterator = impl::table_iterator; + /// \brief A BidirectionalIterator for iterating over key-value pairs in a toml::table. + using iterator = table_iterator; + /// \brief A BidirectionalIterator for iterating over const key-value pairs in a toml::table. + using const_iterator = const_table_iterator; /// \brief Default constructor. TOML_NODISCARD_CTOR diff --git a/python/generate_single_header.py b/python/generate_single_header.py index a1f4c36..ee96d27 100644 --- a/python/generate_single_header.py +++ b/python/generate_single_header.py @@ -134,9 +134,9 @@ against it directly. You should instead make your changes in the relevant source that contributed to this header can be found at the beginnings and ends of the corresponding sections of this file.''') preamble.append(''' TOML language specifications: -Latest: https://github.com/toml-lang/toml/blob/master/README.md -v1.0.0: https://github.com/toml-lang/toml/blob/master/README.md -v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md''') +Latest: https://github.com/toml-lang/toml/blob/master/README.md +v1.0.0-rc.1: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md +v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md''') preamble.append(read_all_text_from_file(path.join(get_script_folder(), '..', 'LICENSE'))) # write the output file diff --git a/tests/manipulating_parse_result.cpp b/tests/manipulating_parse_result.cpp new file mode 100644 index 0000000..e84c067 --- /dev/null +++ b/tests/manipulating_parse_result.cpp @@ -0,0 +1,107 @@ +#include "tests.h" + +#if !TOML_EXCEPTIONS + +TEST_CASE("parse_result - good parse") +{ + auto result = "key = true"_toml; + static_assert(std::is_same_v); + static_assert(!std::is_same_v); + + REQUIRE(result.succeeded()); + REQUIRE(!result.failed()); + REQUIRE(result); + + REQUIRE(!result.get().empty()); + REQUIRE(result.get().size() == 1); + REQUIRE(!std::move(result).get().empty()); + REQUIRE(!static_cast(result).get().empty()); + + REQUIRE(!static_cast(result).empty()); + REQUIRE(!static_cast(result).empty()); + REQUIRE(!static_cast(result).empty()); + + auto& tbl = static_cast(result); + CHECK(tbl[S("key"sv)]); + CHECK(result[S("key"sv)]); + CHECK(&result[S("key"sv)].ref() == &tbl[S("key"sv)].ref()); + CHECK(result.begin() == tbl.begin()); + CHECK(result.end() == tbl.end()); + CHECK(result.begin() != tbl.end()); + CHECK(result.cbegin() == tbl.cbegin()); + CHECK(result.cend() == tbl.cend()); + CHECK(result.cbegin() != tbl.cend()); + + auto& cresult = static_cast(result); + auto& ctbl = static_cast(cresult); + CHECK(cresult.begin() == ctbl.begin()); + CHECK(cresult.end() == ctbl.end()); + CHECK(cresult.begin() != ctbl.end()); + CHECK(cresult.cbegin() == ctbl.cbegin()); + CHECK(cresult.cend() == ctbl.cend()); + CHECK(cresult.cbegin() != ctbl.cend()); + CHECK(ctbl[S("key"sv)]); + CHECK(cresult[S("key"sv)]); + CHECK(&cresult[S("key"sv)].ref() == &ctbl[S("key"sv)].ref()); + + size_t tbl_iterations{}; + for (auto&& [k, v] : tbl) + { + (void)k; (void)v; + tbl_iterations++; + } + size_t result_iterations{}; + for (auto&& [k, v] : result) + { + (void)k; (void)v; + result_iterations++; + } + size_t cresult_iterations{}; + for (auto&& [k, v] : cresult) + { + (void)k; (void)v; + cresult_iterations++; + } + CHECK(tbl_iterations == tbl.size()); + CHECK(tbl_iterations == result_iterations); + CHECK(tbl_iterations == cresult_iterations); +} + + +TEST_CASE("parse_result - bad parse") +{ + auto result = "key = trUe"_toml; + static_assert(std::is_same_v); + static_assert(!std::is_same_v); + + REQUIRE(!result.succeeded()); + REQUIRE(result.failed()); + REQUIRE(!result); + + CHECK(!result[S("key"sv)]); + CHECK(result.begin() == decltype(result.begin()){}); + CHECK(result.end() == decltype(result.end()){}); + CHECK(result.cbegin() == decltype(result.cbegin()){}); + CHECK(result.cend() == decltype(result.cend()){}); + + auto& cresult = static_cast(result); + CHECK(!result[S("key"sv)]); + CHECK(cresult.begin() == decltype(cresult.begin()){}); + CHECK(cresult.end() == decltype(cresult.end()){}); + CHECK(cresult.cbegin() == decltype(cresult.cbegin()){}); + CHECK(cresult.cend() == decltype(cresult.cend()){}); + + for (auto&& [k, v] : result) + { + (void)k; (void)v; + FAIL("This code should not run"); + } + for (auto&& [k, v] : cresult) + { + (void)k; (void)v; + FAIL("This code should not run"); + } +} + + +#endif //!TOML_EXCEPTIONS diff --git a/toml.hpp b/toml.hpp index a75f88c..5a4e592 100644 --- a/toml.hpp +++ b/toml.hpp @@ -16,9 +16,9 @@ //---------------------------------------------------------------------------------------------------------------------- // // TOML language specifications: -// Latest: https://github.com/toml-lang/toml/blob/master/README.md -// v1.0.0: https://github.com/toml-lang/toml/blob/master/README.md -// v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md +// Latest: https://github.com/toml-lang/toml/blob/master/README.md +// v1.0.0-rc.1: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md +// v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md // //---------------------------------------------------------------------------------------------------------------------- // @@ -2488,6 +2488,9 @@ namespace toml template std::basic_ostream& operator << (std::basic_ostream&, const array&); + using array_iterator = impl::array_iterator; + using const_array_iterator = impl::array_iterator; + class TOML_API array final : public node { @@ -2504,8 +2507,8 @@ namespace toml using difference_type = ptrdiff_t; using reference = node&; using const_reference = const node&; - using iterator = impl::array_iterator; - using const_iterator = impl::array_iterator; + using iterator = array_iterator; + using const_iterator = const_array_iterator; TOML_NODISCARD_CTOR array() noexcept; @@ -2890,6 +2893,9 @@ namespace toml template std::basic_ostream& operator << (std::basic_ostream&, const table&); + using table_iterator = impl::table_iterator; + using const_table_iterator = impl::table_iterator; + class TOML_API table final : public node { @@ -2903,8 +2909,8 @@ namespace toml public: - using iterator = impl::table_iterator; - using const_iterator = impl::table_iterator; + using iterator = table_iterator; + using const_iterator = const_table_iterator; TOML_NODISCARD_CTOR table() noexcept; @@ -3098,7 +3104,7 @@ namespace toml friend class toml::table; template friend class toml::node_view; - mutable viewed_type* node_; + mutable viewed_type* node_ = nullptr; TOML_NODISCARD_CTOR node_view(viewed_type* node) noexcept @@ -3111,6 +3117,8 @@ namespace toml public: + TOML_NODISCARD_CTOR + node_view() noexcept = default; [[nodiscard]] explicit operator bool() const noexcept { return node_ != nullptr; } [[nodiscard]] viewed_type* get() const noexcept { return node_; } @@ -4844,6 +4852,8 @@ namespace toml public: + using iterator = table_iterator; + using const_iterator = const_table_iterator; [[nodiscard]] bool succeeded() const noexcept { return !is_err; } [[nodiscard]] bool failed() const noexcept { return is_err; } [[nodiscard]] explicit operator bool() const noexcept { return !is_err; } @@ -4935,6 +4945,46 @@ namespace toml { destroy(); } + + [[nodiscard]] node_view operator[] (string_view key) noexcept + { + return is_err ? node_view{} : get()[key]; + } + + [[nodiscard]] node_view operator[] (string_view key) const noexcept + { + return is_err ? node_view{} : get()[key]; + } + + [[nodiscard]] table_iterator begin() noexcept + { + return is_err ? table_iterator{} : get().begin(); + } + + [[nodiscard]] const_table_iterator begin() const noexcept + { + return is_err ? const_table_iterator{} : get().begin(); + } + + [[nodiscard]] const_table_iterator cbegin() const noexcept + { + return is_err ? const_table_iterator{} : get().cbegin(); + } + + [[nodiscard]] table_iterator end() noexcept + { + return is_err ? table_iterator{} : get().end(); + } + + [[nodiscard]] const_table_iterator end() const noexcept + { + return is_err ? const_table_iterator{} : get().end(); + } + + [[nodiscard]] const_table_iterator cend() const noexcept + { + return is_err ? const_table_iterator{} : get().cend(); + } }; #if TOML_ABI_NAMESPACES @@ -5368,7 +5418,7 @@ namespace toml }; //values, arrays, and inline tables/table arrays - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { const auto type = v.type(); if ((type == node_type::table && !reinterpret_cast(&v)->is_inline()) @@ -5389,7 +5439,7 @@ namespace toml } //non-inline tables - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { const auto type = v.type(); if (type != node_type::table || reinterpret_cast(&v)->is_inline()) @@ -5401,7 +5451,7 @@ namespace toml size_t child_value_count{}; //includes inline tables and non-table arrays size_t child_table_count{}; size_t child_table_array_count{}; - for (auto [child_k, child_v] : child_tbl) + for (auto&& [child_k, child_v] : child_tbl) { const auto child_type = child_v.type(); switch (child_type) @@ -5451,7 +5501,7 @@ namespace toml } //table arrays - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { if (!is_non_inline_array_of_tables(v)) continue; @@ -5534,7 +5584,7 @@ namespace toml impl::print_to_stream("{ "sv, base::stream()); bool first = false; - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { if (first) impl::print_to_stream(", "sv, base::stream()); @@ -5693,7 +5743,7 @@ namespace toml impl::print_to_stream('{', base::stream()); base::increase_indent(); bool first = false; - for (auto [k, v] : tbl) + for (auto&& [k, v] : tbl) { if (first) impl::print_to_stream(", "sv, base::stream()); @@ -9433,7 +9483,7 @@ namespace toml::impl if (n.empty()) return 2_sz; // "{}" size_t weight = 3_sz; // "{ }" - for (auto [k, v] : n) + for (auto&& [k, v] : n) weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", " return weight; } diff --git a/vs/test_char.vcxproj b/vs/test_char.vcxproj index 5c89e62..11acd13 100644 --- a/vs/test_char.vcxproj +++ b/vs/test_char.vcxproj @@ -68,6 +68,7 @@ + diff --git a/vs/test_char8.vcxproj b/vs/test_char8.vcxproj index aab941b..b4c6598 100644 --- a/vs/test_char8.vcxproj +++ b/vs/test_char8.vcxproj @@ -67,7 +67,8 @@ NotUsing - + + diff --git a/vs/test_char8_noexcept.vcxproj b/vs/test_char8_noexcept.vcxproj index 35e829f..15aca93 100644 --- a/vs/test_char8_noexcept.vcxproj +++ b/vs/test_char8_noexcept.vcxproj @@ -69,7 +69,8 @@ NotUsing - + + diff --git a/vs/test_char8_strict.vcxproj b/vs/test_char8_strict.vcxproj index f2f4e84..43dd252 100644 --- a/vs/test_char8_strict.vcxproj +++ b/vs/test_char8_strict.vcxproj @@ -68,7 +68,8 @@ NotUsing - + + diff --git a/vs/test_char8_strict_noexcept.vcxproj b/vs/test_char8_strict_noexcept.vcxproj index 95ffc95..12bc496 100644 --- a/vs/test_char8_strict_noexcept.vcxproj +++ b/vs/test_char8_strict_noexcept.vcxproj @@ -70,7 +70,8 @@ NotUsing - + + diff --git a/vs/test_char_noexcept.vcxproj b/vs/test_char_noexcept.vcxproj index 2c0dffa..a1974f3 100644 --- a/vs/test_char_noexcept.vcxproj +++ b/vs/test_char_noexcept.vcxproj @@ -51,7 +51,7 @@ ..\tests;%(AdditionalIncludeDirectories) TOML_CHAR_8_STRINGS=0;%(PreprocessorDefinitions) - _HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) + _HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) false Use tests.h @@ -69,17 +69,18 @@ NotUsing - - - - - - - - - - - + + + + + + + + + + + + Create diff --git a/vs/test_char_strict.vcxproj b/vs/test_char_strict.vcxproj index a431ac8..cfcfb63 100644 --- a/vs/test_char_strict.vcxproj +++ b/vs/test_char_strict.vcxproj @@ -68,7 +68,8 @@ NotUsing - + + diff --git a/vs/test_char_strict_noexcept.vcxproj b/vs/test_char_strict_noexcept.vcxproj index 41a22ae..f2e1efd 100644 --- a/vs/test_char_strict_noexcept.vcxproj +++ b/vs/test_char_strict_noexcept.vcxproj @@ -70,7 +70,8 @@ NotUsing - + + diff --git a/vs/test_x86_char.vcxproj b/vs/test_x86_char.vcxproj index 3ae57d9..309950d 100644 --- a/vs/test_x86_char.vcxproj +++ b/vs/test_x86_char.vcxproj @@ -68,6 +68,7 @@ + diff --git a/vs/test_x86_char8.vcxproj b/vs/test_x86_char8.vcxproj index 6b1f705..8f22f2b 100644 --- a/vs/test_x86_char8.vcxproj +++ b/vs/test_x86_char8.vcxproj @@ -68,6 +68,7 @@ + diff --git a/vs/test_x86_char8_noexcept.vcxproj b/vs/test_x86_char8_noexcept.vcxproj index fde92cb..8024ac7 100644 --- a/vs/test_x86_char8_noexcept.vcxproj +++ b/vs/test_x86_char8_noexcept.vcxproj @@ -70,6 +70,7 @@ + diff --git a/vs/test_x86_char8_strict.vcxproj b/vs/test_x86_char8_strict.vcxproj index 3b4fe1d..e8bb44d 100644 --- a/vs/test_x86_char8_strict.vcxproj +++ b/vs/test_x86_char8_strict.vcxproj @@ -69,6 +69,7 @@ + diff --git a/vs/test_x86_char8_strict_noexcept.vcxproj b/vs/test_x86_char8_strict_noexcept.vcxproj index 93766fb..4de572e 100644 --- a/vs/test_x86_char8_strict_noexcept.vcxproj +++ b/vs/test_x86_char8_strict_noexcept.vcxproj @@ -71,6 +71,7 @@ + diff --git a/vs/test_x86_char_noexcept.vcxproj b/vs/test_x86_char_noexcept.vcxproj index 567599a..ab83056 100644 --- a/vs/test_x86_char_noexcept.vcxproj +++ b/vs/test_x86_char_noexcept.vcxproj @@ -70,6 +70,7 @@ + diff --git a/vs/test_x86_char_strict.vcxproj b/vs/test_x86_char_strict.vcxproj index 5033c50..0de67ff 100644 --- a/vs/test_x86_char_strict.vcxproj +++ b/vs/test_x86_char_strict.vcxproj @@ -69,6 +69,7 @@ + diff --git a/vs/test_x86_char_strict_noexcept.vcxproj b/vs/test_x86_char_strict_noexcept.vcxproj index 6ea7a10..3e49c27 100644 --- a/vs/test_x86_char_strict_noexcept.vcxproj +++ b/vs/test_x86_char_strict_noexcept.vcxproj @@ -71,6 +71,7 @@ +