1*81ad6265SDimitry Andric // -*- C++ -*- 2*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 3*81ad6265SDimitry Andric // 4*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*81ad6265SDimitry Andric // 8*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 9*81ad6265SDimitry Andric 10*81ad6265SDimitry Andric #ifndef _LIBCPP___FORMAT_BUFFER_H 11*81ad6265SDimitry Andric #define _LIBCPP___FORMAT_BUFFER_H 12*81ad6265SDimitry Andric 13*81ad6265SDimitry Andric #include <__algorithm/copy_n.h> 14*81ad6265SDimitry Andric #include <__algorithm/max.h> 15*81ad6265SDimitry Andric #include <__algorithm/min.h> 16*81ad6265SDimitry Andric #include <__algorithm/unwrap_iter.h> 17*81ad6265SDimitry Andric #include <__config> 18*81ad6265SDimitry Andric #include <__format/enable_insertable.h> 19*81ad6265SDimitry Andric #include <__format/format_to_n_result.h> 20*81ad6265SDimitry Andric #include <__format/formatter.h> // for __char_type TODO FMT Move the concept? 21*81ad6265SDimitry Andric #include <__iterator/back_insert_iterator.h> 22*81ad6265SDimitry Andric #include <__iterator/concepts.h> 23*81ad6265SDimitry Andric #include <__iterator/incrementable_traits.h> 24*81ad6265SDimitry Andric #include <__iterator/iterator_traits.h> 25*81ad6265SDimitry Andric #include <__iterator/wrap_iter.h> 26*81ad6265SDimitry Andric #include <__utility/move.h> 27*81ad6265SDimitry Andric #include <concepts> 28*81ad6265SDimitry Andric #include <cstddef> 29*81ad6265SDimitry Andric #include <type_traits> 30*81ad6265SDimitry Andric 31*81ad6265SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 32*81ad6265SDimitry Andric # pragma GCC system_header 33*81ad6265SDimitry Andric #endif 34*81ad6265SDimitry Andric 35*81ad6265SDimitry Andric _LIBCPP_PUSH_MACROS 36*81ad6265SDimitry Andric #include <__undef_macros> 37*81ad6265SDimitry Andric 38*81ad6265SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 39*81ad6265SDimitry Andric 40*81ad6265SDimitry Andric #if _LIBCPP_STD_VER > 17 41*81ad6265SDimitry Andric 42*81ad6265SDimitry Andric namespace __format { 43*81ad6265SDimitry Andric 44*81ad6265SDimitry Andric /// A "buffer" that handles writing to the proper iterator. 45*81ad6265SDimitry Andric /// 46*81ad6265SDimitry Andric /// This helper is used together with the @ref back_insert_iterator to offer 47*81ad6265SDimitry Andric /// type-erasure for the formatting functions. This reduces the number to 48*81ad6265SDimitry Andric /// template instantiations. 49*81ad6265SDimitry Andric template <__formatter::__char_type _CharT> 50*81ad6265SDimitry Andric class _LIBCPP_TEMPLATE_VIS __output_buffer { 51*81ad6265SDimitry Andric public: 52*81ad6265SDimitry Andric using value_type = _CharT; 53*81ad6265SDimitry Andric 54*81ad6265SDimitry Andric template <class _Tp> 55*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, 56*81ad6265SDimitry Andric size_t __capacity, _Tp* __obj) 57*81ad6265SDimitry Andric : __ptr_(__ptr), __capacity_(__capacity), 58*81ad6265SDimitry Andric __flush_([](_CharT* __p, size_t __size, void* __o) { 59*81ad6265SDimitry Andric static_cast<_Tp*>(__o)->flush(__p, __size); 60*81ad6265SDimitry Andric }), 61*81ad6265SDimitry Andric __obj_(__obj) {} 62*81ad6265SDimitry Andric 63*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void reset(_CharT* __ptr, size_t __capacity) { 64*81ad6265SDimitry Andric __ptr_ = __ptr; 65*81ad6265SDimitry Andric __capacity_ = __capacity; 66*81ad6265SDimitry Andric } 67*81ad6265SDimitry Andric 68*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI auto make_output_iterator() { 69*81ad6265SDimitry Andric return back_insert_iterator{*this}; 70*81ad6265SDimitry Andric } 71*81ad6265SDimitry Andric 72*81ad6265SDimitry Andric // TODO FMT It would be nice to have an overload taking a 73*81ad6265SDimitry Andric // basic_string_view<_CharT> and append it directly. 74*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { 75*81ad6265SDimitry Andric __ptr_[__size_++] = __c; 76*81ad6265SDimitry Andric 77*81ad6265SDimitry Andric // Profiling showed flushing after adding is more efficient than flushing 78*81ad6265SDimitry Andric // when entering the function. 79*81ad6265SDimitry Andric if (__size_ == __capacity_) 80*81ad6265SDimitry Andric flush(); 81*81ad6265SDimitry Andric } 82*81ad6265SDimitry Andric 83*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void flush() { 84*81ad6265SDimitry Andric __flush_(__ptr_, __size_, __obj_); 85*81ad6265SDimitry Andric __size_ = 0; 86*81ad6265SDimitry Andric } 87*81ad6265SDimitry Andric 88*81ad6265SDimitry Andric private: 89*81ad6265SDimitry Andric _CharT* __ptr_; 90*81ad6265SDimitry Andric size_t __capacity_; 91*81ad6265SDimitry Andric size_t __size_{0}; 92*81ad6265SDimitry Andric void (*__flush_)(_CharT*, size_t, void*); 93*81ad6265SDimitry Andric void* __obj_; 94*81ad6265SDimitry Andric }; 95*81ad6265SDimitry Andric 96*81ad6265SDimitry Andric /// A storage using an internal buffer. 97*81ad6265SDimitry Andric /// 98*81ad6265SDimitry Andric /// This storage is used when writing a single element to the output iterator 99*81ad6265SDimitry Andric /// is expensive. 100*81ad6265SDimitry Andric template <__formatter::__char_type _CharT> 101*81ad6265SDimitry Andric class _LIBCPP_TEMPLATE_VIS __internal_storage { 102*81ad6265SDimitry Andric public: 103*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _CharT* begin() { return __buffer_; } 104*81ad6265SDimitry Andric 105*81ad6265SDimitry Andric static constexpr size_t __buffer_size = 256 / sizeof(_CharT); 106*81ad6265SDimitry Andric 107*81ad6265SDimitry Andric private: 108*81ad6265SDimitry Andric _CharT __buffer_[__buffer_size]; 109*81ad6265SDimitry Andric }; 110*81ad6265SDimitry Andric 111*81ad6265SDimitry Andric /// A storage writing directly to the storage. 112*81ad6265SDimitry Andric /// 113*81ad6265SDimitry Andric /// This requires the storage to be a contiguous buffer of \a _CharT. 114*81ad6265SDimitry Andric /// Since the output is directly written to the underlying storage this class 115*81ad6265SDimitry Andric /// is just an empty class. 116*81ad6265SDimitry Andric template <__formatter::__char_type _CharT> 117*81ad6265SDimitry Andric class _LIBCPP_TEMPLATE_VIS __direct_storage {}; 118*81ad6265SDimitry Andric 119*81ad6265SDimitry Andric template <class _OutIt, class _CharT> 120*81ad6265SDimitry Andric concept __enable_direct_output = __formatter::__char_type<_CharT> && 121*81ad6265SDimitry Andric (same_as<_OutIt, _CharT*> 122*81ad6265SDimitry Andric #ifndef _LIBCPP_ENABLE_DEBUG_MODE 123*81ad6265SDimitry Andric || same_as<_OutIt, __wrap_iter<_CharT*>> 124*81ad6265SDimitry Andric #endif 125*81ad6265SDimitry Andric ); 126*81ad6265SDimitry Andric 127*81ad6265SDimitry Andric /// Write policy for directly writing to the underlying output. 128*81ad6265SDimitry Andric template <class _OutIt, __formatter::__char_type _CharT> 129*81ad6265SDimitry Andric class _LIBCPP_TEMPLATE_VIS __writer_direct { 130*81ad6265SDimitry Andric public: 131*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __writer_direct(_OutIt __out_it) 132*81ad6265SDimitry Andric : __out_it_(__out_it) {} 133*81ad6265SDimitry Andric 134*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI auto out() { return __out_it_; } 135*81ad6265SDimitry Andric 136*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void flush(_CharT*, size_t __size) { 137*81ad6265SDimitry Andric // _OutIt can be a __wrap_iter<CharT*>. Therefore the original iterator 138*81ad6265SDimitry Andric // is adjusted. 139*81ad6265SDimitry Andric __out_it_ += __size; 140*81ad6265SDimitry Andric } 141*81ad6265SDimitry Andric 142*81ad6265SDimitry Andric private: 143*81ad6265SDimitry Andric _OutIt __out_it_; 144*81ad6265SDimitry Andric }; 145*81ad6265SDimitry Andric 146*81ad6265SDimitry Andric /// Write policy for copying the buffer to the output. 147*81ad6265SDimitry Andric template <class _OutIt, __formatter::__char_type _CharT> 148*81ad6265SDimitry Andric class _LIBCPP_TEMPLATE_VIS __writer_iterator { 149*81ad6265SDimitry Andric public: 150*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __writer_iterator(_OutIt __out_it) 151*81ad6265SDimitry Andric : __out_it_{_VSTD::move(__out_it)} {} 152*81ad6265SDimitry Andric 153*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI auto out() { return __out_it_; } 154*81ad6265SDimitry Andric 155*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void flush(_CharT* __ptr, size_t __size) { 156*81ad6265SDimitry Andric __out_it_ = _VSTD::copy_n(__ptr, __size, _VSTD::move(__out_it_)); 157*81ad6265SDimitry Andric } 158*81ad6265SDimitry Andric 159*81ad6265SDimitry Andric private: 160*81ad6265SDimitry Andric _OutIt __out_it_; 161*81ad6265SDimitry Andric }; 162*81ad6265SDimitry Andric 163*81ad6265SDimitry Andric /// Concept to see whether a \a _Container is insertable. 164*81ad6265SDimitry Andric /// 165*81ad6265SDimitry Andric /// The concept is used to validate whether multiple calls to a 166*81ad6265SDimitry Andric /// \ref back_insert_iterator can be replace by a call to \c _Container::insert. 167*81ad6265SDimitry Andric /// 168*81ad6265SDimitry Andric /// \note a \a _Container needs to opt-in to the concept by specializing 169*81ad6265SDimitry Andric /// \ref __enable_insertable. 170*81ad6265SDimitry Andric template <class _Container> 171*81ad6265SDimitry Andric concept __insertable = 172*81ad6265SDimitry Andric __enable_insertable<_Container> && __formatter::__char_type<typename _Container::value_type> && 173*81ad6265SDimitry Andric requires(_Container& __t, add_pointer_t<typename _Container::value_type> __first, 174*81ad6265SDimitry Andric add_pointer_t<typename _Container::value_type> __last) { __t.insert(__t.end(), __first, __last); }; 175*81ad6265SDimitry Andric 176*81ad6265SDimitry Andric /// Extract the container type of a \ref back_insert_iterator. 177*81ad6265SDimitry Andric template <class _It> 178*81ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container { 179*81ad6265SDimitry Andric using type = void; 180*81ad6265SDimitry Andric }; 181*81ad6265SDimitry Andric 182*81ad6265SDimitry Andric template <__insertable _Container> 183*81ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container<back_insert_iterator<_Container>> { 184*81ad6265SDimitry Andric using type = _Container; 185*81ad6265SDimitry Andric }; 186*81ad6265SDimitry Andric 187*81ad6265SDimitry Andric /// Write policy for inserting the buffer in a container. 188*81ad6265SDimitry Andric template <class _Container> 189*81ad6265SDimitry Andric class _LIBCPP_TEMPLATE_VIS __writer_container { 190*81ad6265SDimitry Andric public: 191*81ad6265SDimitry Andric using _CharT = typename _Container::value_type; 192*81ad6265SDimitry Andric 193*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __writer_container(back_insert_iterator<_Container> __out_it) 194*81ad6265SDimitry Andric : __container_{__out_it.__get_container()} {} 195*81ad6265SDimitry Andric 196*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI auto out() { return back_inserter(*__container_); } 197*81ad6265SDimitry Andric 198*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void flush(_CharT* __ptr, size_t __size) { 199*81ad6265SDimitry Andric __container_->insert(__container_->end(), __ptr, __ptr + __size); 200*81ad6265SDimitry Andric } 201*81ad6265SDimitry Andric 202*81ad6265SDimitry Andric private: 203*81ad6265SDimitry Andric _Container* __container_; 204*81ad6265SDimitry Andric }; 205*81ad6265SDimitry Andric 206*81ad6265SDimitry Andric /// Selects the type of the writer used for the output iterator. 207*81ad6265SDimitry Andric template <class _OutIt, class _CharT> 208*81ad6265SDimitry Andric class _LIBCPP_TEMPLATE_VIS __writer_selector { 209*81ad6265SDimitry Andric using _Container = typename __back_insert_iterator_container<_OutIt>::type; 210*81ad6265SDimitry Andric 211*81ad6265SDimitry Andric public: 212*81ad6265SDimitry Andric using type = conditional_t<!same_as<_Container, void>, __writer_container<_Container>, 213*81ad6265SDimitry Andric conditional_t<__enable_direct_output<_OutIt, _CharT>, __writer_direct<_OutIt, _CharT>, 214*81ad6265SDimitry Andric __writer_iterator<_OutIt, _CharT>>>; 215*81ad6265SDimitry Andric }; 216*81ad6265SDimitry Andric 217*81ad6265SDimitry Andric /// The generic formatting buffer. 218*81ad6265SDimitry Andric template <class _OutIt, __formatter::__char_type _CharT> 219*81ad6265SDimitry Andric requires(output_iterator<_OutIt, const _CharT&>) class _LIBCPP_TEMPLATE_VIS 220*81ad6265SDimitry Andric __format_buffer { 221*81ad6265SDimitry Andric using _Storage = 222*81ad6265SDimitry Andric conditional_t<__enable_direct_output<_OutIt, _CharT>, 223*81ad6265SDimitry Andric __direct_storage<_CharT>, __internal_storage<_CharT>>; 224*81ad6265SDimitry Andric 225*81ad6265SDimitry Andric public: 226*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it) 227*81ad6265SDimitry Andric requires(same_as<_Storage, __internal_storage<_CharT>>) 228*81ad6265SDimitry Andric : __output_(__storage_.begin(), __storage_.__buffer_size, this), __writer_(_VSTD::move(__out_it)) {} 229*81ad6265SDimitry Andric 230*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it) requires( 231*81ad6265SDimitry Andric same_as<_Storage, __direct_storage<_CharT>>) 232*81ad6265SDimitry Andric : __output_(_VSTD::__unwrap_iter(__out_it), size_t(-1), this), 233*81ad6265SDimitry Andric __writer_(_VSTD::move(__out_it)) {} 234*81ad6265SDimitry Andric 235*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI auto make_output_iterator() { 236*81ad6265SDimitry Andric return __output_.make_output_iterator(); 237*81ad6265SDimitry Andric } 238*81ad6265SDimitry Andric 239*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void flush(_CharT* __ptr, size_t __size) { 240*81ad6265SDimitry Andric __writer_.flush(__ptr, __size); 241*81ad6265SDimitry Andric } 242*81ad6265SDimitry Andric 243*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI _OutIt out() && { 244*81ad6265SDimitry Andric __output_.flush(); 245*81ad6265SDimitry Andric return _VSTD::move(__writer_).out(); 246*81ad6265SDimitry Andric } 247*81ad6265SDimitry Andric 248*81ad6265SDimitry Andric private: 249*81ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Storage __storage_; 250*81ad6265SDimitry Andric __output_buffer<_CharT> __output_; 251*81ad6265SDimitry Andric typename __writer_selector<_OutIt, _CharT>::type __writer_; 252*81ad6265SDimitry Andric }; 253*81ad6265SDimitry Andric 254*81ad6265SDimitry Andric /// A buffer that counts the number of insertions. 255*81ad6265SDimitry Andric /// 256*81ad6265SDimitry Andric /// Since \ref formatted_size only needs to know the size, the output itself is 257*81ad6265SDimitry Andric /// discarded. 258*81ad6265SDimitry Andric template <__formatter::__char_type _CharT> 259*81ad6265SDimitry Andric class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer { 260*81ad6265SDimitry Andric public: 261*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI auto make_output_iterator() { return __output_.make_output_iterator(); } 262*81ad6265SDimitry Andric 263*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void flush(const _CharT*, size_t __size) { __size_ += __size; } 264*81ad6265SDimitry Andric 265*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI size_t result() && { 266*81ad6265SDimitry Andric __output_.flush(); 267*81ad6265SDimitry Andric return __size_; 268*81ad6265SDimitry Andric } 269*81ad6265SDimitry Andric 270*81ad6265SDimitry Andric private: 271*81ad6265SDimitry Andric __internal_storage<_CharT> __storage_; 272*81ad6265SDimitry Andric __output_buffer<_CharT> __output_{__storage_.begin(), __storage_.__buffer_size, this}; 273*81ad6265SDimitry Andric size_t __size_{0}; 274*81ad6265SDimitry Andric }; 275*81ad6265SDimitry Andric 276*81ad6265SDimitry Andric /// The base of a buffer that counts and limits the number of insertions. 277*81ad6265SDimitry Andric template <class _OutIt, __formatter::__char_type _CharT, bool> 278*81ad6265SDimitry Andric requires(output_iterator<_OutIt, const _CharT&>) 279*81ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base { 280*81ad6265SDimitry Andric using _Size = iter_difference_t<_OutIt>; 281*81ad6265SDimitry Andric 282*81ad6265SDimitry Andric public: 283*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __n) 284*81ad6265SDimitry Andric : __writer_(_VSTD::move(__out_it)), __n_(_VSTD::max(_Size(0), __n)) {} 285*81ad6265SDimitry Andric 286*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void flush(_CharT* __ptr, size_t __size) { 287*81ad6265SDimitry Andric if (_Size(__size_) <= __n_) 288*81ad6265SDimitry Andric __writer_.flush(__ptr, _VSTD::min(_Size(__size), __n_ - __size_)); 289*81ad6265SDimitry Andric __size_ += __size; 290*81ad6265SDimitry Andric } 291*81ad6265SDimitry Andric 292*81ad6265SDimitry Andric protected: 293*81ad6265SDimitry Andric __internal_storage<_CharT> __storage_; 294*81ad6265SDimitry Andric __output_buffer<_CharT> __output_{__storage_.begin(), __storage_.__buffer_size, this}; 295*81ad6265SDimitry Andric typename __writer_selector<_OutIt, _CharT>::type __writer_; 296*81ad6265SDimitry Andric 297*81ad6265SDimitry Andric _Size __n_; 298*81ad6265SDimitry Andric _Size __size_{0}; 299*81ad6265SDimitry Andric }; 300*81ad6265SDimitry Andric 301*81ad6265SDimitry Andric /// The base of a buffer that counts and limits the number of insertions. 302*81ad6265SDimitry Andric /// 303*81ad6265SDimitry Andric /// This version is used when \c __enable_direct_output<_OutIt, _CharT> == true. 304*81ad6265SDimitry Andric /// 305*81ad6265SDimitry Andric /// This class limits the size available the the direct writer so it will not 306*81ad6265SDimitry Andric /// exceed the maximum number of code units. 307*81ad6265SDimitry Andric template <class _OutIt, __formatter::__char_type _CharT> 308*81ad6265SDimitry Andric requires(output_iterator<_OutIt, const _CharT&>) 309*81ad6265SDimitry Andric class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base<_OutIt, _CharT, true> { 310*81ad6265SDimitry Andric using _Size = iter_difference_t<_OutIt>; 311*81ad6265SDimitry Andric 312*81ad6265SDimitry Andric public: 313*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __n) 314*81ad6265SDimitry Andric : __output_(_VSTD::__unwrap_iter(__out_it), __n, this), __writer_(_VSTD::move(__out_it)) { 315*81ad6265SDimitry Andric if (__n <= 0) [[unlikely]] 316*81ad6265SDimitry Andric __output_.reset(__storage_.begin(), __storage_.__buffer_size); 317*81ad6265SDimitry Andric } 318*81ad6265SDimitry Andric 319*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI void flush(_CharT* __ptr, size_t __size) { 320*81ad6265SDimitry Andric // A flush to the direct writer happens in two occasions: 321*81ad6265SDimitry Andric // - The format function has written the maximum number of allowed code 322*81ad6265SDimitry Andric // units. At this point it's no longer valid to write to this writer. So 323*81ad6265SDimitry Andric // switch to the internal storage. This internal storage doesn't need to 324*81ad6265SDimitry Andric // be written anywhere so the flush for that storage writes no output. 325*81ad6265SDimitry Andric // - The format_to_n function is finished. In this case there's no need to 326*81ad6265SDimitry Andric // switch the buffer, but for simplicity the buffers are still switched. 327*81ad6265SDimitry Andric // When the __n <= 0 the constructor already switched the buffers. 328*81ad6265SDimitry Andric if (__size_ == 0 && __ptr != __storage_.begin()) { 329*81ad6265SDimitry Andric __writer_.flush(__ptr, __size); 330*81ad6265SDimitry Andric __output_.reset(__storage_.begin(), __storage_.__buffer_size); 331*81ad6265SDimitry Andric } 332*81ad6265SDimitry Andric 333*81ad6265SDimitry Andric __size_ += __size; 334*81ad6265SDimitry Andric } 335*81ad6265SDimitry Andric 336*81ad6265SDimitry Andric protected: 337*81ad6265SDimitry Andric __internal_storage<_CharT> __storage_; 338*81ad6265SDimitry Andric __output_buffer<_CharT> __output_; 339*81ad6265SDimitry Andric __writer_direct<_OutIt, _CharT> __writer_; 340*81ad6265SDimitry Andric 341*81ad6265SDimitry Andric _Size __size_{0}; 342*81ad6265SDimitry Andric }; 343*81ad6265SDimitry Andric 344*81ad6265SDimitry Andric /// The buffer that counts and limits the number of insertions. 345*81ad6265SDimitry Andric template <class _OutIt, __formatter::__char_type _CharT> 346*81ad6265SDimitry Andric requires(output_iterator<_OutIt, const _CharT&>) 347*81ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final 348*81ad6265SDimitry Andric : public __format_to_n_buffer_base< _OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>> { 349*81ad6265SDimitry Andric using _Base = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>; 350*81ad6265SDimitry Andric using _Size = iter_difference_t<_OutIt>; 351*81ad6265SDimitry Andric 352*81ad6265SDimitry Andric public: 353*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __n) : _Base(_VSTD::move(__out_it), __n) {} 354*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI auto make_output_iterator() { return this->__output_.make_output_iterator(); } 355*81ad6265SDimitry Andric 356*81ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> result() && { 357*81ad6265SDimitry Andric this->__output_.flush(); 358*81ad6265SDimitry Andric return {_VSTD::move(this->__writer_).out(), this->__size_}; 359*81ad6265SDimitry Andric } 360*81ad6265SDimitry Andric }; 361*81ad6265SDimitry Andric } // namespace __format 362*81ad6265SDimitry Andric 363*81ad6265SDimitry Andric #endif //_LIBCPP_STD_VER > 17 364*81ad6265SDimitry Andric 365*81ad6265SDimitry Andric _LIBCPP_END_NAMESPACE_STD 366*81ad6265SDimitry Andric 367*81ad6265SDimitry Andric _LIBCPP_POP_MACROS 368*81ad6265SDimitry Andric 369*81ad6265SDimitry Andric #endif // _LIBCPP___FORMAT_BUFFER_H 370