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
This commit is contained in:
Mark Gillard 2020-08-02 12:20:41 +03:00
parent 6f7f6c6554
commit b024ee6dc2
14 changed files with 588 additions and 223 deletions

View File

@ -1,7 +1,6 @@
MIT License
Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de> (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

View File

@ -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

View File

@ -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!"

View File

@ -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

View File

@ -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 <bjoern@hoehrmann.de>
struct utf8_decoder final
{
uint_least32_t state{};

View File

@ -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
);

View File

@ -17,20 +17,20 @@ TEST_CASE("arrays - moving")
// sanity-check initial state of a freshly-parsed array
auto arr1 = tbl["test"].as<array>();
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<std::string>(0_sz));
CHECK(*arr1->get_as<std::string>(0_sz) == "foo"sv);
REQUIRE(arr1->get_as<std::string>(0u));
CHECK(*arr1->get_as<std::string>(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<std::string>(0_sz));
CHECK(*arr2.get_as<std::string>(0_sz) == "foo"sv);
CHECK(arr2.size() == 1u);
REQUIRE(arr2.get_as<std::string>(0u));
CHECK(*arr2.get_as<std::string>(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<std::string>(0_sz));
CHECK(*arr3.get_as<std::string>(0_sz) == "foo"sv);
CHECK(arr3.size() == 1u);
REQUIRE(arr3.get_as<std::string>(0u));
CHECK(*arr3.get_as<std::string>(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<array>();
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<std::string>(0_sz));
CHECK(*arr1->get_as<std::string>(0_sz) == "foo"sv);
REQUIRE(arr1->get_as<std::string>(0u));
CHECK(*arr1->get_as<std::string>(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<std::string>(0_sz));
CHECK(*arr2.get_as<std::string>(0_sz) == "foo"sv);
CHECK(arr2.size() == 1u);
REQUIRE(arr2.get_as<std::string>(0u));
CHECK(*arr2.get_as<std::string>(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<std::string>(0_sz));
CHECK(*arr3.get_as<std::string>(0_sz) == "foo"sv);
CHECK(arr3.size() == 1u);
REQUIRE(arr3.get_as<std::string>(0u));
CHECK(*arr3.get_as<std::string>(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<int64_t>(0_sz));
CHECK(*arr.get_as<int64_t>(0_sz) == 42);
REQUIRE(arr.get_as<int64_t>(0u));
CHECK(*arr.get_as<int64_t>(0u) == 42);
CHECK(arr.is_homogeneous());
CHECK(arr.is_homogeneous<int64_t>());
CHECK(!arr.is_homogeneous<double>());
@ -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<int64_t>(0_sz));
CHECK(*arr.get_as<int64_t>(0_sz) == 42);
REQUIRE(arr.get_as<std::string>(1_sz));
CHECK(*arr.get_as<std::string>(1_sz) == "test"sv);
REQUIRE(arr.get_as<double>(2_sz));
CHECK(*arr.get_as<double>(2_sz) == 10.0);
REQUIRE(arr.get_as<array>(3_sz));
REQUIRE(arr.get_as<int64_t>(4_sz));
CHECK(*arr.get_as<int64_t>(4_sz) == 3);
REQUIRE(arr.get_as<int64_t>(0u));
CHECK(*arr.get_as<int64_t>(0u) == 42);
REQUIRE(arr.get_as<std::string>(1u));
CHECK(*arr.get_as<std::string>(1u) == "test"sv);
REQUIRE(arr.get_as<double>(2u));
CHECK(*arr.get_as<double>(2u) == 10.0);
REQUIRE(arr.get_as<array>(3u));
REQUIRE(arr.get_as<int64_t>(4u));
CHECK(*arr.get_as<int64_t>(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<std::string>());
CHECK(*arr.get_as<std::string>(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<int64_t>(0_sz));
CHECK(*arr.get_as<int64_t>(0_sz) == 42);
REQUIRE(arr.get_as<int64_t>(0u));
CHECK(*arr.get_as<int64_t>(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<double>(1_sz));
CHECK(*arr.get_as<double>(1_sz) == 10.0);
REQUIRE(arr.get_as<double>(2_sz));
CHECK(*arr.get_as<double>(2_sz) == 10.0);
REQUIRE(arr.get_as<double>(3_sz));
CHECK(*arr.get_as<double>(3_sz) == 10.0);
CHECK(arr.size() == 4u);
REQUIRE(arr.get_as<double>(1u));
CHECK(*arr.get_as<double>(1u) == 10.0);
REQUIRE(arr.get_as<double>(2u));
CHECK(*arr.get_as<double>(2u) == 10.0);
REQUIRE(arr.get_as<double>(3u));
CHECK(*arr.get_as<double>(3u) == 10.0);
REQUIRE(arr == array{ 42, 10.0, 10.0, 10.0 });
// emplace(const_iterator pos, Args &&... args) noexcept
it = arr.emplace<array>(arr.cbegin(), 1, 2, 3);
CHECK(it == arr.begin());
CHECK(arr.size() == 5_sz);
REQUIRE(arr.get_as<array>(0_sz));
CHECK(arr.get_as<array>(0_sz)->size() == 3_sz);
CHECK(arr.size() == 5u);
REQUIRE(arr.get_as<array>(0u));
CHECK(arr.get_as<array>(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<std::string>(5_sz));
CHECK(*arr.get_as<std::string>(5_sz) == "test"sv);
CHECK(arr.size() == 6u);
REQUIRE(arr.get_as<std::string>(5u));
CHECK(*arr.get_as<std::string>(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<std::string>("test2"sv);
CHECK(arr.size() == 7_sz);
REQUIRE(arr.get_as<std::string>(6_sz));
CHECK(*arr.get_as<std::string>(6_sz) == "test2"sv);
CHECK(arr.size() == 7u);
REQUIRE(arr.get_as<std::string>(6u));
CHECK(*arr.get_as<std::string>(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<double>(0_sz));
CHECK(*arr.get_as<double>(0_sz) == 1.0);
REQUIRE(arr.get_as<double>(1_sz));
CHECK(*arr.get_as<double>(1_sz) == 2.0);
REQUIRE(arr.get_as<double>(2_sz));
CHECK(*arr.get_as<double>(2_sz) == 3.0);
CHECK(arr.size() == 3u);
REQUIRE(arr.get_as<double>(0u));
CHECK(*arr.get_as<double>(0u) == 1.0);
REQUIRE(arr.get_as<double>(1u));
CHECK(*arr.get_as<double>(1u) == 2.0);
REQUIRE(arr.get_as<double>(2u));
CHECK(*arr.get_as<double>(2u) == 3.0);
arr.insert(arr.cbegin() + 1, vals.begin(), vals.end());
CHECK(arr.size() == 6_sz);
REQUIRE(arr.get_as<double>(0_sz));
CHECK(*arr.get_as<double>(0_sz) == 1.0);
REQUIRE(arr.get_as<double>(1_sz));
CHECK(*arr.get_as<double>(1_sz) == 1.0);
REQUIRE(arr.get_as<double>(2_sz));
CHECK(*arr.get_as<double>(2_sz) == 2.0);
REQUIRE(arr.get_as<double>(3_sz));
CHECK(*arr.get_as<double>(3_sz) == 3.0);
REQUIRE(arr.get_as<double>(4_sz));
CHECK(*arr.get_as<double>(4_sz) == 2.0);
REQUIRE(arr.get_as<double>(5_sz));
CHECK(*arr.get_as<double>(5_sz) == 3.0);
CHECK(arr.size() == 6u);
REQUIRE(arr.get_as<double>(0u));
CHECK(*arr.get_as<double>(0u) == 1.0);
REQUIRE(arr.get_as<double>(1u));
CHECK(*arr.get_as<double>(1u) == 1.0);
REQUIRE(arr.get_as<double>(2u));
CHECK(*arr.get_as<double>(2u) == 2.0);
REQUIRE(arr.get_as<double>(3u));
CHECK(*arr.get_as<double>(3u) == 3.0);
REQUIRE(arr.get_as<double>(4u));
CHECK(*arr.get_as<double>(4u) == 2.0);
REQUIRE(arr.get_as<double>(5u));
CHECK(*arr.get_as<double>(5u) == 3.0);
}
// insert(const_iterator pos, Iter first, Iter last) (with move iterators)
{
arr.clear();
std::vector<std::string> 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<std::string>(0));
CHECK(*arr.get_as<std::string>(0) == "foo");
REQUIRE(arr.get_as<std::string>(1));
CHECK(*arr.get_as<std::string>(1) == "bar");
REQUIRE(arr.get_as<std::string>(2));
CHECK(*arr.get_as<std::string>(2) == "kek");
REQUIRE(vals.size() == 3u);
CHECK(vals[0] == "");
CHECK(vals[1] == "");
CHECK(vals[2] == "");
}
// iterator insert(const_iterator pos, std::initializer_list<ElemType> 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<double>(0_sz));
CHECK(*arr.get_as<double>(0_sz) == 1.0);
REQUIRE(arr.get_as<double>(1_sz));
CHECK(*arr.get_as<double>(1_sz) == 2.0);
REQUIRE(arr.get_as<double>(2_sz));
CHECK(*arr.get_as<double>(2_sz) == 3.0);
CHECK(arr.size() == 3u);
REQUIRE(arr.get_as<double>(0u));
CHECK(*arr.get_as<double>(0u) == 1.0);
REQUIRE(arr.get_as<double>(1u));
CHECK(*arr.get_as<double>(1u) == 2.0);
REQUIRE(arr.get_as<double>(2u));
CHECK(*arr.get_as<double>(2u) == 3.0);
arr.insert(arr.cbegin() + 1, { 1.0, 2.0, 3.0 });
CHECK(arr.size() == 6_sz);
REQUIRE(arr.get_as<double>(0_sz));
CHECK(*arr.get_as<double>(0_sz) == 1.0);
REQUIRE(arr.get_as<double>(1_sz));
CHECK(*arr.get_as<double>(1_sz) == 1.0);
REQUIRE(arr.get_as<double>(2_sz));
CHECK(*arr.get_as<double>(2_sz) == 2.0);
REQUIRE(arr.get_as<double>(3_sz));
CHECK(*arr.get_as<double>(3_sz) == 3.0);
REQUIRE(arr.get_as<double>(4_sz));
CHECK(*arr.get_as<double>(4_sz) == 2.0);
REQUIRE(arr.get_as<double>(5_sz));
CHECK(*arr.get_as<double>(5_sz) == 3.0);
CHECK(arr.size() == 6u);
REQUIRE(arr.get_as<double>(0u));
CHECK(*arr.get_as<double>(0u) == 1.0);
REQUIRE(arr.get_as<double>(1u));
CHECK(*arr.get_as<double>(1u) == 1.0);
REQUIRE(arr.get_as<double>(2u));
CHECK(*arr.get_as<double>(2u) == 2.0);
REQUIRE(arr.get_as<double>(3u));
CHECK(*arr.get_as<double>(3u) == 3.0);
REQUIRE(arr.get_as<double>(4u));
CHECK(*arr.get_as<double>(4u) == 2.0);
REQUIRE(arr.get_as<double>(5u));
CHECK(*arr.get_as<double>(5u) == 3.0);
}
#if TOML_WINDOWS_COMPAT
arr.clear();
it = arr.insert(arr.cbegin(), L"test");
REQUIRE(*arr.get_as<std::string>(0_sz) == "test"sv);
REQUIRE(*arr.get_as<std::string>(0u) == "test"sv);
it = arr.emplace<std::string>(arr.cbegin(), L"test2"sv);
REQUIRE(*arr.get_as<std::string>(0_sz) == "test2"sv);
REQUIRE(*arr.get_as<std::string>(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 });
}

View File

@ -16,7 +16,7 @@ TEST_CASE("tables - moving")
{
// sanity-check initial state of a freshly-parsed table
REQUIRE(tbl["test"].as<table>());
CHECK(tbl["test"].as<table>()->size() == 1_sz);
CHECK(tbl["test"].as<table>()->size() == 1u);
CHECK(tbl["test"].as<table>()->source().begin == source_position{ 1, 8 });
CHECK(tbl["test"].as<table>()->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<table>());
CHECK(tbl2["test"].as<table>()->size() == 1_sz);
CHECK(tbl2["test"].as<table>()->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<table>());
// 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<table>());
CHECK(tbl3["test"].as<table>()->size() == 1_sz);
CHECK(tbl3["test"].as<table>()->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<table>());
},
filename
@ -79,7 +79,7 @@ TEST_CASE("tables - copying")
{
// sanity-check initial state of a freshly-parsed table
REQUIRE(tbl["test"].as<table>());
CHECK(tbl["test"].as<table>()->size() == 1_sz);
CHECK(tbl["test"].as<table>()->size() == 1u);
CHECK(tbl["test"].as<table>()->source().begin == source_position{ 1, 8 });
CHECK(tbl["test"].as<table>()->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<table>());
CHECK(tbl2["test"].as<table>()->size() == 1_sz);
CHECK(tbl2["test"].as<table>()->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<table>());
CHECK(tbl3["test"].as<table>()->size() == 1_sz);
CHECK(tbl3["test"].as<table>()->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<int64_t>("foo"sv));
CHECK(*tbl.get_as<int64_t>("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<std::string>("foo"sv));
CHECK(*tbl.get_as<std::string>("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<int64_t>("a"sv));
CHECK(*tbl.get_as<int64_t>("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<int64_t>("a"));
CHECK(*tbl.get_as<int64_t>("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<int64_t>("a"));
CHECK(*tbl.get_as<int64_t>("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<std::string>("b"));
CHECK(*tbl.get_as<std::string>("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<array>("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<array>("c"));
CHECK(*tbl.get_as<array>("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<int64_t>("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<int64_t>("c"));
REQUIRE(tbl.get_as<array>("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<int64_t>("a"));
CHECK(*tbl.get_as<int64_t>("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<std::pair<std::string, std::string>> vals{
{ "foo", "foo" },
{ "bar", "bar" },
{ "kek", "kek" }
};
tbl.insert(vals.begin(), vals.end());
CHECK(tbl.size() == 3u);
REQUIRE(tbl.get_as<std::string>("foo"));
CHECK(*tbl.get_as<std::string>("foo") == "foo");
REQUIRE(tbl.get_as<std::string>("bar"));
CHECK(*tbl.get_as<std::string>("bar") == "bar");
REQUIRE(tbl.get_as<std::string>("kek"));
CHECK(*tbl.get_as<std::string>("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<std::pair<std::string, std::string>> 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<std::string>("foo"));
CHECK(*tbl.get_as<std::string>("foo") == "foo");
REQUIRE(tbl.get_as<std::string>("bar"));
CHECK(*tbl.get_as<std::string>("bar") == "bar");
REQUIRE(tbl.get_as<std::string>("kek"));
CHECK(*tbl.get_as<std::string>("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<std::string>(L"a"sv) == "test2"sv);
tbl.emplace<std::string>(L"b", L"test3");
REQUIRE(*tbl.get_as<std::string>(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
}

View File

@ -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<type>() == static_cast<type>(v))
#define CHECK_VALUE_FAIL(type) \
CHECK(!n.value<type>())
// 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<int64_t>::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<int64_t>::max)());
CHECK_VALUE_PASS(uint64_t, (std::numeric_limits<int64_t>::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<int64_t>::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<int64_t>::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);
}
}

View File

@ -46,23 +46,23 @@ smooth = true
[](table&& tbl)
{
REQUIRE(tbl["table"].as<table>());
CHECK(tbl["table"].as<table>()->size() == 0_sz);
CHECK(tbl["table"].as<table>()->size() == 0u);
REQUIRE(tbl["table-1"].as<table>());
CHECK(tbl["table-1"].as<table>()->size() == 2_sz);
CHECK(tbl["table-1"].as<table>()->size() == 2u);
CHECK(tbl["table-1"]["key1"] == "some string"sv);
CHECK(tbl["table-1"]["key2"] == 123);
REQUIRE(tbl["table-2"].as<table>());
CHECK(tbl["table-2"].as<table>()->size() == 2_sz);
CHECK(tbl["table-2"].as<table>()->size() == 2u);
CHECK(tbl["table-2"]["key1"] == "another string"sv);
CHECK(tbl["table-2"]["key2"] == 456);
REQUIRE(tbl["dog"].as<table>());
CHECK(tbl["dog"].as<table>()->size() == 1_sz);
CHECK(tbl["dog"].as<table>()->size() == 1u);
REQUIRE(tbl["dog"]["tater.man"].as<table>());
CHECK(tbl["dog"]["tater.man"].as<table>()->size() == 1_sz);
CHECK(tbl["dog"]["tater.man"].as<table>()->size() == 1u);
CHECK(tbl["dog"]["tater.man"]["type"]["name"] == "pug"sv);
CHECK(tbl["a"].as<table>());
@ -136,10 +136,10 @@ apple.taste.sweet = true
[](table&& tbl)
{
REQUIRE(tbl["animal"].as<table>());
CHECK(tbl["animal"].as<table>()->size() == 0_sz);
CHECK(tbl["animal"].as<table>()->size() == 0u);
REQUIRE(tbl["fruit"].as<table>());
CHECK(tbl["fruit"].as<table>()->size() == 2_sz);
CHECK(tbl["fruit"].as<table>()->size() == 2u);
REQUIRE(tbl["fruit"]["apple"].as<table>());
REQUIRE(tbl["fruit"]["orange"].as<table>());
@ -158,10 +158,10 @@ apple.taste.sweet = true
[](table&& tbl)
{
REQUIRE(tbl["animal"].as<table>());
CHECK(tbl["animal"].as<table>()->size() == 0_sz);
CHECK(tbl["animal"].as<table>()->size() == 0u);
REQUIRE(tbl["fruit"].as<table>());
CHECK(tbl["fruit"].as<table>()->size() == 2_sz);
CHECK(tbl["fruit"].as<table>()->size() == 2u);
REQUIRE(tbl["fruit"]["apple"].as<table>());
REQUIRE(tbl["fruit"]["orange"].as<table>());
@ -186,25 +186,25 @@ type = { name = "Nail" }
[](table&& tbl)
{
REQUIRE(tbl["name"].as<table>());
CHECK(tbl["name"].as<table>()->size() == 2_sz);
CHECK(tbl["name"].as<table>()->size() == 2u);
CHECK(tbl["name"]["first"] == "Tom"sv);
CHECK(tbl["name"]["last"] == "Preston-Werner"sv);
REQUIRE(tbl["point"].as<table>());
CHECK(tbl["point"].as<table>()->size() == 2_sz);
CHECK(tbl["point"].as<table>()->size() == 2u);
CHECK(tbl["point"]["x"] == 1);
CHECK(tbl["point"]["y"] == 2);
REQUIRE(tbl["animal"].as<table>());
CHECK(tbl["animal"].as<table>()->size() == 1_sz);
CHECK(tbl["animal"].as<table>()->size() == 1u);
REQUIRE(tbl["animal"]["type"].as<table>());
CHECK(tbl["animal"]["type"].as<table>()->size() == 1_sz);
CHECK(tbl["animal"]["type"].as<table>()->size() == 1u);
CHECK(tbl["animal"]["type"]["name"] == "pug"sv);
REQUIRE(tbl["product"].as<table>());
CHECK(tbl["product"].as<table>()->size() == 1_sz);
CHECK(tbl["product"].as<table>()->size() == 1u);
REQUIRE(tbl["product"]["type"].as<table>());
CHECK(tbl["product"]["type"].as<table>()->size() == 1_sz);
CHECK(tbl["product"]["type"].as<table>()->size() == 1u);
CHECK(tbl["product"]["type"]["name"] == "Nail"sv);
}
);
@ -233,10 +233,10 @@ test = { val1 = "foo", val2 = [
[](table&& tbl)
{
REQUIRE(tbl["test"].as<table>());
CHECK(tbl["test"].as<table>()->size() == 3_sz);
CHECK(tbl["test"].as<table>()->size() == 3u);
CHECK(tbl["test"]["val1"] == "foo"sv);
REQUIRE(tbl["test"]["val2"].as<array>());
CHECK(tbl["test"]["val2"].as<array>()->size() == 3_sz);
CHECK(tbl["test"]["val2"].as<array>()->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<table>());
CHECK(tbl["name"].as<table>()->size() == 2_sz);
CHECK(tbl["name"].as<table>()->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<array>());
CHECK(tbl["points"].as<array>()->size() == 3_sz);
CHECK(tbl["points"].as<array>()->size() == 3u);
CHECK(tbl["points"].as<array>()->is_homogeneous());
CHECK(tbl["points"].as<array>()->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<array>());
CHECK(tbl["products"].as<array>()->size() == 3_sz);
CHECK(tbl["products"].as<array>()->size() == 3u);
CHECK(tbl["products"].as<array>()->is_homogeneous());
CHECK(tbl["products"].as<array>()->is_array_of_tables());
REQUIRE(tbl["products"][0].as<table>());
CHECK(tbl["products"][0].as<table>()->size() == 2_sz);
CHECK(tbl["products"][0].as<table>()->size() == 2u);
CHECK(tbl["products"][0]["name"] == "Hammer"sv);
CHECK(tbl["products"][0]["sku"] == 738594937);
REQUIRE(tbl["products"][1].as<table>());
CHECK(tbl["products"][1].as<table>()->size() == 0_sz);
CHECK(tbl["products"][1].as<table>()->size() == 0u);
REQUIRE(tbl["products"][2].as<table>());
CHECK(tbl["products"][2].as<table>()->size() == 3_sz);
CHECK(tbl["products"][2].as<table>()->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<array>());
CHECK(tbl["fruit"].as<array>()->size() == 2_sz);
CHECK(tbl["fruit"].as<array>()->size() == 2u);
CHECK(tbl["fruit"].as<array>()->is_homogeneous());
CHECK(tbl["fruit"].as<array>()->is_array_of_tables());
REQUIRE(tbl["fruit"][0].as<table>());
CHECK(tbl["fruit"][0].as<table>()->size() == 3_sz);
CHECK(tbl["fruit"][0].as<table>()->size() == 3u);
CHECK(tbl["fruit"][0]["name"] == "apple"sv);
REQUIRE(tbl["fruit"][0]["physical"].as<table>());
CHECK(tbl["fruit"][0]["physical"].as<table>()->size() == 2_sz);
CHECK(tbl["fruit"][0]["physical"].as<table>()->size() == 2u);
CHECK(tbl["fruit"][0]["physical"]["color"] == "red"sv);
CHECK(tbl["fruit"][0]["physical"]["shape"] == "round"sv);
REQUIRE(tbl["fruit"][0]["variety"].as<array>());
CHECK(tbl["fruit"][0]["variety"].as<array>()->size() == 2_sz);
CHECK(tbl["fruit"][0]["variety"].as<array>()->size() == 2u);
CHECK(tbl["fruit"][0]["variety"].as<array>()->is_homogeneous());
CHECK(tbl["fruit"][0]["variety"].as<array>()->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<table>());
CHECK(tbl["fruit"][1].as<table>()->size() == 2_sz);
CHECK(tbl["fruit"][1].as<table>()->size() == 2u);
CHECK(tbl["fruit"][1]["name"] == "banana"sv);
REQUIRE(tbl["fruit"][1]["variety"].as<array>());
CHECK(tbl["fruit"][1]["variety"].as<array>()->size() == 1_sz);
CHECK(tbl["fruit"][1]["variety"].as<array>()->size() == 1u);
CHECK(tbl["fruit"][1]["variety"].as<array>()->is_homogeneous());
CHECK(tbl["fruit"][1]["variety"].as<array>()->is_array_of_tables());
CHECK(tbl["fruit"][1]["variety"][0]["name"] == "plantain"sv);

View File

@ -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<int64_t>() == 10);
REQUIRE(val->value<double>() == 10.0);
}
}

View File

@ -25,7 +25,6 @@
// MIT License
//
// Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
// Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de> (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 <bjoern@hoehrmann.de>
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

View File

@ -66,12 +66,14 @@
<None Include="..\.editorconfig" />
<None Include="..\.gitattributes" />
<None Include="..\.gitignore" />
<None Include="..\CODE_OF_CONDUCT.md" />
<None Include="..\CONTRIBUTING.md" />
<None Include="..\docs\Doxyfile" />
<None Include="..\docs\Doxyfile-mcss" />
<None Include="..\docs\main_page.dox" />
<None Include="..\docs\tomlplusplus.css" />
<None Include="..\docs\tomlplusplus.js" />
<None Include="..\LICENSE" />
<None Include="..\meson.build" />
<None Include="..\python\ci_single_header_check.py" />
<None Include="..\python\generate_conformance_tests.py" />
@ -85,5 +87,8 @@
<ItemGroup>
<Natvis Include="toml++.natvis" />
</ItemGroup>
<ItemGroup>
<Text Include="..\meson_options.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@ -121,6 +121,8 @@
<None Include="..\python\generate_windows_test_targets.py">
<Filter>python</Filter>
</None>
<None Include="..\CODE_OF_CONDUCT.md" />
<None Include="..\LICENSE" />
</ItemGroup>
<ItemGroup>
<Filter Include="include">
@ -136,4 +138,7 @@
<ItemGroup>
<Natvis Include="toml++.natvis" />
</ItemGroup>
<ItemGroup>
<Text Include="..\meson_options.txt" />
</ItemGroup>
</Project>