diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 635a0c2a1b4f..c466362ae618 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -656,21 +656,21 @@ template struct grisu_shortest_handler { uint64_t d = integral ? diff : diff * data::POWERS_OF_10_64[-exp]; while (remainder < d && error - remainder >= divisor && (remainder + divisor < d || - d - remainder > remainder + divisor - d)) { + d - remainder >= remainder + divisor - d)) { --buf[size - 1]; remainder += divisor; } return digits::done; } uint64_t unit = integral ? 1 : data::POWERS_OF_10_64[-exp]; - uint64_t up = diff + unit; // wp_Wup + uint64_t up = (diff - 1) * unit; // wp_Wup while (remainder < up && error - remainder >= divisor && (remainder + divisor < up || - up - remainder > remainder + divisor - up)) { + up - remainder >= remainder + divisor - up)) { --buf[size - 1]; remainder += divisor; } - uint64_t down = diff - unit; // wp_Wdown + uint64_t down = (diff + 1) * unit; // wp_Wdown if (remainder < down && error - remainder >= divisor && (remainder + divisor < down || down - remainder > remainder + divisor - down)) { @@ -684,7 +684,7 @@ template struct grisu_shortest_handler { template FMT_API bool grisu_format(Double value, buffer& buf, int precision, - unsigned options, int& exp) { + unsigned options, int& exp) { FMT_ASSERT(value >= 0, "value is negative"); bool fixed = (options & grisu_options::fixed) != 0; if (value <= 0) { // <= instead of == to silence a warning. diff --git a/include/fmt/format.h b/include/fmt/format.h index 5df57ac6f064..1a566b8b7e05 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -2218,7 +2218,7 @@ class format_string_checker { FMT_CONSTEXPR void on_replacement_field(const Char*) {} FMT_CONSTEXPR const Char* on_format_specs(const Char* begin, const Char*) { - context_.advance_to(begin); + advance_to(context_, begin); return arg_id_ < NUM_ARGS ? parse_funcs_[arg_id_](context_) : begin; } @@ -3226,6 +3226,12 @@ basic_format_context::arg(basic_string_view name) { return arg; } +template +FMT_CONSTEXPR void advance_to(basic_parse_context& ctx, + const Char* p) { + ctx.advance_to(ctx.begin() + (p - &*ctx.begin())); +} + template struct format_handler : internal::error_handler { typedef typename ArgFormatter::range range; @@ -3253,7 +3259,7 @@ struct format_handler : internal::error_handler { void on_arg_id(basic_string_view id) { arg = context.arg(id); } void on_replacement_field(const Char* p) { - parse_context.advance_to(p); + advance_to(parse_context, p); internal::custom_formatter f(parse_context, context); if (!visit_format_arg(f, arg)) context.advance_to( @@ -3261,7 +3267,7 @@ struct format_handler : internal::error_handler { } const Char* on_format_specs(const Char* begin, const Char* end) { - parse_context.advance_to(begin); + advance_to(parse_context, begin); internal::custom_formatter f(parse_context, context); if (visit_format_arg(f, arg)) return parse_context.begin(); basic_format_specs specs; @@ -3272,7 +3278,7 @@ struct format_handler : internal::error_handler { arg.type()); begin = parse_format_specs(begin, end, handler); if (begin == end || *begin != '}') on_error("missing '}' in format string"); - parse_context.advance_to(begin); + advance_to(parse_context, begin); context.advance_to( visit_format_arg(ArgFormatter(context, &parse_context, &specs), arg)); return begin; diff --git a/include/fmt/prepare.h b/include/fmt/prepare.h index bfa7d8165529..6435fb77863d 100644 --- a/include/fmt/prepare.h +++ b/include/fmt/prepare.h @@ -310,7 +310,7 @@ class prepared_format { const format_part_t& part) const { const auto view = to_string_view(format_); const auto specification_begin = view.data() + part.end_of_argument_id; - parse_ctx.advance_to(specification_begin); + advance_to(parse_ctx, specification_begin); } template diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index 646d63f926b3..06fcaad53025 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -82,7 +82,7 @@ template class is_like_std_string { public: static FMT_CONSTEXPR_DECL const bool value = - !std::is_void(FMT_NULL))>::value; + is_string::value || !std::is_void(FMT_NULL))>::value; }; template