Pass writer directly to format_value (#400)

This commit is contained in:
Victor Zverovich
2016-10-26 17:54:11 -07:00
parent b656a1c133
commit 2bba420337
8 changed files with 76 additions and 89 deletions

View File

@ -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 internal::ArgMap<char>::init(const format_args &args);
template void PrintfFormatter<char>::format(CStringRef format); template void PrintfFormatter<char>::format(Writer &writer, CStringRef format);
template int internal::CharTraits<char>::format_float( template int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format, char *buffer, std::size_t size, const char *format,
@ -479,7 +479,8 @@ template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
template void internal::ArgMap<wchar_t>::init(const format_args &args); template void internal::ArgMap<wchar_t>::init(const format_args &args);
template void PrintfFormatter<wchar_t>::format(WCStringRef format); template void PrintfFormatter<wchar_t>::format(WWriter &writer,
WCStringRef format);
template int internal::CharTraits<wchar_t>::format_float( template int internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format, wchar_t *buffer, std::size_t size, const wchar_t *format,

View File

@ -2132,13 +2132,13 @@ private:
next_arg_index_ = -1; next_arg_index_ = -1;
return true; return true;
} }
template <typename Char>
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>
inline void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
if (start != end)
w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
}
} // namespace internal } // namespace internal
/** /**
@ -2173,14 +2173,15 @@ class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
to the part of the format string being parsed for custom argument types. to the part of the format string being parsed for custom argument types.
\endrst \endrst
*/ */
BasicArgFormatter(basic_formatter<Char, Impl> &formatter, BasicArgFormatter(BasicWriter<Char> &writer,
basic_formatter<Char, Impl> &formatter,
FormatSpec &spec, const Char *fmt) FormatSpec &spec, const Char *fmt)
: internal::ArgFormatterBase<Impl, Char>(formatter.writer(), spec), : internal::ArgFormatterBase<Impl, Char>(writer, spec),
formatter_(formatter), format_(fmt) {} formatter_(formatter), format_(fmt) {}
/** Formats an argument of a custom (user-defined) type. */ /** Formats an argument of a custom (user-defined) type. */
void visit_custom(internal::Arg::CustomValue c) { void visit_custom(internal::Arg::CustomValue c) {
c.format(&formatter_.writer(), c.value, &formatter_, &format_); c.format(&this->writer(), c.value, &formatter_, &format_);
} }
}; };
@ -2189,9 +2190,9 @@ template <typename Char>
class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> { class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
public: public:
/** Constructs an argument formatter object. */ /** Constructs an argument formatter object. */
ArgFormatter(basic_formatter<Char> &formatter, ArgFormatter(BasicWriter<Char> &writer, basic_formatter<Char> &formatter,
FormatSpec &spec, const Char *fmt) FormatSpec &spec, const Char *fmt)
: BasicArgFormatter<ArgFormatter<Char>, Char>(formatter, spec, fmt) {} : BasicArgFormatter<ArgFormatter<Char>, Char>(writer, formatter, spec, fmt) {}
}; };
/** This template formats data and writes the output to a writer. */ /** This template formats data and writes the output to a writer. */
@ -2203,7 +2204,6 @@ class basic_formatter :
typedef Char char_type; typedef Char char_type;
private: private:
BasicWriter<Char> &writer_;
internal::ArgMap<Char> map_; internal::ArgMap<Char> map_;
FMT_DISALLOW_COPY_AND_ASSIGN(basic_formatter); FMT_DISALLOW_COPY_AND_ASSIGN(basic_formatter);
@ -2215,41 +2215,26 @@ class basic_formatter :
// specified name. // specified name.
internal::Arg get_arg(BasicStringRef<Char> arg_name, const char *&error); internal::Arg get_arg(BasicStringRef<Char> arg_name, const char *&error);
// 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);
public: public:
/** /**
\rst \rst
Constructs a ``basic_formatter`` object. References to the arguments and Constructs a ``basic_formatter`` object. References to the arguments are
the writer are stored in the formatter object so make sure they have stored in the formatter object so make sure they have appropriate lifetimes.
appropriate lifetimes.
\endrst \endrst
*/ */
basic_formatter(basic_format_args<basic_formatter> args, BasicWriter<Char> &w) basic_formatter(basic_format_args<basic_formatter> args) : Base(args) {}
: Base(args), writer_(w) {}
/** Returns a reference to the writer associated with this formatter. */ // Parses argument index and returns corresponding argument.
BasicWriter<Char> &writer() { return writer_; } internal::Arg parse_arg_index(const Char *&s);
/** Formats stored arguments and writes the output to the writer. */ // Parses argument name and returns corresponding argument.
void format(BasicCStringRef<Char> format_str); internal::Arg parse_arg_name(const Char *&s);
// Formats a single argument and advances format_str, a format string pointer. // Formats a single argument and advances format_str, a format string pointer.
const Char *format(const Char *&format_str, const internal::Arg &arg); const Char *format(BasicWriter<Char> &writer, const Char *&format_str,
const internal::Arg &arg);
}; };
template <typename ArgFormatter, typename Char = typename ArgFormatter::Char>
void vformat(BasicWriter<Char> &writer,
BasicCStringRef<Char> format_str,
basic_format_args<basic_formatter<Char, ArgFormatter>> args) {
basic_formatter<Char, ArgFormatter> formatter(args, writer);
formatter.format(format_str);
}
/** /**
An error returned by an operating system or a language runtime, An error returned by an operating system or a language runtime,
for example a file opening error. for example a file opening error.
@ -3463,13 +3448,13 @@ inline internal::Arg basic_formatter<Char, AF>::parse_arg_name(const Char *&s) {
template <typename Char, typename ArgFormatter> template <typename Char, typename ArgFormatter>
const Char *basic_formatter<Char, ArgFormatter>::format( const Char *basic_formatter<Char, ArgFormatter>::format(
const Char *&format_str, const internal::Arg &arg) { BasicWriter<Char> &writer, const Char *&format_str, const internal::Arg &arg) {
using internal::Arg; using internal::Arg;
const Char *s = format_str; const Char *s = format_str;
FormatSpec spec; FormatSpec spec;
if (*s == ':') { if (*s == ':') {
if (arg.type == Arg::CUSTOM) { if (arg.type == Arg::CUSTOM) {
arg.custom.format(&writer(), arg.custom.value, this, &s); arg.custom.format(&writer, arg.custom.value, this, &s);
return s; return s;
} }
++s; ++s;
@ -3627,30 +3612,33 @@ const Char *basic_formatter<Char, ArgFormatter>::format(
FMT_THROW(format_error("missing '}' in format string")); FMT_THROW(format_error("missing '}' in format string"));
// Format argument. // Format argument.
ArgFormatter(*this, spec, s - 1).visit(arg); ArgFormatter(writer, *this, spec, s - 1).visit(arg);
return s; return s;
} }
template <typename Char, typename AF> /** Formats arguments and writes the output to the writer. */
void basic_formatter<Char, AF>::format(BasicCStringRef<Char> format_str) { template <typename ArgFormatter, typename Char = typename ArgFormatter::Char>
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(); const Char *s = format_str.c_str();
const Char *start = s; const Char *start = s;
while (*s) { while (*s) {
Char c = *s++; Char c = *s++;
if (c != '{' && c != '}') continue; if (c != '{' && c != '}') continue;
if (*s == c) { if (*s == c) {
this->write(writer_, start, s); internal::write(writer, start, s);
start = ++s; start = ++s;
continue; continue;
} }
if (c == '}') if (c == '}')
FMT_THROW(format_error("unmatched '}' in format string")); FMT_THROW(format_error("unmatched '}' in format string"));
this->write(writer_, start, s - 1); internal::write(writer, start, s - 1);
internal::Arg arg = internal::is_name_start(*s) ? internal::Arg arg = internal::is_name_start(*s) ?
parse_arg_name(s) : parse_arg_index(s); formatter.parse_arg_name(s) : formatter.parse_arg_index(s);
start = s = format(s, arg); start = s = formatter.format(writer, s, arg);
} }
this->write(writer_, start, s); internal::write(writer, start, s);
} }
} // namespace fmt } // namespace fmt

