Skip to content

Commit

Permalink
add dynamic width parsing logic for test_formattable in compile-test
Browse files Browse the repository at this point in the history
  • Loading branch information
alexezeder committed May 30, 2021
1 parent dacaecb commit cd72ce7
Showing 1 changed file with 48 additions and 2 deletions.
50 changes: 48 additions & 2 deletions test/compile-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,61 @@ struct test_formattable {};

FMT_BEGIN_NAMESPACE
template <> struct formatter<test_formattable> : formatter<const char*> {
basic_format_specs<char> specs;
detail::arg_ref<char> width_ref;
char word_spec = 'f';

struct spec_handler {
formatter& f;
basic_format_parse_context<char>& context;

void on_error(const char* msg) { FMT_THROW(format_error(msg)); }
FMT_CONSTEXPR void on_fill(basic_string_view<char> fill) {
f.specs.fill = fill;
}
FMT_CONSTEXPR void on_align(align_t align) { f.specs.align = align; }
FMT_CONSTEXPR void on_width(int width) { f.specs.width = width; }
FMT_CONSTEXPR void on_precision(int) {}
FMT_CONSTEXPR void end_precision() {}
template <typename Id>
FMT_CONSTEXPR detail::arg_ref<char> make_arg_ref(Id arg_id) {
context.check_arg_id(arg_id);
return detail::arg_ref<char>(arg_id);
}
FMT_CONSTEXPR detail::arg_ref<char> make_arg_ref(
basic_string_view<char> arg_id) {
context.check_arg_id(arg_id);
return detail::arg_ref<char>(arg_id);
}
FMT_CONSTEXPR detail::arg_ref<char> make_arg_ref(detail::auto_id) {
return detail::arg_ref<char>(context.next_arg_id());
}
template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
f.width_ref = make_arg_ref(arg_id);
}
template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id) {}
};

constexpr auto parse(format_parse_context& ctx) {
auto it = ctx.begin(), end = ctx.end();
if (it == end || *it == '}') return it;
spec_handler handler{*this, ctx};
it = detail::parse_align(it, end, handler);
if (it == end) return it;
it = detail::parse_width(it, end, handler);
if (it == end) return it;
if (it != end && (*it == 'f' || *it == 'b')) word_spec = *it++;
if (it != end && *it != '}') throw format_error("invalid format");
return it;
}
template <typename FormatContext>
constexpr auto format(test_formattable, FormatContext& ctx) const
-> decltype(ctx.out()) {
return formatter<const char*>::format(word_spec == 'f' ? "foo" : "bar",
ctx);
auto specs_copy = specs;
detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width,
width_ref, ctx);
auto word = string_view(word_spec == 'f' ? "foo" : "bar");
return detail::write(ctx.out(), word, specs_copy);
}
};
FMT_END_NAMESPACE
Expand Down Expand Up @@ -349,6 +391,10 @@ TEST(compile_time_formatting_test, combination) {
TEST(compile_time_formatting_test, custom_type) {
EXPECT_EQ("foo", test_format<4>(FMT_COMPILE("{}"), test_formattable()));
EXPECT_EQ("bar", test_format<4>(FMT_COMPILE("{:b}"), test_formattable()));
EXPECT_EQ("=bar=",
test_format<6>(FMT_COMPILE("{:=^5b}"), test_formattable()));
EXPECT_EQ("==foo==",
test_format<8>(FMT_COMPILE("{:=^{}f}"), test_formattable(), 7));
}

TEST(compile_time_formatting_test, multibyte_fill) {
Expand Down

0 comments on commit cd72ce7

Please sign in to comment.