xref: /llvm-project/libcxx/include/__format/buffer.h (revision 14b44179cb61dd551c911dea54de57b588621005)
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