Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom FormatSpec (#439) #444

Merged
merged 7 commits into from
Dec 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ custom argument formatter class::
// A custom argument formatter that formats negative integers as unsigned
// with the ``x`` format specifier.
class CustomArgFormatter :
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: extra space

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought it was just a mistake. Why the extra space?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOL, my bad. I misread the diff and thought it was added. No need for an extra space of course.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(git is so much fun)

public:
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt)
Expand Down
57 changes: 33 additions & 24 deletions fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,9 @@ typedef BasicWriter<wchar_t> WWriter;
template <typename Char>
class ArgFormatter;

template <typename Impl, typename Char>
struct FormatSpec;

template <typename Impl, typename Char, typename Spec = fmt::FormatSpec>
class BasicPrintfArgFormatter;

template <typename CharType,
Expand Down Expand Up @@ -1697,6 +1699,7 @@ struct TypeSpec : EmptySpec {
int precision() const { return -1; }
bool flag(unsigned) const { return false; }
char type() const { return TYPE; }
char type_prefix() const { return TYPE; }
char fill() const { return ' '; }
};

Expand Down Expand Up @@ -1732,6 +1735,7 @@ struct AlignTypeSpec : AlignSpec {

bool flag(unsigned) const { return false; }
char type() const { return TYPE; }
char type_prefix() const { return TYPE; }
};

// A full format specifier.
Expand All @@ -1747,6 +1751,7 @@ struct FormatSpec : AlignSpec {
bool flag(unsigned f) const { return (flags_ & f) != 0; }
int precision() const { return precision_; }
char type() const { return type_; }
char type_prefix() const { return type_; }
};

// An integer format specifier.
Expand Down Expand Up @@ -1922,11 +1927,11 @@ class ArgMap {
}
};

template <typename Impl, typename Char>
template <typename Impl, typename Char, typename Spec = fmt::FormatSpec>
class ArgFormatterBase : public ArgVisitor<Impl, void> {
private:
BasicWriter<Char> &writer_;
FormatSpec &spec_;
Spec &spec_;

FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatterBase);

