Optimize parse_nonnegative_int

This commit is contained in:
Victor Zverovich 2021-06-13 19:05:31 -07:00
parent f28cf3302d
commit 3c8fad126c

View File

@ -8,10 +8,10 @@
#ifndef FMT_CORE_H_ #ifndef FMT_CORE_H_
#define FMT_CORE_H_ #define FMT_CORE_H_
#include <climits> // INT_MAX #include <cstdio> // std::FILE
#include <cstdio> // std::FILE
#include <cstring> #include <cstring>
#include <iterator> #include <iterator>
#include <limits>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
@ -2103,21 +2103,25 @@ template <typename Char, typename ErrorHandler>
FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end, FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end,
ErrorHandler&& eh) -> int { ErrorHandler&& eh) -> int {
FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', ""); FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', "");
unsigned value = 0; unsigned value = 0, prev = 0;
// Convert to unsigned to prevent a warning. auto p = begin;
const unsigned max_int = to_unsigned(INT_MAX);
unsigned big = max_int / 10;
do { do {
// Check for overflow. prev = value;
if (value > big) { value = value * 10 + unsigned(*p - '0');
value = max_int + 1; ++p;
break; } while (p != end && '0' <= *p && *p <= '9');
} auto num_digits = p - begin;
value = value * 10 + unsigned(*begin - '0'); begin = p;
++begin; if (num_digits <= std::numeric_limits<int>::digits10)
} while (begin != end && '0' <= *begin && *begin <= '9'); return static_cast<int>(value);
if (value > max_int) eh.on_error("number is too big"); // Check for overflow.
return static_cast<int>(value); const unsigned big = to_unsigned((std::numeric_limits<int>::max)());
if (num_digits == std::numeric_limits<int>::digits10 + 1 &&
prev * 10ull + unsigned(p[-1] - '0') <= big) {
return static_cast<int>(value);
}
eh.on_error("number is too big");
return -1;
} }
// Parses fill and alignment. // Parses fill and alignment.
@ -2454,8 +2458,8 @@ class compile_parse_context
public: public:
explicit FMT_CONSTEXPR compile_parse_context( explicit FMT_CONSTEXPR compile_parse_context(
basic_string_view<Char> format_str, int num_args = INT_MAX, basic_string_view<Char> format_str,
ErrorHandler eh = {}) int num_args = (std::numeric_limits<int>::max)(), ErrorHandler eh = {})
: base(format_str, eh), num_args_(num_args) {} : base(format_str, eh), num_args_(num_args) {}
FMT_CONSTEXPR auto next_arg_id() -> int { FMT_CONSTEXPR auto next_arg_id() -> int {