custom printfArgFormatter template param

This commit is contained in:
Glen Stark 2016-05-27 16:28:13 +02:00
parent 96c28f748d
commit 321a541ee9
4 changed files with 66 additions and 19 deletions

View File

@ -686,8 +686,8 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
return arg; return arg;
} }
template <typename Char> template <typename Char, typename PAF>
void fmt::internal::PrintfFormatter<Char>::parse_flags( void fmt::internal::PrintfFormatter<Char, PAF>::parse_flags(
FormatSpec &spec, const Char *&s) { FormatSpec &spec, const Char *&s) {
for (;;) { for (;;) {
switch (*s++) { switch (*s++) {
@ -713,8 +713,8 @@ void fmt::internal::PrintfFormatter<Char>::parse_flags(
} }
} }
template <typename Char> template <typename Char, typename PAF>
Arg fmt::internal::PrintfFormatter<Char>::get_arg( Arg fmt::internal::PrintfFormatter<Char, PAF>::get_arg(
const Char *s, unsigned arg_index) { const Char *s, unsigned arg_index) {
(void)s; (void)s;
const char *error = 0; const char *error = 0;
@ -725,8 +725,8 @@ Arg fmt::internal::PrintfFormatter<Char>::get_arg(
return arg; return arg;
} }
template <typename Char> template <typename Char, typename PAF>
unsigned fmt::internal::PrintfFormatter<Char>::parse_header( unsigned fmt::internal::PrintfFormatter<Char, PAF>::parse_header(
const Char *&s, FormatSpec &spec) { const Char *&s, FormatSpec &spec) {
unsigned arg_index = UINT_MAX; unsigned arg_index = UINT_MAX;
Char c = *s; Char c = *s;
@ -759,8 +759,8 @@ unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
return arg_index; return arg_index;
} }
template <typename Char> template <typename Char, typename PAF >
void fmt::internal::PrintfFormatter<Char>::format( void fmt::internal::PrintfFormatter<Char,PAF>::format(
BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) { BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) {
const Char *start = format_str.c_str(); const Char *start = format_str.c_str();
const Char *s = start; const Char *s = start;
@ -853,11 +853,12 @@ void fmt::internal::PrintfFormatter<Char>::format(
start = s; start = s;
// Format argument. // Format argument.
internal::PrintfArgFormatter<Char>(writer, spec).visit(arg); PAF(writer, spec).visit(arg);
} }
write(writer, start, s); write(writer, start, s);
} }
FMT_FUNC void fmt::report_system_error( FMT_FUNC void fmt::report_system_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT { int error_code, fmt::StringRef message) FMT_NOEXCEPT {
// 'fmt::' is for bcc32. // 'fmt::' is for bcc32.

View File

@ -237,7 +237,7 @@ typedef __int64 intmax_t;
# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) # define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
#endif #endif
// Some compilers masquerade as both MSVC and GCC-likes or // Some compilers masquerade as both MSVC and GCC-likes or
// otherwise support __builtin_clz and __builtin_clzll, so // otherwise support __builtin_clz and __builtin_clzll, so
// only define FMT_BUILTIN_CLZ using the MSVC intrinsics // only define FMT_BUILTIN_CLZ using the MSVC intrinsics
// if the clz and clzll builtins are not available. // if the clz and clzll builtins are not available.
@ -253,7 +253,7 @@ inline uint32_t clz(uint32_t x) {
assert(x != 0); assert(x != 0);
// Static analysis complains about using uninitialized data // Static analysis complains about using uninitialized data
// "r", but the only way that can happen is if "x" is 0, // "r", but the only way that can happen is if "x" is 0,
// which the callers guarantee to not happen. // which the callers guarantee to not happen.
# pragma warning(suppress: 6102) # pragma warning(suppress: 6102)
return 31 - r; return 31 - r;
@ -279,7 +279,7 @@ inline uint32_t clzll(uint64_t x) {
assert(x != 0); assert(x != 0);
// Static analysis complains about using uninitialized data // Static analysis complains about using uninitialized data
// "r", but the only way that can happen is if "x" is 0, // "r", but the only way that can happen is if "x" is 0,
// which the callers guarantee to not happen. // which the callers guarantee to not happen.
# pragma warning(suppress: 6102) # pragma warning(suppress: 6102)
return 63 - r; return 63 - r;
@ -378,6 +378,7 @@ class BasicWriter;
typedef BasicWriter<char> Writer; typedef BasicWriter<char> Writer;
typedef BasicWriter<wchar_t> WWriter; typedef BasicWriter<wchar_t> WWriter;
// Define default ArgFormatter and BasicFormatter.
template <typename Char> template <typename Char>
class ArgFormatter; class ArgFormatter;
@ -1296,7 +1297,7 @@ public:
MakeArg() { MakeArg() {
type = Arg::NONE; type = Arg::NONE;
} }
template <typename T> template <typename T>
MakeArg(const T &value) MakeArg(const T &value)
: Arg(MakeValue<Formatter>(value)) { : Arg(MakeValue<Formatter>(value)) {
@ -1939,7 +1940,7 @@ class FormatterBase {
}; };
// A printf formatter. // A printf formatter.
template <typename Char> template <typename Char, typename PAF = fmt::internal::PrintfArgFormatter<Char> >
class PrintfFormatter : private FormatterBase { class PrintfFormatter : private FormatterBase {
private: private:
void parse_flags(FormatSpec &spec, const Char *&s); void parse_flags(FormatSpec &spec, const Char *&s);
@ -2091,7 +2092,7 @@ struct ArgArray;
template <unsigned N> template <unsigned N>
struct ArgArray<N, true/*IsPacked*/> { struct ArgArray<N, true/*IsPacked*/> {
typedef Value Type[N > 0 ? N : 1]; typedef Value Type[N > 0 ? N : 1];
template <typename Formatter, typename T> template <typename Formatter, typename T>
static Value make(const T &value) { static Value make(const T &value) {
#ifdef __clang__ #ifdef __clang__
@ -2287,7 +2288,7 @@ class SystemError : public internal::RuntimeError {
Formats an error returned by an operating system or a language runtime, Formats an error returned by an operating system or a language runtime,
for example a file opening error, and writes it to *out* in the following for example a file opening error, and writes it to *out* in the following
form: form:
.. parsed-literal:: .. parsed-literal::
*<message>*: *<system-message>* *<message>*: *<system-message>*
@ -3187,9 +3188,9 @@ FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args);
*/ */
FMT_API void print(CStringRef format_str, ArgList args); FMT_API void print(CStringRef format_str, ArgList args);
template <typename Char> template <typename Char>
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) { void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
internal::PrintfFormatter<Char>(args).format(w, format); internal::PrintfFormatter<Char>(args).format(w, format);
} }
/** /**
@ -3815,8 +3816,10 @@ struct UdlArg {
} }
}; };
} // namespace internal } // namespace internal
inline namespace literals { inline namespace literals {
/** /**
@ -3850,6 +3853,7 @@ inline internal::UdlArg<wchar_t>
operator"" _a(const wchar_t *s, std::size_t) { return {s}; } operator"" _a(const wchar_t *s, std::size_t) { return {s}; }
} // inline namespace literals } // inline namespace literals
} // namespace fmt } // namespace fmt
#endif // FMT_USE_USER_DEFINED_LITERALS #endif // FMT_USE_USER_DEFINED_LITERALS

View File

@ -80,6 +80,7 @@ add_fmt_test(printf-test)
add_fmt_test(string-test) add_fmt_test(string-test)
add_fmt_test(util-test mock-allocator.h) add_fmt_test(util-test mock-allocator.h)
add_fmt_test(macro-test) add_fmt_test(macro-test)
add_fmt_test(custom-formatter-test)
# Enable stricter options for one test to make sure that the header is free of # Enable stricter options for one test to make sure that the header is free of
# warnings. # warnings.
@ -129,7 +130,7 @@ if (FMT_PEDANTIC)
"${CMAKE_CURRENT_BINARY_DIR}/compile-test" "${CMAKE_CURRENT_BINARY_DIR}/compile-test"
--build-generator ${CMAKE_GENERATOR} --build-generator ${CMAKE_GENERATOR}
--build-makeprogram ${CMAKE_MAKE_PROGRAM} --build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options --build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCPP11_FLAG=${CPP11_FLAG}" "-DCPP11_FLAG=${CPP11_FLAG}"
"-DSUPPORTS_USER_DEFINED_LITERALS=${SUPPORTS_USER_DEFINED_LITERALS}") "-DSUPPORTS_USER_DEFINED_LITERALS=${SUPPORTS_USER_DEFINED_LITERALS}")

View File

@ -0,0 +1,41 @@
#include "fmt/format.h"
#include <iostream>
// A custom argument formatter that doesn't print `-` for floating-point values
// rounded to 0.
class CustomArgFormatter :
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public:
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt)
: fmt::BasicArgFormatter<CustomArgFormatter, char>(f, s, fmt) {}
void visit_double(double value) {
if (round(value * pow(10, spec().precision())) == 0)
value = 0;
fmt::BasicArgFormatter<CustomArgFormatter, char>::visit_double(value);
}
};
std::string custom_format(const char *format_str, fmt::ArgList args) {
fmt::MemoryWriter writer;
// Pass custom argument formatter as a template arg to BasicFormatter.
fmt::BasicFormatter<char, CustomArgFormatter> formatter(args, writer);
formatter.format(format_str);
return writer.str();
}
FMT_VARIADIC(std::string, custom_format, const char *)
std::string printfer(const char* fstr, fmt::ArgList args){
fmt::MemoryWriter writer;
fmt::internal::PrintfFormatter<char> pfer(args);
pfer.format(writer,fstr);
return writer.str();
}
FMT_VARIADIC(std::string, printfer, const char*);
int main() {
std::cout << custom_format("custom: {:.2f}", -0.000001) << std::endl;
std::cout << printfer("printf: %.2f", -0.0001) << std::endl;
}