Improve error reporting.

This commit is contained in:
Victor Zverovich 2014-08-29 07:45:55 -07:00
parent 271fa8c908
commit 605d2600f8
4 changed files with 59 additions and 50 deletions

View File

@ -760,28 +760,28 @@ inline const Arg &fmt::BasicFormatter<Char>::parse_arg_index(const Char *&s) {
return *arg;
}
const Arg *fmt::internal::FormatterBase::next_arg(const char *&error) {
if (next_arg_index_ < 0) {
error = "cannot switch from manual to automatic argument indexing";
return 0;
}
unsigned arg_index = next_arg_index_++;
const Arg *fmt::internal::FormatterBase::do_get_arg(
unsigned arg_index, const char *&error) {
if (arg_index < args_.size())
return &args_[arg_index];
error = "argument index is out of range in format";
error = "argument index out of range";
return 0;
}
const Arg *fmt::internal::FormatterBase::get_arg(
inline const Arg *fmt::internal::FormatterBase::next_arg(const char *&error) {
if (next_arg_index_ >= 0)
return do_get_arg(next_arg_index_++, error);
error = "cannot switch from manual to automatic argument indexing";
return 0;
}
inline const Arg *fmt::internal::FormatterBase::get_arg(
unsigned arg_index, const char *&error) {
if (next_arg_index_ > 0) {
error = "cannot switch from automatic to manual argument indexing";
return 0;
if (next_arg_index_ <= 0) {
next_arg_index_ = -1;
return do_get_arg(arg_index, error);
}
next_arg_index_ = -1;
if (arg_index < args_.size())
return &args_[arg_index];
error = "argument index is out of range in format";
error = "cannot switch from automatic to manual argument indexing";
return 0;
}
@ -862,8 +862,7 @@ void fmt::internal::PrintfFormatter<Char>::format(
BasicWriter<Char> &writer, BasicStringRef<Char> format,
const ArgList &args) {
const Char *start = format.c_str();
args_ = args;
next_arg_index_ = 0;
set_args(args);
const Char *s = start;
while (*s) {
Char c = *s++;
@ -1118,12 +1117,12 @@ const Char *fmt::BasicFormatter<Char>::format(
++s;
const Arg &precision_arg = parse_arg_index(s);
if (*s++ != '}')
throw FormatError("unmatched '{' in format");
throw FormatError("invalid format string");
ULongLong value = 0;
switch (precision_arg.type) {
case Arg::INT:
if (precision_arg.int_value < 0)
throw FormatError("negative precision in format");
throw FormatError("negative precision");
value = precision_arg.int_value;
break;
case Arg::UINT:
@ -1131,7 +1130,7 @@ const Char *fmt::BasicFormatter<Char>::format(
break;
case Arg::LONG_LONG:
if (precision_arg.long_long_value < 0)
throw FormatError("negative precision in format");
throw FormatError("negative precision");
value = precision_arg.long_long_value;
break;
case Arg::ULONG_LONG:
@ -1144,7 +1143,7 @@ const Char *fmt::BasicFormatter<Char>::format(
throw FormatError("number is too big");
spec.precision_ = static_cast<int>(value);
} else {
throw FormatError("missing precision in format");
throw FormatError("missing precision specifier");
}
if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) {
throw FormatError(
@ -1158,7 +1157,7 @@ const Char *fmt::BasicFormatter<Char>::format(
}
if (*s++ != '}')
throw FormatError("unmatched '{' in format");
throw FormatError("missing '}' in format string");
start_ = s;
// Format argument.
@ -1170,8 +1169,7 @@ template <typename Char>
void fmt::BasicFormatter<Char>::format(
BasicStringRef<Char> format_str, const ArgList &args) {
const Char *s = start_ = format_str.c_str();
args_ = args;
next_arg_index_ = 0;
set_args(args);
while (*s) {
Char c = *s++;
if (c != '{' && c != '}') continue;
@ -1181,7 +1179,7 @@ void fmt::BasicFormatter<Char>::format(
continue;
}
if (c == '}')
throw FormatError("unmatched '}' in format");
throw FormatError("unmatched '}' in format string");
write(writer_, start_, s - 1);
Arg arg = parse_arg_index(s);
s = format(s, arg);

View File

@ -842,14 +842,24 @@ struct FormatSpec;
namespace internal {
class FormatterBase {
protected:
private:
ArgList args_;
int next_arg_index_;
// Returns the argument with specified index.
const Arg *do_get_arg(unsigned arg_index, const char *&error);
protected:
void set_args(const ArgList &args) {
args_ = args;
next_arg_index_ = 0;
}
// Returns the next argument.
const Arg *next_arg(const char *&error);
// Returns the argument with specified index.
// Checks if manual indexing is used and returns the argument with
// specified index.
const Arg *get_arg(unsigned arg_index, const char *&error);
template <typename Char>

View File

@ -586,7 +586,7 @@ TEST(FormatterTest, Escape) {
TEST(FormatterTest, UnmatchedBraces) {
EXPECT_THROW_MSG(format("{"), FormatError, "invalid format string");
EXPECT_THROW_MSG(format("}"), FormatError, "unmatched '}' in format");
EXPECT_THROW_MSG(format("}"), FormatError, "unmatched '}' in format string");
EXPECT_THROW_MSG(format("{0{}"), FormatError, "invalid format string");
}
@ -608,15 +608,14 @@ TEST(FormatterTest, ArgErrors) {
EXPECT_THROW_MSG(format("{"), FormatError, "invalid format string");
EXPECT_THROW_MSG(format("{x}"), FormatError, "invalid format string");
EXPECT_THROW_MSG(format("{0"), FormatError, "invalid format string");
EXPECT_THROW_MSG(format("{0}"), FormatError,
"argument index is out of range in format");
EXPECT_THROW_MSG(format("{0}"), FormatError, "argument index out of range");
char format_str[BUFFER_SIZE];
safe_sprintf(format_str, "{%u", INT_MAX);
EXPECT_THROW_MSG(format(format_str), FormatError, "invalid format string");
safe_sprintf(format_str, "{%u}", INT_MAX);
EXPECT_THROW_MSG(format(format_str), FormatError,
"argument index is out of range in format");
"argument index out of range");
safe_sprintf(format_str, "{%u", INT_MAX + 1u);
EXPECT_THROW_MSG(format(format_str), FormatError, "number is too big");
@ -635,8 +634,7 @@ TEST(FormatterTest, AutoArgIndex) {
FormatError, "cannot switch from manual to automatic argument indexing");
EXPECT_THROW_MSG(format("{:.{0}}", 1.2345, 2),
FormatError, "cannot switch from automatic to manual argument indexing");
EXPECT_THROW_MSG(format("{}"), FormatError,
"argument index is out of range in format");
EXPECT_THROW_MSG(format("{}"), FormatError, "argument index out of range");
}
TEST(FormatterTest, EmptySpecs) {
@ -695,7 +693,7 @@ TEST(FormatterTest, NumericAlign) {
EXPECT_EQ("- 42", format("{0:=5}", -42.0));
EXPECT_EQ("- 42", format("{0:=5}", -42.0l));
EXPECT_THROW_MSG(format("{0:=5", 'c'),
FormatError, "unmatched '{' in format");
FormatError, "missing '}' in format string");
EXPECT_THROW_MSG(format("{0:=5}", 'c'),
FormatError, "invalid format specifier for char");
EXPECT_THROW_MSG(format("{0:=5}", "abc"),
@ -759,7 +757,7 @@ TEST(FormatterTest, PlusSign) {
EXPECT_EQ("+42", format("{0:+}", 42.0));
EXPECT_EQ("+42", format("{0:+}", 42.0l));
EXPECT_THROW_MSG(format("{0:+", 'c'),
FormatError, "unmatched '{' in format");
FormatError, "missing '}' in format string");
EXPECT_THROW_MSG(format("{0:+}", 'c'),
FormatError, "invalid format specifier for char");
EXPECT_THROW_MSG(format("{0:+}", "abc"),
@ -785,7 +783,7 @@ TEST(FormatterTest, MinusSign) {
EXPECT_EQ("42", format("{0:-}", 42.0));
EXPECT_EQ("42", format("{0:-}", 42.0l));
EXPECT_THROW_MSG(format("{0:-", 'c'),
FormatError, "unmatched '{' in format");
FormatError, "missing '}' in format string");
EXPECT_THROW_MSG(format("{0:-}", 'c'),
FormatError, "invalid format specifier for char");
EXPECT_THROW_MSG(format("{0:-}", "abc"),
@ -811,7 +809,7 @@ TEST(FormatterTest, SpaceSign) {
EXPECT_EQ(" 42", format("{0: }", 42.0));
EXPECT_EQ(" 42", format("{0: }", 42.0l));
EXPECT_THROW_MSG(format("{0: ", 'c'),
FormatError, "unmatched '{' in format");
FormatError, "missing '}' in format string");
EXPECT_THROW_MSG(format("{0: }", 'c'),
FormatError, "invalid format specifier for char");
EXPECT_THROW_MSG(format("{0: }", "abc"),
@ -858,7 +856,7 @@ TEST(FormatterTest, HashFlag) {
EXPECT_EQ("-42.0000", format("{0:#}", -42.0));
EXPECT_EQ("-42.0000", format("{0:#}", -42.0l));
EXPECT_THROW_MSG(format("{0:#", 'c'),
FormatError, "unmatched '{' in format");
FormatError, "missing '}' in format string");
EXPECT_THROW_MSG(format("{0:#}", 'c'),
FormatError, "invalid format specifier for char");
EXPECT_THROW_MSG(format("{0:#}", "abc"),
@ -880,7 +878,7 @@ TEST(FormatterTest, ZeroFlag) {
EXPECT_EQ("-0042", format("{0:05}", -42.0));
EXPECT_EQ("-0042", format("{0:05}", -42.0l));
EXPECT_THROW_MSG(format("{0:0", 'c'),
FormatError, "unmatched '{' in format");
FormatError, "missing '}' in format string");
EXPECT_THROW_MSG(format("{0:05}", 'c'),
FormatError, "invalid format specifier for char");
EXPECT_THROW_MSG(format("{0:05}", "abc"),
@ -935,9 +933,9 @@ TEST(FormatterTest, Precision) {
EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
EXPECT_THROW_MSG(format("{0:.", 0),
FormatError, "missing precision in format");
FormatError, "missing precision specifier");
EXPECT_THROW_MSG(format("{0:.}", 0),
FormatError, "missing precision in format");
FormatError, "missing precision specifier");
EXPECT_THROW_MSG(format("{0:.2", 0),
FormatError, "precision specifier requires floating-point argument");
@ -1011,14 +1009,17 @@ TEST(FormatterTest, RuntimePrecision) {
EXPECT_THROW_MSG(format("{0:.{1}", 0, 0),
FormatError, "precision specifier requires floating-point argument");
EXPECT_THROW_MSG(format("{0:.{1}}", 0),
FormatError, "argument index is out of range in format");
FormatError, "argument index out of range");
EXPECT_THROW_MSG(format("{0:.{0:}}", 0),
FormatError, "invalid format string");
EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1),
FormatError, "negative precision in format");
FormatError, "negative precision");
EXPECT_THROW_MSG(format("{0:.{1}}", 0, (INT_MAX + 1u)),
FormatError, "number is too big");
EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l),
FormatError, "negative precision in format");
FormatError, "negative precision");
if (sizeof(long) > sizeof(int)) {
long value = INT_MAX;
EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)),
@ -1111,7 +1112,7 @@ TEST(FormatterTest, FormatShort) {
TEST(FormatterTest, FormatInt) {
EXPECT_THROW_MSG(format("{0:v", 42),
FormatError, "unmatched '{' in format");
FormatError, "missing '}' in format string");
check_unknown_types(42, "bBdoxX", "integer");
}

View File

@ -108,11 +108,11 @@ TEST(PrintfTest, SwitchArgIndexing) {
TEST(PrintfTest, InvalidArgIndex) {
EXPECT_THROW_MSG(fmt::sprintf("%0$d", 42), FormatError,
"argument index is out of range in format");
"argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf("%2$d", 42), FormatError,
"argument index is out of range in format");
"argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf(format("%{}$d", INT_MAX), 42),
FormatError, "argument index is out of range in format");
FormatError, "argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf("%2$", 42),
FormatError, "invalid format string");
@ -218,7 +218,7 @@ TEST(PrintfTest, DynamicWidth) {
EXPECT_THROW_MSG(fmt::sprintf("%*d", 5.0, 42), FormatError,
"width is not integer");
EXPECT_THROW_MSG(fmt::sprintf("%*d"), FormatError,
"argument index is out of range in format");
"argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf("%*d", BIG_NUM, 42), FormatError,
"number is too big");
}
@ -265,7 +265,7 @@ TEST(PrintfTest, DynamicPrecision) {
EXPECT_THROW_MSG(fmt::sprintf("%.*d", 5.0, 42), FormatError,
"precision is not integer");
EXPECT_THROW_MSG(fmt::sprintf("%.*d"), FormatError,
"argument index is out of range in format");
"argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf("%.*d", BIG_NUM, 42), FormatError,
"number is too big");
if (sizeof(fmt::LongLong) != sizeof(int)) {