Don't use Writer's buffer directly in formatters. Unfriend BasicFormatter.

This commit is contained in:
Victor Zverovich 2014-07-24 08:53:27 -07:00
parent a7d94f0c61
commit c1db293518
2 changed files with 35 additions and 31 deletions

View File

@ -425,17 +425,17 @@ class fmt::internal::ArgFormatter :
: formatter_(f), writer_(f.writer()), 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_.write_int(value, spec_); }
template <typename T> template <typename T>
void visit_any_double(T value) { writer_.FormatDouble(value, spec_); } void visit_any_double(T value) { writer_.write_double(value, spec_); }
void visit_char(int value) { void visit_char(int value) {
if (spec_.type_ && spec_.type_ != 'c') { if (spec_.type_ && spec_.type_ != 'c') {
switch (spec_.type_) { switch (spec_.type_) {
// TODO: don't duplicate integer format specifiers here // TODO: don't duplicate integer format specifiers here
case 'd': case 'x': case 'X': case 'b': case 'B': case 'o': case 'd': case 'x': case 'X': case 'b': case 'B': case 'o':
writer_.FormatInt(value, spec_); writer_.write_int(value, spec_);
break; break;
default: default:
internal::ReportUnknownType(spec_.type_, "char"); internal::ReportUnknownType(spec_.type_, "char");
@ -474,7 +474,7 @@ class fmt::internal::ArgFormatter :
fmt::internal::ReportUnknownType(spec_.type_, "pointer"); fmt::internal::ReportUnknownType(spec_.type_, "pointer");
spec_.flags_ = fmt::HASH_FLAG; spec_.flags_ = fmt::HASH_FLAG;
spec_.type_ = 'x'; spec_.type_ = 'x';
writer_.FormatInt(reinterpret_cast<uintptr_t>(value), spec_); writer_.write_int(reinterpret_cast<uintptr_t>(value), spec_);
} }
void visit_custom(Arg::CustomValue c) { void visit_custom(Arg::CustomValue c) {
@ -507,7 +507,7 @@ typename fmt::BasicWriter<Char>::CharPtr
template <typename Char> template <typename Char>
template <typename T> template <typename T>
void fmt::BasicWriter<Char>::FormatDouble(T value, const FormatSpec &spec) { void fmt::BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
// Check type. // Check type.
char type = spec.type(); char type = spec.type();
bool upper = false; bool upper = false;
@ -818,11 +818,11 @@ void fmt::internal::PrintfFormatter<Char>::Format(
Char c = *s++; Char c = *s++;
if (c != '%') continue; if (c != '%') continue;
if (*s == c) { if (*s == c) {
writer.buffer_.append(start, s); write(writer, start, s);
start = ++s; start = ++s;
continue; continue;
} }
writer.buffer_.append(start, s - 1); write(writer, start, s - 1);
FormatSpec spec; FormatSpec spec;
spec.align_ = ALIGN_RIGHT; spec.align_ = ALIGN_RIGHT;
@ -892,20 +892,20 @@ void fmt::internal::PrintfFormatter<Char>::Format(
// Format argument. // Format argument.
switch (arg.type) { switch (arg.type) {
case Arg::INT: case Arg::INT:
writer.FormatInt(arg.int_value, spec); writer.write_int(arg.int_value, spec);
break; break;
case Arg::UINT: case Arg::UINT:
writer.FormatInt(arg.uint_value, spec); writer.write_int(arg.uint_value, spec);
break; break;
case Arg::LONG_LONG: case Arg::LONG_LONG:
writer.FormatInt(arg.long_long_value, spec); writer.write_int(arg.long_long_value, spec);
break; break;
case Arg::ULONG_LONG: case Arg::ULONG_LONG:
writer.FormatInt(arg.ulong_long_value, spec); writer.write_int(arg.ulong_long_value, spec);
break; break;
case Arg::CHAR: { case Arg::CHAR: {
if (spec.type_ && spec.type_ != 'c') if (spec.type_ && spec.type_ != 'c')
writer.FormatInt(arg.int_value, spec); writer.write_int(arg.int_value, spec);
typedef typename BasicWriter<Char>::CharPtr CharPtr; typedef typename BasicWriter<Char>::CharPtr CharPtr;
CharPtr out = CharPtr(); CharPtr out = CharPtr();
if (spec.width_ > 1) { if (spec.width_ > 1) {
@ -924,10 +924,10 @@ void fmt::internal::PrintfFormatter<Char>::Format(
break; break;
} }
case Arg::DOUBLE: case Arg::DOUBLE:
writer.FormatDouble(arg.double_value, spec); writer.write_double(arg.double_value, spec);
break; break;
case Arg::LONG_DOUBLE: case Arg::LONG_DOUBLE:
writer.FormatDouble(arg.long_double_value, spec); writer.write_double(arg.long_double_value, spec);
break; break;
case Arg::STRING: case Arg::STRING:
writer.write_str(arg.string, spec); writer.write_str(arg.string, spec);
@ -940,7 +940,7 @@ void fmt::internal::PrintfFormatter<Char>::Format(
internal::ReportUnknownType(spec.type_, "pointer"); internal::ReportUnknownType(spec.type_, "pointer");
spec.flags_= HASH_FLAG; spec.flags_= HASH_FLAG;
spec.type_ = 'x'; spec.type_ = 'x';
writer.FormatInt(reinterpret_cast<uintptr_t>(arg.pointer_value), spec); writer.write_int(reinterpret_cast<uintptr_t>(arg.pointer_value), spec);
break; break;
case Arg::CUSTOM: case Arg::CUSTOM:
if (spec.type_) if (spec.type_)
@ -952,7 +952,7 @@ void fmt::internal::PrintfFormatter<Char>::Format(
break; break;
} }
} }
writer.buffer_.append(start, s); write(writer, start, s);
} }
template <typename Char> template <typename Char>
@ -1111,18 +1111,18 @@ void fmt::BasicFormatter<Char>::Format(
Char c = *s++; Char c = *s++;
if (c != '{' && c != '}') continue; if (c != '{' && c != '}') continue;
if (*s == c) { if (*s == c) {
writer_.buffer_.append(start_, s); write(writer_, start_, s);
start_ = ++s; start_ = ++s;
continue; continue;
} }
if (c == '}') if (c == '}')
throw FormatError("unmatched '}' in format"); throw FormatError("unmatched '}' in format");
report_error_.num_open_braces = 1; report_error_.num_open_braces = 1;
writer_.buffer_.append(start_, s - 1); write(writer_, start_, s - 1);
Arg arg = ParseArgIndex(s); Arg arg = ParseArgIndex(s);
s = format(s, arg); s = format(s, arg);
} }
writer_.buffer_.append(start_, s); write(writer_, start_, s);
} }
void fmt::ReportSystemError( void fmt::ReportSystemError(

View File

@ -853,6 +853,12 @@ protected:
const Arg &handle_arg_index(unsigned arg_index); const Arg &handle_arg_index(unsigned arg_index);
template <typename Char>
void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
if (start != end)
w << BasicStringRef<Char>(start, end - start);
}
// TODO // TODO
}; };
@ -1331,11 +1337,11 @@ class BasicWriter {
// Formats an integer. // Formats an integer.
template <typename T, typename Spec> template <typename T, typename Spec>
void FormatInt(T value, const Spec &spec); void write_int(T value, const Spec &spec);
// Formats a floating-point number (double or long double). // Formats a floating-point number (double or long double).
template <typename T> template <typename T>
void FormatDouble(T value, const FormatSpec &spec); void write_double(T value, const FormatSpec &spec);
// Writes a formatted string. // Writes a formatted string.
template <typename StringChar> template <typename StringChar>
@ -1353,7 +1359,6 @@ class BasicWriter {
void operator<<(typename internal::CharTraits<Char>::UnsupportedStrType); void operator<<(typename internal::CharTraits<Char>::UnsupportedStrType);
friend class internal::ArgFormatter<Char>; friend class internal::ArgFormatter<Char>;
friend class BasicFormatter<Char>;
friend class internal::PrintfFormatter<Char>; friend class internal::PrintfFormatter<Char>;
public: public:
@ -1462,7 +1467,7 @@ class BasicWriter {
} }
BasicWriter &operator<<(double value) { BasicWriter &operator<<(double value) {
FormatDouble(value, FormatSpec()); write_double(value, FormatSpec());
return *this; return *this;
} }
@ -1471,7 +1476,7 @@ class BasicWriter {
(``'g'``) and writes it to the stream. (``'g'``) and writes it to the stream.
*/ */
BasicWriter &operator<<(long double value) { BasicWriter &operator<<(long double value) {
FormatDouble(value, FormatSpec()); write_double(value, FormatSpec());
return *this; return *this;
} }
@ -1479,29 +1484,28 @@ class BasicWriter {
Writes a character to the stream. Writes a character to the stream.
*/ */
BasicWriter &operator<<(char value) { BasicWriter &operator<<(char value) {
*GrowBuffer(1) = value; buffer_.push_back(value);
return *this; return *this;
} }
BasicWriter &operator<<(wchar_t value) { BasicWriter &operator<<(wchar_t value) {
*GrowBuffer(1) = internal::CharTraits<Char>::convert(value); buffer_.push_back(internal::CharTraits<Char>::convert(value));
return *this; return *this;
} }
/** /**
Writes *value* to the stream. Writes *value* to the stream.
*/ */
BasicWriter &operator<<(const fmt::BasicStringRef<Char> value) { BasicWriter &operator<<(fmt::BasicStringRef<Char> value) {
const Char *str = value.c_str(); const Char *str = value.c_str();
std::size_t size = value.size(); buffer_.append(str, str + value.size());
std::copy(str, str + size, GrowBuffer(size));
return *this; return *this;
} }
template <typename T, typename Spec, typename FillChar> template <typename T, typename Spec, typename FillChar>
BasicWriter &operator<<(const IntFormatSpec<T, Spec, FillChar> &spec) { BasicWriter &operator<<(const IntFormatSpec<T, Spec, FillChar> &spec) {
internal::CharTraits<Char>::convert(FillChar()); internal::CharTraits<Char>::convert(FillChar());
FormatInt(spec.value(), spec); write_int(spec.value(), spec);
return *this; return *this;
} }
@ -1603,7 +1607,7 @@ typename fmt::BasicWriter<Char>::CharPtr
template <typename Char> template <typename Char>
template <typename T, typename Spec> template <typename T, typename Spec>
void BasicWriter<Char>::FormatInt(T value, const Spec &spec) { void BasicWriter<Char>::write_int(T value, const Spec &spec) {
unsigned prefix_size = 0; unsigned prefix_size = 0;
typedef typename internal::IntTraits<T>::MainType UnsignedType; typedef typename internal::IntTraits<T>::MainType UnsignedType;
UnsignedType abs_value = value; UnsignedType abs_value = value;