From 42de4f1f7d6c89d09bdaef1b42fe9f9299712f9f Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 27 Aug 2014 08:24:31 -0700 Subject: [PATCH] Get rid of FormatErrorReporter. --- format.cc | 66 +++++++++++++++++++++------------------------ format.h | 10 ------- test/format-test.cc | 59 +++++++++++++++++++++------------------- 3 files changed, 63 insertions(+), 72 deletions(-) diff --git a/format.cc b/format.cc index ce9b90da..92e323aa 100644 --- a/format.cc +++ b/format.cc @@ -565,13 +565,6 @@ class fmt::internal::ArgFormatter : } }; -template -void fmt::internal::FormatErrorReporter::operator()( - const Char *s, fmt::StringRef message) const { - if (find_closing_brace(s, num_open_braces)) - throw fmt::FormatError(message); -} - // Fills the padding around the content and returns the pointer to the // content area. template @@ -763,22 +756,23 @@ inline const Arg unsigned arg_index = 0; if (*s < '0' || *s > '9') { if (*s != '}' && *s != ':') - report_error_(s, "invalid argument index in format string"); + throw FormatError("invalid format string"); const Arg &arg = next_arg(); if (error_) - report_error_(s, error_); + throw FormatError(error_); return arg; } if (next_arg_index_ > 0) { - report_error_(s, + throw FormatError( "cannot switch from automatic to manual argument indexing"); } next_arg_index_ = -1; arg_index = parse_nonnegative_int(s, error_); - if (error_) - report_error_(s, error_); // TODO: don't use report_error_ - if (arg_index >= args_.size()) - report_error_(s, "argument index is out of range in format"); + if (arg_index >= args_.size()) { + if (!error_) + error_ = "argument index is out of range in format"; + return DUMMY_ARG; + } return args_[arg_index]; } @@ -787,12 +781,12 @@ void fmt::BasicFormatter::check_sign( const Char *&s, const Arg &arg) { char sign = static_cast(*s); if (arg.type > Arg::LAST_NUMERIC_TYPE) { - report_error_(s, fmt::format( - "format specifier '{}' requires numeric argument", sign).c_str()); + throw FormatError(fmt::format( + "format specifier '{}' requires numeric argument", sign)); } if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) { - report_error_(s, fmt::format( - "format specifier '{}' requires signed argument", sign).c_str()); + throw FormatError(fmt::format( + "format specifier '{}' requires signed argument", sign)); } ++s; } @@ -1099,12 +1093,12 @@ const Char *fmt::BasicFormatter::format( if (p != s) { if (c == '}') break; if (c == '{') - report_error_(s, "invalid fill character '{'"); + throw FormatError("invalid fill character '{'"); s += 2; spec.fill_ = c; } else ++s; if (spec.align_ == ALIGN_NUMERIC && arg.type > Arg::LAST_NUMERIC_TYPE) - report_error_(s, "format specifier '=' requires numeric argument"); + throw FormatError("format specifier '=' requires numeric argument"); break; } } while (--p >= s); @@ -1128,7 +1122,8 @@ const Char *fmt::BasicFormatter::format( if (*s == '#') { if (arg.type > Arg::LAST_NUMERIC_TYPE) - report_error_(s, "format specifier '#' requires numeric argument"); + // TODO: make FormatError accept arguments + throw FormatError("format specifier '#' requires numeric argument"); spec.flags_ |= HASH_FLAG; ++s; } @@ -1137,7 +1132,7 @@ const Char *fmt::BasicFormatter::format( if ('0' <= *s && *s <= '9') { if (*s == '0') { if (arg.type > Arg::LAST_NUMERIC_TYPE) - report_error_(s, "format specifier '0' requires numeric argument"); + throw FormatError("format specifier '0' requires numeric argument"); spec.align_ = ALIGN_NUMERIC; spec.fill_ = '0'; } @@ -1145,7 +1140,7 @@ const Char *fmt::BasicFormatter::format( // and more efficient than checking if the next char is a digit. spec.width_ = parse_nonnegative_int(s, error); if (error) - report_error_(s, error); + throw FormatError(error); } // Parse precision. @@ -1155,16 +1150,19 @@ const Char *fmt::BasicFormatter::format( if ('0' <= *s && *s <= '9') { spec.precision_ = parse_nonnegative_int(s, error); if (error) - report_error_(s, error); + throw FormatError(error); } else if (*s == '{') { ++s; - ++report_error_.num_open_braces; const Arg &precision_arg = parse_arg_index(s); + if (*s++ != '}') + throw FormatError("unmatched '{' in format"); + if (error_) + throw FormatError(error_); ULongLong value = 0; switch (precision_arg.type) { case Arg::INT: if (precision_arg.int_value < 0) - report_error_(s, "negative precision in format"); + throw FormatError("negative precision in format"); value = precision_arg.int_value; break; case Arg::UINT: @@ -1172,26 +1170,23 @@ const Char *fmt::BasicFormatter::format( break; case Arg::LONG_LONG: if (precision_arg.long_long_value < 0) - report_error_(s, "negative precision in format"); + throw FormatError("negative precision in format"); value = precision_arg.long_long_value; break; case Arg::ULONG_LONG: value = precision_arg.ulong_long_value; break; default: - report_error_(s, "precision is not integer"); + throw FormatError("precision is not integer"); } if (value > INT_MAX) - report_error_(s, "number is too big in format"); + throw FormatError("number is too big in format"); spec.precision_ = static_cast(value); - if (*s++ != '}') - throw FormatError("unmatched '{' in format"); - --report_error_.num_open_braces; } else { - report_error_(s, "missing precision in format"); + throw FormatError("missing precision in format"); } if (arg.type != Arg::DOUBLE && arg.type != Arg::LONG_DOUBLE) { - report_error_(s, + throw FormatError( "precision specifier requires floating-point argument"); } } @@ -1203,6 +1198,8 @@ const Char *fmt::BasicFormatter::format( if (*s++ != '}') throw FormatError("unmatched '{' in format"); + if (error_) + throw FormatError(error_); start_ = s; // Format argument. @@ -1226,7 +1223,6 @@ void fmt::BasicFormatter::format( } if (c == '}') throw FormatError("unmatched '}' in format"); - report_error_.num_open_braces = 1; write(writer_, start_, s - 1); Arg arg = parse_arg_index(s); s = format(s, arg); diff --git a/format.h b/format.h index 94a17475..a2cc1277 100644 --- a/format.h +++ b/format.h @@ -553,15 +553,6 @@ void format_windows_error( fmt::Writer &out, int error_code, fmt::StringRef message); #endif -// Throws Exception(message) if format contains '}', otherwise throws -// FormatError reporting unmatched '{'. The idea is that unmatched '{' -// should override other errors. -template -struct FormatErrorReporter { - int num_open_braces; - void operator()(const Char *s, fmt::StringRef message) const; -}; - // Computes max(Arg, 1) at compile time. It is used to avoid errors about // allocating an array of 0 size. template @@ -893,7 +884,6 @@ class BasicFormatter : private internal::FormatterBase { private: BasicWriter &writer_; const Char *start_; - internal::FormatErrorReporter report_error_; // Parses argument index and returns an argument with this index. const internal::Arg &parse_arg_index(const Char *&s); diff --git a/test/format-test.cc b/test/format-test.cc index 2dd82602..bbe51da0 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -585,7 +585,7 @@ TEST(FormatterTest, Escape) { } TEST(FormatterTest, UnmatchedBraces) { - EXPECT_THROW_MSG(format("{"), FormatError, "unmatched '{' in format"); + EXPECT_THROW_MSG(format("{"), FormatError, "invalid format string"); EXPECT_THROW_MSG(format("}"), FormatError, "unmatched '}' in format"); EXPECT_THROW_MSG(format("{0{}"), FormatError, "unmatched '{' in format"); } @@ -605,9 +605,8 @@ TEST(FormatterTest, ArgsInDifferentPositions) { } TEST(FormatterTest, ArgErrors) { - EXPECT_THROW_MSG(format("{"), FormatError, "unmatched '{' in format"); - EXPECT_THROW_MSG(format("{x}"), FormatError, - "invalid argument index in format string"); + EXPECT_THROW_MSG(format("{"), FormatError, "invalid format string"); + EXPECT_THROW_MSG(format("{x}"), FormatError, "invalid format string"); EXPECT_THROW_MSG(format("{0"), FormatError, "unmatched '{' in format"); EXPECT_THROW_MSG(format("{0}"), FormatError, "argument index is out of range in format"); @@ -622,7 +621,8 @@ TEST(FormatterTest, ArgErrors) { safe_sprintf(format_str, "{%u", INT_MAX + 1u); EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format"); safe_sprintf(format_str, "{%u}", INT_MAX + 1u); - EXPECT_THROW_MSG(format(format_str), FormatError, "number is too big in format"); + EXPECT_THROW_MSG(format(format_str), FormatError, + "number is too big in format"); } TEST(FormatterTest, AutoArgIndex) { @@ -727,7 +727,7 @@ TEST(FormatterTest, CenterAlign) { TEST(FormatterTest, Fill) { EXPECT_THROW_MSG(format("{0:{<5}", 'c'), - FormatError, "unmatched '{' in format"); + FormatError, "invalid fill character '{'"); EXPECT_THROW_MSG(format("{0:{<5}}", 'c'), FormatError, "invalid fill character '{'"); EXPECT_EQ("**42", format("{0:*>4}", 42)); @@ -896,18 +896,20 @@ TEST(FormatterTest, Width) { char format_str[BUFFER_SIZE]; safe_sprintf(format_str, "{0:%u", UINT_MAX); increment(format_str + 3); - EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format"); + EXPECT_THROW_MSG(format(format_str), FormatError, + "number is too big in format"); std::size_t size = std::strlen(format_str); format_str[size] = '}'; format_str[size + 1] = 0; - EXPECT_THROW_MSG(format(format_str, 0), - FormatError, "number is too big in format"); + EXPECT_THROW_MSG(format(format_str, 0), FormatError, + "number is too big in format"); safe_sprintf(format_str, "{0:%u", INT_MAX + 1u); - EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format"); + EXPECT_THROW_MSG(format(format_str), FormatError, + "number is too big in format"); safe_sprintf(format_str, "{0:%u}", INT_MAX + 1u); - EXPECT_THROW_MSG(format(format_str, 0), - FormatError, "number is too big in format"); + EXPECT_THROW_MSG(format(format_str, 0), FormatError, + "number is too big in format"); EXPECT_EQ(" -42", format("{0:4}", -42)); EXPECT_EQ(" 42", format("{0:5}", 42u)); EXPECT_EQ(" -42", format("{0:6}", -42l)); @@ -926,26 +928,28 @@ TEST(FormatterTest, Precision) { char format_str[BUFFER_SIZE]; safe_sprintf(format_str, "{0:.%u", UINT_MAX); increment(format_str + 4); - EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format"); + EXPECT_THROW_MSG(format(format_str), FormatError, + "number is too big in format"); std::size_t size = std::strlen(format_str); format_str[size] = '}'; format_str[size + 1] = 0; - EXPECT_THROW_MSG(format(format_str, 0), - FormatError, "number is too big in format"); + EXPECT_THROW_MSG(format(format_str, 0), FormatError, + "number is too big in format"); safe_sprintf(format_str, "{0:.%u", INT_MAX + 1u); - EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format"); + EXPECT_THROW_MSG(format(format_str), FormatError, + "number is too big in format"); safe_sprintf(format_str, "{0:.%u}", INT_MAX + 1u); - EXPECT_THROW_MSG(format(format_str, 0), - FormatError, "number is too big in format"); + EXPECT_THROW_MSG(format(format_str, 0), FormatError, + "number is too big in format"); EXPECT_THROW_MSG(format("{0:.", 0), - FormatError, "unmatched '{' in format"); + FormatError, "missing precision in format"); EXPECT_THROW_MSG(format("{0:.}", 0), FormatError, "missing precision in format"); - EXPECT_THROW_MSG(format("{0:.2", 0), - FormatError, "unmatched '{' in format"); + EXPECT_THROW_MSG(format("{0:.2", 0), + FormatError, "precision specifier requires floating-point argument"); EXPECT_THROW_MSG(format("{0:.2}", 42), FormatError, "precision specifier requires floating-point argument"); EXPECT_THROW_MSG(format("{0:.2f}", 42), @@ -997,25 +1001,26 @@ TEST(FormatterTest, Precision) { TEST(FormatterTest, RuntimePrecision) { char format_str[BUFFER_SIZE]; safe_sprintf(format_str, "{0:.{%u", UINT_MAX); - increment(format_str + 4); + increment(format_str + 5); EXPECT_THROW_MSG(format(format_str), FormatError, "unmatched '{' in format"); std::size_t size = std::strlen(format_str); format_str[size] = '}'; format_str[size + 1] = 0; - EXPECT_THROW_MSG(format(format_str, 0), FormatError, "unmatched '{' in format"); + EXPECT_THROW_MSG(format(format_str, 0), FormatError, + "number is too big in format"); format_str[size + 1] = '}'; format_str[size + 2] = 0; EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big in format"); EXPECT_THROW_MSG(format("{0:.{", 0), - FormatError, "unmatched '{' in format"); + FormatError, "invalid format string"); EXPECT_THROW_MSG(format("{0:.{}", 0), - FormatError, "unmatched '{' in format"); + FormatError, "cannot switch from manual to automatic argument indexing"); EXPECT_THROW_MSG(format("{0:.{x}}", 0), - FormatError, "invalid argument index in format string"); + FormatError, "invalid format string"); EXPECT_THROW_MSG(format("{0:.{1}", 0, 0), - FormatError, "unmatched '{' in format"); + FormatError, "precision specifier requires floating-point argument"); EXPECT_THROW_MSG(format("{0:.{1}}", 0), FormatError, "argument index is out of range in format");