custom printfArgFormatter template param
This commit is contained in:
parent
96c28f748d
commit
321a541ee9
@ -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.
|
||||||
|
|||||||
22
fmt/format.h
22
fmt/format.h
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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}")
|
||||||
|
|||||||
41
test/custom-formatter-test.cc
Normal file
41
test/custom-formatter-test.cc
Normal 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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user