Make BasicArgFormatter public and add ArgFormatter

This allows providing custom argument formatters without relying on
internal APIs (#235).
This commit is contained in:
vitaut 2016-04-19 08:56:31 -07:00
parent 4d8cee2d48
commit b69e6dcead
2 changed files with 50 additions and 27 deletions

View File

@ -372,17 +372,15 @@ class BasicWriter;
typedef BasicWriter<char> Writer;
typedef BasicWriter<wchar_t> WWriter;
namespace internal {
template <typename Char>
class BasicArgFormatter;
}
class ArgFormatter;
template <typename CharType,
typename ArgFormatter = internal::BasicArgFormatter<CharType> >
typename ArgFormatter = fmt::ArgFormatter<CharType> >
class BasicFormatter;
template <typename Char, typename T>
void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value);
template <typename Char, typename ArgFormatter, typename T>
void format(BasicFormatter<Char, ArgFormatter> &f, const Char *&format_str, const T &value);
/**
\rst
@ -1842,24 +1840,6 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
}
};
// An argument formatter.
template <typename Char>
class BasicArgFormatter :
public ArgFormatterBase<BasicArgFormatter<Char>, Char> {
private:
BasicFormatter<Char> &formatter_;
const Char *format_;
public:
BasicArgFormatter(BasicFormatter<Char> &f, FormatSpec &s, const Char *fmt)
: ArgFormatterBase<BasicArgFormatter<Char>, Char>(f.writer(), s),
formatter_(f), format_(fmt) {}
void visit_custom(Arg::CustomValue c) {
c.format(&formatter_, c.value, &format_);
}
};
class FormatterBase {
private:
ArgList args_;
@ -1927,6 +1907,32 @@ class PrintfFormatter : private FormatterBase {
};
} // namespace internal
// An argument formatter.
template <typename Impl, typename Char>
class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
private:
BasicFormatter<Char, Impl> &formatter_;
const Char *format_;
public:
BasicArgFormatter(BasicFormatter<Char, Impl> &f,
FormatSpec &s, const Char *fmt)
: internal::ArgFormatterBase<Impl, Char>(f.writer(), s),
formatter_(f), format_(fmt) {}
void visit_custom(internal::Arg::CustomValue c) {
c.format(&formatter_, c.value, &format_);
}
};
// The default argument formatter.
template <typename Char>
class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
public:
ArgFormatter(BasicFormatter<Char> &f, FormatSpec &s, const Char *fmt)
: BasicArgFormatter<ArgFormatter<Char>, Char>(f, s, fmt) {}
};
/** This template formats data and writes the output to a writer. */
template <typename CharType, typename ArgFormatter>
class BasicFormatter : private internal::FormatterBase {
@ -3009,8 +3015,9 @@ typedef BasicArrayWriter<char> ArrayWriter;
typedef BasicArrayWriter<wchar_t> WArrayWriter;
// Formats a value.
template <typename Char, typename T>
void format(BasicFormatter<Char> &f, const Char *&format_str, const T &value) {
template <typename Char, typename ArgFormatter, typename T>
void format(BasicFormatter<Char, ArgFormatter> &f,
const Char *&format_str, const T &value) {
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
internal::FormatBuf<Char> format_buf(buffer);

View File

@ -1671,7 +1671,7 @@ TEST(FormatTest, EmptyCustomOutput) {
}
class MockArgFormatter :
public fmt::internal::ArgFormatterBase<MockArgFormatter, char> {
public fmt::internal::ArgFormatterBase<MockArgFormatter, char> {
public:
typedef fmt::internal::ArgFormatterBase<MockArgFormatter, char> Base;
@ -1694,3 +1694,19 @@ FMT_VARIADIC(void, custom_format, const char *)
TEST(FormatTest, CustomArgFormatter) {
custom_format("{}", 42);
}
struct TestArgFormatter : fmt::BasicArgFormatter<TestArgFormatter, char> {
TestArgFormatter(fmt::BasicFormatter<char, TestArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt)
: fmt::BasicArgFormatter<TestArgFormatter, char>(f, s, fmt) {}
};
TEST(ArgFormatterTest, CustomArg) {
fmt::MemoryWriter writer;
typedef fmt::BasicFormatter<char, TestArgFormatter> Formatter;
Formatter formatter(fmt::ArgList(), writer);
fmt::FormatSpec spec;
TestArgFormatter af(formatter, spec, "}");
af.visit(fmt::internal::MakeArg<Formatter>(TestEnum()));
EXPECT_EQ("TestEnum", writer.str());
}