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> template <typename Char>
void write(BasicWriter<Char> &w, const Char *start, const Char *end) { inline void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
if (start != end) if (start != end)
w << BasicStringRef<Char>(start, internal::to_unsigned(end - start)); 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);
public:
/**
\rst
Constructs a ``basic_formatter`` object. References to the arguments are
stored in the formatter object so make sure they have appropriate lifetimes.
\endrst
*/
basic_formatter(basic_format_args<basic_formatter> args) : Base(args) {}
// Parses argument index and returns corresponding argument. // Parses argument index and returns corresponding argument.
internal::Arg parse_arg_index(const Char *&s); internal::Arg parse_arg_index(const Char *&s);
// Parses argument name and returns corresponding argument. // Parses argument name and returns corresponding argument.
internal::Arg parse_arg_name(const Char *&s); internal::Arg parse_arg_name(const Char *&s);
public:
/**
\rst
Constructs a ``basic_formatter`` object. References to the arguments and
the writer are stored in the formatter object so make sure they have
appropriate lifetimes.
\endrst
*/
basic_formatter(basic_format_args<basic_formatter> args, BasicWriter<Char> &w)
: Base(args), writer_(w) {}
/** Returns a reference to the writer associated with this formatter. */
BasicWriter<Char> &writer() { return writer_; }
/** Formats stored arguments and writes the output to the writer. */
void format(BasicCStringRef<Char> format_str);
// 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());
} }