Skip to content

Commit 6f5248b

Browse files
committed
Track the start of the parsing position for each format specifier
The starting position is one of: 1. The position immediately after the colon, if there is one. 2. Otherwise, the position immediately after the format parameter index, if there is one. 3. Otherwise, the position immeidately after the opening brace. This will allow resetting the position of the format string lexer to this starting position before formatting user-defined types at runtime.
1 parent 980a59b commit 6f5248b

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

fly/types/string/detail/format_specifier.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ struct BasicFormatSpecifier
267267
Type m_type {Type::None};
268268
Case m_case {Case::Lower};
269269

270+
std::size_t m_parse_index {0};
270271
std::size_t m_size {0};
271272

272273
private:

fly/types/string/detail/format_string.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ constexpr auto BasicFormatString<CharType, ParameterTypes...>::parse_specifier()
159159
const auto starting_position = m_context.lexer().position() - 1;
160160

161161
FormatSpecifier specifier(m_context);
162+
specifier.m_parse_index = m_context.lexer().position();
162163

163164
if (m_context.parameter_type(specifier.m_position) == ParameterType::UserDefined)
164165
{
@@ -191,6 +192,7 @@ BasicFormatString<CharType, ParameterTypes...>::parse_standard_specifier(FormatS
191192
{
192193
if (m_context.lexer().consume_if(s_colon))
193194
{
195+
specifier.m_parse_index = m_context.lexer().position();
194196
specifier.parse(m_context);
195197
}
196198

test/types/string/format_string.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,46 @@ CATCH_TEMPLATE_TEST_CASE(
667667

668668
CATCH_CHECK_FALSE(format.next_specifier());
669669
}
670+
671+
CATCH_SECTION("Specifiers track their parsing index in the format string")
672+
{
673+
{
674+
auto format = make_format(FMT("ab {0} cd {1:d} ef {002:#0x}"), 1, 2, 3);
675+
CATCH_CHECK_FALSE(format.context().has_error());
676+
677+
auto specifier1 = format.next_specifier();
678+
CATCH_REQUIRE(specifier1);
679+
CATCH_CHECK(specifier1->m_parse_index == 5);
680+
681+
auto specifier2 = format.next_specifier();
682+
CATCH_REQUIRE(specifier2);
683+
CATCH_CHECK(specifier2->m_parse_index == 13);
684+
685+
auto specifier3 = format.next_specifier();
686+
CATCH_REQUIRE(specifier3);
687+
CATCH_CHECK(specifier3->m_parse_index == 24);
688+
689+
CATCH_CHECK_FALSE(format.next_specifier());
690+
}
691+
{
692+
auto format = make_format(FMT("ab {} cd {:d} ef {:#0x}"), 1, 2, 3);
693+
CATCH_CHECK_FALSE(format.context().has_error());
694+
695+
auto specifier1 = format.next_specifier();
696+
CATCH_REQUIRE(specifier1);
697+
CATCH_CHECK(specifier1->m_parse_index == 4);
698+
699+
auto specifier2 = format.next_specifier();
700+
CATCH_REQUIRE(specifier2);
701+
CATCH_CHECK(specifier2->m_parse_index == 11);
702+
703+
auto specifier3 = format.next_specifier();
704+
CATCH_REQUIRE(specifier3);
705+
CATCH_CHECK(specifier3->m_parse_index == 19);
706+
707+
CATCH_CHECK_FALSE(format.next_specifier());
708+
}
709+
}
670710
}
671711

672712
#if defined(FLY_COMPILER_DISABLE_CONSTEVAL)

0 commit comments

Comments
 (0)