Test and correct handling of the width specifier.

This commit is contained in:
Victor Zverovich
2012-12-09 11:32:39 -08:00
parent 8b60a804ba
commit 095b43a8f0
3 changed files with 97 additions and 65 deletions
+17 -10
View File
@@ -32,10 +32,13 @@ class Formatter {
std::vector<char> buffer_; // Output buffer.
enum Type {
CHAR, INT, UINT, LONG, ULONG, DOUBLE, LONG_DOUBLE,
STRING, WSTRING, POINTER, CUSTOM
// Numeric types should go first.
INT, UINT, LONG, ULONG, DOUBLE, LONG_DOUBLE, POINTER,
LAST_NUMERIC_TYPE = POINTER, CHAR, STRING, WSTRING, CUSTOM
};
typedef void (Formatter::*FormatFunc)(const void *arg, int width);
// An argument.
struct Arg {
Type type;
@@ -56,7 +59,7 @@ class Formatter {
};
struct {
const void *custom_value;
void (Formatter::*format)(const void *value);
FormatFunc format;
};
};
@@ -72,8 +75,8 @@ class Formatter {
: type(STRING), string_value(value), size(size) {}
explicit Arg(const wchar_t *value) : type(WSTRING), wstring_value(value) {}
explicit Arg(const void *value) : type(POINTER), pointer_value(value) {}
explicit Arg(const void *value, void (Formatter::*format)(const void *))
: type(CUSTOM), custom_value(value), format(format) {}
explicit Arg(const void *value, FormatFunc f)
: type(CUSTOM), custom_value(value), format(f) {}
};
std::vector<Arg> args_;
@@ -95,7 +98,7 @@ class Formatter {
// Formats an argument of a custom type, such as a user-defined class.
template <typename T>
void FormatCustomArg(const void *arg);
void FormatCustomArg(const void *arg, int width);
void Format();
@@ -244,14 +247,18 @@ class ArgFormatterWithCallback : public ArgFormatter {
};
template <typename T>
void Formatter::FormatCustomArg(const void *arg) {
void Formatter::FormatCustomArg(const void *arg, int width) {
const T &value = *static_cast<const T*>(arg);
std::ostringstream os;
os << value;
std::string str(os.str());
// Extra char is reserved for terminating '\0'.
buffer_.reserve(buffer_.size() + str.size() + 1);
buffer_.insert(buffer_.end(), str.begin(), str.end());
if (width < 0) {
// Extra char is reserved for terminating '\0'.
buffer_.reserve(buffer_.size() + str.size() + 1);
buffer_.insert(buffer_.end(), str.begin(), str.end());
return;
}
FormatBuiltinArg("%-*s", str.c_str(), width, -1);
}
inline ArgFormatter Formatter::operator()(const char *format) {