[libcxx-commits] [libcxx] fb9a692 - [libc++][format][4/6] Improve formatted_size.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sat Apr 9 00:36:33 PDT 2022


Author: Mark de Wever
Date: 2022-04-09T09:36:29+02:00
New Revision: fb9a692be5dd20db62c705bb371977dc30fb407f

URL: https://github.com/llvm/llvm-project/commit/fb9a692be5dd20db62c705bb371977dc30fb407f
DIFF: https://github.com/llvm/llvm-project/commit/fb9a692be5dd20db62c705bb371977dc30fb407f.diff

LOG: [libc++][format][4/6] Improve formatted_size.

Use a specialized "buffer" to count the number of insertions instead of
using a `string` as storage type.

Depends on D110497.

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D110498

Added: 
    

Modified: 
    libcxx/include/__format/buffer.h
    libcxx/include/format

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h
index 584345c98fdbd..e5c3b9fda28fe 100644
--- a/libcxx/include/__format/buffer.h
+++ b/libcxx/include/__format/buffer.h
@@ -244,6 +244,29 @@ requires(output_iterator<_OutIt, const _CharT&>) class _LIBCPP_TEMPLATE_VIS
   __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(const _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 //_LIBCPP_STD_VER > 17

diff  --git a/libcxx/include/format b/libcxx/include/format
index 4ae98ce86c7fe..951627852fdb3 100644
--- a/libcxx/include/format
+++ b/libcxx/include/format
@@ -392,19 +392,25 @@ format_to_n(_OutIt __out_it, iter_
diff erence_t<_OutIt> __n, wstring_view __fmt,
 }
 #endif
 
+template <class _CharT>
+_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
+  __format::__formatted_size_buffer<_CharT> __buffer;
+  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
+                                _VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
+  return _VSTD::move(__buffer).result();
+}
+
 template <class... _Args>
-_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();
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(string_view __fmt,
+                                                                                              const _Args&... __args) {
+  return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_format_args(__args...)});
 }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <class... _Args>
-_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();
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(wstring_view __fmt,
+                                                                                              const _Args&... __args) {
+  return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
 }
 #endif
 
@@ -526,23 +532,28 @@ format_to_n(_OutIt __out_it, iter_
diff erence_t<_OutIt> __n, locale __loc,
 }
 #endif
 
+template <class _CharT>
+_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
+  __format::__formatted_size_buffer<_CharT> __buffer;
+  _VSTD::__format::__vformat_to(
+      basic_format_parse_context{__fmt, __args.__size()},
+      _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
+  return _VSTD::move(__buffer).result();
+}
+
 template <class... _Args>
-_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();
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(locale __loc,
+                                                                                              string_view __fmt,
+                                                                                              const _Args&... __args) {
+  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_format_args(__args...)});
 }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <class... _Args>
-_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();
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(locale __loc,
+                                                                                              wstring_view __fmt,
+                                                                                              const _Args&... __args) {
+  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
 }
 #endif
 


        


More information about the libcxx-commits mailing list