diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h --- a/libcxx/include/__format/buffer.h +++ b/libcxx/include/__format/buffer.h @@ -257,6 +257,34 @@ __output_buffer<_CharT> __output_; typename __writer_selector<_OutIt, _CharT>::type __writer_; }; + +/// A buffer that counts the number of insertions. +/// +/// Since \ref formatted_size only needs to know the size the output itself is +/// discarded. +template <__formatter::__char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer { +public: + _LIBCPP_HIDE_FROM_ABI auto make_output_iterator() { + return __output_.make_output_iterator(); + } + + _LIBCPP_HIDE_FROM_ABI void flush(_CharT*, size_t __size) { + __size_ += __size; + } + + _LIBCPP_HIDE_FROM_ABI size_t result() && { + __output_.flush(); + return __size_; + } + +private: + __internal_storage<_CharT> __storage_; + __output_buffer<_CharT> __output_{__storage_.begin(), __storage_.capacity(), + this}; + size_t __size_{0}; +}; + } // namespace __format #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) diff --git a/libcxx/include/format b/libcxx/include/format --- a/libcxx/include/format +++ b/libcxx/include/format @@ -576,6 +576,28 @@ } #endif +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +formatted_size(string_view __fmt, const _Args&... __args) { + __format::__formatted_size_buffer __buffer; + _VSTD::__vformat_to(__buffer.make_output_iterator(), __fmt, + basic_format_args{_VSTD::make_format_args(__args...)}); + + return _VSTD::move(__buffer).result(); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +formatted_size(wstring_view __fmt, const _Args&... __args) { + __format::__formatted_size_buffer __buffer; + _VSTD::__vformat_to(__buffer.make_output_iterator(), __fmt, + basic_format_args{_VSTD::make_wformat_args(__args...)}); + + return _VSTD::move(__buffer).result(); +} +#endif + template struct _LIBCPP_TEMPLATE_VIS format_to_n_result { _OutIt out; @@ -610,22 +632,6 @@ } #endif -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(string_view __fmt, const _Args&... __args) { - // TODO FMT Improve PoC: using std::string is inefficient. - return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size(); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(wstring_view __fmt, const _Args&... __args) { - // TODO FMT Improve PoC: using std::string is inefficient. - return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size(); -} -#endif - #ifndef _LIBCPP_HAS_NO_LOCALIZATION template @@ -714,6 +720,27 @@ } #endif +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +formatted_size(locale __loc, string_view __fmt, const _Args&... __args) { + __format::__formatted_size_buffer __buffer; + _VSTD::__vformat_to(__buffer.make_output_iterator(), _VSTD::move(__loc),__fmt, + basic_format_args{_VSTD::make_format_args(__args...)}); + return _VSTD::move(__buffer).result(); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) { + __format::__formatted_size_buffer __buffer; + _VSTD::__vformat_to(__buffer.make_output_iterator(), _VSTD::move(__loc),__fmt, + basic_format_args{_VSTD::make_wformat_args(__args...)}); + + return _VSTD::move(__buffer).result(); +} +#endif + template _OutIt, class... _Args> _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, @@ -744,26 +771,6 @@ } #endif -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, string_view __fmt, const _Args&... __args) { - // TODO FMT Improve PoC: using std::string is inefficient. - return _VSTD::vformat(_VSTD::move(__loc), __fmt, - _VSTD::make_format_args(__args...)) - .size(); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) { - // TODO FMT Improve PoC: using std::string is inefficient. - return _VSTD::vformat(_VSTD::move(__loc), __fmt, - _VSTD::make_wformat_args(__args...)) - .size(); -} -#endif - #endif // _LIBCPP_HAS_NO_LOCALIZATION #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)