added iterators for tables and arrays

also:
- fixed parsing table headers allowing invalid characters
- fixed implicit fallthrough warnings
- fixed some issues parsing dates and times
- added `table::erase`
- added `array::operator[]`
- added `value::operator*`
- added stream operators for date, time and date_time
- added `impl::print_to_stream`
- added more parsing diagnostics
- added many tests
This commit is contained in:
Mark Gillard
2020-01-07 17:52:50 +02:00
parent 40ffee43fb
commit 537eb30080
25 changed files with 4037 additions and 2963 deletions

View File

@@ -8,27 +8,27 @@ TEST_CASE("lifetime - tables")
S(R"(test = { val1 = "foo" })"sv),
[&](table&& tbl) noexcept
{
CHECK(tbl.region().begin == source_position{ 1, 1 });
CHECK(tbl.region().end == source_position{ 1, 25 });
CHECK(tbl.region().path);
CHECK(*tbl.region().path == filename);
CHECK(tbl.source().begin == source_position{ 1, 1 });
CHECK(tbl.source().end == source_position{ 1, 25 });
CHECK(tbl.source().path);
CHECK(*tbl.source().path == filename);
CHECK(tbl.size() == 1_sz);
REQUIRE(tbl[S("test")].as<table>());
CHECK(tbl[S("test")].as<table>()->size() == 1_sz);
CHECK(tbl[S("test")][S("val1")] == S("foo"sv));
table test_table;
CHECK(test_table.region().begin == source_position{});
CHECK(test_table.region().end == source_position{});
CHECK(!test_table.region().path);
CHECK(test_table.source().begin == source_position{});
CHECK(test_table.source().end == source_position{});
CHECK(!test_table.source().path);
CHECK(test_table.size() == 0_sz);
CHECK(!test_table[S("test")].as<table>());
test_table = std::move(tbl);
CHECK(test_table.region().begin == source_position{ 1, 1 });
CHECK(test_table.region().end == source_position{ 1, 25 });
CHECK(test_table.region().path);
CHECK(*test_table.region().path == filename);
CHECK(test_table.source().begin == source_position{ 1, 1 });
CHECK(test_table.source().end == source_position{ 1, 25 });
CHECK(test_table.source().path);
CHECK(*test_table.source().path == filename);
CHECK(test_table.size() == 1_sz);
REQUIRE(test_table[S("test")].as<table>());
CHECK(test_table[S("test")].as<table>()->size() == 1_sz);

View File

@@ -1,7 +1,7 @@
#include "tests.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_FIELD_INIT_WARNING
TOML_DISABLE_INIT_WARNINGS
TEST_CASE("parsing dates and times")
{
@@ -20,9 +20,9 @@ lt2 = 00:32:00.999999
{
static constexpr auto odt1 = date_time{ { 1979, 5, 27 }, { 7, 32 }, time_offset{} };
CHECK(tbl[S("odt1")] == odt1);
static constexpr auto odt2 = date_time{ { 1979, 5, 27 }, { 0, 32 }, time_offset{ -7 } };
static constexpr auto odt2 = date_time{ { 1979, 5, 27 }, { 0, 32 }, time_offset::from_hh_mm(-7, 0) };
CHECK(tbl[S("odt2")] == odt2);
static constexpr auto odt3 = date_time{ { 1979, 5, 27 }, { 0, 32, 0, 999999000u }, time_offset{ -7 } };
static constexpr auto odt3 = date_time{ { 1979, 5, 27 }, { 0, 32, 0, 999999000u }, time_offset::from_hh_mm(-7, 0) };
CHECK(tbl[S("odt3")] == odt3);
static constexpr auto odt4 = date_time{ { 1979, 5, 27 }, { 7, 32 }, time_offset{} };
CHECK(tbl[S("odt4")] == odt4);
@@ -38,6 +38,91 @@ lt2 = 00:32:00.999999
CHECK(tbl[S("lt2")] == lt2);
}
);
//value tests
parse_expected_value( "1987-03-16"sv, date{ 1987, 3, 16 } );
parse_expected_value( "10:20:30"sv, toml::time{ 10, 20, 30 } );
parse_expected_value( "10:20:30.04"sv, toml::time{ 10, 20, 30, 40000000 } );
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20, 30 } };
parse_expected_value("1987-03-16T10:20:30"sv, val);
parse_expected_value("1987-03-16 10:20:30"sv, val);
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20, 30 }, time_offset::from_hh_mm( -9, -30 ) };
parse_expected_value("1987-03-16T10:20:30-09:30"sv, val);
parse_expected_value("1987-03-16 10:20:30-09:30"sv, val);
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20, 30 }, time_offset::from_hh_mm( 9, 30 ) };
parse_expected_value("1987-03-16T10:20:30+09:30"sv, val);
parse_expected_value("1987-03-16 10:20:30+09:30"sv, val);
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20, 30, 40000000 } };
parse_expected_value("1987-03-16T10:20:30.04"sv, val);
parse_expected_value("1987-03-16 10:20:30.04"sv, val);
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20, 30, 40000000 }, time_offset::from_hh_mm( -9, -30 ) };
parse_expected_value("1987-03-16T10:20:30.04-09:30"sv, val);
parse_expected_value("1987-03-16 10:20:30.04-09:30"sv, val);
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20, 30, 40000000 }, time_offset::from_hh_mm( 9, 30 ) };
parse_expected_value("1987-03-16T10:20:30.04+09:30"sv, val);
parse_expected_value("1987-03-16 10:20:30.04+09:30"sv, val);
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20, 30 }, time_offset{} };
parse_expected_value("1987-03-16T10:20:30Z"sv, val);
parse_expected_value("1987-03-16 10:20:30Z"sv, val);
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20, 30, 40000000 }, time_offset{} };
parse_expected_value("1987-03-16T10:20:30.04Z"sv, val);
parse_expected_value("1987-03-16 10:20:30.04Z"sv, val);
}
// toml/issues/671 - omitting seconds
#if TOML_LANG_HIGHER_THAN(0, 5, 0)
parse_expected_value( "10:20"sv, toml::time{ 10, 20 } );
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20 } };
parse_expected_value("1987-03-16T10:20"sv, val );
parse_expected_value("1987-03-16 10:20"sv, val );
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20 }, time_offset::from_hh_mm( -9, -30 ) };
parse_expected_value("1987-03-16T10:20-09:30"sv, val);
parse_expected_value("1987-03-16 10:20-09:30"sv, val);
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20 }, time_offset::from_hh_mm( 9, 30 ) };
parse_expected_value("1987-03-16T10:20+09:30"sv, val);
parse_expected_value("1987-03-16 10:20+09:30"sv, val);
}
{
const auto val = date_time{ { 1987, 3, 16 }, { 10, 20 }, time_offset{} };
parse_expected_value("1987-03-16T10:20Z"sv, val);
parse_expected_value("1987-03-16 10:20Z"sv, val);
}
#else
parsing_should_fail("10:20"sv);
parsing_should_fail("1987-03-16T10:20"sv);
parsing_should_fail("1987-03-16 10:20"sv);
parsing_should_fail("1987-03-16T10:20-09:30"sv);
parsing_should_fail("1987-03-16 10:20-09:30"sv);
parsing_should_fail("1987-03-16T10:20+09:30"sv);
parsing_should_fail("1987-03-16 10:20+09:30"sv);
parsing_should_fail("1987-03-16T10:20Z"sv);
parsing_should_fail("1987-03-16 10:20Z"sv);
#endif
}
TOML_POP_WARNINGS

