From acc60e68b86b6aab49f39c32a6b9fd371311feb9 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 14 Jan 2024 11:45:04 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89=20Array=20overload=20safety=20for?= =?UTF-8?q?=20base.h=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/fmt/base.h | 59 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index fc0ea7b9505c..1b8f38f01fff 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -259,6 +259,8 @@ # define FMT_UNICODE !FMT_MSC_VERSION #endif +#define FMT_FWD(...) static_cast(__VA_ARGS__) + // Enable minimal optimizations for more compact code in debug mode. FMT_GCC_PRAGMA("GCC push_options") #if !defined(__OPTIMIZE__) && !defined(__CUDACC__) @@ -2809,15 +2811,43 @@ using format_string = basic_format_string...>; inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; } #endif +template +using format_string = basic_format_string...>; /** Formats a string and writes the output to ``out``. */ template ::value)> -auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt { + FMT_ENABLE_IF(detail::is_output_iterator, + char>::value)> +auto vformat_to(OutputIt&& out, string_view fmt, format_args args) + -> remove_cvref_t { auto&& buf = detail::get_buffer(out); detail::vformat_to(buf, fmt, args, {}); return detail::get_iterator(buf, out); } +template +struct format_to_result { + /** Iterator past the end of the last write. */ + OutputIt out; + /** Iterator to the end of the output range. */ + OutputSen out_last; + + FMT_CONSTEXPR operator OutputIt&() & noexcept { return out; } + FMT_CONSTEXPR operator const OutputIt&() const& noexcept { return out; } + FMT_CONSTEXPR operator OutputIt&&() && noexcept { + return static_cast(out); + } +}; + +/** Formats a string and writes the output to ``out``. */ +template +auto vformat_to(char (&out)[Size], string_view fmt, format_args args) + -> format_to_result { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer(out, Size); + detail::vformat_to(buf, fmt, args, {}); + return {out + buf.count(), out + Size}; +} + /** \rst Formats ``args`` according to specifications in ``fmt``, writes the result to @@ -2831,9 +2861,28 @@ auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt { \endrst */ template ::value)> -FMT_INLINE auto format_to(OutputIt out, format_string fmt, T&&... args) - -> OutputIt { + FMT_ENABLE_IF(detail::is_output_iterator, + char>::value)> +FMT_INLINE auto format_to(OutputIt&& out, format_string fmt, T&&... args) + -> remove_cvref_t { + return vformat_to(FMT_FWD(out), fmt, fmt::make_format_args(args...)); +} + +/** + \rst + Formats ``args`` according to specifications in ``fmt``, writes the result to + the output iterator ``out`` and returns the iterator past the end of the output + range. `format_to` does not append a terminating null character. + + **Example**:: + + auto out = std::vector(); + fmt::format_to(std::back_inserter(out), "{}", 42); + \endrst + */ +template +FMT_INLINE auto format_to(char (&out)[Size], format_string fmt, + T&&... args) -> format_to_result { return vformat_to(out, fmt, fmt::make_format_args(args...)); }