diff --git a/include/fmt/base.h b/include/fmt/base.h index 9bbf88fdfd5aa..c1a13f8a4424f 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -2961,8 +2961,8 @@ template struct format_to_result { /** Iterator pointing to just after the last successful write in the range. */ OutputIt out; - /** Sentinel indicating the end of the output range. */ - Sentinel out_last; + /** Specifies if the output was truncated. */ + bool truncated; FMT_CONSTEXPR operator OutputIt&() & noexcept { return out; } FMT_CONSTEXPR operator const OutputIt&() const& noexcept { return out; } @@ -2974,13 +2974,15 @@ struct format_to_result { template auto vformat_to(char (&out)[N], string_view fmt, format_args args) -> format_to_result { - return {vformat_to_n(out, N, fmt, args).out, out + N}; + auto result = vformat_to_n(out, N, fmt, args); + return {result.out, result.size > N}; } template FMT_INLINE auto format_to(char (&out)[N], format_string fmt, T&&... args) -> format_to_result { - return vformat_to(out, fmt, fmt::make_format_args(args...)); + auto result = format_to_n(out, N, fmt, args...); + return {result.out, result.size > N}; } /** Returns the number of chars in the output of ``format(fmt, args...)``. */ diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index af3609c0c6d13..f2b0f0e944dce 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -388,7 +388,6 @@ struct range_formatter< detail::string_literal{}; basic_string_view closing_bracket_ = detail::string_literal{}; - bool is_string_format = false; bool is_debug = false; public: @@ -413,9 +412,7 @@ struct range_formatter< auto it = ctx.begin(); auto end = ctx.end(); detail::maybe_set_debug_format(underlying_, true); - if (it == end) { - return underlying_.parse(ctx); - } + if (it == end) return underlying_.parse(ctx); switch (detail::to_ascii(*it)) { case 'n': @@ -426,21 +423,17 @@ struct range_formatter< is_debug = true; set_brackets({}, {}); ++it; - if (it == end || *it != 's') { - report_error("invalid format specifier"); - } + if (it == end || *it != 's') report_error("invalid format specifier"); FMT_FALLTHROUGH; case 's': - if (!std::is_same::value) { + if (!std::is_same::value) report_error("invalid format specifier"); - } if (!is_debug) { set_brackets(detail::string_literal{}, detail::string_literal{}); set_separator({}); detail::maybe_set_debug_format(underlying_, false); } - is_string_format = true; ++it; return it; } @@ -455,21 +448,19 @@ struct range_formatter< return underlying_.parse(ctx); } - template ::value)> - auto write_debug_string(Output& out, Iter& it, IterEnd& end) const -> Output { + auto write_debug_string(Output& out, It it, Sentinel end) const -> Output { auto buf = basic_memory_buffer(); - for (; it != end; ++it) { - buf.push_back(*it); - } - format_specs spec_str; - spec_str.type = presentation_type::debug; + for (; it != end; ++it) buf.push_back(*it); + auto specs = format_specs(); + specs.type = presentation_type::debug; return detail::write( - out, basic_string_view(buf.data(), buf.size()), spec_str); + out, basic_string_view(buf.data(), buf.size()), specs); } - template ::value)> - auto write_debug_string(Output& out, Iter&, IterEnd&) const -> Output { + auto write_debug_string(Output& out, It, Sentinel) const -> Output { return out; } @@ -479,17 +470,14 @@ struct range_formatter< auto out = ctx.out(); auto it = detail::range_begin(range); auto end = detail::range_end(range); - if (is_debug) { - return write_debug_string(out, it, end); - } + if (is_debug) return write_debug_string(out, it, end); out = detail::copy(opening_bracket_, out); int i = 0; for (; it != end; ++it) { if (i > 0) out = detail::copy(separator_, out); ctx.advance_to(out); - auto&& item = *it; - out = underlying_.format(mapper.map(item), ctx); + out = underlying_.format(mapper.map(*it), ctx); ++i; } out = detail::copy(closing_bracket_, out); diff --git a/test/base-test.cc b/test/base-test.cc index 1a9776c80574d..b8ec60d8b7339 100644 --- a/test/base-test.cc +++ b/test/base-test.cc @@ -697,13 +697,13 @@ TEST(core_test, format_to_c_array) { char buffer[4]; auto result = fmt::format_to(buffer, "{}", 12345); EXPECT_EQ(4, std::distance(&buffer[0], result.out)); - EXPECT_EQ(0, std::distance(result.out, result.out_last)); + EXPECT_TRUE(result.truncated); EXPECT_EQ(buffer + 4, result.out); EXPECT_EQ("1234", fmt::string_view(buffer, 4)); result = fmt::format_to(buffer, "{:s}", "foobar"); EXPECT_EQ(4, std::distance(&buffer[0], result.out)); - EXPECT_EQ(0, std::distance(result.out, result.out_last)); + EXPECT_TRUE(result.truncated); EXPECT_EQ(buffer + 4, result.out); EXPECT_EQ("foob", fmt::string_view(buffer, 4)); @@ -713,24 +713,24 @@ TEST(core_test, format_to_c_array) { buffer[3] = 'x'; result = fmt::format_to(buffer, "{}", 'A'); EXPECT_EQ(1, std::distance(&buffer[0], result.out)); - EXPECT_EQ(3, std::distance(result.out, result.out_last)); + EXPECT_FALSE(result.truncated); EXPECT_EQ(buffer + 1, result.out); EXPECT_EQ("Axxx", fmt::string_view(buffer, 4)); result = fmt::format_to(buffer, "{}{} ", 'B', 'C'); EXPECT_EQ(3, std::distance(&buffer[0], result.out)); - EXPECT_EQ(1, std::distance(result.out, result.out_last)); + EXPECT_FALSE(result.truncated); EXPECT_EQ(buffer + 3, result.out); EXPECT_EQ("BC x", fmt::string_view(buffer, 4)); result = fmt::format_to(buffer, "{}", "ABCDE"); EXPECT_EQ(4, std::distance(&buffer[0], result.out)); - EXPECT_EQ(0, std::distance(result.out, result.out_last)); + EXPECT_TRUE(result.truncated); EXPECT_EQ("ABCD", fmt::string_view(buffer, 4)); result = fmt::format_to(buffer, "{}", std::string(1000, '*')); EXPECT_EQ(4, std::distance(&buffer[0], result.out)); - EXPECT_EQ(0, std::distance(result.out, result.out_last)); + EXPECT_TRUE(result.truncated); EXPECT_EQ("****", fmt::string_view(buffer, 4)); }