View File

@@ -47,43 +47,60 @@ flt8 = 224_617.445_991_228
);
//value tests
parse_expected_value( "1e1"sv, 1e1 );
parse_expected_value( "1e-1"sv, 1e-1 );
parse_expected_value( "1e+1"sv, 1e+1 );
parse_expected_value( "1.0"sv, 1.0 );
parse_expected_value( "0.1"sv, 0.1 );
parse_expected_value( "0.001"sv, 0.001 );
parse_expected_value( "0.100"sv, 0.1 );
parse_expected_value( "+3.14"sv, 3.14 );
parse_expected_value( "-3.14"sv, -3.14 );
parse_expected_value( "3.1415_9265_3589"sv, 3.141592653589 );
parse_expected_value( "+3.1415_9265_3589"sv, 3.141592653589 );
parse_expected_value( "-3.1415_9265_3589"sv, -3.141592653589 );
parse_expected_value( "123_456.789"sv, 123456.789 );
parse_expected_value( "+123_456.789"sv, 123456.789 );
parse_expected_value( "-123_456.789"sv, -123456.789 );
parse_expected_value( "+0.0"sv, 0.0 );
parse_expected_value( "-0.0"sv, -0.0 );
parse_expected_value( "1e10"sv, 1e10 );
parse_expected_value( "1e+10"sv, 1e10 );
parse_expected_value( "1e-10"sv, 1e-10 );
parse_expected_value( "+1e10"sv, 1e10 );
parse_expected_value( "+1e+10"sv, 1e10 );
parse_expected_value( "+1e-10"sv, 1e-10 );
parse_expected_value( "-1e10"sv, -1e10 );
parse_expected_value( "-1e+10"sv, -1e10 );
parse_expected_value( "-1e-10"sv, -1e-10 );
parse_expected_value( "123e-10"sv, 123e-10 );
parse_expected_value( "1E10"sv, 1e10 );
parse_expected_value( "1E+10"sv, 1e10 );
parse_expected_value( "1E-10"sv, 1e-10 );
parse_expected_value( "123E-10"sv, 123e-10 );
parse_expected_value( "1_2_3E-10"sv, 123e-10 );
parse_expected_value( "1_2_3E-1_0"sv, 123e-10 );
parse_expected_value( "+0e0"sv, 0.0 );
parse_expected_value( "-0e0"sv, -0.0 );
parse_expected_value( "1_2_3E-01"sv, 123e-1 );
parse_expected_value( "1_2_3E-0_1"sv, 123e-1 );
parse_expected_value( "6.02e23"sv, 6.02e23 );
parse_expected_value( "6.02e+23"sv, 6.02e23 );
parse_expected_value( "1.112_650_06e-17"sv, 1.11265006e-17 );
parse_expected_value( "1.0e1"sv, 1.0e1 );
parse_expected_value( "1.0e-1"sv, 1.0e-1 );
parse_expected_value( "1.0e+1"sv, 1.0e+1 );
parse_expected_value( "+1e1"sv, +1e1 );
parse_expected_value( "+1.0"sv, +1.0 );
parse_expected_value( "+1.0e1"sv, +1.0e1 );
parse_expected_value( "+1.0e+1"sv, +1.0e+1 );
parse_expected_value( "+1.0e-1"sv, +1.0e-1 );
parse_expected_value( "-1.0e+1"sv, -1.0e+1 );
parse_expected_value( "-1e1"sv, -1e1 );
parse_expected_value( "-1.0"sv, -1.0 );
parse_expected_value( "-1.0e1"sv, -1.0e1 );
parse_expected_value( "-1.0e-1"sv, -1.0e-1 );
parse_expected_value( "1.0"sv, 1.0 );
parse_expected_value( "0.1"sv, 0.1 );
parse_expected_value( "0.001"sv, 0.001 );
parse_expected_value( "0.100"sv, 0.100 );
parse_expected_value( "+3.14"sv, +3.14 );
parse_expected_value( "-3.14"sv, -3.14 );
parse_expected_value( "3.1415_9265_3589"sv, 3.141592653589 );
parse_expected_value( "+3.1415_9265_3589"sv, +3.141592653589 );
parse_expected_value( "-3.1415_9265_3589"sv, -3.141592653589 );
parse_expected_value( "123_456.789"sv, 123456.789 );
parse_expected_value( "+123_456.789"sv, +123456.789 );
parse_expected_value( "-123_456.789"sv, -123456.789 );
parse_expected_value( "+0.0"sv, +0.0 );
parse_expected_value( "-0.0"sv, -0.0 );
parse_expected_value( "1e10"sv, 1e10 );
parse_expected_value( "1e+10"sv, 1e+10 );
parse_expected_value( "1e-10"sv, 1e-10 );
parse_expected_value( "+1e10"sv, +1e10 );
parse_expected_value( "+1e+10"sv, +1e+10 );
parse_expected_value( "+1e-10"sv, +1e-10 );
parse_expected_value( "-1e10"sv, -1e10 );
parse_expected_value( "-1e+10"sv, -1e+10 );
parse_expected_value( "-1e-10"sv, -1e-10 );
parse_expected_value( "123e-10"sv, 123e-10 );
parse_expected_value( "1E10"sv, 1E10 );
parse_expected_value( "1E+10"sv, 1E+10 );
parse_expected_value( "1E-10"sv, 1E-10 );
parse_expected_value( "123E-10"sv, 123E-10 );
parse_expected_value( "1_2_3E-10"sv, 123E-10 );
parse_expected_value( "1_2_3E-1_0"sv, 123E-10 );
parse_expected_value( "+0e0"sv, +0e0 );
parse_expected_value( "-0e0"sv, -0e0 );
parse_expected_value( "1_2_3E-01"sv, 123E-01 );
parse_expected_value( "1_2_3E-0_1"sv, 123E-01 );
parse_expected_value( "6.02e23"sv, 6.02e23 );
parse_expected_value( "6.02e+23"sv, 6.02e+23 );
parse_expected_value( "1.112_650_06e-17"sv, 1.11265006e-17 );
//toml/issues/562 - hexfloat literals
#if TOML_LANG_HIGHER_THAN(0, 5, 0) && !TOML_USE_STREAMS_FOR_FLOATS