Expand All @@ -1938,7 +1943,7 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {

protected:
BasicWriter<Char> &writer() { return writer_; }
FormatSpec &spec() { return spec_; }
Spec &spec() { return spec_; }

void write(bool value) {
const char *str_value = value ? "true" : "false";
Expand All @@ -1952,7 +1957,9 @@ class ArgFormatterBase : public ArgVisitor<Impl, void> {
}

public:
ArgFormatterBase(BasicWriter<Char> &w, FormatSpec &s)
typedef Spec SpecType;

ArgFormatterBase(BasicWriter<Char> &w, Spec &s)
: writer_(w), spec_(s) {}

template <typename T>
Expand Down Expand Up @@ -2086,8 +2093,8 @@ class FormatterBase {
will be called.
\endrst
*/
template <typename Impl, typename Char>
class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
template <typename Impl, typename Char, typename Spec = fmt::FormatSpec>
class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char, Spec> {
private:
BasicFormatter<Char, Impl> &formatter_;
const Char *format_;
Expand All @@ -2102,8 +2109,8 @@ class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
\endrst
*/
BasicArgFormatter(BasicFormatter<Char, Impl> &formatter,
FormatSpec &spec, const Char *fmt)
: internal::ArgFormatterBase<Impl, Char>(formatter.writer(), spec),
Spec &spec, const Char *fmt)
: internal::ArgFormatterBase<Impl, Char, Spec>(formatter.writer(), spec),
formatter_(formatter), format_(fmt) {}

/** Formats an argument of a custom (user-defined) type. */
Expand All @@ -2114,12 +2121,14 @@ class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {

/** The default argument formatter. */
template <typename Char>
class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
class ArgFormatter :
public BasicArgFormatter<ArgFormatter<Char>, Char, FormatSpec> {
public:
/** Constructs an argument formatter object. */
ArgFormatter(BasicFormatter<Char> &formatter,
FormatSpec &spec, const Char *fmt)
: BasicArgFormatter<ArgFormatter<Char>, Char>(formatter, spec, fmt) {}
: BasicArgFormatter<ArgFormatter<Char>,
Char, FormatSpec>(formatter, spec, fmt) {}
};

/** This template formats data and writes the output to a writer. */
Expand Down Expand Up @@ -2501,16 +2510,16 @@ class BasicWriter {
void write_int(T value, Spec spec);

// Formats a floating-point number (double or long double).
template <typename T>
void write_double(T value, const FormatSpec &spec);
template <typename T, typename Spec>
void write_double(T value, const Spec &spec);

// Writes a formatted string.
template <typename StrChar>
CharPtr write_str(const StrChar *s, std::size_t size, const AlignSpec &spec);

template <typename StrChar>
template <typename StrChar, typename Spec>
void write_str(const internal::Arg::StringValue<StrChar> &str,
const FormatSpec &spec);
const Spec &spec);

// This following methods are private to disallow writing wide characters
// and strings to a char stream. If you want to print a wide string as a
Expand All @@ -2529,10 +2538,10 @@ class BasicWriter {
template<typename T>
void append_float_length(Char *&, T) {}

template <typename Impl, typename Char_>
template <typename Impl, typename Char_, typename Spec_>
friend class internal::ArgFormatterBase;

template <typename Impl, typename Char_>
template <typename Impl, typename Char_, typename Spec_>
friend class BasicPrintfArgFormatter;

protected:
Expand Down Expand Up @@ -2729,9 +2738,9 @@ typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
}

template <typename Char>
template <typename StrChar>
template <typename StrChar, typename Spec>
void BasicWriter<Char>::write_str(
const internal::Arg::StringValue<StrChar> &s, const FormatSpec &spec) {
const internal::Arg::StringValue<StrChar> &s, const Spec &spec) {
// Check if StrChar is convertible to Char.
internal::CharTraits<Char>::convert(StrChar());
if (spec.type_ && spec.type_ != 's')
Expand Down Expand Up @@ -2855,7 +2864,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0';
prefix[prefix_size++] = spec.type();
prefix[prefix_size++] = spec.type_prefix();
}
unsigned num_digits = 0;
do {
Expand All @@ -2875,7 +2884,7 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0';
prefix[prefix_size++] = spec.type();
prefix[prefix_size++] = spec.type_prefix();
}
unsigned num_digits = 0;
do {
Expand Down Expand Up @@ -2923,8 +2932,8 @@ void BasicWriter<Char>::write_int(T value, Spec spec) {
}

template <typename Char>
template <typename T>
void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
template <typename T, typename Spec>
void BasicWriter<Char>::write_double(T value, const Spec &spec) {
// Check type.
char type = spec.type();
bool upper = false;
Expand Down Expand Up @@ -3661,7 +3670,7 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
const Char *&format_str, const internal::Arg &arg) {
using internal::Arg;
const Char *s = format_str;
FormatSpec spec;
typename ArgFormatter::SpecType spec;
if (*s == ':') {
if (arg.type == Arg::CUSTOM) {
arg.custom.format(this, arg.custom.value, &s);
Expand Down
21 changes: 11 additions & 10 deletions fmt/printf.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,16 @@ class WidthHandler : public ArgVisitor<WidthHandler, unsigned> {
superclass will be called.
\endrst
*/
template <typename Impl, typename Char>
class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
template <typename Impl, typename Char, typename Spec>
class BasicPrintfArgFormatter :
public internal::ArgFormatterBase<Impl, Char, Spec> {
private:
void write_null_pointer() {
this->spec().type_ = 0;
this->write("(nil)");
}

typedef internal::ArgFormatterBase<Impl, Char> Base;
typedef internal::ArgFormatterBase<Impl, Char, Spec> Base;

public:
/**
Expand All @@ -207,12 +208,12 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
specifier information for standard argument types.
\endrst
*/
BasicPrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: internal::ArgFormatterBase<Impl, Char>(w, s) {}
BasicPrintfArgFormatter(BasicWriter<Char> &w, Spec &s)
: internal::ArgFormatterBase<Impl, Char, Spec>(w, s) {}

/** Formats an argument of type ``bool``. */
void visit_bool(bool value) {
FormatSpec &fmt_spec = this->spec();
Spec &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return this->visit_any_int(value);
fmt_spec.type_ = 0;
Expand All @@ -221,7 +222,7 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {

/** Formats a character. */
void visit_char(int value) {
const FormatSpec &fmt_spec = this->spec();
const Spec &fmt_spec = this->spec();
BasicWriter<Char> &w = this->writer();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
w.write_int(value, fmt_spec);
Expand Down Expand Up @@ -271,12 +272,12 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char> {

/** The default printf argument formatter. */
template <typename Char>
class PrintfArgFormatter
: public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char> {
class PrintfArgFormatter :
public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec> {
public:
/** Constructs an argument formatter object. */
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {}
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>(w, s) {}
};

/** This template formats data and writes the output to a writer. */
Expand Down
4 changes: 2 additions & 2 deletions test/custom-formatter-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class CustomArgFormatter

// A custom argument formatter that doesn't print `-` for floating-point values
// rounded to 0.
class CustomPrintfArgFormatter :
public BasicPrintfArgFormatter<CustomPrintfArgFormatter, char> {
class CustomPrintfArgFormatter
: public BasicPrintfArgFormatter<CustomPrintfArgFormatter, char> {
public:
typedef BasicPrintfArgFormatter<CustomPrintfArgFormatter, char> Base;

Expand Down
1 change: 0 additions & 1 deletion test/format-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1660,4 +1660,3 @@ void convert(int);
TEST(FormatTest, ConvertCollision) {
fmt::format("{}", 42);
}