mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-09 21:00:06 +00:00
Replace formatter with context
This commit is contained in:
parent
2bba420337
commit
9998f66f8c
@ -446,7 +446,7 @@ void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format,
|
||||
format_args args);
|
||||
|
||||
FMT_FUNC int vfprintf(std::FILE *f, CStringRef format,
|
||||
basic_format_args<PrintfFormatter<char>> args) {
|
||||
basic_format_args<printf_context<char>> args) {
|
||||
MemoryWriter w;
|
||||
printf(w, format, args);
|
||||
std::size_t size = w.size();
|
||||
@ -463,7 +463,7 @@ template void internal::FixedBuffer<char>::grow(std::size_t);
|
||||
|
||||
template void internal::ArgMap<char>::init(const format_args &args);
|
||||
|
||||
template void PrintfFormatter<char>::format(Writer &writer, CStringRef format);
|
||||
template void printf_context<char>::format(Writer &writer);
|
||||
|
||||
template int internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
@ -479,8 +479,7 @@ template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
|
||||
|
||||
template void internal::ArgMap<wchar_t>::init(const format_args &args);
|
||||
|
||||
template void PrintfFormatter<wchar_t>::format(WWriter &writer,
|
||||
WCStringRef format);
|
||||
template void printf_context<wchar_t>::format(WWriter &writer);
|
||||
|
||||
template int internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
|
282
fmt/format.h
282
fmt/format.h
@ -377,8 +377,11 @@ class ArgFormatter;
|
||||
template <typename Impl, typename Char>
|
||||
class BasicPrintfArgFormatter;
|
||||
|
||||
template <typename Char, typename ArgFormatter = fmt::ArgFormatter<Char> >
|
||||
class basic_formatter;
|
||||
template <typename Char>
|
||||
class basic_format_context;
|
||||
|
||||
typedef basic_format_context<char> format_context;
|
||||
typedef basic_format_context<wchar_t> wformat_context;
|
||||
|
||||
/**
|
||||
\rst
|
||||
@ -993,7 +996,7 @@ struct Value {
|
||||
};
|
||||
|
||||
typedef void (*FormatFunc)(
|
||||
void *writer, const void *arg, void *formatter, void *format_str_ptr);
|
||||
void *writer, const void *arg, void *ctx);
|
||||
|
||||
struct CustomValue {
|
||||
const void *value;
|
||||
@ -1230,10 +1233,10 @@ template <typename T>
|
||||
constexpr Type type() { return gettype<typename std::decay<T>::type>(); }
|
||||
|
||||
// Makes an Arg object from any type.
|
||||
template <typename Formatter>
|
||||
template <typename Context>
|
||||
class MakeValue : public Arg {
|
||||
public:
|
||||
typedef typename Formatter::char_type Char;
|
||||
typedef typename Context::char_type Char;
|
||||
|
||||
private:
|
||||
// The following two methods are private to disallow formatting of
|
||||
@ -1271,12 +1274,10 @@ class MakeValue : public Arg {
|
||||
// Formats an argument of a custom type, such as a user-defined class.
|
||||
template <typename T>
|
||||
static void format_custom_arg(
|
||||
void *writer, const void *arg, void *formatter, void *format_str_ptr) {
|
||||
typedef BasicWriter<typename Formatter::char_type> Writer;
|
||||
format_value(*static_cast<Writer*>(writer),
|
||||
void *writer, const void *arg, void *context) {
|
||||
format_value(*static_cast<BasicWriter<Char>*>(writer),
|
||||
*static_cast<const T*>(arg),
|
||||
*static_cast<Formatter*>(formatter),
|
||||
*static_cast<const Char**>(format_str_ptr));
|
||||
*static_cast<Context*>(context));
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1406,7 +1407,7 @@ struct NamedArg : Arg {
|
||||
|
||||
template <typename T>
|
||||
NamedArg(BasicStringRef<Char> argname, const T &value)
|
||||
: Arg(MakeArg< basic_formatter<Char> >(value)), name(argname) {}
|
||||
: Arg(MakeArg< basic_format_context<Char> >(value)), name(argname) {}
|
||||
};
|
||||
|
||||
class RuntimeError : public std::runtime_error {
|
||||
@ -1430,7 +1431,7 @@ constexpr uint64_t make_type<void>() { return 0; }
|
||||
enum { MAX_PACKED_ARGS = 16 };
|
||||
} // namespace internal
|
||||
|
||||
template <typename Formatter, typename ...Args>
|
||||
template <typename Context, typename ...Args>
|
||||
class format_arg_store {
|
||||
private:
|
||||
static const size_t NUM_ARGS = sizeof...(Args);
|
||||
@ -1443,26 +1444,25 @@ class format_arg_store {
|
||||
std::array<value_type, NUM_ARGS + (IS_PACKED ? 0 : 1)> data_;
|
||||
|
||||
template <typename ...A>
|
||||
friend format_arg_store<Formatter, A...> make_format_args(const A & ... args);
|
||||
friend format_arg_store<Context, A...> make_format_args(const A & ... args);
|
||||
|
||||
public:
|
||||
static const uint64_t TYPES = internal::make_type<Args..., void>();
|
||||
|
||||
format_arg_store(const Args &... args, Formatter *)
|
||||
: data_{{internal::MakeValue<Formatter>(args)...}} {}
|
||||
format_arg_store(const Args &... args)
|
||||
: data_{{internal::MakeValue<Context>(args)...}} {}
|
||||
|
||||
const value_type *data() const { return data_.data(); }
|
||||
};
|
||||
|
||||
template <typename Formatter, typename ...Args>
|
||||
inline format_arg_store<Formatter, Args...>
|
||||
template <typename Context, typename ...Args>
|
||||
inline format_arg_store<Context, Args...>
|
||||
make_format_args(const Args & ... args) {
|
||||
Formatter *f = nullptr;
|
||||
return format_arg_store<Formatter, Args...>(args..., f);
|
||||
return format_arg_store<Context, Args...>(args...);
|
||||
}
|
||||
|
||||
/** Formatting arguments. */
|
||||
template <typename Formatter>
|
||||
template <typename Context>
|
||||
class basic_format_args {
|
||||
private:
|
||||
// To reduce compiled code size per formatting function call, types of first
|
||||
@ -1496,7 +1496,7 @@ class basic_format_args {
|
||||
basic_format_args() : types_(0) {}
|
||||
|
||||
template <typename... Args>
|
||||
basic_format_args(const format_arg_store<Formatter, Args...> &store)
|
||||
basic_format_args(const format_arg_store<Context, Args...> &store)
|
||||
: types_(store.TYPES) {
|
||||
set_data(store.data());
|
||||
}
|
||||
@ -1527,8 +1527,8 @@ class basic_format_args {
|
||||
}
|
||||
};
|
||||
|
||||
typedef basic_format_args<basic_formatter<char>> format_args;
|
||||
typedef basic_format_args<basic_formatter<wchar_t>> wformat_args;
|
||||
typedef basic_format_args<basic_format_context<char>> format_args;
|
||||
typedef basic_format_args<basic_format_context<wchar_t>> wformat_args;
|
||||
|
||||
#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
|
||||
|
||||
@ -2014,6 +2014,8 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Char char_type;
|
||||
|
||||
ArgFormatterBase(BasicWriter<Char> &w, FormatSpec &s)
|
||||
: writer_(w), spec_(s) {}
|
||||
|
||||
@ -2082,21 +2084,35 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Formatter>
|
||||
class FormatterBase {
|
||||
private:
|
||||
basic_format_args<Formatter> args_;
|
||||
template <typename Char>
|
||||
inline void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
|
||||
if (start != end)
|
||||
w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
|
||||
}
|
||||
|
||||
template <typename Char, typename Context>
|
||||
class format_context_base {
|
||||
private:
|
||||
const Char *ptr_;
|
||||
basic_format_args<Context> args_;
|
||||
int next_arg_index_;
|
||||
|
||||
protected:
|
||||
format_context_base(const Char *format_str, basic_format_args<Context> args)
|
||||
: ptr_(format_str), args_(args), next_arg_index_(0) {}
|
||||
~format_context_base() {}
|
||||
|
||||
basic_format_args<Context> args() const { return args_; }
|
||||
|
||||
// Returns the argument with specified index.
|
||||
Arg do_get_arg(unsigned arg_index, const char *&error) {
|
||||
Arg arg = args_[arg_index];
|
||||
format_arg do_get_arg(unsigned arg_index, const char *&error) {
|
||||
format_arg arg = args_[arg_index];
|
||||
switch (arg.type) {
|
||||
case Arg::NONE:
|
||||
case format_arg::NONE:
|
||||
error = "argument index out of range";
|
||||
break;
|
||||
case Arg::NAMED_ARG:
|
||||
arg = *static_cast<const internal::Arg*>(arg.pointer);
|
||||
case format_arg::NAMED_ARG:
|
||||
arg = *static_cast<const format_arg*>(arg.pointer);
|
||||
break;
|
||||
default:
|
||||
/*nothing*/;
|
||||
@ -2104,24 +2120,19 @@ private:
|
||||
return arg;
|
||||
}
|
||||
|
||||
protected:
|
||||
FormatterBase(basic_format_args<Formatter> args)
|
||||
: args_(args), next_arg_index_(0) {}
|
||||
|
||||
const basic_format_args<Formatter> &args() const { return args_; }
|
||||
|
||||
// Returns the next argument.
|
||||
Arg next_arg(const char *&error) {
|
||||
if (next_arg_index_ >= 0)
|
||||
return do_get_arg(internal::to_unsigned(next_arg_index_++), error);
|
||||
error = "cannot switch from manual to automatic argument indexing";
|
||||
return Arg();
|
||||
}
|
||||
|
||||
// Checks if manual indexing is used and returns the argument with
|
||||
// specified index.
|
||||
Arg get_arg(unsigned arg_index, const char *&error) {
|
||||
return check_no_auto_index(error) ? do_get_arg(arg_index, error) : Arg();
|
||||
format_arg get_arg(unsigned arg_index, const char *&error) {
|
||||
return this->check_no_auto_index(error) ?
|
||||
this->do_get_arg(arg_index, error) : format_arg();
|
||||
}
|
||||
|
||||
// Returns the next argument.
|
||||
format_arg next_arg(const char *&error) {
|
||||
if (next_arg_index_ >= 0)
|
||||
return this->do_get_arg(internal::to_unsigned(next_arg_index_++), error);
|
||||
error = "cannot switch from manual to automatic argument indexing";
|
||||
return format_arg();
|
||||
}
|
||||
|
||||
bool check_no_auto_index(const char *&error) {
|
||||
@ -2132,13 +2143,11 @@ private:
|
||||
next_arg_index_ = -1;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
inline void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
|
||||
if (start != end)
|
||||
w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
|
||||
}
|
||||
public:
|
||||
// Returns a pointer to the current position in the format string.
|
||||
const Char *&ptr() { return ptr_; }
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
@ -2161,8 +2170,7 @@ inline void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
|
||||
template <typename Impl, typename Char>
|
||||
class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
|
||||
private:
|
||||
basic_formatter<Char, Impl> &formatter_;
|
||||
const Char *format_;
|
||||
basic_format_context<Char> &ctx_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -2173,15 +2181,13 @@ class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
|
||||
to the part of the format string being parsed for custom argument types.
|
||||
\endrst
|
||||
*/
|
||||
BasicArgFormatter(BasicWriter<Char> &writer,
|
||||
basic_formatter<Char, Impl> &formatter,
|
||||
FormatSpec &spec, const Char *fmt)
|
||||
: internal::ArgFormatterBase<Impl, Char>(writer, spec),
|
||||
formatter_(formatter), format_(fmt) {}
|
||||
BasicArgFormatter(BasicWriter<Char> &writer, basic_format_context<Char> &ctx,
|
||||
FormatSpec &spec)
|
||||
: internal::ArgFormatterBase<Impl, Char>(writer, spec), ctx_(ctx) {}
|
||||
|
||||
/** Formats an argument of a custom (user-defined) type. */
|
||||
void visit_custom(internal::Arg::CustomValue c) {
|
||||
c.format(&this->writer(), c.value, &formatter_, &format_);
|
||||
c.format(&this->writer(), c.value, &ctx_);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2190,49 +2196,45 @@ template <typename Char>
|
||||
class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
|
||||
public:
|
||||
/** Constructs an argument formatter object. */
|
||||
ArgFormatter(BasicWriter<Char> &writer, basic_formatter<Char> &formatter,
|
||||
FormatSpec &spec, const Char *fmt)
|
||||
: BasicArgFormatter<ArgFormatter<Char>, Char>(writer, formatter, spec, fmt) {}
|
||||
ArgFormatter(BasicWriter<Char> &writer, basic_format_context<Char> &ctx,
|
||||
FormatSpec &spec)
|
||||
: BasicArgFormatter<ArgFormatter<Char>, Char>(writer, ctx, spec) {}
|
||||
};
|
||||
|
||||
/** This template formats data and writes the output to a writer. */
|
||||
template <typename Char, typename ArgFormatter>
|
||||
class basic_formatter :
|
||||
private internal::FormatterBase<basic_formatter<Char, ArgFormatter>> {
|
||||
public:
|
||||
/** The character type for the output. */
|
||||
typedef Char char_type;
|
||||
|
||||
template <typename Char>
|
||||
class basic_format_context :
|
||||
public internal::format_context_base<Char, basic_format_context<Char>> {
|
||||
private:
|
||||
internal::ArgMap<Char> map_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(basic_formatter);
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(basic_format_context);
|
||||
|
||||
typedef internal::format_context_base<Char, basic_format_context> Base;
|
||||
|
||||
typedef internal::FormatterBase<basic_formatter> Base;
|
||||
using Base::get_arg;
|
||||
|
||||
// Checks if manual indexing is used and returns the argument with
|
||||
// specified name.
|
||||
internal::Arg get_arg(BasicStringRef<Char> arg_name, const char *&error);
|
||||
format_arg get_arg(BasicStringRef<Char> name, const char *&error);
|
||||
|
||||
public:
|
||||
/** The character type for the output. */
|
||||
typedef Char char_type;
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs a ``basic_formatter`` object. References to the arguments are
|
||||
stored in the formatter object so make sure they have appropriate lifetimes.
|
||||
Constructs a ``basic_format_context`` object. References to the arguments are
|
||||
stored in the object so make sure they have appropriate lifetimes.
|
||||
\endrst
|
||||
*/
|
||||
basic_formatter(basic_format_args<basic_formatter> args) : Base(args) {}
|
||||
basic_format_context(const Char *format_str,
|
||||
basic_format_args<basic_format_context> args)
|
||||
: Base(format_str, args) {}
|
||||
|
||||
// Parses argument index and returns corresponding argument.
|
||||
internal::Arg parse_arg_index(const Char *&s);
|
||||
|
||||
// Parses argument name and returns corresponding argument.
|
||||
internal::Arg parse_arg_name(const Char *&s);
|
||||
// Parses argument id and returns corresponding argument.
|
||||
format_arg parse_arg_id();
|
||||
|
||||
// Formats a single argument and advances format_str, a format string pointer.
|
||||
const Char *format(BasicWriter<Char> &writer, const Char *&format_str,
|
||||
const internal::Arg &arg);
|
||||
using Base::ptr;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2269,7 +2271,7 @@ class SystemError : public internal::RuntimeError {
|
||||
*/
|
||||
template <typename... Args>
|
||||
SystemError(int error_code, CStringRef message, const Args & ... args) {
|
||||
init(error_code, message, make_format_args<basic_formatter<char>>(args...));
|
||||
init(error_code, message, make_format_args<format_context>(args...));
|
||||
}
|
||||
|
||||
~SystemError() throw();
|
||||
@ -2464,10 +2466,7 @@ class BasicWriter {
|
||||
}
|
||||
|
||||
void vwrite(BasicCStringRef<Char> format,
|
||||
basic_format_args<basic_formatter<Char>> args) {
|
||||
vformat(*this, format, args);
|
||||
}
|
||||
|
||||
basic_format_args<basic_format_context<Char>> args);
|
||||
/**
|
||||
\rst
|
||||
Writes formatted data.
|
||||
@ -2495,7 +2494,7 @@ class BasicWriter {
|
||||
*/
|
||||
template <typename... Args>
|
||||
void write(BasicCStringRef<Char> format, const Args & ... args) {
|
||||
vwrite(format, make_format_args<fmt::basic_formatter<Char>>(args...));
|
||||
vwrite(format, make_format_args<basic_format_context<Char>>(args...));
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(int value) {
|
||||
@ -3123,7 +3122,7 @@ class WindowsError : public SystemError {
|
||||
*/
|
||||
template <typename... Args>
|
||||
WindowsError(int error_code, CStringRef message, const Args & ... args) {
|
||||
init(error_code, message, make_format_args<basic_formatter<char>>(args...));
|
||||
init(error_code, message, make_format_args<format_context>(args...));
|
||||
}
|
||||
};
|
||||
|
||||
@ -3147,8 +3146,7 @@ FMT_API void vprint_colored(Color c, CStringRef format, format_args args);
|
||||
template <typename... Args>
|
||||
inline void print_colored(Color c, CStringRef format_str,
|
||||
const Args & ... args) {
|
||||
vprint_colored(c, format_str,
|
||||
make_format_args<basic_formatter<char>>(args...));
|
||||
vprint_colored(c, format_str, make_format_args<format_context>(args...));
|
||||
}
|
||||
|
||||
inline std::string vformat(CStringRef format_str, format_args args) {
|
||||
@ -3168,7 +3166,7 @@ inline std::string vformat(CStringRef format_str, format_args args) {
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline std::string format(CStringRef format_str, const Args & ... args) {
|
||||
return vformat(format_str, make_format_args<basic_formatter<char>>(args...));
|
||||
return vformat(format_str, make_format_args<format_context>(args...));
|
||||
}
|
||||
|
||||
inline std::wstring vformat(WCStringRef format_str, wformat_args args) {
|
||||
@ -3179,7 +3177,7 @@ inline std::wstring vformat(WCStringRef format_str, wformat_args args) {
|
||||
|
||||
template <typename... Args>
|
||||
inline std::wstring format(WCStringRef format_str, const Args & ... args) {
|
||||
auto vargs = make_format_args<basic_formatter<wchar_t>>(args...);
|
||||
auto vargs = make_format_args<wformat_context>(args...);
|
||||
return vformat(format_str, vargs);
|
||||
}
|
||||
|
||||
@ -3196,7 +3194,7 @@ FMT_API void vprint(std::FILE *f, CStringRef format_str, format_args args);
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline void print(std::FILE *f, CStringRef format_str, const Args & ... args) {
|
||||
vprint(f, format_str, make_format_args<basic_formatter<char>>(args...));
|
||||
vprint(f, format_str, make_format_args<format_context>(args...));
|
||||
}
|
||||
|
||||
FMT_API void vprint(CStringRef format_str, format_args args);
|
||||
@ -3212,7 +3210,7 @@ FMT_API void vprint(CStringRef format_str, format_args args);
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline void print(CStringRef format_str, const Args & ... args) {
|
||||
vprint(format_str, make_format_args<basic_formatter<char>>(args...));
|
||||
vprint(format_str, make_format_args<format_context>(args...));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3405,57 +3403,55 @@ void check_sign(const Char *&s, const Arg &arg) {
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
template <typename Char, typename AF>
|
||||
inline internal::Arg basic_formatter<Char, AF>::get_arg(
|
||||
BasicStringRef<Char> arg_name, const char *&error) {
|
||||
template <typename Char>
|
||||
inline format_arg basic_format_context<Char>::get_arg(
|
||||
BasicStringRef<Char> name, const char *&error) {
|
||||
if (this->check_no_auto_index(error)) {
|
||||
map_.init(this->args());
|
||||
const internal::Arg *arg = map_.find(arg_name);
|
||||
const internal::Arg *arg = map_.find(name);
|
||||
if (arg)
|
||||
return *arg;
|
||||
error = "argument not found";
|
||||
}
|
||||
return internal::Arg();
|
||||
return format_arg();
|
||||
}
|
||||
|
||||
template <typename Char, typename AF>
|
||||
inline internal::Arg basic_formatter<Char, AF>::parse_arg_index(
|
||||
const Char *&s) {
|
||||
const char *error = 0;
|
||||
internal::Arg arg = *s < '0' || *s > '9' ?
|
||||
this->next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error);
|
||||
if (error) {
|
||||
FMT_THROW(format_error(
|
||||
*s != '}' && *s != ':' ? "invalid format string" : error));
|
||||
template <typename Char>
|
||||
inline format_arg basic_format_context<Char>::parse_arg_id() {
|
||||
const Char *&s = this->ptr();
|
||||
if (!internal::is_name_start(*s)) {
|
||||
const char *error = 0;
|
||||
format_arg arg = *s < '0' || *s > '9' ?
|
||||
this->next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error);
|
||||
if (error) {
|
||||
FMT_THROW(format_error(
|
||||
*s != '}' && *s != ':' ? "invalid format string" : error));
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <typename Char, typename AF>
|
||||
inline internal::Arg basic_formatter<Char, AF>::parse_arg_name(const Char *&s) {
|
||||
assert(internal::is_name_start(*s));
|
||||
const Char *start = s;
|
||||
Char c;
|
||||
do {
|
||||
c = *++s;
|
||||
} while (internal::is_name_start(c) || ('0' <= c && c <= '9'));
|
||||
const char *error = 0;
|
||||
internal::Arg arg = get_arg(BasicStringRef<Char>(start, s - start), error);
|
||||
format_arg arg = get_arg(BasicStringRef<Char>(start, s - start), error);
|
||||
if (error)
|
||||
FMT_THROW(format_error(error));
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <typename Char, typename ArgFormatter>
|
||||
const Char *basic_formatter<Char, ArgFormatter>::format(
|
||||
BasicWriter<Char> &writer, const Char *&format_str, const internal::Arg &arg) {
|
||||
// Formats a single argument.
|
||||
template <typename ArgFormatter, typename Char, typename Context>
|
||||
void format_arg(BasicWriter<Char> &writer, const internal::Arg &arg,
|
||||
Context &ctx) {
|
||||
using internal::Arg;
|
||||
const Char *s = format_str;
|
||||
const Char *&s = ctx.ptr();
|
||||
FormatSpec spec;
|
||||
if (*s == ':') {
|
||||
if (arg.type == Arg::CUSTOM) {
|
||||
arg.custom.format(&writer, arg.custom.value, this, &s);
|
||||
return s;
|
||||
arg.custom.format(&writer, arg.custom.value, &ctx);
|
||||
return;
|
||||
}
|
||||
++s;
|
||||
// Parse fill and alignment.
|
||||
@ -3527,8 +3523,7 @@ const Char *basic_formatter<Char, ArgFormatter>::format(
|
||||
spec.width_ = internal::parse_nonnegative_int(s);
|
||||
} else if (*s == '{') {
|
||||
++s;
|
||||
Arg width_arg = internal::is_name_start(*s) ?
|
||||
parse_arg_name(s) : parse_arg_index(s);
|
||||
Arg width_arg = ctx.parse_arg_id();
|
||||
if (*s++ != '}')
|
||||
FMT_THROW(format_error("invalid format string"));
|
||||
ULongLong value = 0;
|
||||
@ -3565,8 +3560,7 @@ const Char *basic_formatter<Char, ArgFormatter>::format(
|
||||
spec.precision_ = internal::parse_nonnegative_int(s);
|
||||
} else if (*s == '{') {
|
||||
++s;
|
||||
Arg precision_arg = internal::is_name_start(*s) ?
|
||||
parse_arg_name(s) : parse_arg_index(s);
|
||||
Arg precision_arg = ctx.parse_arg_id();
|
||||
if (*s++ != '}')
|
||||
FMT_THROW(format_error("invalid format string"));
|
||||
ULongLong value = 0;
|
||||
@ -3608,20 +3602,19 @@ const Char *basic_formatter<Char, ArgFormatter>::format(
|
||||
spec.type_ = static_cast<char>(*s++);
|
||||
}
|
||||
|
||||
if (*s++ != '}')
|
||||
if (*s != '}')
|
||||
FMT_THROW(format_error("missing '}' in format string"));
|
||||
|
||||
// Format argument.
|
||||
ArgFormatter(writer, *this, spec, s - 1).visit(arg);
|
||||
return s;
|
||||
ArgFormatter(writer, ctx, spec).visit(arg);
|
||||
}
|
||||
|
||||
/** Formats arguments and writes the output to the writer. */
|
||||
template <typename ArgFormatter, typename Char = typename ArgFormatter::Char>
|
||||
template <typename ArgFormatter, typename Char, typename Context>
|
||||
void vformat(BasicWriter<Char> &writer, BasicCStringRef<Char> format_str,
|
||||
basic_format_args<basic_formatter<Char, ArgFormatter>> args) {
|
||||
basic_formatter<Char, ArgFormatter> formatter(args);
|
||||
const Char *s = format_str.c_str();
|
||||
basic_format_args<Context> args) {
|
||||
basic_format_context<Char> ctx(format_str.c_str(), args);
|
||||
const Char *&s = ctx.ptr();
|
||||
const Char *start = s;
|
||||
while (*s) {
|
||||
Char c = *s++;
|
||||
@ -3634,12 +3627,19 @@ void vformat(BasicWriter<Char> &writer, BasicCStringRef<Char> format_str,
|
||||
if (c == '}')
|
||||
FMT_THROW(format_error("unmatched '}' in format string"));
|
||||
internal::write(writer, start, s - 1);
|
||||
internal::Arg arg = internal::is_name_start(*s) ?
|
||||
formatter.parse_arg_name(s) : formatter.parse_arg_index(s);
|
||||
start = s = formatter.format(writer, s, arg);
|
||||
format_arg<ArgFormatter>(writer, ctx.parse_arg_id(), ctx);
|
||||
assert(*s == '}');
|
||||
start = ++s;
|
||||
}
|
||||
internal::write(writer, start, s);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void BasicWriter<Char>::vwrite(
|
||||
BasicCStringRef<Char> format,
|
||||
basic_format_args<basic_format_context<Char>> args) {
|
||||
vformat<ArgFormatter<Char>>(*this, format, args);
|
||||
}
|
||||
} // namespace fmt
|
||||
|
||||
#if FMT_USE_USER_DEFINED_LITERALS
|
||||
|
@ -82,14 +82,13 @@ BasicStringRef<Char> format_value(
|
||||
} // namespace internal
|
||||
|
||||
// Formats a value.
|
||||
template <typename Char, typename ArgFormatter, typename T>
|
||||
template <typename Char, typename T>
|
||||
void format_value(BasicWriter<Char> &w, const T &value,
|
||||
basic_formatter<Char, ArgFormatter> &f,
|
||||
const Char *&format_str) {
|
||||
basic_format_context<Char> &ctx) {
|
||||
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||
auto str = internal::format_value(buffer, value);
|
||||
typedef internal::MakeArg< basic_formatter<Char> > MakeArg;
|
||||
format_str = f.format(w, format_str, MakeArg(str));
|
||||
typedef internal::MakeArg< basic_format_context<Char> > MakeArg;
|
||||
format_arg< ArgFormatter<Char> >(w, MakeArg(str), ctx);
|
||||
}
|
||||
|
||||
FMT_API void vprint(std::ostream &os, CStringRef format_str, format_args args);
|
||||
@ -106,7 +105,7 @@ FMT_API void vprint(std::ostream &os, CStringRef format_str, format_args args);
|
||||
template <typename... Args>
|
||||
inline void print(std::ostream &os, CStringRef format_str,
|
||||
const Args & ... args) {
|
||||
vprint(os, format_str, make_format_args<basic_formatter<char>>(args...));
|
||||
vprint(os, format_str, make_format_args<format_context>(args...));
|
||||
}
|
||||
} // namespace fmt
|
||||
|
||||
|
@ -172,7 +172,7 @@ public:
|
||||
|
||||
template <typename... Args>
|
||||
inline void print(CStringRef format_str, const Args & ... args) {
|
||||
vprint(format_str, make_format_args<basic_formatter<char>>(args...));
|
||||
vprint(format_str, make_format_args<format_context>(args...));
|
||||
}
|
||||
};
|
||||
|
||||
|
69
fmt/printf.h
69
fmt/printf.h
@ -262,11 +262,10 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
|
||||
|
||||
/** Formats an argument of a custom (user-defined) type. */
|
||||
void visit_custom(internal::Arg::CustomValue c) {
|
||||
typedef basic_formatter<Char> Formatter;
|
||||
Formatter formatter((basic_format_args<Formatter>()));
|
||||
const Char format_str[] = {'}', 0};
|
||||
const Char *format = format_str;
|
||||
c.format(&this->writer(), c.value, &formatter, &format);
|
||||
const Char format_str[] = {'}', '\0'};
|
||||
auto args = basic_format_args<basic_format_context<Char>>();
|
||||
basic_format_context<Char> ctx(format_str, args);
|
||||
c.format(&this->writer(), c.value, &ctx);
|
||||
}
|
||||
};
|
||||
|
||||
@ -283,14 +282,15 @@ class PrintfArgFormatter
|
||||
/** This template formats data and writes the output to a writer. */
|
||||
template <typename Char,
|
||||
typename ArgFormatter = PrintfArgFormatter<Char> >
|
||||
class PrintfFormatter :
|
||||
private internal::FormatterBase<PrintfFormatter<Char, ArgFormatter>> {
|
||||
class printf_context :
|
||||
private internal::format_context_base<
|
||||
Char, printf_context<Char, ArgFormatter>> {
|
||||
public:
|
||||
/** The character type for the output. */
|
||||
typedef Char char_type;
|
||||
|
||||
private:
|
||||
typedef internal::FormatterBase<PrintfFormatter> Base;
|
||||
typedef internal::format_context_base<Char, printf_context> Base;
|
||||
|
||||
void parse_flags(FormatSpec &spec, const Char *&s);
|
||||
|
||||
@ -306,21 +306,21 @@ class PrintfFormatter :
|
||||
public:
|
||||
/**
|
||||
\rst
|
||||
Constructs a ``PrintfFormatter`` object. References to the arguments and
|
||||
the writer are stored in the formatter object so make sure they have
|
||||
Constructs a ``printf_context`` object. References to the arguments and
|
||||
the writer are stored in the context object so make sure they have
|
||||
appropriate lifetimes.
|
||||
\endrst
|
||||
*/
|
||||
explicit PrintfFormatter(basic_format_args<PrintfFormatter> args)
|
||||
: Base(args) {}
|
||||
|
||||
explicit printf_context(BasicCStringRef<Char> format_str,
|
||||
basic_format_args<printf_context> args)
|
||||
: Base(format_str.c_str(), args) {}
|
||||
|
||||
/** Formats stored arguments and writes the output to the writer. */
|
||||
FMT_API void format(BasicWriter<Char> &writer,
|
||||
BasicCStringRef<Char> format_str);
|
||||
FMT_API void format(BasicWriter<Char> &writer);
|
||||
};
|
||||
|
||||
template <typename Char, typename AF>
|
||||
void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) {
|
||||
void printf_context<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) {
|
||||
for (;;) {
|
||||
switch (*s++) {
|
||||
case '-':
|
||||
@ -346,8 +346,8 @@ void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) {
|
||||
}
|
||||
|
||||
template <typename Char, typename AF>
|
||||
internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
|
||||
unsigned arg_index) {
|
||||
internal::Arg printf_context<Char, AF>::get_arg(const Char *s,
|
||||
unsigned arg_index) {
|
||||
(void)s;
|
||||
const char *error = 0;
|
||||
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
|
||||
@ -358,7 +358,7 @@ internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
|
||||
}
|
||||
|
||||
template <typename Char, typename AF>
|
||||
unsigned PrintfFormatter<Char, AF>::parse_header(
|
||||
unsigned printf_context<Char, AF>::parse_header(
|
||||
const Char *&s, FormatSpec &spec) {
|
||||
unsigned arg_index = std::numeric_limits<unsigned>::max();
|
||||
Char c = *s;
|
||||
@ -392,9 +392,8 @@ unsigned PrintfFormatter<Char, AF>::parse_header(
|
||||
}
|
||||
|
||||
template <typename Char, typename AF>
|
||||
void PrintfFormatter<Char, AF>::format(BasicWriter<Char> &writer,
|
||||
BasicCStringRef<Char> format_str) {
|
||||
const Char *start = format_str.c_str();
|
||||
void printf_context<Char, AF>::format(BasicWriter<Char> &writer) {
|
||||
const Char *start = this->ptr();
|
||||
const Char *s = start;
|
||||
while (*s) {
|
||||
Char c = *s++;
|
||||
@ -495,19 +494,19 @@ void PrintfFormatter<Char, AF>::format(BasicWriter<Char> &writer,
|
||||
// Formats a value.
|
||||
template <typename Char, typename T>
|
||||
void format_value(BasicWriter<Char> &w, const T &value,
|
||||
PrintfFormatter<Char> &f, const Char *&) {
|
||||
printf_context<Char>& ctx) {
|
||||
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||
w << internal::format_value(buffer, value);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format,
|
||||
basic_format_args<PrintfFormatter<Char>> args) {
|
||||
PrintfFormatter<Char>(args).format(w, format);
|
||||
basic_format_args<printf_context<Char>> args) {
|
||||
printf_context<Char>(format, args).format(w);
|
||||
}
|
||||
|
||||
inline std::string vsprintf(CStringRef format,
|
||||
basic_format_args<PrintfFormatter<char>> args) {
|
||||
basic_format_args<printf_context<char>> args) {
|
||||
MemoryWriter w;
|
||||
printf(w, format, args);
|
||||
return w.str();
|
||||
@ -524,11 +523,11 @@ inline std::string vsprintf(CStringRef format,
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline std::string sprintf(CStringRef format_str, const Args & ... args) {
|
||||
return vsprintf(format_str, make_format_args<PrintfFormatter<char>>(args...));
|
||||
return vsprintf(format_str, make_format_args<printf_context<char>>(args...));
|
||||
}
|
||||
|
||||
inline std::wstring vsprintf(WCStringRef format,
|
||||
basic_format_args<PrintfFormatter<wchar_t>> args) {
|
||||
basic_format_args<printf_context<wchar_t>> args) {
|
||||
WMemoryWriter w;
|
||||
printf(w, format, args);
|
||||
return w.str();
|
||||
@ -536,12 +535,12 @@ inline std::wstring vsprintf(WCStringRef format,
|
||||
|
||||
template <typename... Args>
|
||||
inline std::wstring sprintf(WCStringRef format_str, const Args & ... args) {
|
||||
auto vargs = make_format_args<PrintfFormatter<wchar_t>>(args...);
|
||||
auto vargs = make_format_args<printf_context<wchar_t>>(args...);
|
||||
return vsprintf(format_str, vargs);
|
||||
}
|
||||
|
||||
FMT_API int vfprintf(std::FILE *f, CStringRef format,
|
||||
basic_format_args<PrintfFormatter<char>> args);
|
||||
basic_format_args<printf_context<char>> args);
|
||||
|
||||
/**
|
||||
\rst
|
||||
@ -554,12 +553,12 @@ FMT_API int vfprintf(std::FILE *f, CStringRef format,
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline int fprintf(std::FILE *f, CStringRef format_str, const Args & ... args) {
|
||||
auto vargs = make_format_args<PrintfFormatter<char>>(args...);
|
||||
auto vargs = make_format_args<printf_context<char>>(args...);
|
||||
return vfprintf(f, format_str, vargs);
|
||||
}
|
||||
|
||||
inline int vprintf(CStringRef format,
|
||||
basic_format_args<PrintfFormatter<char>> args) {
|
||||
basic_format_args<printf_context<char>> args) {
|
||||
return vfprintf(stdout, format, args);
|
||||
}
|
||||
|
||||
@ -574,11 +573,11 @@ inline int vprintf(CStringRef format,
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline int printf(CStringRef format_str, const Args & ... args) {
|
||||
return vprintf(format_str, make_format_args<PrintfFormatter<char>>(args...));
|
||||
return vprintf(format_str, make_format_args<printf_context<char>>(args...));
|
||||
}
|
||||
|
||||
inline int vfprintf(std::ostream &os, CStringRef format_str,
|
||||
basic_format_args<PrintfFormatter<char>> args) {
|
||||
basic_format_args<printf_context<char>> args) {
|
||||
MemoryWriter w;
|
||||
printf(w, format_str, args);
|
||||
internal::write(os, w);
|
||||
@ -597,7 +596,7 @@ inline int vfprintf(std::ostream &os, CStringRef format_str,
|
||||
template <typename... Args>
|
||||
inline int fprintf(std::ostream &os, CStringRef format_str,
|
||||
const Args & ... args) {
|
||||
auto vargs = make_format_args<PrintfFormatter<char>>(args...);
|
||||
auto vargs = make_format_args<printf_context<char>>(args...);
|
||||
return vfprintf(os, format_str, vargs);
|
||||
}
|
||||
} // namespace fmt
|
||||
|
16
fmt/time.h
16
fmt/time.h
@ -15,19 +15,17 @@
|
||||
|
||||
namespace fmt {
|
||||
|
||||
template <typename ArgFormatter>
|
||||
void format_value(Writer &w, const std::tm &tm,
|
||||
basic_formatter<char, ArgFormatter> &f,
|
||||
const char *&format_str) {
|
||||
if (*format_str == ':')
|
||||
++format_str;
|
||||
const char *end = format_str;
|
||||
void format_value(Writer &w, const std::tm &tm, format_context &ctx) {
|
||||
const char *&s = ctx.ptr();
|
||||
if (*s == ':')
|
||||
++s;
|
||||
const char *end = s;
|
||||
while (*end && *end != '}')
|
||||
++end;
|
||||
if (*end != '}')
|
||||
FMT_THROW(format_error("missing '}' in format string"));
|
||||
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> format;
|
||||
format.append(format_str, end + 1);
|
||||
format.append(s, end + 1);
|
||||
format[format.size() - 1] = '\0';
|
||||
Buffer<char> &buffer = w.buffer();
|
||||
std::size_t start = buffer.size();
|
||||
@ -48,7 +46,7 @@ void format_value(Writer &w, const std::tm &tm,
|
||||
const std::size_t MIN_GROWTH = 10;
|
||||
buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
|
||||
}
|
||||
format_str = end + 1;
|
||||
s = end;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,9 @@ using fmt::BasicPrintfArgFormatter;
|
||||
class CustomArgFormatter
|
||||
: public fmt::BasicArgFormatter<CustomArgFormatter, char> {
|
||||
public:
|
||||
CustomArgFormatter(fmt::Writer &w,
|
||||
fmt::basic_formatter<char, CustomArgFormatter> &f,
|
||||
fmt::FormatSpec &s, const char *fmt)
|
||||
: fmt::BasicArgFormatter<CustomArgFormatter, char>(w, f, s, fmt) {}
|
||||
CustomArgFormatter(fmt::Writer &w, fmt::basic_format_context<char> &ctx,
|
||||
fmt::FormatSpec &s)
|
||||
: fmt::BasicArgFormatter<CustomArgFormatter, char>(w, ctx, s) {}
|
||||
|
||||
void visit_double(double value) {
|
||||
if (round(value * pow(10, spec().precision())) == 0)
|
||||
@ -46,10 +45,7 @@ class CustomPrintfArgFormatter :
|
||||
}
|
||||
};
|
||||
|
||||
typedef fmt::basic_formatter<char, CustomArgFormatter> CustomFormatter;
|
||||
|
||||
std::string custom_vformat(fmt::CStringRef format_str,
|
||||
fmt::basic_format_args<CustomFormatter> args) {
|
||||
std::string custom_vformat(fmt::CStringRef format_str, fmt::format_args args) {
|
||||
fmt::MemoryWriter writer;
|
||||
// Pass custom argument formatter as a template arg to vformat.
|
||||
fmt::vformat<CustomArgFormatter>(writer, format_str, args);
|
||||
@ -58,19 +54,19 @@ std::string custom_vformat(fmt::CStringRef format_str,
|
||||
|
||||
template <typename... Args>
|
||||
std::string custom_format(const char *format_str, const Args & ... args) {
|
||||
auto va = fmt::make_format_args<CustomFormatter>(args...);
|
||||
auto va = fmt::make_format_args<fmt::format_context>(args...);
|
||||
return custom_vformat(format_str, va);
|
||||
}
|
||||
|
||||
typedef fmt::PrintfFormatter<char, CustomPrintfArgFormatter>
|
||||
typedef fmt::printf_context<char, CustomPrintfArgFormatter>
|
||||
CustomPrintfFormatter;
|
||||
|
||||
std::string custom_vsprintf(
|
||||
const char* format_str,
|
||||
fmt::basic_format_args<CustomPrintfFormatter> args) {
|
||||
fmt::MemoryWriter writer;
|
||||
CustomPrintfFormatter formatter(args);
|
||||
formatter.format(writer, format_str);
|
||||
CustomPrintfFormatter formatter(format_str, args);
|
||||
formatter.format(writer);
|
||||
return writer.str();
|
||||
}
|
||||
|
||||
|
@ -1355,8 +1355,7 @@ TEST(FormatterTest, FormatCStringRef) {
|
||||
EXPECT_EQ("test", format("{0}", CStringRef("test")));
|
||||
}
|
||||
|
||||
void format_value(fmt::Writer &w, const Date &d, fmt::basic_formatter<char> &f,
|
||||
const char *) {
|
||||
void format_value(fmt::Writer &w, const Date &d, fmt::format_context &) {
|
||||
w << d.year() << '-' << d.month() << '-' << d.day();
|
||||
}
|
||||
|
||||
@ -1369,8 +1368,7 @@ TEST(FormatterTest, FormatCustom) {
|
||||
class Answer {};
|
||||
|
||||
template <typename Char>
|
||||
void format_value(BasicWriter<Char> &w, Answer, fmt::basic_formatter<Char> &f,
|
||||
const Char *) {
|
||||
void format_value(BasicWriter<Char> &w, Answer, fmt::format_context &) {
|
||||
w << "42";
|
||||
}
|
||||
|
||||
@ -1561,7 +1559,7 @@ std::string vformat_message(int id, const char *format, fmt::format_args args) {
|
||||
|
||||
template <typename... Args>
|
||||
std::string format_message(int id, const char *format, const Args & ... args) {
|
||||
auto va = fmt::make_format_args<fmt::basic_formatter<char>>(args...);
|
||||
auto va = fmt::make_format_args<fmt::format_context>(args...);
|
||||
return vformat_message(id, format, va);
|
||||
}
|
||||
|
||||
@ -1626,9 +1624,8 @@ class MockArgFormatter :
|
||||
public:
|
||||
typedef fmt::internal::ArgFormatterBase<MockArgFormatter, char> Base;
|
||||
|
||||
MockArgFormatter(fmt::Writer &w,
|
||||
fmt::basic_formatter<char, MockArgFormatter> &f,
|
||||
fmt::FormatSpec &s, const char *)
|
||||
MockArgFormatter(fmt::Writer &w, fmt::format_context &ctx,
|
||||
fmt::FormatSpec &s)
|
||||
: fmt::internal::ArgFormatterBase<MockArgFormatter, char>(w, s) {
|
||||
EXPECT_CALL(*this, visit_int(42));
|
||||
}
|
||||
@ -1636,17 +1633,14 @@ class MockArgFormatter :
|
||||
MOCK_METHOD1(visit_int, void (int value));
|
||||
};
|
||||
|
||||
typedef fmt::basic_formatter<char, MockArgFormatter> CustomFormatter;
|
||||
|
||||
void custom_vformat(fmt::CStringRef format_str,
|
||||
fmt::basic_format_args<CustomFormatter> args) {
|
||||
void custom_vformat(fmt::CStringRef format_str, fmt::format_args args) {
|
||||
fmt::MemoryWriter writer;
|
||||
vformat(writer, format_str, args);
|
||||
fmt::vformat<MockArgFormatter>(writer, format_str, args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void custom_format(const char *format_str, const Args & ... args) {
|
||||
auto va = fmt::make_format_args<CustomFormatter>(args...);
|
||||
auto va = fmt::make_format_args<fmt::format_context>(args...);
|
||||
return custom_vformat(format_str, va);
|
||||
}
|
||||
|
||||
|
@ -59,19 +59,17 @@ TEST(OStreamTest, Enum) {
|
||||
}
|
||||
|
||||
struct TestArgFormatter : fmt::BasicArgFormatter<TestArgFormatter, char> {
|
||||
TestArgFormatter(fmt::Writer &w,
|
||||
fmt::basic_formatter<char, TestArgFormatter> &f,
|
||||
fmt::FormatSpec &s, const char *fmt)
|
||||
: fmt::BasicArgFormatter<TestArgFormatter, char>(w, f, s, fmt) {}
|
||||
TestArgFormatter(fmt::Writer &w, fmt::format_context &ctx,
|
||||
fmt::FormatSpec &s)
|
||||
: fmt::BasicArgFormatter<TestArgFormatter, char>(w, ctx, s) {}
|
||||
};
|
||||
|
||||
TEST(OStreamTest, CustomArg) {
|
||||
fmt::MemoryWriter writer;
|
||||
typedef fmt::basic_formatter<char, TestArgFormatter> Formatter;
|
||||
Formatter formatter((fmt::basic_format_args<Formatter>()));
|
||||
fmt::format_context ctx("}", fmt::format_args());
|
||||
fmt::FormatSpec spec;
|
||||
TestArgFormatter af(writer, formatter, spec, "}");
|
||||
af.visit(fmt::internal::MakeArg<Formatter>(TestEnum()));
|
||||
TestArgFormatter af(writer, ctx, spec);
|
||||
af.visit(fmt::internal::MakeArg<fmt::format_context>(TestEnum()));
|
||||
EXPECT_EQ("TestEnum", writer.str());
|
||||
}
|
||||
|
||||
|
@ -65,13 +65,13 @@ struct Test {};
|
||||
|
||||
template <typename Char>
|
||||
void format_value(fmt::BasicWriter<Char> &w, Test,
|
||||
fmt::basic_formatter<Char> &f, const Char *) {
|
||||
fmt::basic_format_context<Char> &) {
|
||||
w << "test";
|
||||
}
|
||||
|
||||
template <typename Char, typename T>
|
||||
Arg make_arg(const T &value) {
|
||||
typedef fmt::internal::MakeValue< fmt::basic_formatter<Char> > MakeValue;
|
||||
typedef fmt::internal::MakeValue< fmt::basic_format_context<Char> > MakeValue;
|
||||
Arg arg = MakeValue(value);
|
||||
arg.type = fmt::internal::type<T>();
|
||||
return arg;
|
||||
@ -567,9 +567,8 @@ TEST(ArgTest, MakeArg) {
|
||||
EXPECT_EQ(fmt::internal::Arg::CUSTOM, arg.type);
|
||||
EXPECT_EQ(&t, arg.custom.value);
|
||||
fmt::MemoryWriter w;
|
||||
fmt::basic_formatter<char> formatter((fmt::format_args()));
|
||||
const char *s = "}";
|
||||
arg.custom.format(&w, &formatter, &t, &s);
|
||||
fmt::format_context ctx("}", fmt::format_args());
|
||||
arg.custom.format(&w, &t, &ctx);
|
||||
EXPECT_EQ("test", w.str());
|
||||
}
|
||||
|
||||
@ -580,21 +579,20 @@ TEST(UtilTest, FormatArgs) {
|
||||
|
||||
struct CustomFormatter {
|
||||
typedef char char_type;
|
||||
bool called;
|
||||
};
|
||||
|
||||
void format_value(fmt::Writer &, const Test &, CustomFormatter &,
|
||||
const char *&s) {
|
||||
s = "custom_format";
|
||||
void format_value(fmt::Writer &, const Test &, CustomFormatter &ctx) {
|
||||
ctx.called = true;
|
||||
}
|
||||
|
||||
TEST(UtilTest, MakeValueWithCustomFormatter) {
|
||||
::Test t;
|
||||
Arg arg = fmt::internal::MakeValue<CustomFormatter>(t);
|
||||
CustomFormatter formatter;
|
||||
const char *s = "";
|
||||
CustomFormatter ctx = {false};
|
||||
fmt::MemoryWriter w;
|
||||
arg.custom.format(&w, &formatter, &t, &s);
|
||||
EXPECT_STREQ("custom_format", s);
|
||||
arg.custom.format(&w, &t, &ctx);
|
||||
EXPECT_TRUE(ctx.called);
|
||||
}
|
||||
|
||||
struct Result {
|
||||
|
Loading…
Reference in New Issue
Block a user