-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restructure printf_arg_formatter to make it customizable #1093
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -554,3 +554,51 @@ TEST(PrintfTest, VSPrintfMakeWArgsExample) { | |
fmt::make_wprintf_args(42, L"something"))); | ||
#endif | ||
} | ||
|
||
typedef fmt::printf_arg_formatter< | ||
fmt::back_insert_range<fmt::internal::buffer<char>>> formatter_t; | ||
typedef fmt::basic_printf_context<formatter_t::iterator, char> context_t; | ||
|
||
// A custom printf argument formatter that doesn't print `-` for floating-point | ||
// values rounded to 0. | ||
class custom_printf_arg_formatter : public formatter_t { | ||
public: | ||
using formatter_t::iterator; | ||
|
||
custom_printf_arg_formatter(formatter_t::iterator iter, formatter_t::format_specs& spec, context_t& ctx) | ||
: formatter_t(iter, spec, ctx) {} | ||
|
||
using formatter_t::operator(); | ||
|
||
#if FMT_MSC_VER > 0 && FMT_MSC_VER <= 1804 | ||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> | ||
iterator operator()(T value) { | ||
#else | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use the above SFINAE-based definition for all compilers and remove conditional compilation (adding a comment clarifying that this is a workaround for MSVC). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately this doesn't work. Other compilers (clang and gcc as far as I recall) complain then. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, let's keep it as is. |
||
iterator operator()(double value) { | ||
#endif | ||
// Comparing a float to 0.0 is safe. | ||
if (round(value * pow(10, spec()->precision)) == 0.0) value = 0; | ||
return formatter_t::operator()(value); | ||
} | ||
}; | ||
|
||
typedef fmt::basic_format_args<context_t> format_args_t; | ||
|
||
std::string custom_vformat(fmt::string_view format_str, format_args_t args) { | ||
fmt::memory_buffer buffer; | ||
fmt::vprintf<custom_printf_arg_formatter>(buffer, format_str, args); | ||
return std::string(buffer.data(), buffer.size()); | ||
} | ||
|
||
template <typename... Args> | ||
std::string custom_format(const char* format_str, const Args&... args) { | ||
auto va = fmt::make_printf_args (args...); | ||
return custom_vformat(format_str, va); | ||
} | ||
|
||
TEST(CustomFormatterTest, Format) { | ||
EXPECT_EQ("0.00", custom_format("%.2f", -.00001)); | ||
EXPECT_EQ("0.00", custom_format("%.2f", .00001)); | ||
EXPECT_EQ("1.00", custom_format("%.2f", 1.00001)); | ||
EXPECT_EQ("-1.00", custom_format("%.2f", -1.00001)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think these should be public because the children won't be able to use these types directly anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. But I have to keep the iterator public (like in the arg_formatter) to get my approach working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, making
iterator
public makes sense.