Add FormatterBase.

This commit is contained in:
Victor Zverovich
2014-07-16 08:38:15 -07:00
parent 9144a8fbbe
commit 4edc88f609
2 changed files with 89 additions and 69 deletions

View File

@@ -415,13 +415,14 @@ template <typename Char>
class fmt::internal::ArgFormatter : class fmt::internal::ArgFormatter :
public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> { public fmt::internal::ArgVisitor<fmt::internal::ArgFormatter<Char>, void> {
private: private:
fmt::BasicFormatter<Char> &formatter_;
fmt::BasicWriter<Char> &writer_; fmt::BasicWriter<Char> &writer_;
fmt::FormatSpec &spec_; fmt::FormatSpec &spec_;
const Char *format_; const Char *format_;
public: public:
ArgFormatter(fmt::BasicWriter<Char> &w, fmt::FormatSpec &s, const Char *fmt) ArgFormatter(fmt::BasicFormatter<Char> &f, fmt::FormatSpec &s, const Char *fmt)
: writer_(w), spec_(s), format_(fmt) {} : formatter_(f), writer_(f.writer()), spec_(s), format_(fmt) {}
template <typename T> template <typename T>
void visit_any_int(T value) { writer_.FormatInt(value, spec_); } void visit_any_int(T value) { writer_.FormatInt(value, spec_); }
@@ -467,7 +468,7 @@ class fmt::internal::ArgFormatter :
} }
void visit_custom(Arg::CustomValue c) { void visit_custom(Arg::CustomValue c) {
c.format(this, c.value, format_); c.format(&formatter_, c.value, format_);
} }
}; };
@@ -670,22 +671,20 @@ inline const Arg
if (*s < '0' || *s > '9') { if (*s < '0' || *s > '9') {
if (*s != '}' && *s != ':') if (*s != '}' && *s != ':')
report_error_(s, "invalid argument index in format string"); report_error_(s, "invalid argument index in format string");
if (next_arg_index_ < 0) { const Arg &arg = next_arg();
report_error_(s, if (error_)
"cannot switch from manual to automatic argument indexing"); report_error_(s, error_);
} return arg;
arg_index = next_arg_index_++;
} else {
if (next_arg_index_ > 0) {
report_error_(s,
"cannot switch from automatic to manual argument indexing");
}
next_arg_index_ = -1;
const char *error = 0;
arg_index = ParseNonnegativeInt(s, error);
if (error)
report_error_(s, error); // TODO
} }
if (next_arg_index_ > 0) {
report_error_(s,
"cannot switch from automatic to manual argument indexing");
}
next_arg_index_ = -1;
const char *error = 0;
arg_index = ParseNonnegativeInt(s, error);
if (error)
report_error_(s, error); // TODO
if (arg_index >= args_.size()) if (arg_index >= args_.size())
report_error_(s, "argument index is out of range in format"); report_error_(s, "argument index is out of range in format");
return args_[arg_index]; return args_[arg_index];
@@ -706,6 +705,41 @@ void fmt::BasicFormatter<Char>::CheckSign(
++s; ++s;
} }
const Arg &fmt::internal::FormatterBase::next_arg() {
if (next_arg_index_ < 0) {
if (!error_)
error_ = "cannot switch from manual to automatic argument indexing";
return DUMMY_ARG;
}
unsigned arg_index = next_arg_index_++;
if (arg_index < args_.size())
return args_[arg_index];
if (!error_)
error_ = "argument index is out of range in format";
return DUMMY_ARG;
}
const Arg &fmt::internal::FormatterBase::HandleArgIndex(
unsigned arg_index, const char *&error) {
if (arg_index != UINT_MAX) {
if (next_arg_index_ <= 0) {
next_arg_index_ = -1;
--arg_index;
} else if (!error) {
error = "cannot switch from automatic to manual argument indexing";
}
} else if (next_arg_index_ >= 0) {
arg_index = next_arg_index_++;
} else if (!error) {
error = "cannot switch from manual to automatic argument indexing";
}
if (arg_index < args_.size())
return args_[arg_index];
if (!error)
error = "argument index is out of range in format";
return DUMMY_ARG;
}
template <typename Char> template <typename Char>
void fmt::internal::PrintfFormatter<Char>::ParseFlags( void fmt::internal::PrintfFormatter<Char>::ParseFlags(
FormatSpec &spec, const Char *&s) { FormatSpec &spec, const Char *&s) {
@@ -767,29 +801,6 @@ unsigned fmt::internal::PrintfFormatter<Char>::ParseHeader(
return arg_index; return arg_index;
} }
// TODO: move to a base class that doesn't depend on template argument
template <typename Char>
const Arg &fmt::internal::PrintfFormatter<Char>::HandleArgIndex(
unsigned arg_index, const char *&error) {
if (arg_index != UINT_MAX) {
if (next_arg_index_ <= 0) {
next_arg_index_ = -1;
--arg_index;
} else if (!error) {
error = "cannot switch from automatic to manual argument indexing";
}
} else if (next_arg_index_ >= 0) {
arg_index = next_arg_index_++;
} else if (!error) {
error = "cannot switch from manual to automatic argument indexing";
}
if (arg_index < args_.size())
return args_[arg_index];
if (!error)
error = "argument index is out of range in format";
return DUMMY_ARG;
}
template <typename Char> template <typename Char>
void fmt::internal::PrintfFormatter<Char>::Format( void fmt::internal::PrintfFormatter<Char>::Format(
BasicWriter<Char> &writer, BasicStringRef<Char> format, BasicWriter<Char> &writer, BasicStringRef<Char> format,
@@ -1083,7 +1094,7 @@ const Char *fmt::BasicFormatter<Char>::format(
start_ = s; start_ = s;
// Format argument. // Format argument.
internal::ArgFormatter<Char>(writer_, spec, s - 1).visit(arg); internal::ArgFormatter<Char>(*this, spec, s - 1).visit(arg);
return s; return s;
} }

View File

@@ -845,13 +845,44 @@ class ArgList {
struct FormatSpec; struct FormatSpec;
// A formatter. namespace internal {
template <typename Char>
class BasicFormatter { class FormatterBase {
private: protected:
BasicWriter<Char> &writer_;
ArgList args_; ArgList args_;
int next_arg_index_; int next_arg_index_;
const char *error_;
FormatterBase() : error_(0) {}
const Arg &next_arg();
const Arg &HandleArgIndex(unsigned arg_index, const char *&error);
// TODO
};
// A printf formatter.
template <typename Char>
class PrintfFormatter : private FormatterBase {
private:
void ParseFlags(FormatSpec &spec, const Char *&s);
// Parses argument index, flags and width and returns the parsed
// argument index.
unsigned ParseHeader(const Char *&s, FormatSpec &spec, const char *&error);
public:
void Format(BasicWriter<Char> &writer,
BasicStringRef<Char> format, const ArgList &args);
};
} // namespace internal
// A formatter.
template <typename Char>
class BasicFormatter : private internal::FormatterBase {
private:
BasicWriter<Char> &writer_;
const Char *start_; const Char *start_;
internal::FormatErrorReporter<Char> report_error_; internal::FormatErrorReporter<Char> report_error_;
@@ -870,28 +901,6 @@ public:
const Char *format(const Char *format_str, const internal::Arg &arg); const Char *format(const Char *format_str, const internal::Arg &arg);
}; };
namespace internal {
// A printf formatter.
template <typename Char>
class PrintfFormatter {
private:
ArgList args_;
int next_arg_index_;
void ParseFlags(FormatSpec &spec, const Char *&s);
// Parses argument index, flags and width and returns the parsed
// argument index.
unsigned ParseHeader(const Char *&s, FormatSpec &spec, const char *&error);
const internal::Arg &HandleArgIndex(unsigned arg_index, const char *&error);
public:
void Format(BasicWriter<Char> &writer,
BasicStringRef<Char> format, const ArgList &args);
};
} // namespace internal
enum Alignment { enum Alignment {
ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC
}; };