Implement dynamic width in printf.

This commit is contained in:
Victor Zverovich 2014-06-17 06:53:48 -07:00
parent 8666ea82f7
commit 1275923a68
3 changed files with 31 additions and 23 deletions

View File

@ -632,23 +632,18 @@ void fmt::BasicWriter<Char>::PrintfParser::ParseFlags(
} }
} }
// FIXME: this doesnt' depend on template argument
template <typename Char> template <typename Char>
unsigned fmt::BasicWriter<Char>::PrintfParser::ParseArgIndex( unsigned fmt::BasicWriter<Char>::PrintfParser::HandleArgIndex(
const Char *&s, const char *&error) { unsigned arg_index, const char *&error) {
Char c = *s; if (arg_index != UINT_MAX) {
unsigned value = 0;
if (c >= '0' && c <= '9') {
value = internal::ParseNonnegativeInt(s, error);
if (*s == '$') {
++s;
if (next_arg_index_ <= 0) { if (next_arg_index_ <= 0) {
next_arg_index_ = -1; next_arg_index_ = -1;
return value - 1; return arg_index - 1;
} }
if (!error) if (!error)
error = "cannot switch from automatic to manual argument indexing"; error = "cannot switch from automatic to manual argument indexing";
} }
}
if (next_arg_index_ >= 0) if (next_arg_index_ >= 0)
return next_arg_index_++; return next_arg_index_++;
// Don't check if the error has already been set because the argument // Don't check if the error has already been set because the argument
@ -656,7 +651,7 @@ unsigned fmt::BasicWriter<Char>::PrintfParser::ParseArgIndex(
// indexing errors are reported first even though parsing width // indexing errors are reported first even though parsing width
// above can cause another error. // above can cause another error.
error = "cannot switch from manual to automatic argument indexing"; error = "cannot switch from manual to automatic argument indexing";
return value; return 0;
} }
template <typename Char> template <typename Char>
@ -694,15 +689,27 @@ void fmt::BasicWriter<Char>::PrintfParser::Format(
const char *error = 0; const char *error = 0;
c = *s; c = *s;
unsigned arg_index = ParseArgIndex(s, error); unsigned arg_index = UINT_MAX;
if (c >= '0' && c <= '9' && s[-1] != '$') { // TODO if (c >= '0' && c <= '9') {
unsigned value = internal::ParseNonnegativeInt(s, error);
if (*s != '$') {
if (c == '0') if (c == '0')
spec.fill_ = '0'; spec.fill_ = '0';
if (arg_index != 0) if (value != 0)
spec.width_ = arg_index + 1; spec.width_ = value;
arg_index = 0; } else {
++s;
arg_index = value;
} }
} else if (c == '*') {
++s;
const ArgInfo &arg = args_[HandleArgIndex(UINT_MAX, error)];
// TODO: check if arg is integer
spec.width_ = GetIntValue(arg);
}
arg_index = HandleArgIndex(arg_index, error);
// TODO: move to HandleArgIndex
const ArgInfo *arg = 0; const ArgInfo *arg = 0;
if (arg_index < num_args) { if (arg_index < num_args) {
arg = &args_[arg_index]; arg = &args_[arg_index];

View File

@ -1043,7 +1043,7 @@ class BasicWriter {
const ArgInfo *args_; const ArgInfo *args_;
int next_arg_index_; int next_arg_index_;
unsigned ParseArgIndex(const Char *&s, const char *&error); unsigned HandleArgIndex(unsigned arg_index, const char *&error);
void ParseFlags(FormatSpec &spec, const Char *&s, const ArgInfo &arg); void ParseFlags(FormatSpec &spec, const Char *&s, const ArgInfo &arg);
public: public:

View File

@ -135,6 +135,7 @@ TEST(PrintfTest, DefaultAlignRight) {
TEST(PrintfTest, Width) { TEST(PrintfTest, Width) {
EXPECT_PRINTF(" abc", "%5s", "abc"); EXPECT_PRINTF(" abc", "%5s", "abc");
EXPECT_EQ(" 42", str(fmt::sprintf("%*d", 5, 42)));
// Width cannot be specified twice. // Width cannot be specified twice.
EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), FormatError, EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), FormatError,