Replace formatter with context

This commit is contained in:
Victor Zverovich 2016-11-06 16:11:24 -08:00
parent 2bba420337
commit 9998f66f8c
10 changed files with 223 additions and 242 deletions

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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...));
}
};

View File

@ -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

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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());
}

View File

@ -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 {