From 1275923a6862314323d0d01e103a9ff43f9d643e Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Tue, 17 Jun 2014 06:53:48 -0700 Subject: [PATCH] Implement dynamic width in printf. --- format.cc | 51 ++++++++++++++++++++++++++------------------- format.h | 2 +- test/printf-test.cc | 1 + 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/format.cc b/format.cc index a612f0c3..49392906 100644 --- a/format.cc +++ b/format.cc @@ -632,22 +632,17 @@ void fmt::BasicWriter::PrintfParser::ParseFlags( } } +// FIXME: this doesnt' depend on template argument template -unsigned fmt::BasicWriter::PrintfParser::ParseArgIndex( - const Char *&s, const char *&error) { - Char c = *s; - unsigned value = 0; - if (c >= '0' && c <= '9') { - value = internal::ParseNonnegativeInt(s, error); - if (*s == '$') { - ++s; - if (next_arg_index_ <= 0) { - next_arg_index_ = -1; - return value - 1; - } - if (!error) - error = "cannot switch from automatic to manual argument indexing"; +unsigned fmt::BasicWriter::PrintfParser::HandleArgIndex( + unsigned arg_index, const char *&error) { + if (arg_index != UINT_MAX) { + if (next_arg_index_ <= 0) { + next_arg_index_ = -1; + return arg_index - 1; } + if (!error) + error = "cannot switch from automatic to manual argument indexing"; } if (next_arg_index_ >= 0) return next_arg_index_++; @@ -656,7 +651,7 @@ unsigned fmt::BasicWriter::PrintfParser::ParseArgIndex( // indexing errors are reported first even though parsing width // above can cause another error. error = "cannot switch from manual to automatic argument indexing"; - return value; + return 0; } template @@ -694,15 +689,27 @@ void fmt::BasicWriter::PrintfParser::Format( const char *error = 0; c = *s; - unsigned arg_index = ParseArgIndex(s, error); - if (c >= '0' && c <= '9' && s[-1] != '$') { // TODO - if (c == '0') - spec.fill_ = '0'; - if (arg_index != 0) - spec.width_ = arg_index + 1; - arg_index = 0; + unsigned arg_index = UINT_MAX; + if (c >= '0' && c <= '9') { + unsigned value = internal::ParseNonnegativeInt(s, error); + if (*s != '$') { + if (c == '0') + spec.fill_ = '0'; + if (value != 0) + spec.width_ = value; + } 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; if (arg_index < num_args) { arg = &args_[arg_index]; diff --git a/format.h b/format.h index b1c45bb6..b019d302 100644 --- a/format.h +++ b/format.h @@ -1043,7 +1043,7 @@ class BasicWriter { const ArgInfo *args_; 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); public: diff --git a/test/printf-test.cc b/test/printf-test.cc index b37f8d63..5e7e41ce 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -135,6 +135,7 @@ TEST(PrintfTest, DefaultAlignRight) { TEST(PrintfTest, Width) { EXPECT_PRINTF(" abc", "%5s", "abc"); + EXPECT_EQ(" 42", str(fmt::sprintf("%*d", 5, 42))); // Width cannot be specified twice. EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), FormatError,