1555214cbSMark de Wever // -*- C++ -*- 2555214cbSMark de Wever //===----------------------------------------------------------------------===// 3555214cbSMark de Wever // 4555214cbSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5555214cbSMark de Wever // See https://llvm.org/LICENSE.txt for license information. 6555214cbSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7555214cbSMark de Wever // 8555214cbSMark de Wever //===----------------------------------------------------------------------===// 9555214cbSMark de Wever 10555214cbSMark de Wever #ifndef _LIBCPP___FORMAT_BUFFER_H 11555214cbSMark de Wever #define _LIBCPP___FORMAT_BUFFER_H 12555214cbSMark de Wever 13555214cbSMark de Wever #include <__algorithm/copy_n.h> 14f7c0df00SMark de Wever #include <__algorithm/fill_n.h> 15f0c06c04SMark de Wever #include <__algorithm/max.h> 16f0c06c04SMark de Wever #include <__algorithm/min.h> 17*14b44179SMark de Wever #include <__algorithm/ranges_copy.h> 1891dd0723SMark de Wever #include <__algorithm/ranges_copy_n.h> 19f7c0df00SMark de Wever #include <__algorithm/transform.h> 20555214cbSMark de Wever #include <__algorithm/unwrap_iter.h> 2189b356f0SNikolas Klauser #include <__concepts/same_as.h> 22555214cbSMark de Wever #include <__config> 23a595fcf9SMark de Wever #include <__format/concepts.h> 2488930229SMark de Wever #include <__format/enable_insertable.h> 25f0c06c04SMark de Wever #include <__format/format_to_n_result.h> 26555214cbSMark de Wever #include <__iterator/back_insert_iterator.h> 27555214cbSMark de Wever #include <__iterator/concepts.h> 28f0c06c04SMark de Wever #include <__iterator/incrementable_traits.h> 29555214cbSMark de Wever #include <__iterator/iterator_traits.h> 30555214cbSMark de Wever #include <__iterator/wrap_iter.h> 31c9d36bd8SNikolas Klauser #include <__memory/addressof.h> 3203c7b93aSMark de Wever #include <__memory/allocate_at_least.h> 33*14b44179SMark de Wever #include <__memory/allocator.h> 3403c7b93aSMark de Wever #include <__memory/allocator_traits.h> 3503c7b93aSMark de Wever #include <__memory/construct_at.h> 3603c7b93aSMark de Wever #include <__memory/ranges_construct_at.h> 3703c7b93aSMark de Wever #include <__memory/uninitialized_algorithms.h> 380a4aa8a1SNikolas Klauser #include <__type_traits/add_pointer.h> 39d6cd4257SMark de Wever #include <__type_traits/conditional.h> 4003c7b93aSMark de Wever #include <__utility/exception_guard.h> 41555214cbSMark de Wever #include <__utility/move.h> 42*14b44179SMark de Wever #include <stdexcept> 43f7c0df00SMark de Wever #include <string_view> 44555214cbSMark de Wever 45555214cbSMark de Wever #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 46555214cbSMark de Wever # pragma GCC system_header 47555214cbSMark de Wever #endif 48555214cbSMark de Wever 49f0c06c04SMark de Wever _LIBCPP_PUSH_MACROS 50f0c06c04SMark de Wever #include <__undef_macros> 51f0c06c04SMark de Wever 52555214cbSMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD 53555214cbSMark de Wever 544f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20 55555214cbSMark de Wever 56555214cbSMark de Wever namespace __format { 57555214cbSMark de Wever 58*14b44179SMark de Wever // A helper to limit the total size of code units written. 59*14b44179SMark de Wever class _LIBCPP_HIDE_FROM_ABI __max_output_size { 60*14b44179SMark de Wever public: 61*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __max_output_size(size_t __max_size) : __max_size_{__max_size} {} 62*14b44179SMark de Wever 63*14b44179SMark de Wever // This function adjusts the size of a (bulk) write operations. It ensures the 64*14b44179SMark de Wever // number of code units written by a __output_buffer never exceeds 65*14b44179SMark de Wever // __max_size_ code units. 66*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __write_request(size_t __code_units) { 67*14b44179SMark de Wever size_t __result = 68*14b44179SMark de Wever __code_units_written_ < __max_size_ ? std::min(__code_units, __max_size_ - __code_units_written_) : 0; 69*14b44179SMark de Wever __code_units_written_ += __code_units; 70*14b44179SMark de Wever return __result; 71*14b44179SMark de Wever } 72*14b44179SMark de Wever 73*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __code_units_written() const noexcept { return __code_units_written_; } 74*14b44179SMark de Wever 75*14b44179SMark de Wever private: 76*14b44179SMark de Wever size_t __max_size_; 77*14b44179SMark de Wever // The code units that would have been written if there was no limit. 78*14b44179SMark de Wever // format_to_n returns this value. 79*14b44179SMark de Wever size_t __code_units_written_{0}; 80*14b44179SMark de Wever }; 81*14b44179SMark de Wever 82555214cbSMark de Wever /// A "buffer" that handles writing to the proper iterator. 83555214cbSMark de Wever /// 84555214cbSMark de Wever /// This helper is used together with the @ref back_insert_iterator to offer 85555214cbSMark de Wever /// type-erasure for the formatting functions. This reduces the number to 86555214cbSMark de Wever /// template instantiations. 87*14b44179SMark de Wever /// 88*14b44179SMark de Wever /// The design is the following: 89*14b44179SMark de Wever /// - There is an external object that connects the buffer to the output. 90*14b44179SMark de Wever /// - This buffer object: 91*14b44179SMark de Wever /// - inherits publicly from this class. 92*14b44179SMark de Wever /// - has a static or dynamic buffer. 93*14b44179SMark de Wever /// - has a static member function to make space in its buffer write 94*14b44179SMark de Wever /// operations. This can be done by increasing the size of the internal 95*14b44179SMark de Wever /// buffer or by writing the contents of the buffer to the output iterator. 96*14b44179SMark de Wever /// 97*14b44179SMark de Wever /// This member function is a constructor argument, so its name is not 98*14b44179SMark de Wever /// fixed. The code uses the name __prepare_write. 99*14b44179SMark de Wever /// - The number of output code units can be limited by a __max_output_size 100*14b44179SMark de Wever /// object. This is used in format_to_n This object: 101*14b44179SMark de Wever /// - Contains the maximum number of code units to be written. 102*14b44179SMark de Wever /// - Contains the number of code units that are requested to be written. 103*14b44179SMark de Wever /// This number is returned to the user of format_to_n. 104*14b44179SMark de Wever /// - The write functions call the object's __request_write member function. 105*14b44179SMark de Wever /// This function: 106*14b44179SMark de Wever /// - Updates the number of code units that are requested to be written. 107*14b44179SMark de Wever /// - Returns the number of code units that can be written without 108*14b44179SMark de Wever /// exceeding the maximum number of code units to be written. 109*14b44179SMark de Wever /// 110*14b44179SMark de Wever /// Documentation for the buffer usage members: 111*14b44179SMark de Wever /// - __ptr_ 112*14b44179SMark de Wever /// The start of the buffer. 113*14b44179SMark de Wever /// - __capacity_ 114*14b44179SMark de Wever /// The number of code units that can be written. This means 115*14b44179SMark de Wever /// [__ptr_, __ptr_ + __capacity_) is a valid range to write to. 116*14b44179SMark de Wever /// - __size_ 117*14b44179SMark de Wever /// The number of code units written in the buffer. The next code unit will 118*14b44179SMark de Wever /// be written at __ptr_ + __size_. This __size_ may NOT contain the total 119*14b44179SMark de Wever /// number of code units written by the __output_buffer. Whether or not it 120*14b44179SMark de Wever /// does depends on the sub-class used. Typically the total number of code 121*14b44179SMark de Wever /// units written is not interesting. It is interesting for format_to_n which 122*14b44179SMark de Wever /// has its own way to track this number. 123*14b44179SMark de Wever /// 124*14b44179SMark de Wever /// Documentation for the modifying buffer operations: 125*14b44179SMark de Wever /// The subclasses have a function with the following signature: 126*14b44179SMark de Wever /// 127*14b44179SMark de Wever /// static void __prepare_write( 128*14b44179SMark de Wever /// __output_buffer<_CharT>& __buffer, size_t __code_units); 129*14b44179SMark de Wever /// 130*14b44179SMark de Wever /// This function is called when a write function writes more code units than 131*14b44179SMark de Wever /// the buffer's available space. When an __max_output_size object is provided 132*14b44179SMark de Wever /// the number of code units is the number of code units returned from 133*14b44179SMark de Wever /// __max_output_size::__request_write function. 134*14b44179SMark de Wever /// 135*14b44179SMark de Wever /// - The __buffer contains *this. Since the class containing this function 136*14b44179SMark de Wever /// inherits from __output_buffer it's safe to cast it to the subclass being 137*14b44179SMark de Wever /// used. 138*14b44179SMark de Wever /// - The __code_units is the number of code units the caller will write + 1. 139*14b44179SMark de Wever /// - This value does not take the available space of the buffer into account. 140*14b44179SMark de Wever /// - The push_back function is more efficient when writing before resizing, 141*14b44179SMark de Wever /// this means the buffer should always have room for one code unit. Hence 142*14b44179SMark de Wever /// the + 1 is the size. 143*14b44179SMark de Wever /// - When the function returns there is room for at least one additional code 144*14b44179SMark de Wever /// unit. There is no requirement there is room for __code_units code units: 145*14b44179SMark de Wever /// - The class has some "bulk" operations. For example, __copy which copies 146*14b44179SMark de Wever /// the contents of a basic_string_view to the output. If the sub-class has 147*14b44179SMark de Wever /// a fixed size buffer the size of the basic_string_view may be larger 148*14b44179SMark de Wever /// than the buffer. In that case it's impossible to honor the requested 149*14b44179SMark de Wever /// size. 150*14b44179SMark de Wever /// - When the buffer has room for at least one code unit the function may be 151*14b44179SMark de Wever /// a no-op. 152*14b44179SMark de Wever /// - When the function makes space for more code units it uses one for these 153*14b44179SMark de Wever /// functions to signal the change: 154*14b44179SMark de Wever /// - __buffer_flushed() 155*14b44179SMark de Wever /// - This function is typically used for a fixed sized buffer. 156*14b44179SMark de Wever /// - The current contents of [__ptr_, __ptr_ + __size_) have been 157*14b44179SMark de Wever /// processed. 158*14b44179SMark de Wever /// - __ptr_ remains unchanged. 159*14b44179SMark de Wever /// - __capacity_ remains unchanged. 160*14b44179SMark de Wever /// - __size_ will be set to 0. 161*14b44179SMark de Wever /// - __buffer_moved(_CharT* __ptr, size_t __capacity) 162*14b44179SMark de Wever /// - This function is typically used for a dynamic sized buffer. There the 163*14b44179SMark de Wever /// location of the buffer changes due to reallocations. 164*14b44179SMark de Wever /// - __ptr_ will be set to __ptr. (This value may be the old value of 165*14b44179SMark de Wever /// __ptr_). 166*14b44179SMark de Wever /// - __capacity_ will be set to __capacity. (This value may be the old 167*14b44179SMark de Wever /// value of __capacity_). 168*14b44179SMark de Wever /// - __size_ remains unchanged, 169*14b44179SMark de Wever /// - The range [__ptr, __ptr + __size_) contains the original data of the 170*14b44179SMark de Wever /// range [__ptr_, __ptr_ + __size_). 171*14b44179SMark de Wever /// 172*14b44179SMark de Wever /// The push_back function expects a valid buffer and a capacity of at least 1. 173*14b44179SMark de Wever /// This means: 174*14b44179SMark de Wever /// - The class is constructed with a valid buffer, 175*14b44179SMark de Wever /// - __buffer_moved is called with a valid buffer is used before the first 176*14b44179SMark de Wever /// write operation, 177*14b44179SMark de Wever /// - no write function is ever called, or 178*14b44179SMark de Wever /// - the class is constructed with a __max_output_size object with __max_size 0. 179*14b44179SMark de Wever /// 180*14b44179SMark de Wever /// The latter option allows formatted_size to use the output buffer without 181*14b44179SMark de Wever /// ever writing anything to the buffer. 182a595fcf9SMark de Wever template <__fmt_char_type _CharT> 183555214cbSMark de Wever class _LIBCPP_TEMPLATE_VIS __output_buffer { 184555214cbSMark de Wever public: 185*14b44179SMark de Wever using value_type _LIBCPP_NODEBUG = _CharT; 186*14b44179SMark de Wever using __prepare_write_type _LIBCPP_NODEBUG = void (*)(__output_buffer<_CharT>&, size_t); 187555214cbSMark de Wever 188*14b44179SMark de Wever [[nodiscard]] 189*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, __prepare_write_type __function) 190*14b44179SMark de Wever : __output_buffer{__ptr, __capacity, __function, nullptr} {} 191555214cbSMark de Wever 192*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __output_buffer( 193*14b44179SMark de Wever _CharT* __ptr, size_t __capacity, __prepare_write_type __function, __max_output_size* __max_output_size) 194*14b44179SMark de Wever : __ptr_(__ptr), __capacity_(__capacity), __prepare_write_(__function), __max_output_size_(__max_output_size) {} 195*14b44179SMark de Wever 196*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI void __buffer_flushed() { __size_ = 0; } 197*14b44179SMark de Wever 198*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI void __buffer_moved(_CharT* __ptr, size_t __capacity) { 199555214cbSMark de Wever __ptr_ = __ptr; 200555214cbSMark de Wever __capacity_ = __capacity; 201555214cbSMark de Wever } 202555214cbSMark de Wever 203da6ff3aeSMark de Wever _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return std::back_insert_iterator{*this}; } 204555214cbSMark de Wever 205da6ff3aeSMark de Wever // Used in std::back_insert_iterator. 206555214cbSMark de Wever _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { 207*14b44179SMark de Wever if (__max_output_size_ && __max_output_size_->__write_request(1) == 0) 208*14b44179SMark de Wever return; 209*14b44179SMark de Wever 210*14b44179SMark de Wever _LIBCPP_ASSERT_INTERNAL( 211*14b44179SMark de Wever __ptr_ && __size_ < __capacity_ && __available() >= 1, "attempted to write outside the buffer"); 212*14b44179SMark de Wever 213555214cbSMark de Wever __ptr_[__size_++] = __c; 214555214cbSMark de Wever 215555214cbSMark de Wever // Profiling showed flushing after adding is more efficient than flushing 216555214cbSMark de Wever // when entering the function. 217555214cbSMark de Wever if (__size_ == __capacity_) 218*14b44179SMark de Wever __prepare_write(0); 219555214cbSMark de Wever } 220555214cbSMark de Wever 221f7c0df00SMark de Wever /// Copies the input __str to the buffer. 222f7c0df00SMark de Wever /// 223f7c0df00SMark de Wever /// Since some of the input is generated by std::to_chars, there needs to be a 224f7c0df00SMark de Wever /// conversion when _CharT is wchar_t. 22537c98da3SMark de Wever template <__fmt_char_type _InCharT> 226f7c0df00SMark de Wever _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) { 227f7c0df00SMark de Wever // When the underlying iterator is a simple iterator the __capacity_ is 228f7c0df00SMark de Wever // infinite. For a string or container back_inserter it isn't. This means 229b397921fSLouis Dionne // that adding a large string to the buffer can cause some overhead. In that 230f7c0df00SMark de Wever // case a better approach could be: 231f7c0df00SMark de Wever // - flush the buffer 232f7c0df00SMark de Wever // - container.append(__str.begin(), __str.end()); 233f7c0df00SMark de Wever // The same holds true for the fill. 234f7c0df00SMark de Wever // For transform it might be slightly harder, however the use case for 235f7c0df00SMark de Wever // transform is slightly less common; it converts hexadecimal values to 236f7c0df00SMark de Wever // upper case. For integral these strings are short. 237f7c0df00SMark de Wever // TODO FMT Look at the improvements above. 238f7c0df00SMark de Wever size_t __n = __str.size(); 239*14b44179SMark de Wever if (__max_output_size_) { 240*14b44179SMark de Wever __n = __max_output_size_->__write_request(__n); 241*14b44179SMark de Wever if (__n == 0) 242f7c0df00SMark de Wever return; 243f7c0df00SMark de Wever } 244f7c0df00SMark de Wever 245f7c0df00SMark de Wever const _InCharT* __first = __str.data(); 246f7c0df00SMark de Wever do { 247*14b44179SMark de Wever __prepare_write(__n); 248*14b44179SMark de Wever size_t __chunk = std::min(__n, __available()); 24977a00c0dSLouis Dionne std::copy_n(__first, __chunk, std::addressof(__ptr_[__size_])); 250*14b44179SMark de Wever __size_ += __chunk; 251f7c0df00SMark de Wever __first += __chunk; 252f7c0df00SMark de Wever __n -= __chunk; 253f7c0df00SMark de Wever } while (__n); 254f7c0df00SMark de Wever } 255f7c0df00SMark de Wever 256f7c0df00SMark de Wever /// A std::transform wrapper. 257f7c0df00SMark de Wever /// 258f7c0df00SMark de Wever /// Like @ref __copy it may need to do type conversion. 259a35629cdSLouis Dionne template <contiguous_iterator _Iterator, 260a35629cdSLouis Dionne class _UnaryOperation, 261a35629cdSLouis Dionne __fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type> 262a35629cdSLouis Dionne _LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) { 2634f215fddSKonstantin Varlamov _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range"); 264f7c0df00SMark de Wever 265f7c0df00SMark de Wever size_t __n = static_cast<size_t>(__last - __first); 266*14b44179SMark de Wever if (__max_output_size_) { 267*14b44179SMark de Wever __n = __max_output_size_->__write_request(__n); 268*14b44179SMark de Wever if (__n == 0) 269f7c0df00SMark de Wever return; 270f7c0df00SMark de Wever } 271f7c0df00SMark de Wever 272f7c0df00SMark de Wever do { 273*14b44179SMark de Wever __prepare_write(__n); 274*14b44179SMark de Wever size_t __chunk = std::min(__n, __available()); 27577a00c0dSLouis Dionne std::transform(__first, __first + __chunk, std::addressof(__ptr_[__size_]), __operation); 276*14b44179SMark de Wever __size_ += __chunk; 277f7c0df00SMark de Wever __first += __chunk; 278f7c0df00SMark de Wever __n -= __chunk; 279f7c0df00SMark de Wever } while (__n); 280f7c0df00SMark de Wever } 281f7c0df00SMark de Wever 282f7c0df00SMark de Wever /// A \c fill_n wrapper. 283f7c0df00SMark de Wever _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { 284*14b44179SMark de Wever if (__max_output_size_) { 285*14b44179SMark de Wever __n = __max_output_size_->__write_request(__n); 286*14b44179SMark de Wever if (__n == 0) 287f7c0df00SMark de Wever return; 288f7c0df00SMark de Wever } 289f7c0df00SMark de Wever 290f7c0df00SMark de Wever do { 291*14b44179SMark de Wever __prepare_write(__n); 292*14b44179SMark de Wever size_t __chunk = std::min(__n, __available()); 29377a00c0dSLouis Dionne std::fill_n(std::addressof(__ptr_[__size_]), __chunk, __value); 294*14b44179SMark de Wever __size_ += __chunk; 295f7c0df00SMark de Wever __n -= __chunk; 296f7c0df00SMark de Wever } while (__n); 297f7c0df00SMark de Wever } 298f7c0df00SMark de Wever 299*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __capacity() const { return __capacity_; } 300*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __size() const { return __size_; } 301555214cbSMark de Wever 302555214cbSMark de Wever private: 303555214cbSMark de Wever _CharT* __ptr_; 304555214cbSMark de Wever size_t __capacity_; 305555214cbSMark de Wever size_t __size_{0}; 306*14b44179SMark de Wever void (*__prepare_write_)(__output_buffer<_CharT>&, size_t); 307*14b44179SMark de Wever __max_output_size* __max_output_size_; 308f7c0df00SMark de Wever 309*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __available() const { return __capacity_ - __size_; } 310*14b44179SMark de Wever 311*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI void __prepare_write(size_t __code_units) { 312*14b44179SMark de Wever // Always have space for one additional code unit. This is a precondition of the push_back function. 313*14b44179SMark de Wever __code_units += 1; 314*14b44179SMark de Wever if (__available() < __code_units) 315*14b44179SMark de Wever __prepare_write_(*this, __code_units + 1); 316f7c0df00SMark de Wever } 317555214cbSMark de Wever }; 318555214cbSMark de Wever 319555214cbSMark de Wever template <class _OutIt, class _CharT> 3209783f28cSLouis Dionne concept __enable_direct_output = 3219783f28cSLouis Dionne __fmt_char_type<_CharT> && 322555214cbSMark de Wever (same_as<_OutIt, _CharT*> 323b5270ba2Svarconst // TODO(hardening): the following check might not apply to hardened iterators and might need to be wrapped in an 324b5270ba2Svarconst // `#ifdef`. 3259783f28cSLouis Dionne || same_as<_OutIt, __wrap_iter<_CharT*>>); 326555214cbSMark de Wever 32788930229SMark de Wever /// Concept to see whether a \a _Container is insertable. 32888930229SMark de Wever /// 32988930229SMark de Wever /// The concept is used to validate whether multiple calls to a 33088930229SMark de Wever /// \ref back_insert_iterator can be replace by a call to \c _Container::insert. 33188930229SMark de Wever /// 33288930229SMark de Wever /// \note a \a _Container needs to opt-in to the concept by specializing 33388930229SMark de Wever /// \ref __enable_insertable. 33488930229SMark de Wever template <class _Container> 33588930229SMark de Wever concept __insertable = 336a595fcf9SMark de Wever __enable_insertable<_Container> && __fmt_char_type<typename _Container::value_type> && 3379783f28cSLouis Dionne requires(_Container& __t, 3389783f28cSLouis Dionne add_pointer_t<typename _Container::value_type> __first, 33988930229SMark de Wever add_pointer_t<typename _Container::value_type> __last) { __t.insert(__t.end(), __first, __last); }; 34088930229SMark de Wever 34188930229SMark de Wever /// Extract the container type of a \ref back_insert_iterator. 34288930229SMark de Wever template <class _It> 34388930229SMark de Wever struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container { 344*14b44179SMark de Wever using type _LIBCPP_NODEBUG = void; 34588930229SMark de Wever }; 34688930229SMark de Wever 34788930229SMark de Wever template <__insertable _Container> 34888930229SMark de Wever struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container<back_insert_iterator<_Container>> { 349*14b44179SMark de Wever using type _LIBCPP_NODEBUG = _Container; 35088930229SMark de Wever }; 35188930229SMark de Wever 352*14b44179SMark de Wever // A dynamically growing buffer. 353a595fcf9SMark de Wever template <__fmt_char_type _CharT> 354*14b44179SMark de Wever class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT> { 355fb9a692bSMark de Wever public: 356*14b44179SMark de Wever __allocating_buffer(const __allocating_buffer&) = delete; 357*14b44179SMark de Wever __allocating_buffer& operator=(const __allocating_buffer&) = delete; 358fb9a692bSMark de Wever 359*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __allocating_buffer() : __allocating_buffer{nullptr} {} 360fb9a692bSMark de Wever 361*14b44179SMark de Wever [[nodiscard]] 362*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI explicit __allocating_buffer(__max_output_size* __max_output_size) 363*14b44179SMark de Wever : __output_buffer<_CharT>{__small_buffer_, __buffer_size_, __prepare_write, __max_output_size} {} 364*14b44179SMark de Wever 365*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI ~__allocating_buffer() { 366*14b44179SMark de Wever if (__ptr_ != __small_buffer_) 367*14b44179SMark de Wever _Alloc{}.deallocate(__ptr_, this->__capacity()); 368*14b44179SMark de Wever } 369*14b44179SMark de Wever 370*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, this->__size()}; } 371*14b44179SMark de Wever 372*14b44179SMark de Wever private: 373*14b44179SMark de Wever using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>; 374*14b44179SMark de Wever 375*14b44179SMark de Wever // Since allocating is expensive the class has a small internal buffer. When 376*14b44179SMark de Wever // its capacity is exceeded a dynamic buffer will be allocated. 377*14b44179SMark de Wever static constexpr size_t __buffer_size_ = 256; 378*14b44179SMark de Wever _CharT __small_buffer_[__buffer_size_]; 379*14b44179SMark de Wever 380*14b44179SMark de Wever _CharT* __ptr_{__small_buffer_}; 381*14b44179SMark de Wever 382*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) { 383*14b44179SMark de Wever if (__capacity < __buffer_size_) 384*14b44179SMark de Wever return; 385*14b44179SMark de Wever 386*14b44179SMark de Wever _LIBCPP_ASSERT_INTERNAL(__capacity > this->__capacity(), "the buffer must grow"); 387*14b44179SMark de Wever 388*14b44179SMark de Wever // _CharT is an implicit lifetime type so can be used without explicit 389*14b44179SMark de Wever // construction or destruction. 390*14b44179SMark de Wever _Alloc __alloc; 391*14b44179SMark de Wever auto __result = std::__allocate_at_least(__alloc, __capacity); 392*14b44179SMark de Wever std::copy_n(__ptr_, this->__size(), __result.ptr); 393*14b44179SMark de Wever if (__ptr_ != __small_buffer_) 394*14b44179SMark de Wever __alloc.deallocate(__ptr_, this->__capacity()); 395*14b44179SMark de Wever 396*14b44179SMark de Wever __ptr_ = __result.ptr; 397*14b44179SMark de Wever this->__buffer_moved(__ptr_, __result.count); 398*14b44179SMark de Wever } 399*14b44179SMark de Wever 400*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI void __prepare_write(size_t __size_hint) { 401*14b44179SMark de Wever __grow_buffer(std::max<size_t>(this->__capacity() + __size_hint, this->__capacity() * 1.6)); 402*14b44179SMark de Wever } 403*14b44179SMark de Wever 404*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI static void __prepare_write(__output_buffer<_CharT>& __buffer, size_t __size_hint) { 405*14b44179SMark de Wever static_cast<__allocating_buffer<_CharT>&>(__buffer).__prepare_write(__size_hint); 406*14b44179SMark de Wever } 407*14b44179SMark de Wever }; 408*14b44179SMark de Wever 409*14b44179SMark de Wever // A buffer that directly writes to the underlying buffer. 410*14b44179SMark de Wever template <class _OutIt, __fmt_char_type _CharT> 411*14b44179SMark de Wever class _LIBCPP_TEMPLATE_VIS __direct_iterator_buffer : public __output_buffer<_CharT> { 412*14b44179SMark de Wever public: 413*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it) 414*14b44179SMark de Wever : __direct_iterator_buffer{__out_it, nullptr} {} 415*14b44179SMark de Wever 416*14b44179SMark de Wever [[nodiscard]] 417*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size) 418*14b44179SMark de Wever : __output_buffer<_CharT>{std::__unwrap_iter(__out_it), __buffer_size, __prepare_write, __max_output_size}, 419*14b44179SMark de Wever __out_it_(__out_it) {} 420*14b44179SMark de Wever 421*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return __out_it_ + this->__size(); } 422*14b44179SMark de Wever 423*14b44179SMark de Wever private: 424*14b44179SMark de Wever // The function format_to expects a buffer large enough for the output. The 425*14b44179SMark de Wever // function format_to_n has its own helper class that restricts the number of 426*14b44179SMark de Wever // write options. So this function class can pretend to have an infinite 427*14b44179SMark de Wever // buffer. 428*14b44179SMark de Wever static constexpr size_t __buffer_size = -1; 429*14b44179SMark de Wever 430*14b44179SMark de Wever _OutIt __out_it_; 431*14b44179SMark de Wever 432*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI static void 433*14b44179SMark de Wever __prepare_write([[maybe_unused]] __output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) { 434*14b44179SMark de Wever std::__throw_length_error("__direct_iterator_buffer"); 435*14b44179SMark de Wever } 436*14b44179SMark de Wever }; 437*14b44179SMark de Wever 438*14b44179SMark de Wever // A buffer that writes its output to the end of a container. 439*14b44179SMark de Wever template <class _OutIt, __fmt_char_type _CharT> 440*14b44179SMark de Wever class _LIBCPP_TEMPLATE_VIS __container_inserter_buffer : public __output_buffer<_CharT> { 441*14b44179SMark de Wever public: 442*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it) 443*14b44179SMark de Wever : __container_inserter_buffer{__out_it, nullptr} {} 444*14b44179SMark de Wever 445*14b44179SMark de Wever [[nodiscard]] 446*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it, __max_output_size* __max_output_size) 447*14b44179SMark de Wever : __output_buffer<_CharT>{__small_buffer_, __buffer_size, __prepare_write, __max_output_size}, 448*14b44179SMark de Wever __container_{__out_it.__get_container()} {} 449*14b44179SMark de Wever 450*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && { 451*14b44179SMark de Wever __container_->insert(__container_->end(), __small_buffer_, __small_buffer_ + this->__size()); 452*14b44179SMark de Wever return std::back_inserter(*__container_); 453fb9a692bSMark de Wever } 454fb9a692bSMark de Wever 455fb9a692bSMark de Wever private: 456*14b44179SMark de Wever typename __back_insert_iterator_container<_OutIt>::type* __container_; 457fb9a692bSMark de Wever 458*14b44179SMark de Wever // This class uses a fixed size buffer and appends the elements in 459*14b44179SMark de Wever // __buffer_size chunks. An alternative would be to use an allocating buffer 460*14b44179SMark de Wever // and append the output in a single write operation. Benchmarking showed no 461*14b44179SMark de Wever // performance difference. 462*14b44179SMark de Wever static constexpr size_t __buffer_size = 256; 463*14b44179SMark de Wever _CharT __small_buffer_[__buffer_size]; 464f0c06c04SMark de Wever 465*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI void __prepare_write() { 466*14b44179SMark de Wever __container_->insert(__container_->end(), __small_buffer_, __small_buffer_ + this->__size()); 467*14b44179SMark de Wever this->__buffer_flushed(); 468f0c06c04SMark de Wever } 469f0c06c04SMark de Wever 470*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI static void 471*14b44179SMark de Wever __prepare_write(__output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) { 472*14b44179SMark de Wever static_cast<__container_inserter_buffer<_OutIt, _CharT>&>(__buffer).__prepare_write(); 473*14b44179SMark de Wever } 474f0c06c04SMark de Wever }; 475f0c06c04SMark de Wever 476*14b44179SMark de Wever // A buffer that writes to an iterator. 477*14b44179SMark de Wever // 478*14b44179SMark de Wever // Unlike the __container_inserter_buffer this class' performance does benefit 479*14b44179SMark de Wever // from allocating and then inserting. 480a595fcf9SMark de Wever template <class _OutIt, __fmt_char_type _CharT> 481*14b44179SMark de Wever class _LIBCPP_TEMPLATE_VIS __iterator_buffer : public __allocating_buffer<_CharT> { 482f0c06c04SMark de Wever public: 483*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it) 484*14b44179SMark de Wever : __allocating_buffer<_CharT>{}, __out_it_{std::move(__out_it)} {} 485*14b44179SMark de Wever 486*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size) 487*14b44179SMark de Wever : __allocating_buffer<_CharT>{__max_output_size}, __out_it_{std::move(__out_it)} {} 488*14b44179SMark de Wever 489*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && { 490*14b44179SMark de Wever return std::ranges::copy(this->__view(), std::move(__out_it_)).out; 491f0c06c04SMark de Wever } 492f0c06c04SMark de Wever 493*14b44179SMark de Wever private: 494*14b44179SMark de Wever _OutIt __out_it_; 495f0c06c04SMark de Wever }; 496f0c06c04SMark de Wever 497*14b44179SMark de Wever // Selects the type of the buffer used for the output iterator. 498a595fcf9SMark de Wever template <class _OutIt, __fmt_char_type _CharT> 499*14b44179SMark de Wever class _LIBCPP_TEMPLATE_VIS __buffer_selector { 500*14b44179SMark de Wever using _Container _LIBCPP_NODEBUG = __back_insert_iterator_container<_OutIt>::type; 501f0c06c04SMark de Wever 502f0c06c04SMark de Wever public: 503*14b44179SMark de Wever using type _LIBCPP_NODEBUG = 504*14b44179SMark de Wever conditional_t<!same_as<_Container, void>, 505*14b44179SMark de Wever __container_inserter_buffer<_OutIt, _CharT>, 506*14b44179SMark de Wever conditional_t<__enable_direct_output<_OutIt, _CharT>, 507*14b44179SMark de Wever __direct_iterator_buffer<_OutIt, _CharT>, 508*14b44179SMark de Wever __iterator_buffer<_OutIt, _CharT>>>; 509*14b44179SMark de Wever }; 510f0c06c04SMark de Wever 511*14b44179SMark de Wever // A buffer that counts and limits the number of insertions. 512*14b44179SMark de Wever template <class _OutIt, __fmt_char_type _CharT> 513*14b44179SMark de Wever class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer : private __buffer_selector<_OutIt, _CharT>::type { 514*14b44179SMark de Wever public: 515*14b44179SMark de Wever using _Base _LIBCPP_NODEBUG = __buffer_selector<_OutIt, _CharT>::type; 516*14b44179SMark de Wever 517*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_to_n_buffer(_OutIt __out_it, iter_difference_t<_OutIt> __n) 518*14b44179SMark de Wever : _Base{std::move(__out_it), std::addressof(__max_output_size_)}, 519*14b44179SMark de Wever __max_output_size_{__n < 0 ? size_t{0} : static_cast<size_t>(__n)} {} 520*14b44179SMark de Wever 521*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return _Base::__make_output_iterator(); } 522*14b44179SMark de Wever 523*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && { 524*14b44179SMark de Wever return {static_cast<_Base&&>(*this).__out_it(), 525*14b44179SMark de Wever static_cast<iter_difference_t<_OutIt>>(__max_output_size_.__code_units_written())}; 526*14b44179SMark de Wever } 527*14b44179SMark de Wever 528*14b44179SMark de Wever private: 529*14b44179SMark de Wever __max_output_size __max_output_size_; 530*14b44179SMark de Wever }; 531*14b44179SMark de Wever 532*14b44179SMark de Wever // A buffer that counts the number of insertions. 533*14b44179SMark de Wever // 534*14b44179SMark de Wever // Since formatted_size only needs to know the size, the output itself is 535*14b44179SMark de Wever // discarded. 536*14b44179SMark de Wever template <__fmt_char_type _CharT> 537*14b44179SMark de Wever class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer : private __output_buffer<_CharT> { 538*14b44179SMark de Wever public: 539*14b44179SMark de Wever using _Base _LIBCPP_NODEBUG = __output_buffer<_CharT>; 540*14b44179SMark de Wever 541*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __formatted_size_buffer() 542*14b44179SMark de Wever : _Base{nullptr, 0, __prepare_write, std::addressof(__max_output_size_)} {} 543*14b44179SMark de Wever 544*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return _Base::__make_output_iterator(); } 545*14b44179SMark de Wever 546*14b44179SMark de Wever // This function does not need to be r-value qualified, however this is 547*14b44179SMark de Wever // consistent with similar objects. 548*14b44179SMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __result() && { return __max_output_size_.__code_units_written(); } 549*14b44179SMark de Wever 550*14b44179SMark de Wever private: 551*14b44179SMark de Wever __max_output_size __max_output_size_{0}; 552*14b44179SMark de Wever 553*14b44179SMark de Wever _LIBCPP_HIDE_FROM_ABI static void 554*14b44179SMark de Wever __prepare_write([[maybe_unused]] __output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) { 555*14b44179SMark de Wever // Note this function does not satisfy the requirement of giving a 1 code unit buffer. 556*14b44179SMark de Wever _LIBCPP_ASSERT_INTERNAL( 557*14b44179SMark de Wever false, "Since __max_output_size_.__max_size_ == 0 there should never be call to this function."); 558f0c06c04SMark de Wever } 559f0c06c04SMark de Wever }; 56022e8525dSMark de Wever 56122e8525dSMark de Wever // A dynamically growing buffer intended to be used for retargeting a context. 56222e8525dSMark de Wever // 56322e8525dSMark de Wever // P2286 Formatting ranges adds range formatting support. It allows the user to 56422e8525dSMark de Wever // specify the minimum width for the entire formatted range. The width of the 56522e8525dSMark de Wever // range is not known until the range is formatted. Formatting is done to an 56622e8525dSMark de Wever // output_iterator so there's no guarantee it would be possible to add the fill 56722e8525dSMark de Wever // to the front of the output. Instead the range is formatted to a temporary 56822e8525dSMark de Wever // buffer and that buffer is formatted as a string. 56922e8525dSMark de Wever // 57022e8525dSMark de Wever // There is an issue with that approach, the format context used in 57122e8525dSMark de Wever // std::formatter<T>::format contains the output iterator used as part of its 57222e8525dSMark de Wever // type. So using this output iterator means there needs to be a new format 57322e8525dSMark de Wever // context and the format arguments need to be retargeted to the new context. 57422e8525dSMark de Wever // This retargeting is done by a basic_format_context specialized for the 57522e8525dSMark de Wever // __iterator of this container. 57603c7b93aSMark de Wever // 57703c7b93aSMark de Wever // This class uses its own buffer management, since using vector 57803c7b93aSMark de Wever // would lead to a circular include with formatter for vector<bool>. 57922e8525dSMark de Wever template <__fmt_char_type _CharT> 58022e8525dSMark de Wever class _LIBCPP_TEMPLATE_VIS __retarget_buffer { 581f6958523SNikolas Klauser using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>; 58203c7b93aSMark de Wever 58322e8525dSMark de Wever public: 584*14b44179SMark de Wever using value_type _LIBCPP_NODEBUG = _CharT; 58522e8525dSMark de Wever 58622e8525dSMark de Wever struct __iterator { 587*14b44179SMark de Wever using difference_type _LIBCPP_NODEBUG = ptrdiff_t; 588*14b44179SMark de Wever using value_type _LIBCPP_NODEBUG = _CharT; 58922e8525dSMark de Wever 59022e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(__retarget_buffer& __buffer) 59122e8525dSMark de Wever : __buffer_(std::addressof(__buffer)) {} 59222e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(const _CharT& __c) { 59322e8525dSMark de Wever __buffer_->push_back(__c); 59422e8525dSMark de Wever return *this; 59522e8525dSMark de Wever } 59622e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(_CharT&& __c) { 59722e8525dSMark de Wever __buffer_->push_back(__c); 59822e8525dSMark de Wever return *this; 59922e8525dSMark de Wever } 60022e8525dSMark de Wever 60122e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator*() { return *this; } 60222e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { return *this; } 60322e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { return *this; } 60422e8525dSMark de Wever __retarget_buffer* __buffer_; 60522e8525dSMark de Wever }; 60622e8525dSMark de Wever 60703c7b93aSMark de Wever __retarget_buffer(const __retarget_buffer&) = delete; 60803c7b93aSMark de Wever __retarget_buffer& operator=(const __retarget_buffer&) = delete; 60903c7b93aSMark de Wever 61003c7b93aSMark de Wever _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { 6113f65f718SMark de Wever // When the initial size is very small a lot of resizes happen 6123f65f718SMark de Wever // when elements added. So use a hard-coded minimum size. 6133f65f718SMark de Wever // 6143f65f718SMark de Wever // Note a size < 2 will not work 6153f65f718SMark de Wever // - 0 there is no buffer, while push_back requires 1 empty element. 6163f65f718SMark de Wever // - 1 multiplied by the grow factor is 1 and thus the buffer never 6173f65f718SMark de Wever // grows. 6183f65f718SMark de Wever auto __result = std::__allocate_at_least(__alloc_, std::max(__size_hint, 256 / sizeof(_CharT))); 61903c7b93aSMark de Wever __ptr_ = __result.ptr; 62003c7b93aSMark de Wever __capacity_ = __result.count; 62103c7b93aSMark de Wever } 62203c7b93aSMark de Wever 62303c7b93aSMark de Wever _LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() { 62403c7b93aSMark de Wever ranges::destroy_n(__ptr_, __size_); 62503c7b93aSMark de Wever allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); 62603c7b93aSMark de Wever } 62722e8525dSMark de Wever 62822e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; } 62922e8525dSMark de Wever 63003c7b93aSMark de Wever _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { 63103c7b93aSMark de Wever std::construct_at(__ptr_ + __size_, __c); 63203c7b93aSMark de Wever ++__size_; 63303c7b93aSMark de Wever 63403c7b93aSMark de Wever if (__size_ == __capacity_) 63503c7b93aSMark de Wever __grow_buffer(); 63603c7b93aSMark de Wever } 63722e8525dSMark de Wever 63822e8525dSMark de Wever template <__fmt_char_type _InCharT> 63922e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) { 64003c7b93aSMark de Wever size_t __n = __str.size(); 64103c7b93aSMark de Wever if (__size_ + __n >= __capacity_) 64203c7b93aSMark de Wever // Push_back requires the buffer to have room for at least one character. 64303c7b93aSMark de Wever __grow_buffer(__size_ + __n + 1); 64403c7b93aSMark de Wever 64503c7b93aSMark de Wever std::uninitialized_copy_n(__str.data(), __n, __ptr_ + __size_); 64603c7b93aSMark de Wever __size_ += __n; 64722e8525dSMark de Wever } 64822e8525dSMark de Wever 649a35629cdSLouis Dionne template <contiguous_iterator _Iterator, 650a35629cdSLouis Dionne class _UnaryOperation, 651a35629cdSLouis Dionne __fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type> 652a35629cdSLouis Dionne _LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) { 6534f215fddSKonstantin Varlamov _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range"); 65403c7b93aSMark de Wever 65503c7b93aSMark de Wever size_t __n = static_cast<size_t>(__last - __first); 65603c7b93aSMark de Wever if (__size_ + __n >= __capacity_) 65703c7b93aSMark de Wever // Push_back requires the buffer to have room for at least one character. 65803c7b93aSMark de Wever __grow_buffer(__size_ + __n + 1); 65903c7b93aSMark de Wever 66003c7b93aSMark de Wever std::uninitialized_default_construct_n(__ptr_ + __size_, __n); 66103c7b93aSMark de Wever std::transform(__first, __last, __ptr_ + __size_, std::move(__operation)); 66203c7b93aSMark de Wever __size_ += __n; 66322e8525dSMark de Wever } 66422e8525dSMark de Wever 66503c7b93aSMark de Wever _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { 66603c7b93aSMark de Wever if (__size_ + __n >= __capacity_) 66703c7b93aSMark de Wever // Push_back requires the buffer to have room for at least one character. 66803c7b93aSMark de Wever __grow_buffer(__size_ + __n + 1); 66922e8525dSMark de Wever 67003c7b93aSMark de Wever std::uninitialized_fill_n(__ptr_ + __size_, __n, __value); 67103c7b93aSMark de Wever __size_ += __n; 67203c7b93aSMark de Wever } 67303c7b93aSMark de Wever 67403c7b93aSMark de Wever _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, __size_}; } 67522e8525dSMark de Wever 67622e8525dSMark de Wever private: 67703c7b93aSMark de Wever _LIBCPP_HIDE_FROM_ABI void __grow_buffer() { __grow_buffer(__capacity_ * 1.6); } 67803c7b93aSMark de Wever 67903c7b93aSMark de Wever _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) { 6804f215fddSKonstantin Varlamov _LIBCPP_ASSERT_INTERNAL(__capacity > __capacity_, "the buffer must grow"); 68103c7b93aSMark de Wever auto __result = std::__allocate_at_least(__alloc_, __capacity); 68203c7b93aSMark de Wever auto __guard = std::__make_exception_guard([&] { 68303c7b93aSMark de Wever allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count); 68403c7b93aSMark de Wever }); 6852c07ca85SMark de Wever // This shouldn't throw, but just to be safe. Note that at -O1 this 68603c7b93aSMark de Wever // guard is optimized away so there is no runtime overhead. 68703c7b93aSMark de Wever std::uninitialized_move_n(__ptr_, __size_, __result.ptr); 68803c7b93aSMark de Wever __guard.__complete(); 68903c7b93aSMark de Wever ranges::destroy_n(__ptr_, __size_); 69003c7b93aSMark de Wever allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); 69103c7b93aSMark de Wever 69203c7b93aSMark de Wever __ptr_ = __result.ptr; 69303c7b93aSMark de Wever __capacity_ = __result.count; 69403c7b93aSMark de Wever } 69503c7b93aSMark de Wever _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_; 69603c7b93aSMark de Wever _CharT* __ptr_; 69703c7b93aSMark de Wever size_t __capacity_; 69803c7b93aSMark de Wever size_t __size_{0}; 69922e8525dSMark de Wever }; 70022e8525dSMark de Wever 701555214cbSMark de Wever } // namespace __format 702555214cbSMark de Wever 7034f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20 704555214cbSMark de Wever 705555214cbSMark de Wever _LIBCPP_END_NAMESPACE_STD 706555214cbSMark de Wever 707f0c06c04SMark de Wever _LIBCPP_POP_MACROS 708f0c06c04SMark de Wever 709555214cbSMark de Wever #endif // _LIBCPP___FORMAT_BUFFER_H 710