diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 50d9ef48..933668c4 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -15,7 +15,7 @@ namespace detail { template FMT_CONSTEXPR inline counting_iterator copy_str(InputIt begin, InputIt end, - counting_iterator it) { + counting_iterator it) { return it + (end - begin); } @@ -341,7 +341,7 @@ constexpr parse_specs_result parse_specs(basic_string_view str, next_arg_id); auto f = formatter(); auto end = f.parse(ctx); - return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1, + return {f, pos + fmt::detail::to_unsigned(end - str.data()), next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()}; } @@ -397,13 +397,20 @@ constexpr auto parse_replacement_field_then_tail(S format_str) { return parse_tail( field::type, ARG_INDEX>(), format_str); - } else if constexpr (c == ':') { + } else if constexpr (c != ':') { + FMT_THROW(format_error("expected ':'")); + } else { constexpr auto result = parse_specs::type>( str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID); - return parse_tail( - spec_field::type, ARG_INDEX>{ - result.fmt}, - format_str); + if constexpr (result.end >= str.size() || str[result.end] != '}') { + FMT_THROW(format_error("expected '}'")); + return 0; + } else { + return parse_tail( + spec_field::type, ARG_INDEX>{ + result.fmt}, + format_str); + } } } @@ -568,7 +575,8 @@ format_to_n_result format_to_n(OutputIt out, size_t n, template ::value)> -FMT_CONSTEXPR20 size_t formatted_size(const S& format_str, const Args&... args) { +FMT_CONSTEXPR20 size_t formatted_size(const S& format_str, + const Args&... args) { return fmt::format_to(detail::counting_iterator(), format_str, args...) .count(); }