From b024ee6dc27607b955be3cb64bb59a21f637e6ff Mon Sep 17 00:00:00 2001 From: Mark Gillard Date: Sun, 2 Aug 2020 12:20:41 +0300 Subject: [PATCH] added tests for copying and insertion (closes #49) also: - added tests to catch any regressions of pull/50 - moved UTF-8 decoder copyright notice - cleaned up static assert messages --- LICENSE | 1 - include/toml++/toml.h | 1 - include/toml++/toml_common.h | 2 +- include/toml++/toml_node.h | 2 - include/toml++/toml_utf8.h | 2 + include/toml++/toml_value.h | 39 +++-- tests/manipulating_arrays.cpp | 246 ++++++++++++++++-------------- tests/manipulating_tables.cpp | 116 +++++++++++---- tests/manipulating_values.cpp | 273 ++++++++++++++++++++++++++++++++++ tests/parsing_tables.cpp | 58 ++++---- tests/user_feedback.cpp | 14 ++ toml.hpp | 47 +++--- vs/toml++.vcxproj | 5 + vs/toml++.vcxproj.filters | 5 + 14 files changed, 588 insertions(+), 223 deletions(-) diff --git a/LICENSE b/LICENSE index c408275..95c2438 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,6 @@ MIT License Copyright (c) 2019-2020 Mark Gillard -Copyright (c) 2008-2010 Bjoern Hoehrmann (utf8_decoder) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the diff --git a/include/toml++/toml.h b/include/toml++/toml.h index dfe70bb..c07eae3 100644 --- a/include/toml++/toml.h +++ b/include/toml++/toml.h @@ -115,7 +115,6 @@ #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 diff --git a/include/toml++/toml_common.h b/include/toml++/toml_common.h index 3e32db4..a1ce19d 100644 --- a/include/toml++/toml_common.h +++ b/include/toml++/toml_common.h @@ -47,7 +47,7 @@ TOML_POP_WARNINGS #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 " \ + "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!" diff --git a/include/toml++/toml_node.h b/include/toml++/toml_node.h index 2af2561..42fef61 100644 --- a/include/toml++/toml_node.h +++ b/include/toml++/toml_node.h @@ -18,7 +18,6 @@ TOML_DISABLE_MISC_WARNINGS #define TOML_SA_LIST_END ")" #define TOML_SA_LIST_NEW " " #define TOML_SA_LIST_NXT ", " -#define TOML_SA_LIST_CAP(...) #else @@ -28,7 +27,6 @@ TOML_DISABLE_MISC_WARNINGS #define TOML_SA_LIST_END #define TOML_SA_LIST_NEW TOML_SA_NEWLINE TOML_SA_NEWLINE #define TOML_SA_LIST_NXT TOML_SA_LIST_NEW -#define TOML_SA_LIST_CAP(val) val #endif diff --git a/include/toml++/toml_utf8.h b/include/toml++/toml_utf8.h index 7621b92..80537ac 100644 --- a/include/toml++/toml_utf8.h +++ b/include/toml++/toml_utf8.h @@ -909,6 +909,8 @@ TOML_IMPL_NAMESPACE_START return codepoint >= 0xD800u && codepoint <= 0xDFFF; } + // utf8_decoder based on this: https://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // Copyright (c) 2008-2009 Bjoern Hoehrmann struct utf8_decoder final { uint_least32_t state{}; diff --git a/include/toml++/toml_value.h b/include/toml++/toml_value.h index 0af8e65..aac2944 100644 --- a/include/toml++/toml_value.h +++ b/include/toml++/toml_value.h @@ -553,14 +553,16 @@ TOML_NAMESPACE_START TOML_SA_LIST_SEP "std::wstring" #endif TOML_SA_LIST_SEP "any signed integer type >= 64 bits" - TOML_SA_LIST_SEP "any floating-point type >= 64 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 64 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "An immutable view type not requiring additional temporary storage" TOML_SA_LIST_BEG "std::string_view" - TOML_SA_LIST_SEP "const char*" #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "std::u8string_view" + #endif + TOML_SA_LIST_SEP "const char*" + #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "const char8_t*" #endif TOML_SA_LIST_END @@ -598,19 +600,21 @@ TOML_NAMESPACE_START TOML_SA_LIST_SEP "std::wstring" #endif TOML_SA_LIST_SEP "any signed integer type >= 64 bits" - TOML_SA_LIST_SEP "any floating-point type >= 64 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 64 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type" TOML_SA_LIST_BEG "any other integer type" - TOML_SA_LIST_SEP "any floating-point type >= 32 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 32 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "An immutable view type not requiring additional temporary storage" TOML_SA_LIST_BEG "std::string_view" - TOML_SA_LIST_SEP "const char*" #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "std::u8string_view" + #endif + TOML_SA_LIST_SEP "const char*" + #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "const char8_t*" #endif TOML_SA_LIST_END @@ -766,33 +770,28 @@ TOML_NAMESPACE_START TOML_SA_LIST_SEP "std::wstring" #endif TOML_SA_LIST_SEP "any signed integer type >= 64 bits" - TOML_SA_LIST_SEP "any floating-point type >= 64 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 64 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type" TOML_SA_LIST_BEG "any other integer type" - TOML_SA_LIST_SEP "any floating-point type >= 32 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 32 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "A compatible view type" TOML_SA_LIST_BEG "std::string_view" - TOML_SA_LIST_SEP "const char*" - TOML_SA_LIST_SEP "const char[]" TOML_SA_LIST_CAP(" (returned as const char*)") - TOML_SA_LIST_SEP "char*" TOML_SA_LIST_CAP(" (returned as const char*)") - TOML_SA_LIST_SEP "char[]" TOML_SA_LIST_CAP(" (returned as const char*)") #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "std::u8string_view" - TOML_SA_LIST_SEP "const char8_t*" - TOML_SA_LIST_SEP "const char8_t[]" TOML_SA_LIST_CAP(" (returned as const char8_t*)") - TOML_SA_LIST_SEP "char8_t*" TOML_SA_LIST_CAP(" (returned as const char8_t*)") - TOML_SA_LIST_SEP "char8_t[]" TOML_SA_LIST_CAP(" (returned as const char8_t*)") #endif #if TOML_WINDOWS_COMPAT - TOML_SA_LIST_SEP "std::wstring_view" TOML_SA_LIST_CAP(" (returned as std::wstring)") - TOML_SA_LIST_SEP "const wchar_t*" TOML_SA_LIST_CAP(" (returned as std::wstring)") - TOML_SA_LIST_SEP "const wchar_t[]" TOML_SA_LIST_CAP(" (returned as std::wstring)") - TOML_SA_LIST_SEP "wchar_t*" TOML_SA_LIST_CAP(" (returned as std::wstring)") - TOML_SA_LIST_SEP "wchar_t[]" TOML_SA_LIST_CAP(" (returned as std::wstring)") + TOML_SA_LIST_SEP "std::wstring_view" + #endif + TOML_SA_LIST_SEP "const char*" + #ifdef __cpp_lib_char8_t + TOML_SA_LIST_SEP "const char8_t*" + #endif + #if TOML_WINDOWS_COMPAT + TOML_SA_LIST_SEP "const wchar_t*" #endif TOML_SA_LIST_END ); diff --git a/tests/manipulating_arrays.cpp b/tests/manipulating_arrays.cpp index dd0432b..6cdaf34 100644 --- a/tests/manipulating_arrays.cpp +++ b/tests/manipulating_arrays.cpp @@ -17,20 +17,20 @@ TEST_CASE("arrays - moving") // sanity-check initial state of a freshly-parsed array auto arr1 = tbl["test"].as(); REQUIRE(arr1); - CHECK(arr1->size() == 1_sz); + CHECK(arr1->size() == 1u); CHECK(arr1->source().begin == source_position{ 1, 8 }); CHECK(arr1->source().end == source_position{ 1, 17 }); CHECK(arr1->source().path); CHECK(*arr1->source().path == filename); - REQUIRE(arr1->get_as(0_sz)); - CHECK(*arr1->get_as(0_sz) == "foo"sv); + REQUIRE(arr1->get_as(0u)); + CHECK(*arr1->get_as(0u) == "foo"sv); // sanity-check initial state of default-constructed array array arr2; CHECK(arr2.source().begin == source_position{}); CHECK(arr2.source().end == source_position{}); CHECK(!arr2.source().path); - CHECK(arr2.size() == 0_sz); + CHECK(arr2.size() == 0u); // check the results of move-assignment arr2 = std::move(*arr1); @@ -38,15 +38,15 @@ TEST_CASE("arrays - moving") CHECK(arr2.source().end == source_position{ 1, 17 }); CHECK(arr2.source().path); CHECK(*arr2.source().path == filename); - CHECK(arr2.size() == 1_sz); - REQUIRE(arr2.get_as(0_sz)); - CHECK(*arr2.get_as(0_sz) == "foo"sv); + CHECK(arr2.size() == 1u); + REQUIRE(arr2.get_as(0u)); + CHECK(*arr2.get_as(0u) == "foo"sv); // check that moved-from array is now the same as default-constructed CHECK(arr1->source().begin == source_position{}); CHECK(arr1->source().end == source_position{}); CHECK(!arr1->source().path); - CHECK(arr1->size() == 0_sz); + CHECK(arr1->size() == 0u); // check the results of move-construction array arr3{ std::move(arr2) }; @@ -54,15 +54,15 @@ TEST_CASE("arrays - moving") CHECK(arr3.source().end == source_position{ 1, 17 }); CHECK(arr3.source().path); CHECK(*arr3.source().path == filename); - CHECK(arr3.size() == 1_sz); - REQUIRE(arr3.get_as(0_sz)); - CHECK(*arr3.get_as(0_sz) == "foo"sv); + CHECK(arr3.size() == 1u); + REQUIRE(arr3.get_as(0u)); + CHECK(*arr3.get_as(0u) == "foo"sv); // check that moved-from array is now the same as default-constructed CHECK(arr2.source().begin == source_position{}); CHECK(arr2.source().end == source_position{}); CHECK(!arr2.source().path); - CHECK(arr2.size() == 0_sz); + CHECK(arr2.size() == 0u); }, filename ); @@ -80,29 +80,29 @@ TEST_CASE("arrays - copying") // sanity-check initial state of a freshly-parsed array auto arr1 = tbl["test"].as(); REQUIRE(arr1); - CHECK(arr1->size() == 1_sz); + CHECK(arr1->size() == 1u); CHECK(arr1->source().begin == source_position{ 1, 8 }); CHECK(arr1->source().end == source_position{ 1, 17 }); CHECK(arr1->source().path); CHECK(*arr1->source().path == filename); - REQUIRE(arr1->get_as(0_sz)); - CHECK(*arr1->get_as(0_sz) == "foo"sv); + REQUIRE(arr1->get_as(0u)); + CHECK(*arr1->get_as(0u) == "foo"sv); // sanity-check initial state of default-constructed array array arr2; CHECK(arr2.source().begin == source_position{}); CHECK(arr2.source().end == source_position{}); CHECK(!arr2.source().path); - CHECK(arr2.size() == 0_sz); + CHECK(arr2.size() == 0u); // check the results of copy-assignment arr2 = *arr1; CHECK(arr2.source().begin == source_position{}); CHECK(arr2.source().end == source_position{}); CHECK(!arr2.source().path); - CHECK(arr2.size() == 1_sz); - REQUIRE(arr2.get_as(0_sz)); - CHECK(*arr2.get_as(0_sz) == "foo"sv); + CHECK(arr2.size() == 1u); + REQUIRE(arr2.get_as(0u)); + CHECK(*arr2.get_as(0u) == "foo"sv); CHECK(arr2 == *arr1); // check the results of copy-construction @@ -110,9 +110,9 @@ TEST_CASE("arrays - copying") CHECK(arr3.source().begin == source_position{}); CHECK(arr3.source().end == source_position{}); CHECK(!arr3.source().path); - CHECK(arr3.size() == 1_sz); - REQUIRE(arr3.get_as(0_sz)); - CHECK(*arr3.get_as(0_sz) == "foo"sv); + CHECK(arr3.size() == 1u); + REQUIRE(arr3.get_as(0u)); + CHECK(*arr3.get_as(0u) == "foo"sv); CHECK(arr3 == *arr1); CHECK(arr3 == arr2); }, @@ -124,7 +124,7 @@ TEST_CASE("arrays - construction") { { array arr; - CHECK(arr.size() == 0_sz); + CHECK(arr.size() == 0u); CHECK(arr.empty()); CHECK(arr.begin() == arr.end()); CHECK(arr.cbegin() == arr.cend()); @@ -136,12 +136,12 @@ TEST_CASE("arrays - construction") { array arr{ 42 }; - CHECK(arr.size() == 1_sz); + CHECK(arr.size() == 1u); CHECK(!arr.empty()); CHECK(arr.begin() != arr.end()); CHECK(arr.cbegin() != arr.cend()); - REQUIRE(arr.get_as(0_sz)); - CHECK(*arr.get_as(0_sz) == 42); + REQUIRE(arr.get_as(0u)); + CHECK(*arr.get_as(0u) == 42); CHECK(arr.is_homogeneous()); CHECK(arr.is_homogeneous()); CHECK(!arr.is_homogeneous()); @@ -149,24 +149,24 @@ TEST_CASE("arrays - construction") { array arr{ 42, "test"sv, 10.0f, array{}, value{ 3 } }; - CHECK(arr.size() == 5_sz); + CHECK(arr.size() == 5u); CHECK(!arr.empty()); - REQUIRE(arr.get_as(0_sz)); - CHECK(*arr.get_as(0_sz) == 42); - REQUIRE(arr.get_as(1_sz)); - CHECK(*arr.get_as(1_sz) == "test"sv); - REQUIRE(arr.get_as(2_sz)); - CHECK(*arr.get_as(2_sz) == 10.0); - REQUIRE(arr.get_as(3_sz)); - REQUIRE(arr.get_as(4_sz)); - CHECK(*arr.get_as(4_sz) == 3); + REQUIRE(arr.get_as(0u)); + CHECK(*arr.get_as(0u) == 42); + REQUIRE(arr.get_as(1u)); + CHECK(*arr.get_as(1u) == "test"sv); + REQUIRE(arr.get_as(2u)); + CHECK(*arr.get_as(2u) == 10.0); + REQUIRE(arr.get_as(3u)); + REQUIRE(arr.get_as(4u)); + CHECK(*arr.get_as(4u) == 3); CHECK(!arr.is_homogeneous()); } #if TOML_WINDOWS_COMPAT { array arr{ "mixed", "string"sv, L"test", L"kek"sv }; - CHECK(arr.size() == 4_sz); + CHECK(arr.size() == 4u); CHECK(arr.is_homogeneous()); CHECK(arr.is_homogeneous()); CHECK(*arr.get_as(0) == "mixed"sv); @@ -226,39 +226,39 @@ TEST_CASE("arrays - insertion and erasure") // insert(const_iterator pos, ElemType&& val) auto it = arr.insert(arr.cbegin(), 42); CHECK(it == arr.begin()); - CHECK(arr.size() == 1_sz); + CHECK(arr.size() == 1u); CHECK(!arr.empty()); - REQUIRE(arr.get_as(0_sz)); - CHECK(*arr.get_as(0_sz) == 42); + REQUIRE(arr.get_as(0u)); + CHECK(*arr.get_as(0u) == 42); REQUIRE(arr == array{ 42 }); // insert(const_iterator pos, size_t count, ElemType&& val) it = arr.insert(arr.cend(), 3, 10.0f); CHECK(it == arr.begin() + 1); - CHECK(arr.size() == 4_sz); - REQUIRE(arr.get_as(1_sz)); - CHECK(*arr.get_as(1_sz) == 10.0); - REQUIRE(arr.get_as(2_sz)); - CHECK(*arr.get_as(2_sz) == 10.0); - REQUIRE(arr.get_as(3_sz)); - CHECK(*arr.get_as(3_sz) == 10.0); + CHECK(arr.size() == 4u); + REQUIRE(arr.get_as(1u)); + CHECK(*arr.get_as(1u) == 10.0); + REQUIRE(arr.get_as(2u)); + CHECK(*arr.get_as(2u) == 10.0); + REQUIRE(arr.get_as(3u)); + CHECK(*arr.get_as(3u) == 10.0); REQUIRE(arr == array{ 42, 10.0, 10.0, 10.0 }); // emplace(const_iterator pos, Args &&... args) noexcept it = arr.emplace(arr.cbegin(), 1, 2, 3); CHECK(it == arr.begin()); - CHECK(arr.size() == 5_sz); - REQUIRE(arr.get_as(0_sz)); - CHECK(arr.get_as(0_sz)->size() == 3_sz); + CHECK(arr.size() == 5u); + REQUIRE(arr.get_as(0u)); + CHECK(arr.get_as(0u)->size() == 3u); REQUIRE(arr == array{ array{ 1, 2, 3 }, 42, 10.0, 10.0, 10.0 }); // push_back(ElemType&& val) noexcept { arr.push_back("test"sv); auto& val = *arr.back().as_string(); - CHECK(arr.size() == 6_sz); - REQUIRE(arr.get_as(5_sz)); - CHECK(*arr.get_as(5_sz) == "test"sv); + CHECK(arr.size() == 6u); + REQUIRE(arr.get_as(5u)); + CHECK(*arr.get_as(5u) == "test"sv); CHECK(val == "test"sv); CHECK(&val == &arr.back()); REQUIRE(arr == array{ array{ 1, 2, 3 }, 42, 10.0, 10.0, 10.0, "test"sv }); @@ -267,9 +267,9 @@ TEST_CASE("arrays - insertion and erasure") // decltype(auto) emplace_back(Args&&... args) noexcept { decltype(auto) val = arr.emplace_back("test2"sv); - CHECK(arr.size() == 7_sz); - REQUIRE(arr.get_as(6_sz)); - CHECK(*arr.get_as(6_sz) == "test2"sv); + CHECK(arr.size() == 7u); + REQUIRE(arr.get_as(6u)); + CHECK(*arr.get_as(6u) == "test2"sv); CHECK(val == "test2"sv); CHECK(&val == &arr.back()); REQUIRE(arr == array{ array{ 1, 2, 3 }, 42, 10.0, 10.0, 10.0, "test"sv, "test2"sv }); @@ -279,49 +279,69 @@ TEST_CASE("arrays - insertion and erasure") it = arr.erase(arr.cbegin()); REQUIRE(arr == array{ 42, 10.0, 10.0, 10.0, "test"sv, "test2"sv }); CHECK(it == arr.begin()); - CHECK(arr.size() == 6_sz); + CHECK(arr.size() == 6u); // erase(const_iterator first, const_iterator last) noexcept; it = arr.erase(arr.cbegin() + 2, arr.cbegin() + 4); REQUIRE(arr == array{ 42, 10.0, "test"sv, "test2"sv }); CHECK(it == arr.begin() + 2); - CHECK(arr.size() == 4_sz); + CHECK(arr.size() == 4u); arr.pop_back(); REQUIRE(arr == array{ 42, 10.0, "test"sv }); - CHECK(arr.size() == 3_sz); + CHECK(arr.size() == 3u); arr.clear(); REQUIRE(arr == array{}); - CHECK(arr.size() == 0_sz); + CHECK(arr.size() == 0u); CHECK(arr.empty()); // insert(const_iterator pos, Iter first, Iter last) { auto vals = std::vector{ 1.0, 2.0, 3.0 }; arr.insert(arr.cbegin(), vals.begin(), vals.end()); - CHECK(arr.size() == 3_sz); - REQUIRE(arr.get_as(0_sz)); - CHECK(*arr.get_as(0_sz) == 1.0); - REQUIRE(arr.get_as(1_sz)); - CHECK(*arr.get_as(1_sz) == 2.0); - REQUIRE(arr.get_as(2_sz)); - CHECK(*arr.get_as(2_sz) == 3.0); + CHECK(arr.size() == 3u); + REQUIRE(arr.get_as(0u)); + CHECK(*arr.get_as(0u) == 1.0); + REQUIRE(arr.get_as(1u)); + CHECK(*arr.get_as(1u) == 2.0); + REQUIRE(arr.get_as(2u)); + CHECK(*arr.get_as(2u) == 3.0); arr.insert(arr.cbegin() + 1, vals.begin(), vals.end()); - CHECK(arr.size() == 6_sz); - REQUIRE(arr.get_as(0_sz)); - CHECK(*arr.get_as(0_sz) == 1.0); - REQUIRE(arr.get_as(1_sz)); - CHECK(*arr.get_as(1_sz) == 1.0); - REQUIRE(arr.get_as(2_sz)); - CHECK(*arr.get_as(2_sz) == 2.0); - REQUIRE(arr.get_as(3_sz)); - CHECK(*arr.get_as(3_sz) == 3.0); - REQUIRE(arr.get_as(4_sz)); - CHECK(*arr.get_as(4_sz) == 2.0); - REQUIRE(arr.get_as(5_sz)); - CHECK(*arr.get_as(5_sz) == 3.0); + CHECK(arr.size() == 6u); + REQUIRE(arr.get_as(0u)); + CHECK(*arr.get_as(0u) == 1.0); + REQUIRE(arr.get_as(1u)); + CHECK(*arr.get_as(1u) == 1.0); + REQUIRE(arr.get_as(2u)); + CHECK(*arr.get_as(2u) == 2.0); + REQUIRE(arr.get_as(3u)); + CHECK(*arr.get_as(3u) == 3.0); + REQUIRE(arr.get_as(4u)); + CHECK(*arr.get_as(4u) == 2.0); + REQUIRE(arr.get_as(5u)); + CHECK(*arr.get_as(5u) == 3.0); + } + + // insert(const_iterator pos, Iter first, Iter last) (with move iterators) + { + arr.clear(); + + std::vector vals{ "foo", "bar", "kek" }; + arr.insert(arr.cbegin(), std::make_move_iterator(vals.begin()), std::make_move_iterator(vals.end())); + CHECK(arr.size() == 3u); + REQUIRE(arr.get_as(0)); + CHECK(*arr.get_as(0) == "foo"); + REQUIRE(arr.get_as(1)); + CHECK(*arr.get_as(1) == "bar"); + REQUIRE(arr.get_as(2)); + CHECK(*arr.get_as(2) == "kek"); + + REQUIRE(vals.size() == 3u); + CHECK(vals[0] == ""); + CHECK(vals[1] == ""); + CHECK(vals[2] == ""); } // iterator insert(const_iterator pos, std::initializer_list ilist) noexcept @@ -329,38 +349,38 @@ TEST_CASE("arrays - insertion and erasure") arr.clear(); arr.insert(arr.cbegin(), { 1.0, 2.0, 3.0 }); - CHECK(arr.size() == 3_sz); - REQUIRE(arr.get_as(0_sz)); - CHECK(*arr.get_as(0_sz) == 1.0); - REQUIRE(arr.get_as(1_sz)); - CHECK(*arr.get_as(1_sz) == 2.0); - REQUIRE(arr.get_as(2_sz)); - CHECK(*arr.get_as(2_sz) == 3.0); + CHECK(arr.size() == 3u); + REQUIRE(arr.get_as(0u)); + CHECK(*arr.get_as(0u) == 1.0); + REQUIRE(arr.get_as(1u)); + CHECK(*arr.get_as(1u) == 2.0); + REQUIRE(arr.get_as(2u)); + CHECK(*arr.get_as(2u) == 3.0); arr.insert(arr.cbegin() + 1, { 1.0, 2.0, 3.0 }); - CHECK(arr.size() == 6_sz); - REQUIRE(arr.get_as(0_sz)); - CHECK(*arr.get_as(0_sz) == 1.0); - REQUIRE(arr.get_as(1_sz)); - CHECK(*arr.get_as(1_sz) == 1.0); - REQUIRE(arr.get_as(2_sz)); - CHECK(*arr.get_as(2_sz) == 2.0); - REQUIRE(arr.get_as(3_sz)); - CHECK(*arr.get_as(3_sz) == 3.0); - REQUIRE(arr.get_as(4_sz)); - CHECK(*arr.get_as(4_sz) == 2.0); - REQUIRE(arr.get_as(5_sz)); - CHECK(*arr.get_as(5_sz) == 3.0); + CHECK(arr.size() == 6u); + REQUIRE(arr.get_as(0u)); + CHECK(*arr.get_as(0u) == 1.0); + REQUIRE(arr.get_as(1u)); + CHECK(*arr.get_as(1u) == 1.0); + REQUIRE(arr.get_as(2u)); + CHECK(*arr.get_as(2u) == 2.0); + REQUIRE(arr.get_as(3u)); + CHECK(*arr.get_as(3u) == 3.0); + REQUIRE(arr.get_as(4u)); + CHECK(*arr.get_as(4u) == 2.0); + REQUIRE(arr.get_as(5u)); + CHECK(*arr.get_as(5u) == 3.0); } #if TOML_WINDOWS_COMPAT arr.clear(); it = arr.insert(arr.cbegin(), L"test"); - REQUIRE(*arr.get_as(0_sz) == "test"sv); + REQUIRE(*arr.get_as(0u) == "test"sv); it = arr.emplace(arr.cbegin(), L"test2"sv); - REQUIRE(*arr.get_as(0_sz) == "test2"sv); + REQUIRE(*arr.get_as(0u) == "test2"sv); arr.push_back(L"test3"s); REQUIRE(*arr.back().as_string() == "test3"sv); @@ -400,30 +420,30 @@ TEST_CASE("arrays - flattening") TEST_CASE("arrays - resizing and truncation") { array arr{ 1, 2, 3, 4, 5 }; - REQUIRE(arr.size() == 5_sz); + REQUIRE(arr.size() == 5u); // truncate with no change - arr.truncate(5_sz); - REQUIRE(arr.size() == 5_sz); + arr.truncate(5u); + REQUIRE(arr.size() == 5u); REQUIRE(arr == array{ 1, 2, 3, 4, 5 }); // truncate down to three elements - arr.truncate(3_sz); - REQUIRE(arr.size() == 3_sz); + arr.truncate(3u); + REQUIRE(arr.size() == 3u); REQUIRE(arr == array{ 1, 2, 3 }); // resize down to two elements - arr.resize(2_sz, 42); - REQUIRE(arr.size() == 2_sz); + arr.resize(2u, 42); + REQUIRE(arr.size() == 2u); REQUIRE(arr == array{ 1, 2 }); // resize with no change - arr.resize(2_sz, 42); - REQUIRE(arr.size() == 2_sz); + arr.resize(2u, 42); + REQUIRE(arr.size() == 2u); REQUIRE(arr == array{ 1, 2 }); //resize up to six elements - arr.resize(6_sz, 42); - REQUIRE(arr.size() == 6_sz); + arr.resize(6u, 42); + REQUIRE(arr.size() == 6u); REQUIRE(arr == array{ 1, 2, 42, 42, 42, 42 }); } diff --git a/tests/manipulating_tables.cpp b/tests/manipulating_tables.cpp index 82f1d0c..6626fde 100644 --- a/tests/manipulating_tables.cpp +++ b/tests/manipulating_tables.cpp @@ -16,7 +16,7 @@ TEST_CASE("tables - moving") { // sanity-check initial state of a freshly-parsed table REQUIRE(tbl["test"].as()); - CHECK(tbl["test"].as
()->size() == 1_sz); + CHECK(tbl["test"].as
()->size() == 1u); CHECK(tbl["test"].as
()->source().begin == source_position{ 1, 8 }); CHECK(tbl["test"].as
()->source().end == source_position{ 1, 24 }); CHECK(tbl["test"]["val1"] == "foo"); @@ -26,7 +26,7 @@ TEST_CASE("tables - moving") CHECK(tbl2.source().begin == source_position{}); CHECK(tbl2.source().end == source_position{}); CHECK(!tbl2.source().path); - CHECK(tbl2.size() == 0_sz); + CHECK(tbl2.size() == 0u); // check the results of move-assignment tbl2 = std::move(tbl); @@ -34,16 +34,16 @@ TEST_CASE("tables - moving") CHECK(tbl2.source().end == source_position{ 1, 24 }); CHECK(tbl2.source().path); CHECK(*tbl2.source().path == filename); - CHECK(tbl2.size() == 1_sz); + CHECK(tbl2.size() == 1u); REQUIRE(tbl2["test"].as
()); - CHECK(tbl2["test"].as
()->size() == 1_sz); + CHECK(tbl2["test"].as
()->size() == 1u); CHECK(tbl2["test"]["val1"] == "foo"sv); // check that moved-from table is now the same as default-constructed CHECK(tbl.source().begin == source_position{}); CHECK(tbl.source().end == source_position{}); CHECK(!tbl.source().path); - CHECK(tbl.size() == 0_sz); + CHECK(tbl.size() == 0u); CHECK(!tbl["test"].as
()); // check the results of move-construction @@ -52,16 +52,16 @@ TEST_CASE("tables - moving") CHECK(tbl3.source().end == source_position{ 1, 24 }); CHECK(tbl3.source().path); CHECK(*tbl3.source().path == filename); - CHECK(tbl3.size() == 1_sz); + CHECK(tbl3.size() == 1u); REQUIRE(tbl3["test"].as
()); - CHECK(tbl3["test"].as
()->size() == 1_sz); + CHECK(tbl3["test"].as
()->size() == 1u); CHECK(tbl3["test"]["val1"] == "foo"sv); // check that moved-from table is now the same as default-constructed CHECK(tbl2.source().begin == source_position{}); CHECK(tbl2.source().end == source_position{}); CHECK(!tbl2.source().path); - CHECK(tbl2.size() == 0_sz); + CHECK(tbl2.size() == 0u); CHECK(!tbl2["test"].as
()); }, filename @@ -79,7 +79,7 @@ TEST_CASE("tables - copying") { // sanity-check initial state of a freshly-parsed table REQUIRE(tbl["test"].as
()); - CHECK(tbl["test"].as
()->size() == 1_sz); + CHECK(tbl["test"].as
()->size() == 1u); CHECK(tbl["test"].as
()->source().begin == source_position{ 1, 8 }); CHECK(tbl["test"].as
()->source().end == source_position{ 1, 24 }); CHECK(tbl["test"]["val1"] == "foo"); @@ -89,16 +89,16 @@ TEST_CASE("tables - copying") CHECK(tbl2.source().begin == source_position{}); CHECK(tbl2.source().end == source_position{}); CHECK(!tbl2.source().path); - CHECK(tbl2.size() == 0_sz); + CHECK(tbl2.size() == 0u); // check the results of copy-assignment tbl2 = tbl; CHECK(tbl2.source().begin == source_position{}); CHECK(tbl2.source().end == source_position{}); CHECK(!tbl2.source().path); - CHECK(tbl2.size() == 1_sz); + CHECK(tbl2.size() == 1u); REQUIRE(tbl2["test"].as
()); - CHECK(tbl2["test"].as
()->size() == 1_sz); + CHECK(tbl2["test"].as
()->size() == 1u); CHECK(tbl2["test"]["val1"] == "foo"sv); CHECK(tbl2 == tbl); @@ -107,9 +107,9 @@ TEST_CASE("tables - copying") CHECK(tbl3.source().begin == source_position{}); CHECK(tbl3.source().end == source_position{}); CHECK(!tbl3.source().path); - CHECK(tbl3.size() == 1_sz); + CHECK(tbl3.size() == 1u); REQUIRE(tbl3["test"].as
()); - CHECK(tbl3["test"].as
()->size() == 1_sz); + CHECK(tbl3["test"].as
()->size() == 1u); CHECK(tbl3["test"]["val1"] == "foo"sv); CHECK(tbl3 == tbl2); CHECK(tbl3 == tbl); @@ -122,7 +122,7 @@ TEST_CASE("tables - construction") { { table tbl; - CHECK(tbl.size() == 0_sz); + CHECK(tbl.size() == 0u); CHECK(tbl.empty()); CHECK(tbl.begin() == tbl.end()); CHECK(tbl.cbegin() == tbl.cend()); @@ -135,7 +135,7 @@ TEST_CASE("tables - construction") table tbl{{ { "foo"sv, 42 } }}; - CHECK(tbl.size() == 1_sz); + CHECK(tbl.size() == 1u); CHECK(!tbl.empty()); CHECK(tbl.begin() != tbl.end()); CHECK(tbl.cbegin() != tbl.cend()); @@ -150,7 +150,7 @@ TEST_CASE("tables - construction") { "kek"sv, false }, { "qux"sv, array{ 1 } } }}; - CHECK(tbl.size() == 4_sz); + CHECK(tbl.size() == 4u); CHECK(!tbl.empty()); REQUIRE(tbl.get_as("foo"sv)); CHECK(*tbl.get_as("foo"sv) == 42); @@ -170,7 +170,7 @@ TEST_CASE("tables - construction") { L"kek"s, L"test3"sv }, { L"qux"sv.data(), L"test4"sv.data() } } }; - CHECK(tbl.size() == 4_sz); + CHECK(tbl.size() == 4u); CHECK(!tbl.empty()); REQUIRE(tbl.get_as("foo"sv)); CHECK(*tbl.get_as("foo"sv) == "test1"sv); @@ -256,7 +256,7 @@ TEST_CASE("tables - insertion and erasure") auto res = tbl.insert("a", 42); CHECK(res.first == tbl.begin()); CHECK(res.second == true); - CHECK(tbl.size() == 1_sz); + CHECK(tbl.size() == 1u); CHECK(!tbl.empty()); REQUIRE(tbl.get_as("a"sv)); CHECK(*tbl.get_as("a"sv) == 42); @@ -265,7 +265,7 @@ TEST_CASE("tables - insertion and erasure") res = tbl.insert("a", 69); CHECK(res.first == tbl.begin()); CHECK(res.second == false); - CHECK(tbl.size() == 1_sz); + CHECK(tbl.size() == 1u); REQUIRE(tbl.get_as("a")); CHECK(*tbl.get_as("a") == 42); REQUIRE(tbl == table{{ { "a"sv, 42 } }}); @@ -274,7 +274,7 @@ TEST_CASE("tables - insertion and erasure") res = tbl.insert_or_assign(a, 69); CHECK(res.first == tbl.begin()); CHECK(res.second == false); // should assign - CHECK(tbl.size() == 1_sz); + CHECK(tbl.size() == 1u); REQUIRE(tbl.get_as("a")); CHECK(*tbl.get_as("a") == 69); REQUIRE(tbl == table{{ { "a"sv, 69 } }}); @@ -282,7 +282,7 @@ TEST_CASE("tables - insertion and erasure") res = tbl.insert_or_assign("b", "kek"); CHECK(res.first == advance(tbl.begin(), 1)); CHECK(res.second == true); // should insert - CHECK(tbl.size() == 2_sz); + CHECK(tbl.size() == 2u); REQUIRE(tbl.get_as("b")); CHECK(*tbl.get_as("b") == "kek"sv); REQUIRE(tbl == table{{ { "a"sv, 69 }, { "b"sv, "kek" } }}); @@ -290,7 +290,7 @@ TEST_CASE("tables - insertion and erasure") res = tbl.emplace("c", 1, 2, 3); CHECK(res.first == advance(tbl.begin(), 2)); CHECK(res.second == true); - CHECK(tbl.size() == 3_sz); + CHECK(tbl.size() == 3u); REQUIRE(tbl.get_as("c")); CHECK(*tbl.get_as("c") == array{ 1, 2, 3 }); REQUIRE(tbl == table{{ { "a"sv, 69 }, { "b"sv, "kek"sv }, { "c"sv, array{ 1, 2, 3 } } }}); @@ -298,7 +298,7 @@ TEST_CASE("tables - insertion and erasure") res = tbl.emplace("c", 1); CHECK(res.first == advance(tbl.begin(), 2)); CHECK(res.second == false); - CHECK(tbl.size() == 3_sz); + CHECK(tbl.size() == 3u); REQUIRE(!tbl.get_as("c")); REQUIRE(tbl.get_as("c")); REQUIRE(tbl == table{{ { "a"sv, 69 }, { "b"sv, "kek"s }, { "c"sv, array{ 1, 2, 3 } } }}); @@ -306,12 +306,12 @@ TEST_CASE("tables - insertion and erasure") auto it = tbl.erase(tbl.cbegin()); REQUIRE(tbl == table{{ { "b"sv, "kek" }, { "c"sv, array{ 1, 2, 3 } } }}); CHECK(it == tbl.begin()); - CHECK(tbl.size() == 2_sz); + CHECK(tbl.size() == 2u); res = tbl.insert_or_assign("a"sv, 69); CHECK(res.first == tbl.begin()); CHECK(res.second == true); // should insert - CHECK(tbl.size() == 3_sz); + CHECK(tbl.size() == 3u); REQUIRE(tbl.get_as("a")); CHECK(*tbl.get_as("a") == 69); REQUIRE(tbl == table{{ { "a"sv, 69 }, { "b"sv, "kek" }, { "c"sv, array{ 1, 2, 3 } } }}); @@ -319,13 +319,67 @@ TEST_CASE("tables - insertion and erasure") it = tbl.erase(advance(tbl.cbegin(), 1), advance(tbl.cbegin(), 3)); REQUIRE(tbl == table{{ { "a"sv, 69 } }}); CHECK(it == tbl.end()); - CHECK(tbl.size() == 1_sz); + CHECK(tbl.size() == 1u); tbl.clear(); REQUIRE(tbl == table{}); - CHECK(tbl.size() == 0_sz); + CHECK(tbl.size() == 0u); CHECK(tbl.empty()); + // void insert(Iter first, Iter last) + { + std::vector> vals{ + { "foo", "foo" }, + { "bar", "bar" }, + { "kek", "kek" } + }; + tbl.insert(vals.begin(), vals.end()); + CHECK(tbl.size() == 3u); + REQUIRE(tbl.get_as("foo")); + CHECK(*tbl.get_as("foo") == "foo"); + REQUIRE(tbl.get_as("bar")); + CHECK(*tbl.get_as("bar") == "bar"); + REQUIRE(tbl.get_as("kek")); + CHECK(*tbl.get_as("kek") == "kek"); + + REQUIRE(vals.size() == 3u); + CHECK(vals[0].first == "foo"); + CHECK(vals[0].second == "foo"); + CHECK(vals[1].first == "bar"); + CHECK(vals[1].second == "bar"); + CHECK(vals[2].first == "kek"); + CHECK(vals[2].second == "kek"); + + tbl.clear(); + } + + // void insert(Iter first, Iter last) (with move iterators) + { + std::vector> vals{ + { "foo", "foo" }, + { "bar", "bar" }, + { "kek", "kek" } + }; + tbl.insert(std::make_move_iterator(vals.begin()), std::make_move_iterator(vals.end())); + CHECK(tbl.size() == 3u); + REQUIRE(tbl.get_as("foo")); + CHECK(*tbl.get_as("foo") == "foo"); + REQUIRE(tbl.get_as("bar")); + CHECK(*tbl.get_as("bar") == "bar"); + REQUIRE(tbl.get_as("kek")); + CHECK(*tbl.get_as("kek") == "kek"); + + REQUIRE(vals.size() == 3u); + CHECK(vals[0].first == ""); + CHECK(vals[0].second == ""); + CHECK(vals[1].first == ""); + CHECK(vals[1].second == ""); + CHECK(vals[2].first == ""); + CHECK(vals[2].second == ""); + + tbl.clear(); + } + #if TOML_WINDOWS_COMPAT @@ -335,11 +389,11 @@ TEST_CASE("tables - insertion and erasure") REQUIRE(*tbl.get_as(L"a"sv) == "test2"sv); tbl.emplace(L"b", L"test3"); REQUIRE(*tbl.get_as(L"b"sv) == "test3"sv); - CHECK(tbl.size() == 2_sz); + CHECK(tbl.size() == 2u); tbl.erase(L"b"); - CHECK(tbl.size() == 1_sz); + CHECK(tbl.size() == 1u); tbl.erase(L"a"s); - CHECK(tbl.size() == 0_sz); + CHECK(tbl.size() == 0u); #endif // TOML_WINDOWS_COMPAT } diff --git a/tests/manipulating_values.cpp b/tests/manipulating_values.cpp index 9a38969..452632b 100644 --- a/tests/manipulating_values.cpp +++ b/tests/manipulating_values.cpp @@ -130,3 +130,276 @@ TEST_CASE("values - printing") CHECK(print_value(10000000000) == "10000000000"); CHECK(print_value(100000000000000) == "100000000000000"); } + +TEST_CASE("nodes - value() int/float/bool conversions") +{ + #define CHECK_VALUE_PASS(type, v) \ + CHECK(n.value() == static_cast(v)) + #define CHECK_VALUE_FAIL(type) \ + CHECK(!n.value()) + + // bools + { + value val{ false }; + const node& n = val; + CHECK_VALUE_PASS(bool, false); + CHECK_VALUE_PASS(int8_t, 0); + CHECK_VALUE_PASS(uint8_t, 0); + CHECK_VALUE_PASS(int16_t, 0); + CHECK_VALUE_PASS(uint16_t, 0); + CHECK_VALUE_PASS(int32_t, 0); + CHECK_VALUE_PASS(uint32_t, 0); + CHECK_VALUE_PASS(int64_t, 0); + CHECK_VALUE_PASS(uint64_t, 0); + CHECK_VALUE_FAIL(float); + CHECK_VALUE_FAIL(double); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = true; + CHECK_VALUE_PASS(bool, true); + CHECK_VALUE_PASS(int8_t, 1); + CHECK_VALUE_PASS(uint8_t, 1); + CHECK_VALUE_PASS(int16_t, 1); + CHECK_VALUE_PASS(uint16_t, 1); + CHECK_VALUE_PASS(int32_t, 1); + CHECK_VALUE_PASS(uint32_t, 1); + CHECK_VALUE_PASS(int64_t, 1); + CHECK_VALUE_PASS(uint64_t, 1); + CHECK_VALUE_FAIL(float); + CHECK_VALUE_FAIL(double); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + } + + // ints + { + value val{ 0 }; + const node& n = val; + CHECK_VALUE_PASS(bool, false); // int -> bool coercion + CHECK_VALUE_PASS(int8_t, 0); + CHECK_VALUE_PASS(uint8_t, 0); + CHECK_VALUE_PASS(int16_t, 0); + CHECK_VALUE_PASS(uint16_t, 0); + CHECK_VALUE_PASS(int32_t, 0); + CHECK_VALUE_PASS(uint32_t, 0); + CHECK_VALUE_PASS(int64_t, 0); + CHECK_VALUE_PASS(uint64_t, 0); + CHECK_VALUE_PASS(float, 0); + CHECK_VALUE_PASS(double, 0); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = 100; + CHECK_VALUE_PASS(bool, true); // int -> bool coercion + CHECK_VALUE_PASS(int8_t, 100); + CHECK_VALUE_PASS(uint8_t, 100); + CHECK_VALUE_PASS(int16_t, 100); + CHECK_VALUE_PASS(uint16_t, 100); + CHECK_VALUE_PASS(int32_t, 100); + CHECK_VALUE_PASS(uint32_t, 100); + CHECK_VALUE_PASS(int64_t, 100); + CHECK_VALUE_PASS(uint64_t, 100); + CHECK_VALUE_PASS(float, 100); + CHECK_VALUE_PASS(double, 100); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = -100; + CHECK_VALUE_PASS(bool, true); // int -> bool coercion + CHECK_VALUE_PASS(int8_t, -100); + CHECK_VALUE_FAIL(uint8_t); + CHECK_VALUE_PASS(int16_t, -100); + CHECK_VALUE_FAIL(uint16_t); + CHECK_VALUE_PASS(int32_t, -100); + CHECK_VALUE_FAIL(uint32_t); + CHECK_VALUE_PASS(int64_t, -100); + CHECK_VALUE_FAIL(uint64_t); + CHECK_VALUE_PASS(float, -100); + CHECK_VALUE_PASS(double, -100); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = 1000; + CHECK_VALUE_PASS(bool, true); // int -> bool coercion + CHECK_VALUE_FAIL(int8_t); + CHECK_VALUE_FAIL(uint8_t); + CHECK_VALUE_PASS(int16_t, 1000); + CHECK_VALUE_PASS(uint16_t, 1000); + CHECK_VALUE_PASS(int32_t, 1000); + CHECK_VALUE_PASS(uint32_t, 1000); + CHECK_VALUE_PASS(int64_t, 1000); + CHECK_VALUE_PASS(uint64_t, 1000); + CHECK_VALUE_PASS(float, 1000); + CHECK_VALUE_PASS(double, 1000); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = -1000; + CHECK_VALUE_PASS(bool, true); // int -> bool coercion + CHECK_VALUE_FAIL(int8_t); + CHECK_VALUE_FAIL(uint8_t); + CHECK_VALUE_PASS(int16_t, -1000); + CHECK_VALUE_FAIL(uint16_t); + CHECK_VALUE_PASS(int32_t, -1000); + CHECK_VALUE_FAIL(uint32_t); + CHECK_VALUE_PASS(int64_t, -1000); + CHECK_VALUE_FAIL(uint64_t); + CHECK_VALUE_PASS(float, -1000); + CHECK_VALUE_PASS(double, -1000); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = (std::numeric_limits::max)(); + CHECK_VALUE_PASS(bool, true); // int -> bool coercion + CHECK_VALUE_FAIL(int8_t); + CHECK_VALUE_FAIL(uint8_t); + CHECK_VALUE_FAIL(int16_t); + CHECK_VALUE_FAIL(uint16_t); + CHECK_VALUE_FAIL(int32_t); + CHECK_VALUE_FAIL(uint32_t); + CHECK_VALUE_PASS(int64_t, (std::numeric_limits::max)()); + CHECK_VALUE_PASS(uint64_t, (std::numeric_limits::max)()); + CHECK_VALUE_FAIL(float); + CHECK_VALUE_FAIL(double); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = (std::numeric_limits::min)(); + CHECK_VALUE_PASS(bool, true); // int -> bool coercion + CHECK_VALUE_FAIL(int8_t); + CHECK_VALUE_FAIL(uint8_t); + CHECK_VALUE_FAIL(int16_t); + CHECK_VALUE_FAIL(uint16_t); + CHECK_VALUE_FAIL(int32_t); + CHECK_VALUE_FAIL(uint32_t); + CHECK_VALUE_PASS(int64_t, (std::numeric_limits::min)()); + CHECK_VALUE_FAIL(uint64_t); + CHECK_VALUE_FAIL(float); + CHECK_VALUE_FAIL(double); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + } + + // floats + { + value val{ 0.0 }; + const node& n = val; + CHECK_VALUE_FAIL(bool); + CHECK_VALUE_PASS(int8_t, 0); + CHECK_VALUE_PASS(uint8_t, 0); + CHECK_VALUE_PASS(int16_t, 0); + CHECK_VALUE_PASS(uint16_t, 0); + CHECK_VALUE_PASS(int32_t, 0); + CHECK_VALUE_PASS(uint32_t, 0); + CHECK_VALUE_PASS(int64_t, 0); + CHECK_VALUE_PASS(uint64_t, 0); + CHECK_VALUE_PASS(float, 0); + CHECK_VALUE_PASS(double, 0); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + + *val = 1.0; + CHECK_VALUE_FAIL(bool); + CHECK_VALUE_PASS(int8_t, 1); + CHECK_VALUE_PASS(uint8_t, 1); + CHECK_VALUE_PASS(int16_t, 1); + CHECK_VALUE_PASS(uint16_t, 1); + CHECK_VALUE_PASS(int32_t, 1); + CHECK_VALUE_PASS(uint32_t, 1); + CHECK_VALUE_PASS(int64_t, 1); + CHECK_VALUE_PASS(uint64_t, 1); + CHECK_VALUE_PASS(float, 1); + CHECK_VALUE_PASS(double, 1); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = -1.0; + CHECK_VALUE_FAIL(bool); + CHECK_VALUE_PASS(int8_t, -1); + CHECK_VALUE_FAIL(uint8_t); + CHECK_VALUE_PASS(int16_t, -1); + CHECK_VALUE_FAIL(uint16_t); + CHECK_VALUE_PASS(int32_t, -1); + CHECK_VALUE_FAIL(uint32_t); + CHECK_VALUE_PASS(int64_t, -1); + CHECK_VALUE_FAIL(uint64_t); + CHECK_VALUE_PASS(float, -1); + CHECK_VALUE_PASS(double, -1); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = 1.5; + CHECK_VALUE_FAIL(bool); + CHECK_VALUE_FAIL(int8_t); + CHECK_VALUE_FAIL(uint8_t); + CHECK_VALUE_FAIL(int16_t); + CHECK_VALUE_FAIL(uint16_t); + CHECK_VALUE_FAIL(int32_t); + CHECK_VALUE_FAIL(uint32_t); + CHECK_VALUE_FAIL(int64_t); + CHECK_VALUE_FAIL(uint64_t); + CHECK_VALUE_PASS(float, 1.5); + CHECK_VALUE_PASS(double, 1.5); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + + *val = -1.5; + CHECK_VALUE_FAIL(bool); + CHECK_VALUE_FAIL(int8_t); + CHECK_VALUE_FAIL(uint8_t); + CHECK_VALUE_FAIL(int16_t); + CHECK_VALUE_FAIL(uint16_t); + CHECK_VALUE_FAIL(int32_t); + CHECK_VALUE_FAIL(uint32_t); + CHECK_VALUE_FAIL(int64_t); + CHECK_VALUE_FAIL(uint64_t); + CHECK_VALUE_PASS(float, -1.5); + CHECK_VALUE_PASS(double, -1.5); + CHECK_VALUE_FAIL(std::string); + CHECK_VALUE_FAIL(std::string_view); + CHECK_VALUE_FAIL(toml::date); + CHECK_VALUE_FAIL(toml::time); + CHECK_VALUE_FAIL(toml::date_time); + } +} diff --git a/tests/parsing_tables.cpp b/tests/parsing_tables.cpp index f3a0961..8db8884 100644 --- a/tests/parsing_tables.cpp +++ b/tests/parsing_tables.cpp @@ -46,23 +46,23 @@ smooth = true [](table&& tbl) { REQUIRE(tbl["table"].as
()); - CHECK(tbl["table"].as
()->size() == 0_sz); + CHECK(tbl["table"].as
()->size() == 0u); REQUIRE(tbl["table-1"].as
()); - CHECK(tbl["table-1"].as
()->size() == 2_sz); + CHECK(tbl["table-1"].as
()->size() == 2u); CHECK(tbl["table-1"]["key1"] == "some string"sv); CHECK(tbl["table-1"]["key2"] == 123); REQUIRE(tbl["table-2"].as
()); - CHECK(tbl["table-2"].as
()->size() == 2_sz); + CHECK(tbl["table-2"].as
()->size() == 2u); CHECK(tbl["table-2"]["key1"] == "another string"sv); CHECK(tbl["table-2"]["key2"] == 456); REQUIRE(tbl["dog"].as
()); - CHECK(tbl["dog"].as
()->size() == 1_sz); + CHECK(tbl["dog"].as
()->size() == 1u); REQUIRE(tbl["dog"]["tater.man"].as
()); - CHECK(tbl["dog"]["tater.man"].as
()->size() == 1_sz); + CHECK(tbl["dog"]["tater.man"].as
()->size() == 1u); CHECK(tbl["dog"]["tater.man"]["type"]["name"] == "pug"sv); CHECK(tbl["a"].as
()); @@ -136,10 +136,10 @@ apple.taste.sweet = true [](table&& tbl) { REQUIRE(tbl["animal"].as
()); - CHECK(tbl["animal"].as
()->size() == 0_sz); + CHECK(tbl["animal"].as
()->size() == 0u); REQUIRE(tbl["fruit"].as
()); - CHECK(tbl["fruit"].as
()->size() == 2_sz); + CHECK(tbl["fruit"].as
()->size() == 2u); REQUIRE(tbl["fruit"]["apple"].as
()); REQUIRE(tbl["fruit"]["orange"].as
()); @@ -158,10 +158,10 @@ apple.taste.sweet = true [](table&& tbl) { REQUIRE(tbl["animal"].as
()); - CHECK(tbl["animal"].as
()->size() == 0_sz); + CHECK(tbl["animal"].as
()->size() == 0u); REQUIRE(tbl["fruit"].as
()); - CHECK(tbl["fruit"].as
()->size() == 2_sz); + CHECK(tbl["fruit"].as
()->size() == 2u); REQUIRE(tbl["fruit"]["apple"].as
()); REQUIRE(tbl["fruit"]["orange"].as
()); @@ -186,25 +186,25 @@ type = { name = "Nail" } [](table&& tbl) { REQUIRE(tbl["name"].as
()); - CHECK(tbl["name"].as
()->size() == 2_sz); + CHECK(tbl["name"].as
()->size() == 2u); CHECK(tbl["name"]["first"] == "Tom"sv); CHECK(tbl["name"]["last"] == "Preston-Werner"sv); REQUIRE(tbl["point"].as
()); - CHECK(tbl["point"].as
()->size() == 2_sz); + CHECK(tbl["point"].as
()->size() == 2u); CHECK(tbl["point"]["x"] == 1); CHECK(tbl["point"]["y"] == 2); REQUIRE(tbl["animal"].as
()); - CHECK(tbl["animal"].as
()->size() == 1_sz); + CHECK(tbl["animal"].as
()->size() == 1u); REQUIRE(tbl["animal"]["type"].as
()); - CHECK(tbl["animal"]["type"].as
()->size() == 1_sz); + CHECK(tbl["animal"]["type"].as
()->size() == 1u); CHECK(tbl["animal"]["type"]["name"] == "pug"sv); REQUIRE(tbl["product"].as
()); - CHECK(tbl["product"].as
()->size() == 1_sz); + CHECK(tbl["product"].as
()->size() == 1u); REQUIRE(tbl["product"]["type"].as
()); - CHECK(tbl["product"]["type"].as
()->size() == 1_sz); + CHECK(tbl["product"]["type"].as
()->size() == 1u); CHECK(tbl["product"]["type"]["name"] == "Nail"sv); } ); @@ -233,10 +233,10 @@ test = { val1 = "foo", val2 = [ [](table&& tbl) { REQUIRE(tbl["test"].as
()); - CHECK(tbl["test"].as
()->size() == 3_sz); + CHECK(tbl["test"].as
()->size() == 3u); CHECK(tbl["test"]["val1"] == "foo"sv); REQUIRE(tbl["test"]["val2"].as()); - CHECK(tbl["test"]["val2"].as()->size() == 3_sz); + CHECK(tbl["test"]["val2"].as()->size() == 3u); CHECK(tbl["test"]["val2"][0] == 1); CHECK(tbl["test"]["val2"][1] == 2); CHECK(tbl["test"]["val2"][2] == 3); @@ -258,7 +258,7 @@ name = { [](table&& tbl) { REQUIRE(tbl["name"].as
()); - CHECK(tbl["name"].as
()->size() == 2_sz); + CHECK(tbl["name"].as
()->size() == 2u); CHECK(tbl["name"]["first"] == "Tom"sv); CHECK(tbl["name"]["last"] == "Preston-Werner"sv); } @@ -327,7 +327,7 @@ color = "gray" [](table&& tbl) { REQUIRE(tbl["points"].as()); - CHECK(tbl["points"].as()->size() == 3_sz); + CHECK(tbl["points"].as()->size() == 3u); CHECK(tbl["points"].as()->is_homogeneous()); CHECK(tbl["points"].as()->is_array_of_tables()); CHECK(tbl["points"][0]["x"] == 1); @@ -341,52 +341,52 @@ color = "gray" CHECK(tbl["points"][2]["z"] == 8); REQUIRE(tbl["products"].as()); - CHECK(tbl["products"].as()->size() == 3_sz); + CHECK(tbl["products"].as()->size() == 3u); CHECK(tbl["products"].as()->is_homogeneous()); CHECK(tbl["products"].as()->is_array_of_tables()); REQUIRE(tbl["products"][0].as
()); - CHECK(tbl["products"][0].as
()->size() == 2_sz); + CHECK(tbl["products"][0].as
()->size() == 2u); CHECK(tbl["products"][0]["name"] == "Hammer"sv); CHECK(tbl["products"][0]["sku"] == 738594937); REQUIRE(tbl["products"][1].as
()); - CHECK(tbl["products"][1].as
()->size() == 0_sz); + CHECK(tbl["products"][1].as
()->size() == 0u); REQUIRE(tbl["products"][2].as
()); - CHECK(tbl["products"][2].as
()->size() == 3_sz); + CHECK(tbl["products"][2].as
()->size() == 3u); CHECK(tbl["products"][2]["name"] == "Nail"sv); CHECK(tbl["products"][2]["sku"] == 284758393); CHECK(tbl["products"][2]["color"] == "gray"sv); REQUIRE(tbl["fruit"].as()); - CHECK(tbl["fruit"].as()->size() == 2_sz); + CHECK(tbl["fruit"].as()->size() == 2u); CHECK(tbl["fruit"].as()->is_homogeneous()); CHECK(tbl["fruit"].as()->is_array_of_tables()); REQUIRE(tbl["fruit"][0].as
()); - CHECK(tbl["fruit"][0].as
()->size() == 3_sz); + CHECK(tbl["fruit"][0].as
()->size() == 3u); CHECK(tbl["fruit"][0]["name"] == "apple"sv); REQUIRE(tbl["fruit"][0]["physical"].as
()); - CHECK(tbl["fruit"][0]["physical"].as
()->size() == 2_sz); + CHECK(tbl["fruit"][0]["physical"].as
()->size() == 2u); CHECK(tbl["fruit"][0]["physical"]["color"] == "red"sv); CHECK(tbl["fruit"][0]["physical"]["shape"] == "round"sv); REQUIRE(tbl["fruit"][0]["variety"].as()); - CHECK(tbl["fruit"][0]["variety"].as()->size() == 2_sz); + CHECK(tbl["fruit"][0]["variety"].as()->size() == 2u); CHECK(tbl["fruit"][0]["variety"].as()->is_homogeneous()); CHECK(tbl["fruit"][0]["variety"].as()->is_array_of_tables()); CHECK(tbl["fruit"][0]["variety"][0]["name"] == "red delicious"sv); CHECK(tbl["fruit"][0]["variety"][1]["name"] == "granny smith"sv); REQUIRE(tbl["fruit"][1].as
()); - CHECK(tbl["fruit"][1].as
()->size() == 2_sz); + CHECK(tbl["fruit"][1].as
()->size() == 2u); CHECK(tbl["fruit"][1]["name"] == "banana"sv); REQUIRE(tbl["fruit"][1]["variety"].as()); - CHECK(tbl["fruit"][1]["variety"].as()->size() == 1_sz); + CHECK(tbl["fruit"][1]["variety"].as()->size() == 1u); CHECK(tbl["fruit"][1]["variety"].as()->is_homogeneous()); CHECK(tbl["fruit"][1]["variety"].as()->is_array_of_tables()); CHECK(tbl["fruit"][1]["variety"][0]["name"] == "plantain"sv); diff --git a/tests/user_feedback.cpp b/tests/user_feedback.cpp index 140df11..345905a 100644 --- a/tests/user_feedback.cpp +++ b/tests/user_feedback.cpp @@ -86,3 +86,17 @@ TEST_CASE("feedback - github/issues/49") }}); } } + +TEST_CASE("feedback - github/pull/50") +{ + // see: https://github.com/marzer/tomlplusplus/pull/50 + { + auto tbl = toml::table{ {{"value", 10}} }; + const toml::node* val = tbl.get("value"); + REQUIRE(val); + REQUIRE(val->is_number()); + REQUIRE(val->is_integer()); + REQUIRE(val->ref() == 10); + REQUIRE(val->value() == 10.0); + } +} diff --git a/toml.hpp b/toml.hpp index 194d8f1..cc44731 100644 --- a/toml.hpp +++ b/toml.hpp @@ -25,7 +25,6 @@ // MIT License // // Copyright (c) 2019-2020 Mark Gillard -// Copyright (c) 2008-2010 Bjoern Hoehrmann (utf8_decoder) // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated // documentation files (the "Software"), to deal in the Software without restriction, including without limitation the @@ -619,7 +618,7 @@ TOML_POP_WARNINGS #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 " \ + "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!" @@ -2039,7 +2038,6 @@ TOML_DISABLE_MISC_WARNINGS #define TOML_SA_LIST_END ")" #define TOML_SA_LIST_NEW " " #define TOML_SA_LIST_NXT ", " -#define TOML_SA_LIST_CAP(...) #else @@ -2049,7 +2047,6 @@ TOML_DISABLE_MISC_WARNINGS #define TOML_SA_LIST_END #define TOML_SA_LIST_NEW TOML_SA_NEWLINE TOML_SA_NEWLINE #define TOML_SA_LIST_NXT TOML_SA_LIST_NEW -#define TOML_SA_LIST_CAP(val) val #endif @@ -2904,14 +2901,16 @@ TOML_NAMESPACE_START TOML_SA_LIST_SEP "std::wstring" #endif TOML_SA_LIST_SEP "any signed integer type >= 64 bits" - TOML_SA_LIST_SEP "any floating-point type >= 64 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 64 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "An immutable view type not requiring additional temporary storage" TOML_SA_LIST_BEG "std::string_view" - TOML_SA_LIST_SEP "const char*" #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "std::u8string_view" + #endif + TOML_SA_LIST_SEP "const char*" + #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "const char8_t*" #endif TOML_SA_LIST_END @@ -2949,19 +2948,21 @@ TOML_NAMESPACE_START TOML_SA_LIST_SEP "std::wstring" #endif TOML_SA_LIST_SEP "any signed integer type >= 64 bits" - TOML_SA_LIST_SEP "any floating-point type >= 64 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 64 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type" TOML_SA_LIST_BEG "any other integer type" - TOML_SA_LIST_SEP "any floating-point type >= 32 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 32 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "An immutable view type not requiring additional temporary storage" TOML_SA_LIST_BEG "std::string_view" - TOML_SA_LIST_SEP "const char*" #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "std::u8string_view" + #endif + TOML_SA_LIST_SEP "const char*" + #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "const char8_t*" #endif TOML_SA_LIST_END @@ -3116,33 +3117,28 @@ TOML_NAMESPACE_START TOML_SA_LIST_SEP "std::wstring" #endif TOML_SA_LIST_SEP "any signed integer type >= 64 bits" - TOML_SA_LIST_SEP "any floating-point type >= 64 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 64 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type" TOML_SA_LIST_BEG "any other integer type" - TOML_SA_LIST_SEP "any floating-point type >= 32 bits of precision" + TOML_SA_LIST_SEP "any floating-point type >= 32 bits" TOML_SA_LIST_END TOML_SA_LIST_NXT "A compatible view type" TOML_SA_LIST_BEG "std::string_view" - TOML_SA_LIST_SEP "const char*" - TOML_SA_LIST_SEP "const char[]" TOML_SA_LIST_CAP(" (returned as const char*)") - TOML_SA_LIST_SEP "char*" TOML_SA_LIST_CAP(" (returned as const char*)") - TOML_SA_LIST_SEP "char[]" TOML_SA_LIST_CAP(" (returned as const char*)") #ifdef __cpp_lib_char8_t TOML_SA_LIST_SEP "std::u8string_view" - TOML_SA_LIST_SEP "const char8_t*" - TOML_SA_LIST_SEP "const char8_t[]" TOML_SA_LIST_CAP(" (returned as const char8_t*)") - TOML_SA_LIST_SEP "char8_t*" TOML_SA_LIST_CAP(" (returned as const char8_t*)") - TOML_SA_LIST_SEP "char8_t[]" TOML_SA_LIST_CAP(" (returned as const char8_t*)") #endif #if TOML_WINDOWS_COMPAT - TOML_SA_LIST_SEP "std::wstring_view" TOML_SA_LIST_CAP(" (returned as std::wstring)") - TOML_SA_LIST_SEP "const wchar_t*" TOML_SA_LIST_CAP(" (returned as std::wstring)") - TOML_SA_LIST_SEP "const wchar_t[]" TOML_SA_LIST_CAP(" (returned as std::wstring)") - TOML_SA_LIST_SEP "wchar_t*" TOML_SA_LIST_CAP(" (returned as std::wstring)") - TOML_SA_LIST_SEP "wchar_t[]" TOML_SA_LIST_CAP(" (returned as std::wstring)") + TOML_SA_LIST_SEP "std::wstring_view" + #endif + TOML_SA_LIST_SEP "const char*" + #ifdef __cpp_lib_char8_t + TOML_SA_LIST_SEP "const char8_t*" + #endif + #if TOML_WINDOWS_COMPAT + TOML_SA_LIST_SEP "const wchar_t*" #endif TOML_SA_LIST_END ); @@ -5568,6 +5564,8 @@ TOML_IMPL_NAMESPACE_START return codepoint >= 0xD800u && codepoint <= 0xDFFF; } + // utf8_decoder based on this: https://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // Copyright (c) 2008-2009 Bjoern Hoehrmann struct utf8_decoder final { uint_least32_t state{}; @@ -11579,7 +11577,6 @@ TOML_NAMESPACE_END #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 diff --git a/vs/toml++.vcxproj b/vs/toml++.vcxproj index bef1340..7d38a37 100644 --- a/vs/toml++.vcxproj +++ b/vs/toml++.vcxproj @@ -66,12 +66,14 @@ + + @@ -85,5 +87,8 @@ + + + \ No newline at end of file diff --git a/vs/toml++.vcxproj.filters b/vs/toml++.vcxproj.filters index 39cb500..6249edc 100644 --- a/vs/toml++.vcxproj.filters +++ b/vs/toml++.vcxproj.filters @@ -121,6 +121,8 @@ python + + @@ -136,4 +138,7 @@ + + + \ No newline at end of file