From 5a32e64b0514cbe89874962fb64bb815f80e5d50 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 19 Nov 2017 06:35:23 -0800 Subject: [PATCH] More tests --- include/fmt/format.h | 74 +++++++++++++++++++++----------------------- include/fmt/printf.h | 2 +- include/fmt/time.h | 2 +- test/format-test.cc | 5 ++- test/printf-test.cc | 4 +-- 5 files changed, 44 insertions(+), 43 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 49a8a27d..1a327416 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -407,7 +407,7 @@ class basic_string_view { constexpr iterator begin() const { return data_; } constexpr iterator end() const { return data_ + size_; } - void remove_prefix(size_t n) { + constexpr void remove_prefix(size_t n) { data_ += n; size_ -= n; } @@ -460,7 +460,7 @@ namespace internal { // Casts nonnegative integer to unsigned. template -inline typename std::make_unsigned::type to_unsigned(Int value) { +constexpr typename std::make_unsigned::type to_unsigned(Int value) { FMT_ASSERT(value >= 0, "negative value"); return static_cast::type>(value); } @@ -1956,9 +1956,9 @@ class parse_context : public ErrorHandler { int next_arg_index_; protected: - bool check_no_auto_index(const char *&error) { + constexpr bool check_no_auto_index() { if (next_arg_index_ > 0) { - error = "cannot switch from automatic to manual argument indexing"; + on_error("cannot switch from automatic to manual argument indexing"); return false; } next_arg_index_ = -1; @@ -1981,26 +1981,25 @@ class parse_context : public ErrorHandler { constexpr iterator end() const { return format_str_.end(); } // Advances the begin iterator to ``it``. - void advance_to(iterator it) { + constexpr void advance_to(iterator it) { format_str_.remove_prefix(it - begin()); } // Returns the next argument index. - unsigned next_arg_index(const char *&error) { + constexpr unsigned next_arg_index() { if (next_arg_index_ >= 0) return internal::to_unsigned(next_arg_index_++); - error = "cannot switch from manual to automatic argument indexing"; + on_error("cannot switch from manual to automatic argument indexing"); return 0; } - void check_arg_id(unsigned) { - const char *error = 0; - if (!check_no_auto_index(error)) - FMT_THROW(format_error(error)); - } - + constexpr void check_arg_id(unsigned) { check_no_auto_index(); } void check_arg_id(basic_string_view) {} + constexpr void on_error(const char *message) { + ErrorHandler::on_error(message); + } + constexpr ErrorHandler error_handler() const { return *this; } }; @@ -2029,7 +2028,7 @@ class context_base : public parse_context{ // Checks if manual indexing is used and returns the argument with // specified index. format_arg get_arg(unsigned arg_index, const char *&error) { - return this->check_no_auto_index(error) ? + return this->check_no_auto_index() ? this->do_get_arg(arg_index, error) : format_arg(); } @@ -2365,11 +2364,7 @@ class dynamic_specs_handler : } constexpr arg_ref_type make_arg_ref(auto_id) { - const char *error = 0; - auto index = context_.next_arg_index(error); - if (error) - FMT_THROW(format_error(error)); - return arg_ref_type(index); + return arg_ref_type(context_.next_arg_index()); } dynamic_format_specs &specs_; @@ -2607,19 +2602,21 @@ constexpr const typename ParseContext::char_type * } template -class format_string_checker : public ErrorHandler { +class format_string_checker { public: - explicit constexpr format_string_checker(ErrorHandler eh, const Char *end) - : ErrorHandler(eh), end_(end) {} + explicit constexpr format_string_checker( + basic_string_view format_str, ErrorHandler eh) + : context_(format_str, eh) {} constexpr void on_text(const Char *, const Char *) {} constexpr void on_arg_id() { - ++arg_index_; + arg_index_ = context_.next_arg_index(); check_arg_index(); } constexpr void on_arg_id(unsigned index) { arg_index_ = index; + context_.check_arg_id(index); check_arg_index(); } constexpr void on_arg_id(basic_string_view) {} @@ -2627,8 +2624,13 @@ class format_string_checker : public ErrorHandler { constexpr void on_replacement_field(const Char *) {} constexpr const Char *on_format_specs(const Char *s) { - parse_context_type ctx(basic_string_view(s, end_ - s), *this); - return arg_index_ < NUM_ARGS ? parse_funcs_[arg_index_](ctx) : s; + context_.advance_to(s); + return to_unsigned(arg_index_) < NUM_ARGS ? + parse_funcs_[arg_index_](context_) : s; + } + + constexpr void on_error(const char *message) { + context_.on_error(message); } private: @@ -2636,16 +2638,15 @@ class format_string_checker : public ErrorHandler { constexpr static size_t NUM_ARGS = sizeof...(Args); constexpr void check_arg_index() { - unsigned unsigned_index = arg_index_; - if (arg_index_ < 0 || unsigned_index >= NUM_ARGS) - this->on_error("argument index out of range"); + if (internal::to_unsigned(arg_index_) >= NUM_ARGS) + context_.on_error("argument index out of range"); } // Format specifier parsing function. using parse_func = const Char *(*)(parse_context_type &); - const Char *end_; int arg_index_ = -1; + parse_context_type context_; parse_func parse_funcs_[NUM_ARGS > 0 ? NUM_ARGS : 1] = { &parse_format_specs... }; @@ -2654,7 +2655,7 @@ class format_string_checker : public ErrorHandler { template constexpr bool check_format_string( basic_string_view s, ErrorHandler eh = ErrorHandler()) { - format_string_checker checker(eh, s.end()); + format_string_checker checker(s, eh); parse_format_string(s.begin(), checker); return true; } @@ -2751,7 +2752,7 @@ class basic_context : format_arg next_arg() { const char *error = 0; - format_arg arg = this->do_get_arg(this->next_arg_index(error), error); + format_arg arg = this->do_get_arg(this->next_arg_index(), error); if (error) FMT_THROW(format_error(error)); return arg; @@ -3861,15 +3862,12 @@ struct dynamic_formatter { template inline typename basic_context::format_arg basic_context::get_arg(basic_string_view name) { - const char *error = 0; - if (this->check_no_auto_index(error)) { + if (this->check_no_auto_index()) { map_.init(this->args()); if (const format_arg *arg = map_.find(name)) return *arg; - error = "argument not found"; + this->on_error("argument not found"); } - if (error) - FMT_THROW(format_error(error)); return format_arg(); } @@ -3881,8 +3879,8 @@ void vformat_to(basic_buffer &buffer, basic_string_view format_str, struct handler : internal::error_handler { handler(basic_buffer &b, basic_string_view str, - basic_args args) - : buffer(b), context(str, args) {} + basic_args format_args) + : buffer(b), context(str, format_args) {} void on_text(iterator begin, iterator end) { buffer.append(pointer_from(begin), pointer_from(end)); diff --git a/include/fmt/printf.h b/include/fmt/printf.h index a8533ef2..263fa5ab 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -370,7 +370,7 @@ typename printf_context::format_arg printf_context::get_arg( const char *error = 0; format_arg arg; if (arg_index == std::numeric_limits::max()) { - arg_index = this->next_arg_index(error); + arg_index = this->next_arg_index(); if (!error) arg = this->do_get_arg(arg_index, error); } else { diff --git a/include/fmt/time.h b/include/fmt/time.h index c1687373..1a7c6e03 100644 --- a/include/fmt/time.h +++ b/include/fmt/time.h @@ -32,7 +32,7 @@ struct formatter { return pointer_from(end); } - void format(buffer &buf, const std::tm &tm, context &ctx) { + void format(buffer &buf, const std::tm &tm, context &) { std::size_t start = buf.size(); for (;;) { std::size_t size = buf.capacity() - start; diff --git a/test/format-test.cc b/test/format-test.cc index f10cd472..9d19fd5f 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1702,7 +1702,7 @@ struct test_context { template constexpr void check_arg_id(Id) {} - constexpr unsigned next_arg_index(const char *&) { return 33; } + constexpr unsigned next_arg_index() { return 33; } void on_error(const char *) {} @@ -1903,4 +1903,7 @@ TEST(FormatTest, FormatStringErrors) { EXPECT_ERROR("{:.x}", "missing precision specifier", int); EXPECT_ERROR("{}", "argument index out of range"); EXPECT_ERROR("{1}", "argument index out of range", int); + EXPECT_ERROR("{1}{}", + "cannot switch from manual to automatic argument indexing", + int, int); } diff --git a/test/printf-test.cc b/test/printf-test.cc index 7ab5390e..aabc5e26 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -87,14 +87,14 @@ TEST(PrintfTest, NumberIsTooBigInArgIndex) { TEST(PrintfTest, SwitchArgIndexing) { EXPECT_THROW_MSG(fmt::sprintf("%1$d%", 1, 2), - format_error, "invalid format string"); + format_error, "cannot switch from manual to automatic argument indexing"); EXPECT_THROW_MSG(fmt::sprintf(format("%1$d%{}d", BIG_NUM), 1, 2), format_error, "number is too big"); EXPECT_THROW_MSG(fmt::sprintf("%1$d%d", 1, 2), format_error, "cannot switch from manual to automatic argument indexing"); EXPECT_THROW_MSG(fmt::sprintf("%d%1$", 1, 2), - format_error, "invalid format string"); + format_error, "cannot switch from automatic to manual argument indexing"); EXPECT_THROW_MSG(fmt::sprintf(format("%d%{}$d", BIG_NUM), 1, 2), format_error, "number is too big"); EXPECT_THROW_MSG(fmt::sprintf("%d%1$d", 1, 2),