View File

@@ -1,7 +1,7 @@
#include "tests.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_FIELD_INIT_WARNING
TOML_DISABLE_INIT_WARNINGS
TEST_CASE("parsing TOML spec example")
{
@@ -49,7 +49,7 @@ hosts = [
CHECK(tbl[S("owner")]);
CHECK(tbl[S("owner")].as<table>());
CHECK(tbl[S("owner")][S("name")] == S("Tom Preston-Werner"sv));
const auto dob = date_time{ { 1979, 5, 27 }, { 7, 32 }, time_offset{ -8 } };
const auto dob = date_time{ { 1979, 5, 27 }, { 7, 32 }, time_offset::from_hh_mm(-8, 0) };
CHECK(tbl[S("owner")][S("dob")] == dob);
CHECK(tbl[S("database")].as<table>());

View File

@@ -16,14 +16,14 @@ void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func,
{
constexpr auto validate_table = [](table&& tabl, std::string_view path) noexcept -> table&&
{
CHECK(tabl.region().begin != source_position{});
CHECK(tabl.region().end != source_position{});
CHECK(tabl.source().begin != source_position{});
CHECK(tabl.source().end != source_position{});
if (path.empty())
CHECK(tabl.region().path == nullptr);
CHECK(tabl.source().path == nullptr);
else
{
REQUIRE(tabl.region().path != nullptr);
CHECK(*tabl.region().path == path);
REQUIRE(tabl.source().path != nullptr);
CHECK(*tabl.source().path == path);
}
return std::move(tabl);
@@ -58,9 +58,9 @@ void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func,
else
{
FAIL(
"Parse error on line "sv << result.error().where.begin.line
<< ", column "sv << result.error().where.begin.column
<< ":\n"sv << result.error().what
"Parse error on line "sv << result.error().where().begin.line
<< ", column "sv << result.error().where().begin.column
<< ":\n"sv << result.error().what()
);
return;
}
@@ -75,9 +75,9 @@ void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func,
else
{
FAIL(
"Parse error on line "sv << result.error().where.begin.line
<< ", column "sv << result.error().where.begin.column
<< ":\n"sv << result.error().what
"Parse error on line "sv << result.error().where().begin.line
<< ", column "sv << result.error().where().begin.column
<< ":\n"sv << result.error().what()
);
return;
}
@@ -160,13 +160,13 @@ void parse_expected_value(std::string_view value_str, const T& expected) noexcep
static constexpr auto is_val = [](char32_t codepoint) noexcept
{
if constexpr (std::is_same_v<string, value_of<T>>)
if constexpr (std::is_same_v<string, promoted<T>>)
return codepoint == U'"' || codepoint == U'\'';
else
return !impl::is_whitespace(codepoint);
};
source_position pos{ 1, static_cast<uint32_t>(value_key.length()) };
source_position pos{ 1, static_cast<source_index>(value_key.length()) };
source_position begin{}, end{};
impl::utf8_decoder decoder;
for (auto c : value_str)
@@ -180,7 +180,7 @@ void parse_expected_value(std::string_view value_str, const T& expected) noexcep
if (decoder.codepoint != U'\r')
{
pos.line++;
pos.column = 1u;
pos.column = source_index{ 1 };
}
continue;
}
@@ -201,9 +201,9 @@ void parse_expected_value(std::string_view value_str, const T& expected) noexcep
parsing_should_succeed(std::string_view{ value }, [&](table&& tbl) noexcept
{
CHECK(tbl.size() == 1);
REQUIRE(tbl[S("val"sv)].as<value_of<T>>());
CHECK(tbl[S("val"sv)].as<value_of<T>>()->get() == expected);
CHECK(tbl[S("val"sv)].get()->region().begin == begin);
CHECK(tbl[S("val"sv)].get()->region().end == end);
REQUIRE(tbl[S("val"sv)].as<promoted<T>>());
CHECK(tbl[S("val"sv)].as<promoted<T>>()->get() == expected);
CHECK(tbl[S("val"sv)].get()->source().begin == begin);
CHECK(tbl[S("val"sv)].get()->source().end == end);
});
}