fixed keys containing \t formatting incorrectly

This commit is contained in:
Mark Gillard 2023-10-09 19:41:18 +03:00
parent 941341fce6
commit be30d11245
6 changed files with 276 additions and 46 deletions

View File

@ -32,6 +32,7 @@ template:
- fixed `noexcept(...)` sometimes being incorrectly derived on `for_each()`
- fixed `for_each()` compilation error on GCC <= 7 (#197) (@sagi-ottopia, @damirbarr)
- fixed `FLT_RADIX` check getting broken by Intel MKL headers (#202) (@iago-lito)
- fixed keys containing `\t` incorrectly formatting as bare keys (@jasmine-zhu, @arp242)
#### Additions

View File

@ -206,6 +206,10 @@ TOML_IMPL_NAMESPACE_START
bad_unicode();
}
// strings with line breaks and tabs can't be bare
if (!!(traits & (formatted_string_traits::line_breaks | formatted_string_traits::tabs)))
traits |= formatted_string_traits::non_bare;
// if the string meets the requirements of being 'bare' we can emit a bare string
// (bare strings are composed of letters and numbers; no whitespace, control chars, quotes, etc)
if (!(traits & formatted_string_traits::non_bare)

View File

@ -105,6 +105,8 @@ d = 2006-01-01T00:60:00-00:00)"sv;
d = 2006-13-01T00:00:00-00:00)"sv;
static constexpr auto datetime_month_under = R"(# date-month = 2DIGIT ; 01-12
d = 2007-00-01T00:00:00-00:00)"sv;
static constexpr auto datetime_no_leads_month = R"(# Month "7" instead of "07"; the leading zero is required.
no-leads = 1987-7-05T17:45:00Z)"sv;
static constexpr auto datetime_no_leads_with_milli = R"(# Day "5" instead of "05"; the leading zero is required.
with-milli = 1987-07-5T17:45:00.12Z)"sv;
static constexpr auto datetime_no_leads = R"(# Month "7" instead of "07"; the leading zero is required.
@ -115,12 +117,8 @@ no-t = 1987-07-0517:45:00Z)"sv;
R"(# time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second
# ; rules
d = 2006-01-01T00:00:61-00:00)"sv;
static constexpr auto datetime_time_no_leads_2 = R"(# Leading 0 is always required.
d = 01:32:0)"sv;
static constexpr auto datetime_time_no_leads = R"(# Leading 0 is always required.
d = 1:32:00)"sv;
static constexpr auto datetime_trailing_t = R"(# Date cannot end with trailing T
d = 2006-01-30T)"sv;
static constexpr auto datetime_time_no_leads = R"(# Leading 0 is always required.
d = 2023-10-01T1:32:00Z)"sv;
#if !TOML_LANG_UNRELEASED
@ -178,7 +176,7 @@ no-secs = 1987-07-05T17:45Z)"sv;
static constexpr auto float_exp_leading_us = R"(exp-leading-us = 1e_23)"sv;
static constexpr auto float_exp_point_1 = R"(exp-point-1 = 1e2.3)"sv;
static constexpr auto float_exp_point_2 = R"(exp-point-2 = 1.e2)"sv;
static constexpr auto float_exp_trailing_us = R"(exp-trailing-us = 1e_23_)"sv;
static constexpr auto float_exp_trailing_us = R"(exp-trailing-us = 1e23_)"sv;
static constexpr auto float_inf_capital = R"(v = Inf)"sv;
static constexpr auto float_inf_incomplete_1 = R"(inf-incomplete-1 = in)"sv;
static constexpr auto float_inf_incomplete_2 = R"(inf-incomplete-2 = +in)"sv;
@ -199,10 +197,8 @@ no-secs = 1987-07-05T17:45Z)"sv;
static constexpr auto float_trailing_point_min = R"(trailing-point-min = -1.)"sv;
static constexpr auto float_trailing_point_plus = R"(trailing-point-plus = +1.)"sv;
static constexpr auto float_trailing_point = R"(trailing-point = 1.)"sv;
static constexpr auto float_trailing_us_exp = R"(# trailing underscore in integer part is not allowed
trailing-us-exp = 1_e2
# trailing underscore in float part is not allowed
trailing-us-exp2 = 1.2_e2)"sv;
static constexpr auto float_trailing_us_exp_1 = R"(trailing-us-exp-1 = 1_e2)"sv;
static constexpr auto float_trailing_us_exp_2 = R"(trailing-us-exp-2 = 1.2_e2)"sv;
static constexpr auto float_trailing_us = R"(trailing-us = 1.2_)"sv;
static constexpr auto float_us_after_point = R"(us-after-point = 1._2)"sv;
static constexpr auto float_us_before_point = R"(us-before-point = 1_.2)"sv;
@ -327,6 +323,68 @@ key""" = 1)"sv;
#endif // !TOML_LANG_UNRELEASED && UNICODE_LITERALS_OK
static constexpr auto local_date_mday_over = R"(# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
# ; month/year
d = 2006-01-32)"sv;
static constexpr auto local_date_mday_under = R"(# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
# ; month/year
d = 2006-01-00)"sv;
static constexpr auto local_date_month_over = R"(# date-month = 2DIGIT ; 01-12
d = 2006-13-01)"sv;
static constexpr auto local_date_month_under = R"(# date-month = 2DIGIT ; 01-12
d = 2007-00-01)"sv;
static constexpr auto local_date_no_leads_with_milli = R"(# Day "5" instead of "05"; the leading zero is required.
with-milli = 1987-07-5)"sv;
static constexpr auto local_date_no_leads = R"(# Month "7" instead of "07"; the leading zero is required.
no-leads = 1987-7-05)"sv;
static constexpr auto local_date_trailing_t = R"(# Date cannot end with trailing T
d = 2006-01-30T)"sv;
static constexpr auto local_datetime_hour_over = R"(# time-hour = 2DIGIT ; 00-23
d = 2006-01-01T24:00:00)"sv;
static constexpr auto local_datetime_mday_over =
R"(# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
# ; month/year
d = 2006-01-32T00:00:00)"sv;
static constexpr auto local_datetime_mday_under =
R"(# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
# ; month/year
d = 2006-01-00T00:00:00)"sv;
static constexpr auto local_datetime_minute_over = R"(# time-minute = 2DIGIT ; 00-59
d = 2006-01-01T00:60:00)"sv;
static constexpr auto local_datetime_month_over = R"(# date-month = 2DIGIT ; 01-12
d = 2006-13-01T00:00:00)"sv;
static constexpr auto local_datetime_month_under = R"(# date-month = 2DIGIT ; 01-12
d = 2007-00-01T00:00:00)"sv;
static constexpr auto local_datetime_no_leads_with_milli =
R"(# Day "5" instead of "05"; the leading zero is required.
with-milli = 1987-07-5T17:45:00.12)"sv;
static constexpr auto local_datetime_no_leads = R"(# Month "7" instead of "07"; the leading zero is required.
no-leads = 1987-7-05T17:45:00)"sv;
static constexpr auto local_datetime_no_secs = R"(# No seconds in time.
no-secs = 1987-07-05T17:45)"sv;
static constexpr auto local_datetime_no_t = R"(# No "t" or "T" between the date and time.
no-t = 1987-07-0517:45:00)"sv;
static constexpr auto local_datetime_second_over =
R"(# time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second
# ; rules
d = 2006-01-01T00:00:61)"sv;
static constexpr auto local_datetime_time_no_leads = R"(# Leading 0 is always required.
d = 2023-10-01T1:32:00Z)"sv;
static constexpr auto local_time_hour_over = R"(# time-hour = 2DIGIT ; 00-23
d = 24:00:00)"sv;
static constexpr auto local_time_minute_over = R"(# time-minute = 2DIGIT ; 00-59
d = 00:60:00)"sv;
static constexpr auto local_time_no_secs = R"(# No seconds in time.
no-secs = 17:45)"sv;
static constexpr auto local_time_second_over =
R"(# time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second
# ; rules
d = 00:00:61)"sv;
static constexpr auto local_time_time_no_leads_2 = R"(# Leading 0 is always required.
d = 01:32:0)"sv;
static constexpr auto local_time_time_no_leads = R"(# Leading 0 is always required.
d = 1:32:00)"sv;
static constexpr auto spec_inline_table_2_0 = R"([product]
type = { name = "Nail" }
type.edible = false # INVALID)"sv;
@ -507,16 +565,16 @@ zyx = 42)"sv;
zyx = 42)"sv;
static constexpr auto table_quoted_no_close = R"(["where will it end]
name = value)"sv;
static constexpr auto table_redefine = R"(# Define b as int, and try to use it as a table: error
static constexpr auto table_redefine = R"(# Define b as int, and try to use it as a table: error
[a]
b = 1
[a.b]
c = 2)"sv;
static constexpr auto table_rrbrace = R"([[table] ])"sv;
static constexpr auto table_text_after_table = R"([error] this shouldn't be here)"sv;
static constexpr auto table_whitespace = R"([invalid key])"sv;
static constexpr auto table_with_pound = R"([key#group]
static constexpr auto table_rrbrace = R"([[table] ])"sv;
static constexpr auto table_text_after_table = R"([error] this shouldn't be here)"sv;
static constexpr auto table_whitespace = R"([invalid key])"sv;
static constexpr auto table_with_pound = R"([key#group]
answer = 42)"sv;
}
@ -802,6 +860,11 @@ TEST_CASE("conformance - burntsushi/invalid")
parsing_should_fail(FILE_LINE_ARGS, datetime_month_under); // datetime-month-under
}
SECTION("datetime-no-leads-month")
{
parsing_should_fail(FILE_LINE_ARGS, datetime_no_leads_month); // datetime-no-leads-month
}
SECTION("datetime-no-leads-with-milli")
{
parsing_should_fail(FILE_LINE_ARGS, datetime_no_leads_with_milli); // datetime-no-leads-with-milli
@ -822,21 +885,11 @@ TEST_CASE("conformance - burntsushi/invalid")
parsing_should_fail(FILE_LINE_ARGS, datetime_second_over); // datetime-second-over
}
SECTION("datetime-time-no-leads-2")
{
parsing_should_fail(FILE_LINE_ARGS, datetime_time_no_leads_2); // datetime-time-no-leads-2
}
SECTION("datetime-time-no-leads")
{
parsing_should_fail(FILE_LINE_ARGS, datetime_time_no_leads); // datetime-time-no-leads
}
SECTION("datetime-trailing-t")
{
parsing_should_fail(FILE_LINE_ARGS, datetime_trailing_t); // datetime-trailing-t
}
#if !TOML_LANG_UNRELEASED
SECTION("datetime-no-secs")
@ -1047,9 +1100,14 @@ TEST_CASE("conformance - burntsushi/invalid")
parsing_should_fail(FILE_LINE_ARGS, float_trailing_point); // float-trailing-point
}
SECTION("float-trailing-us-exp")
SECTION("float-trailing-us-exp-1")
{
parsing_should_fail(FILE_LINE_ARGS, float_trailing_us_exp); // float-trailing-us-exp
parsing_should_fail(FILE_LINE_ARGS, float_trailing_us_exp_1); // float-trailing-us-exp-1
}
SECTION("float-trailing-us-exp-2")
{
parsing_should_fail(FILE_LINE_ARGS, float_trailing_us_exp_2); // float-trailing-us-exp-2
}
SECTION("float-trailing-us")
@ -1470,6 +1528,131 @@ TEST_CASE("conformance - burntsushi/invalid")
#endif // !TOML_LANG_UNRELEASED && UNICODE_LITERALS_OK
SECTION("local-date-mday-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_date_mday_over); // local-date-mday-over
}
SECTION("local-date-mday-under")
{
parsing_should_fail(FILE_LINE_ARGS, local_date_mday_under); // local-date-mday-under
}
SECTION("local-date-month-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_date_month_over); // local-date-month-over
}
SECTION("local-date-month-under")
{
parsing_should_fail(FILE_LINE_ARGS, local_date_month_under); // local-date-month-under
}
SECTION("local-date-no-leads-with-milli")
{
parsing_should_fail(FILE_LINE_ARGS, local_date_no_leads_with_milli); // local-date-no-leads-with-milli
}
SECTION("local-date-no-leads")
{
parsing_should_fail(FILE_LINE_ARGS, local_date_no_leads); // local-date-no-leads
}
SECTION("local-date-trailing-t")
{
parsing_should_fail(FILE_LINE_ARGS, local_date_trailing_t); // local-date-trailing-t
}
SECTION("local-datetime-hour-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_hour_over); // local-datetime-hour-over
}
SECTION("local-datetime-mday-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_mday_over); // local-datetime-mday-over
}
SECTION("local-datetime-mday-under")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_mday_under); // local-datetime-mday-under
}
SECTION("local-datetime-minute-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_minute_over); // local-datetime-minute-over
}
SECTION("local-datetime-month-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_month_over); // local-datetime-month-over
}
SECTION("local-datetime-month-under")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_month_under); // local-datetime-month-under
}
SECTION("local-datetime-no-leads-with-milli")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_no_leads_with_milli); // local-datetime-no-leads-with-milli
}
SECTION("local-datetime-no-leads")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_no_leads); // local-datetime-no-leads
}
SECTION("local-datetime-no-secs")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_no_secs); // local-datetime-no-secs
}
SECTION("local-datetime-no-t")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_no_t); // local-datetime-no-t
}
SECTION("local-datetime-second-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_second_over); // local-datetime-second-over
}
SECTION("local-datetime-time-no-leads")
{
parsing_should_fail(FILE_LINE_ARGS, local_datetime_time_no_leads); // local-datetime-time-no-leads
}
SECTION("local-time-hour-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_time_hour_over); // local-time-hour-over
}
SECTION("local-time-minute-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_time_minute_over); // local-time-minute-over
}
SECTION("local-time-no-secs")
{
parsing_should_fail(FILE_LINE_ARGS, local_time_no_secs); // local-time-no-secs
}
SECTION("local-time-second-over")
{
parsing_should_fail(FILE_LINE_ARGS, local_time_second_over); // local-time-second-over
}
SECTION("local-time-time-no-leads-2")
{
parsing_should_fail(FILE_LINE_ARGS, local_time_time_no_leads_2); // local-time-time-no-leads-2
}
SECTION("local-time-time-no-leads")
{
parsing_should_fail(FILE_LINE_ARGS, local_time_time_no_leads); // local-time-time-no-leads
}
SECTION("spec-inline-table-2-0")
{
parsing_should_fail(FILE_LINE_ARGS, spec_inline_table_2_0); // spec-inline-table-2-0

View File

@ -67,11 +67,15 @@ Job: XXXX""",
static constexpr auto bool_bool = R"(t = true
f = false)"sv;
static constexpr auto comment_at_eof = R"(# This is a full-line comment
static constexpr auto comment_after_literal_no_ws = R"(inf=inf#infinity
nan=nan#not a number
true=true#true
false=false#false)"sv;
static constexpr auto comment_at_eof = R"(# This is a full-line comment
key = "value" # This is a comment at the end of a line)"sv;
static constexpr auto comment_at_eof2 = R"(# This is a full-line comment
static constexpr auto comment_at_eof2 = R"(# This is a full-line comment
key = "value" # This is a comment at the end of a line)"sv;
static constexpr auto comment_everywhere = R"(# Top comment.
static constexpr auto comment_everywhere = R"(# Top comment.
# Top comment.
# Top comment.
@ -99,8 +103,8 @@ more = [ # Comment
# Make sure the space between the datetime and "#" isn't lexed.
dt = 1979-05-27T07:32:12-07:00 # c
d = 1979-05-27 # Comment)"sv;
static constexpr auto comment_noeol = R"(# single comment without any eol characters)"sv;
static constexpr auto comment_tricky = R"([section]#attached comment
static constexpr auto comment_noeol = R"(# single comment without any eol characters)"sv;
static constexpr auto comment_tricky = R"([section]#attached comment
#[notsection]
one = "11"#cmt
two = "22#"
@ -1491,6 +1495,22 @@ Job: XXXX)"sv,
});
}
SECTION("comment-after-literal-no-ws")
{
parsing_should_succeed(FILE_LINE_ARGS,
comment_after_literal_no_ws,
[](toml::table&& tbl) // comment-after-literal-no-ws
{
const auto expected = toml::table{
{ R"(false)"sv, false },
{ R"(inf)"sv, std::numeric_limits<double>::infinity() },
{ R"(nan)"sv, std::numeric_limits<double>::quiet_NaN() },
{ R"(true)"sv, true },
};
REQUIRE(tbl == expected);
});
}
SECTION("comment-at-eof")
{
parsing_should_succeed(FILE_LINE_ARGS,
@ -1528,8 +1548,8 @@ Job: XXXX)"sv,
{ R"(group)"sv,
toml::table{
{ R"(answer)"sv, 42 },
{ R"(dt)"sv, toml::date_time{ { 1979, 5, 27 }, { 7, 32, 12 }, { -7, 0 } } },
{ R"(d)"sv, toml::date{ 1979, 5, 27 } },
{ R"(dt)"sv, toml::date_time{ { 1979, 5, 27 }, { 7, 32, 12 }, { -7, 0 } } },
{ R"(more)"sv,
toml::array{
42,
@ -1857,13 +1877,13 @@ Job: XXXX)"sv,
[](toml::table&& tbl) // float-zero
{
const auto expected = toml::table{
{ R"(zero)"sv, 0.0 },
{ R"(signed-pos)"sv, 0.0 },
{ R"(signed-neg)"sv, 0.0 },
{ R"(exponent)"sv, 0.0 },
{ R"(exponent-two-0)"sv, 0.0 },
{ R"(exponent-signed-neg)"sv, -0.0 },
{ R"(exponent-signed-pos)"sv, 0.0 },
{ R"(exponent-signed-neg)"sv, 0.0 },
{ R"(exponent-two-0)"sv, 0.0 },
{ R"(signed-neg)"sv, -0.0 },
{ R"(signed-pos)"sv, 0.0 },
{ R"(zero)"sv, 0.0 },
};
REQUIRE(tbl == expected);
});
@ -2517,10 +2537,6 @@ another line)"sv },
toml::table{
{ R"(x)"sv, R"(empty.x)"sv },
} },
{ R"(x)"sv,
toml::table{
{ ""sv, R"(x.empty)"sv },
} },
{ R"(a)"sv,
toml::table{
{ ""sv,
@ -2528,6 +2544,10 @@ another line)"sv },
{ ""sv, R"(empty.empty)"sv },
} },
} },
{ R"(x)"sv,
toml::table{
{ ""sv, R"(x.empty)"sv },
} },
};
REQUIRE(tbl == expected);
});
@ -4093,9 +4113,9 @@ has ' a quote character
and more than
one newline
in it.)"sv },
{ R"(oneline)"sv, R"(This string has a ' quote character.)"sv },
{ R"(multiline_with_tab)"sv, R"(First line
Followed by a tab)"sv },
{ R"(oneline)"sv, R"(This string has a ' quote character.)"sv },
};
REQUIRE(tbl == expected);
});
@ -4463,11 +4483,11 @@ in it.)"sv },
const auto expected = toml::table{
{ ""sv,
toml::table{
{ R"(x)"sv, 1 },
{ R"(a)"sv,
toml::table{
{ R"(x)"sv, 2 },
} },
{ R"(x)"sv, 1 },
} },
{ R"(a)"sv,
toml::table{
@ -4501,10 +4521,10 @@ in it.)"sv },
[](toml::table&& tbl) // table-keyword
{
const auto expected = toml::table{
{ R"(true)"sv, toml::table{} },
{ R"(false)"sv, toml::table{} },
{ R"(inf)"sv, toml::table{} },
{ R"(nan)"sv, toml::table{} },
{ R"(true)"sv, toml::table{} },
};
REQUIRE(tbl == expected);
});

View File

@ -412,4 +412,22 @@ b = []
CHECK(val == an_enum::two);
});
}
SECTION("tomlplusplus/issues/176") // https://github.com/marzer/tomlplusplus/issues/176
{
parsing_should_succeed(FILE_LINE_ARGS,
R"(
"a" = "x\ty"
"a\tb" = "x\ty"
)",
[](auto&& tbl)
{
CHECK(tbl["a"]);
CHECK(tbl["a\tb"]);
std::stringstream ss;
ss << tbl;
CHECK(ss.str() == "a = 'x\ty'\n'a\tb' = 'x\ty'"sv);
});
}
}

View File

@ -16561,6 +16561,10 @@ TOML_IMPL_NAMESPACE_START
bad_unicode();
}
// strings with line breaks and tabs can't be bare
if (!!(traits & (formatted_string_traits::line_breaks | formatted_string_traits::tabs)))
traits |= formatted_string_traits::non_bare;
// if the string meets the requirements of being 'bare' we can emit a bare string
// (bare strings are composed of letters and numbers; no whitespace, control chars, quotes, etc)
if (!(traits & formatted_string_traits::non_bare)