View File

@ -89,7 +89,7 @@ void format_value(BasicWriter<Char> &w, const T &value,
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer; internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
auto str = internal::format_value(buffer, value); auto str = internal::format_value(buffer, value);
typedef internal::MakeArg< basic_formatter<Char> > MakeArg; typedef internal::MakeArg< basic_formatter<Char> > MakeArg;
format_str = f.format(format_str, MakeArg(str)); format_str = f.format(w, format_str, MakeArg(str));
} }
FMT_API void vprint(std::ostream &os, CStringRef format_str, format_args args); FMT_API void vprint(std::ostream &os, CStringRef format_str, format_args args);

View File

@ -262,11 +262,11 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
/** Formats an argument of a custom (user-defined) type. */ /** Formats an argument of a custom (user-defined) type. */
void visit_custom(internal::Arg::CustomValue c) { void visit_custom(internal::Arg::CustomValue c) {
basic_formatter<Char> formatter(basic_format_args<basic_formatter<Char>>(), typedef basic_formatter<Char> Formatter;
this->writer()); Formatter formatter((basic_format_args<Formatter>()));
const Char format_str[] = {'}', 0}; const Char format_str[] = {'}', 0};
const Char *format = format_str; const Char *format = format_str;
c.format(&formatter.writer(), c.value, &formatter, &format); c.format(&this->writer(), c.value, &formatter, &format);
} }
}; };
@ -290,8 +290,6 @@ class PrintfFormatter :
typedef Char char_type; typedef Char char_type;
private: private:
BasicWriter<Char> &writer_;
typedef internal::FormatterBase<PrintfFormatter> Base; typedef internal::FormatterBase<PrintfFormatter> Base;
void parse_flags(FormatSpec &spec, const Char *&s); void parse_flags(FormatSpec &spec, const Char *&s);
@ -313,14 +311,12 @@ class PrintfFormatter :
appropriate lifetimes. appropriate lifetimes.
\endrst \endrst
*/ */
explicit PrintfFormatter(basic_format_args<PrintfFormatter> args, explicit PrintfFormatter(basic_format_args<PrintfFormatter> args)
BasicWriter<Char> &w) : Base(args) {}
: Base(args), writer_(w) {}
BasicWriter<Char> &writer() { return writer_; }
/** Formats stored arguments and writes the output to the writer. */ /** Formats stored arguments and writes the output to the writer. */
FMT_API void format(BasicCStringRef<Char> format_str); FMT_API void format(BasicWriter<Char> &writer,
BasicCStringRef<Char> format_str);
}; };
template <typename Char, typename AF> template <typename Char, typename AF>
@ -396,18 +392,19 @@ unsigned PrintfFormatter<Char, AF>::parse_header(
} }
template <typename Char, typename AF> template <typename Char, typename AF>
void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) { void PrintfFormatter<Char, AF>::format(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;
while (*s) { while (*s) {
Char c = *s++; Char c = *s++;
if (c != '%') continue; if (c != '%') continue;
if (*s == c) { if (*s == c) {
this->write(writer_, start, s); internal::write(writer, start, s);
start = ++s; start = ++s;
continue; continue;
} }
this->write(writer_, start, s - 1); internal::write(writer, start, s - 1);
FormatSpec spec; FormatSpec spec;
spec.align_ = ALIGN_RIGHT; spec.align_ = ALIGN_RIGHT;
@ -490,9 +487,9 @@ void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) {
start = s; start = s;
// Format argument. // Format argument.
AF(writer_, spec).visit(arg); AF(writer, spec).visit(arg);
} }
this->write(writer_, start, s); internal::write(writer, start, s);
} }
// Formats a value. // Formats a value.
@ -500,13 +497,13 @@ template <typename Char, typename T>
void format_value(BasicWriter<Char> &w, const T &value, void format_value(BasicWriter<Char> &w, const T &value,
PrintfFormatter<Char> &f, const Char *&) { PrintfFormatter<Char> &f, const Char *&) {
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer; internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
f.writer() << internal::format_value(buffer, value); w << internal::format_value(buffer, value);
} }
template <typename Char> template <typename Char>
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format,
basic_format_args<PrintfFormatter<Char>> args) { basic_format_args<PrintfFormatter<Char>> args) {
PrintfFormatter<Char>(args, w).format(format); PrintfFormatter<Char>(args).format(w, format);
} }
inline std::string vsprintf(CStringRef format, inline std::string vsprintf(CStringRef format,

View File

@ -17,9 +17,10 @@ using fmt::BasicPrintfArgFormatter;
class CustomArgFormatter class CustomArgFormatter
: public fmt::BasicArgFormatter<CustomArgFormatter, char> { : public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public: public:
CustomArgFormatter(fmt::basic_formatter<char, CustomArgFormatter> &f, CustomArgFormatter(fmt::Writer &w,
fmt::basic_formatter<char, CustomArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt) fmt::FormatSpec &s, const char *fmt)
: fmt::BasicArgFormatter<CustomArgFormatter, char>(f, s, fmt) {} : fmt::BasicArgFormatter<CustomArgFormatter, char>(w, f, s, fmt) {}
void visit_double(double value) { void visit_double(double value) {
if (round(value * pow(10, spec().precision())) == 0) if (round(value * pow(10, spec().precision())) == 0)
@ -47,12 +48,11 @@ class CustomPrintfArgFormatter :
typedef fmt::basic_formatter<char, CustomArgFormatter> CustomFormatter; typedef fmt::basic_formatter<char, CustomArgFormatter> CustomFormatter;
std::string custom_vformat(const char *format_str, std::string custom_vformat(fmt::CStringRef format_str,
fmt::basic_format_args<CustomFormatter> args) { fmt::basic_format_args<CustomFormatter> args) {
fmt::MemoryWriter writer; fmt::MemoryWriter writer;
// Pass custom argument formatter as a template arg to basic_formatter. // Pass custom argument formatter as a template arg to vformat.
CustomFormatter formatter(args, writer); fmt::vformat<CustomArgFormatter>(writer, format_str, args);
formatter.format(format_str);
return writer.str(); return writer.str();
} }
@ -69,8 +69,8 @@ std::string custom_vsprintf(
const char* format_str, const char* format_str,
fmt::basic_format_args<CustomPrintfFormatter> args) { fmt::basic_format_args<CustomPrintfFormatter> args) {
fmt::MemoryWriter writer; fmt::MemoryWriter writer;
CustomPrintfFormatter formatter(args, writer); CustomPrintfFormatter formatter(args);
formatter.format(format_str); formatter.format(writer, format_str);
return writer.str(); return writer.str();
} }

View File

@ -1357,7 +1357,7 @@ TEST(FormatterTest, FormatCStringRef) {
void format_value(fmt::Writer &w, const Date &d, fmt::basic_formatter<char> &f, void format_value(fmt::Writer &w, const Date &d, fmt::basic_formatter<char> &f,
const char *) { const char *) {
f.writer() << d.year() << '-' << d.month() << '-' << d.day(); w << d.year() << '-' << d.month() << '-' << d.day();
} }
TEST(FormatterTest, FormatCustom) { TEST(FormatterTest, FormatCustom) {
@ -1371,7 +1371,7 @@ class Answer {};
template <typename Char> template <typename Char>
void format_value(BasicWriter<Char> &w, Answer, fmt::basic_formatter<Char> &f, void format_value(BasicWriter<Char> &w, Answer, fmt::basic_formatter<Char> &f,
const Char *) { const Char *) {
f.writer() << "42"; w << "42";
} }
TEST(FormatterTest, CustomFormat) { TEST(FormatterTest, CustomFormat) {
@ -1626,9 +1626,10 @@ class MockArgFormatter :
public: public:
typedef fmt::internal::ArgFormatterBase<MockArgFormatter, char> Base; typedef fmt::internal::ArgFormatterBase<MockArgFormatter, char> Base;
MockArgFormatter(fmt::basic_formatter<char, MockArgFormatter> &f, MockArgFormatter(fmt::Writer &w,
fmt::basic_formatter<char, MockArgFormatter> &f,
fmt::FormatSpec &s, const char *) fmt::FormatSpec &s, const char *)
: fmt::internal::ArgFormatterBase<MockArgFormatter, char>(f.writer(), s) { : fmt::internal::ArgFormatterBase<MockArgFormatter, char>(w, s) {
EXPECT_CALL(*this, visit_int(42)); EXPECT_CALL(*this, visit_int(42));
} }
@ -1637,11 +1638,10 @@ class MockArgFormatter :
typedef fmt::basic_formatter<char, MockArgFormatter> CustomFormatter; typedef fmt::basic_formatter<char, MockArgFormatter> CustomFormatter;
void custom_vformat(const char *format_str, void custom_vformat(fmt::CStringRef format_str,
fmt::basic_format_args<CustomFormatter> args) { fmt::basic_format_args<CustomFormatter> args) {
fmt::MemoryWriter writer; fmt::MemoryWriter writer;
CustomFormatter formatter(args, writer); vformat(writer, format_str, args);
formatter.format(format_str);
} }
template <typename... Args> template <typename... Args>

View File

@ -59,17 +59,18 @@ TEST(OStreamTest, Enum) {
} }
struct TestArgFormatter : fmt::BasicArgFormatter<TestArgFormatter, char> { struct TestArgFormatter : fmt::BasicArgFormatter<TestArgFormatter, char> {
TestArgFormatter(fmt::basic_formatter<char, TestArgFormatter> &f, TestArgFormatter(fmt::Writer &w,
fmt::basic_formatter<char, TestArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt) fmt::FormatSpec &s, const char *fmt)
: fmt::BasicArgFormatter<TestArgFormatter, char>(f, s, fmt) {} : fmt::BasicArgFormatter<TestArgFormatter, char>(w, f, s, fmt) {}
}; };
TEST(OStreamTest, CustomArg) { TEST(OStreamTest, CustomArg) {
fmt::MemoryWriter writer; fmt::MemoryWriter writer;
typedef fmt::basic_formatter<char, TestArgFormatter> Formatter; typedef fmt::basic_formatter<char, TestArgFormatter> Formatter;
Formatter formatter(fmt::basic_format_args<Formatter>(), writer); Formatter formatter((fmt::basic_format_args<Formatter>()));
fmt::FormatSpec spec; fmt::FormatSpec spec;
TestArgFormatter af(formatter, spec, "}"); TestArgFormatter af(writer, formatter, spec, "}");
af.visit(fmt::internal::MakeArg<Formatter>(TestEnum())); af.visit(fmt::internal::MakeArg<Formatter>(TestEnum()));
EXPECT_EQ("TestEnum", writer.str()); EXPECT_EQ("TestEnum", writer.str());
} }

View File

@ -567,9 +567,9 @@ TEST(ArgTest, MakeArg) {
EXPECT_EQ(fmt::internal::Arg::CUSTOM, arg.type); EXPECT_EQ(fmt::internal::Arg::CUSTOM, arg.type);
EXPECT_EQ(&t, arg.custom.value); EXPECT_EQ(&t, arg.custom.value);
fmt::MemoryWriter w; fmt::MemoryWriter w;
fmt::basic_formatter<char> formatter(fmt::format_args(), w); fmt::basic_formatter<char> formatter((fmt::format_args()));
const char *s = "}"; const char *s = "}";
arg.custom.format(&formatter.writer(), &formatter, &t, &s); arg.custom.format(&w, &formatter, &t, &s);
EXPECT_EQ("test", w.str()); EXPECT_EQ("test", w.str());
} }