Skip to content

Commit

Permalink
Make BasicArgFormatter public and add ArgFormatter
Browse files Browse the repository at this point in the history
This allows providing custom argument formatters without relying on
internal APIs (#235).
  • Loading branch information
vitaut committed Apr 19, 2016
1 parent 4d8cee2 commit b69e6dc
Showing 2 changed files with 50 additions and 27 deletions.
59 changes: 33 additions & 26 deletions cppformat/format.h
Original file line number Diff line number Diff line change
@@ -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);
18 changes: 17 additions & 1 deletion test/format-test.cc
Original file line number Diff line number Diff line change
@@ -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());
}

0 comments on commit b69e6dc

Please sign in to comment.