mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-31 19:24:48 +02:00
Add FormatterBase.
This commit is contained in:
95
format.cc
95
format.cc
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
63
format.h
63
format.h
@@ -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
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user