[libcxx-commits] [PATCH] D110498: [libc++][format][4/6] Improve formatted_size.

Mark de Wever via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Sun Sep 26 07:49:20 PDT 2021


Mordante created this revision.
Mordante added reviewers: ldionne, vitaut.
Mordante requested review of this revision.
Herald added a project: libc++.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.

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

Depends on D110497 <https://reviews.llvm.org/D110497>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D110498

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


Index: libcxx/include/format
===================================================================
--- libcxx/include/format
+++ libcxx/include/format
@@ -608,15 +608,25 @@
 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();
+  using _Buffer = __format::__formatted_size_buffer<char>;
+  _Buffer __buffer;
+  _VSTD::__vformat_to(
+      __format::__output_iterator<char>{&__format::__put<_Buffer, char>,
+                                        &__buffer},
+      __fmt, basic_format_args{_VSTD::make_format_args(__args...)});
+  return __buffer.formatted_size();
 }
 
 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();
+  using _Buffer = __format::__formatted_size_buffer<wchar_t>;
+  _Buffer __buffer;
+  _VSTD::__vformat_to(
+      __format::__output_iterator<wchar_t>{&__format::__put<_Buffer, wchar_t>,
+                                           &__buffer},
+      __fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
+  return __buffer.formatted_size();
 }
 
 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
@@ -743,19 +753,27 @@
 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();
+  using _Buffer = __format::__formatted_size_buffer<char>;
+  _Buffer __buffer;
+  _VSTD::__vformat_to(
+      __format::__output_iterator<char>{&__format::__put<_Buffer, char>,
+                                        &__buffer},
+      _VSTD::move(__loc), __fmt,
+      basic_format_args{_VSTD::make_format_args(__args...)});
+  return __buffer.formatted_size();
 }
 
 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();
+  using _Buffer = __format::__formatted_size_buffer<wchar_t>;
+  _Buffer __buffer;
+  _VSTD::__vformat_to(
+      __format::__output_iterator<wchar_t>{&__format::__put<_Buffer, wchar_t>,
+                                           &__buffer},
+      _VSTD::move(__loc), __fmt,
+      basic_format_args{_VSTD::make_wformat_args(__args...)});
+  return __buffer.formatted_size();
 }
 
 #endif
Index: libcxx/include/__format/buffer.h
===================================================================
--- libcxx/include/__format/buffer.h
+++ libcxx/include/__format/buffer.h
@@ -190,6 +190,23 @@
                              __container_buffer<_Iterator>>;
 };
 
+/// 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 void put(_CharT) { ++__size_; }
+
+  _LIBCPP_HIDE_FROM_ABI size_t formatted_size() const noexcept {
+    return __size_;
+  }
+
+private:
+  size_t __size_{0};
+};
+
 } // namespace __format
 
 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D110498.375105.patch
Type: text/x-patch
Size: 3762 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20210926/9ecf634c/attachment.bin>


More information about the libcxx-commits mailing list