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