1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___FORMAT_BUFFER_H
11#define _LIBCPP___FORMAT_BUFFER_H
12
13#include <__algorithm/copy_n.h>
14#include <__algorithm/fill_n.h>
15#include <__algorithm/max.h>
16#include <__algorithm/min.h>
17#include <__algorithm/ranges_copy_n.h>
18#include <__algorithm/transform.h>
19#include <__algorithm/unwrap_iter.h>
20#include <__concepts/same_as.h>
21#include <__config>
22#include <__format/concepts.h>
23#include <__format/enable_insertable.h>
24#include <__format/format_to_n_result.h>
25#include <__iterator/back_insert_iterator.h>
26#include <__iterator/concepts.h>
27#include <__iterator/incrementable_traits.h>
28#include <__iterator/iterator_traits.h>
29#include <__iterator/wrap_iter.h>
30#include <__memory/addressof.h>
31#include <__memory/allocate_at_least.h>
32#include <__memory/allocator_traits.h>
33#include <__memory/construct_at.h>
34#include <__memory/ranges_construct_at.h>
35#include <__memory/uninitialized_algorithms.h>
36#include <__type_traits/add_pointer.h>
37#include <__type_traits/conditional.h>
38#include <__utility/exception_guard.h>
39#include <__utility/move.h>
40#include <cstddef>
41#include <string_view>
42
43#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
44#  pragma GCC system_header
45#endif
46
47_LIBCPP_PUSH_MACROS
48#include <__undef_macros>
49
50_LIBCPP_BEGIN_NAMESPACE_STD
51
52#if _LIBCPP_STD_VER >= 20
53
54namespace __format {
55
56/// A "buffer" that handles writing to the proper iterator.
57///
58/// This helper is used together with the @ref back_insert_iterator to offer
59/// type-erasure for the formatting functions. This reduces the number to
60/// template instantiations.
61template <__fmt_char_type _CharT>
62class _LIBCPP_TEMPLATE_VIS __output_buffer {
63public:
64  using value_type = _CharT;
65
66  template <class _Tp>
67  _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, _Tp* __obj)
68      : __ptr_(__ptr),
69        __capacity_(__capacity),
70        __flush_([](_CharT* __p, size_t __n, void* __o) { static_cast<_Tp*>(__o)->__flush(__p, __n); }),
71        __obj_(__obj) {}
72
73  _LIBCPP_HIDE_FROM_ABI void __reset(_CharT* __ptr, size_t __capacity) {
74    __ptr_      = __ptr;
75    __capacity_ = __capacity;
76  }
77
78  _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return std::back_insert_iterator{*this}; }
79
80  // Used in std::back_insert_iterator.
81  _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) {
82    __ptr_[__size_++] = __c;
83
84    // Profiling showed flushing after adding is more efficient than flushing
85    // when entering the function.
86    if (__size_ == __capacity_)
87      __flush();
88  }
89
90  /// Copies the input __str to the buffer.
91  ///
92  /// Since some of the input is generated by std::to_chars, there needs to be a
93  /// conversion when _CharT is wchar_t.
94  template <__fmt_char_type _InCharT>
95  _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) {
96    // When the underlying iterator is a simple iterator the __capacity_ is
97    // infinite. For a string or container back_inserter it isn't. This means
98    // that adding a large string to the buffer can cause some overhead. In that
99    // case a better approach could be:
100    // - flush the buffer
101    // - container.append(__str.begin(), __str.end());
102    // The same holds true for the fill.
103    // For transform it might be slightly harder, however the use case for
104    // transform is slightly less common; it converts hexadecimal values to
105    // upper case. For integral these strings are short.
106    // TODO FMT Look at the improvements above.
107    size_t __n = __str.size();
108
109    __flush_on_overflow(__n);
110    if (__n < __capacity_) { //  push_back requires the buffer to have room for at least one character (so use <).
111      std::copy_n(__str.data(), __n, std::addressof(__ptr_[__size_]));
112      __size_ += __n;
113      return;
114    }
115
116    // The output doesn't fit in the internal buffer.
117    // Copy the data in "__capacity_" sized chunks.
118    _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow");
119    const _InCharT* __first = __str.data();
120    do {
121      size_t __chunk = std::min(__n, __capacity_);
122      std::copy_n(__first, __chunk, std::addressof(__ptr_[__size_]));
123      __size_ = __chunk;
124      __first += __chunk;
125      __n -= __chunk;
126      __flush();
127    } while (__n);
128  }
129
130  /// A std::transform wrapper.
131  ///
132  /// Like @ref __copy it may need to do type conversion.
133  template <contiguous_iterator _Iterator,
134            class _UnaryOperation,
135            __fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type>
136  _LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) {
137    _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range");
138
139    size_t __n = static_cast<size_t>(__last - __first);
140    __flush_on_overflow(__n);
141    if (__n < __capacity_) { //  push_back requires the buffer to have room for at least one character (so use <).
142      std::transform(__first, __last, std::addressof(__ptr_[__size_]), std::move(__operation));
143      __size_ += __n;
144      return;
145    }
146
147    // The output doesn't fit in the internal buffer.
148    // Transform the data in "__capacity_" sized chunks.
149    _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow");
150    do {
151      size_t __chunk = std::min(__n, __capacity_);
152      std::transform(__first, __first + __chunk, std::addressof(__ptr_[__size_]), __operation);
153      __size_ = __chunk;
154      __first += __chunk;
155      __n -= __chunk;
156      __flush();
157    } while (__n);
158  }
159
160  /// A \c fill_n wrapper.
161  _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) {
162    __flush_on_overflow(__n);
163    if (__n < __capacity_) { //  push_back requires the buffer to have room for at least one character (so use <).
164      std::fill_n(std::addressof(__ptr_[__size_]), __n, __value);
165      __size_ += __n;
166      return;
167    }
168
169    // The output doesn't fit in the internal buffer.
170    // Fill the buffer in "__capacity_" sized chunks.
171    _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow");
172    do {
173      size_t __chunk = std::min(__n, __capacity_);
174      std::fill_n(std::addressof(__ptr_[__size_]), __chunk, __value);
175      __size_ = __chunk;
176      __n -= __chunk;
177      __flush();
178    } while (__n);
179  }
180
181  _LIBCPP_HIDE_FROM_ABI void __flush() {
182    __flush_(__ptr_, __size_, __obj_);
183    __size_ = 0;
184  }
185
186private:
187  _CharT* __ptr_;
188  size_t __capacity_;
189  size_t __size_{0};
190  void (*__flush_)(_CharT*, size_t, void*);
191  void* __obj_;
192
193  /// Flushes the buffer when the output operation would overflow the buffer.
194  ///
195  /// A simple approach for the overflow detection would be something along the
196  /// lines:
197  /// \code
198  /// // The internal buffer is large enough.
199  /// if (__n <= __capacity_) {
200  ///   // Flush when we really would overflow.
201  ///   if (__size_ + __n >= __capacity_)
202  ///     __flush();
203  ///   ...
204  /// }
205  /// \endcode
206  ///
207  /// This approach works for all cases but one:
208  /// A __format_to_n_buffer_base where \ref __enable_direct_output is true.
209  /// In that case the \ref __capacity_ of the buffer changes during the first
210  /// \ref __flush. During that operation the output buffer switches from its
211  /// __writer_ to its __storage_. The \ref __capacity_ of the former depends
212  /// on the value of n, of the latter is a fixed size. For example:
213  /// - a format_to_n call with a 10'000 char buffer,
214  /// - the buffer is filled with 9'500 chars,
215  /// - adding 1'000 elements would overflow the buffer so the buffer gets
216  ///   changed and the \ref __capacity_ decreases from 10'000 to
217  ///   __buffer_size (256 at the time of writing).
218  ///
219  /// This means that the \ref __flush for this class may need to copy a part of
220  /// the internal buffer to the proper output. In this example there will be
221  /// 500 characters that need this copy operation.
222  ///
223  /// Note it would be more efficient to write 500 chars directly and then swap
224  /// the buffers. This would make the code more complex and \ref format_to_n is
225  /// not the most common use case. Therefore the optimization isn't done.
226  _LIBCPP_HIDE_FROM_ABI void __flush_on_overflow(size_t __n) {
227    if (__size_ + __n >= __capacity_)
228      __flush();
229  }
230};
231
232/// A storage using an internal buffer.
233///
234/// This storage is used when writing a single element to the output iterator
235/// is expensive.
236template <__fmt_char_type _CharT>
237class _LIBCPP_TEMPLATE_VIS __internal_storage {
238public:
239  _LIBCPP_HIDE_FROM_ABI _CharT* __begin() { return __buffer_; }
240
241  static constexpr size_t __buffer_size = 256 / sizeof(_CharT);
242
243private:
244  _CharT __buffer_[__buffer_size];
245};
246
247/// A storage writing directly to the storage.
248///
249/// This requires the storage to be a contiguous buffer of \a _CharT.
250/// Since the output is directly written to the underlying storage this class
251/// is just an empty class.
252template <__fmt_char_type _CharT>
253class _LIBCPP_TEMPLATE_VIS __direct_storage {};
254
255template <class _OutIt, class _CharT>
256concept __enable_direct_output =
257    __fmt_char_type<_CharT> &&
258    (same_as<_OutIt, _CharT*>
259     // TODO(hardening): the following check might not apply to hardened iterators and might need to be wrapped in an
260     // `#ifdef`.
261     || same_as<_OutIt, __wrap_iter<_CharT*>>);
262
263/// Write policy for directly writing to the underlying output.
264template <class _OutIt, __fmt_char_type _CharT>
265class _LIBCPP_TEMPLATE_VIS __writer_direct {
266public:
267  _LIBCPP_HIDE_FROM_ABI explicit __writer_direct(_OutIt __out_it) : __out_it_(__out_it) {}
268
269  _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() { return __out_it_; }
270
271  _LIBCPP_HIDE_FROM_ABI void __flush(_CharT*, size_t __n) {
272    // _OutIt can be a __wrap_iter<CharT*>. Therefore the original iterator
273    // is adjusted.
274    __out_it_ += __n;
275  }
276
277private:
278  _OutIt __out_it_;
279};
280
281/// Write policy for copying the buffer to the output.
282template <class _OutIt, __fmt_char_type _CharT>
283class _LIBCPP_TEMPLATE_VIS __writer_iterator {
284public:
285  _LIBCPP_HIDE_FROM_ABI explicit __writer_iterator(_OutIt __out_it) : __out_it_{std::move(__out_it)} {}
286
287  _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return std::move(__out_it_); }
288
289  _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
290    __out_it_ = std::ranges::copy_n(__ptr, __n, std::move(__out_it_)).out;
291  }
292
293private:
294  _OutIt __out_it_;
295};
296
297/// Concept to see whether a \a _Container is insertable.
298///
299/// The concept is used to validate whether multiple calls to a
300/// \ref back_insert_iterator can be replace by a call to \c _Container::insert.
301///
302/// \note a \a _Container needs to opt-in to the concept by specializing
303/// \ref __enable_insertable.
304template <class _Container>
305concept __insertable =
306    __enable_insertable<_Container> && __fmt_char_type<typename _Container::value_type> &&
307    requires(_Container& __t,
308             add_pointer_t<typename _Container::value_type> __first,
309             add_pointer_t<typename _Container::value_type> __last) { __t.insert(__t.end(), __first, __last); };
310
311/// Extract the container type of a \ref back_insert_iterator.
312template <class _It>
313struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container {
314  using type = void;
315};
316
317template <__insertable _Container>
318struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container<back_insert_iterator<_Container>> {
319  using type = _Container;
320};
321
322/// Write policy for inserting the buffer in a container.
323template <class _Container>
324class _LIBCPP_TEMPLATE_VIS __writer_container {
325public:
326  using _CharT = typename _Container::value_type;
327
328  _LIBCPP_HIDE_FROM_ABI explicit __writer_container(back_insert_iterator<_Container> __out_it)
329      : __container_{__out_it.__get_container()} {}
330
331  _LIBCPP_HIDE_FROM_ABI auto __out_it() { return std::back_inserter(*__container_); }
332
333  _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
334    __container_->insert(__container_->end(), __ptr, __ptr + __n);
335  }
336
337private:
338  _Container* __container_;
339};
340
341/// Selects the type of the writer used for the output iterator.
342template <class _OutIt, class _CharT>
343class _LIBCPP_TEMPLATE_VIS __writer_selector {
344  using _Container = typename __back_insert_iterator_container<_OutIt>::type;
345
346public:
347  using type =
348      conditional_t<!same_as<_Container, void>,
349                    __writer_container<_Container>,
350                    conditional_t<__enable_direct_output<_OutIt, _CharT>,
351                                  __writer_direct<_OutIt, _CharT>,
352                                  __writer_iterator<_OutIt, _CharT>>>;
353};
354
355/// The generic formatting buffer.
356template <class _OutIt, __fmt_char_type _CharT>
357  requires(output_iterator<_OutIt, const _CharT&>)
358class _LIBCPP_TEMPLATE_VIS __format_buffer {
359  using _Storage =
360      conditional_t<__enable_direct_output<_OutIt, _CharT>, __direct_storage<_CharT>, __internal_storage<_CharT>>;
361
362public:
363  _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it)
364    requires(same_as<_Storage, __internal_storage<_CharT>>)
365      : __output_(__storage_.__begin(), __storage_.__buffer_size, this), __writer_(std::move(__out_it)) {}
366
367  _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it)
368    requires(same_as<_Storage, __direct_storage<_CharT>>)
369      : __output_(std::__unwrap_iter(__out_it), size_t(-1), this), __writer_(std::move(__out_it)) {}
370
371  _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return __output_.__make_output_iterator(); }
372
373  _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { __writer_.__flush(__ptr, __n); }
374
375  _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && {
376    __output_.__flush();
377    return std::move(__writer_).__out_it();
378  }
379
380private:
381  _LIBCPP_NO_UNIQUE_ADDRESS _Storage __storage_;
382  __output_buffer<_CharT> __output_;
383  typename __writer_selector<_OutIt, _CharT>::type __writer_;
384};
385
386/// A buffer that counts the number of insertions.
387///
388/// Since \ref formatted_size only needs to know the size, the output itself is
389/// discarded.
390template <__fmt_char_type _CharT>
391class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer {
392public:
393  _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return __output_.__make_output_iterator(); }
394
395  _LIBCPP_HIDE_FROM_ABI void __flush(const _CharT*, size_t __n) { __size_ += __n; }
396
397  _LIBCPP_HIDE_FROM_ABI size_t __result() && {
398    __output_.__flush();
399    return __size_;
400  }
401
402private:
403  __internal_storage<_CharT> __storage_;
404  __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this};
405  size_t __size_{0};
406};
407
408/// The base of a buffer that counts and limits the number of insertions.
409template <class _OutIt, __fmt_char_type _CharT, bool>
410  requires(output_iterator<_OutIt, const _CharT&>)
411struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base {
412  using _Size = iter_difference_t<_OutIt>;
413
414public:
415  _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size)
416      : __writer_(std::move(__out_it)), __max_size_(std::max(_Size(0), __max_size)) {}
417
418  _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
419    if (_Size(__size_) <= __max_size_)
420      __writer_.__flush(__ptr, std::min(_Size(__n), __max_size_ - __size_));
421    __size_ += __n;
422  }
423
424protected:
425  __internal_storage<_CharT> __storage_;
426  __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this};
427  typename __writer_selector<_OutIt, _CharT>::type __writer_;
428
429  _Size __max_size_;
430  _Size __size_{0};
431};
432
433/// The base of a buffer that counts and limits the number of insertions.
434///
435/// This version is used when \c __enable_direct_output<_OutIt, _CharT> == true.
436///
437/// This class limits the size available to the direct writer so it will not
438/// exceed the maximum number of code units.
439template <class _OutIt, __fmt_char_type _CharT>
440  requires(output_iterator<_OutIt, const _CharT&>)
441class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base<_OutIt, _CharT, true> {
442  using _Size = iter_difference_t<_OutIt>;
443
444public:
445  _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size)
446      : __output_(std::__unwrap_iter(__out_it), __max_size, this),
447        __writer_(std::move(__out_it)),
448        __max_size_(__max_size) {
449    if (__max_size <= 0) [[unlikely]]
450      __output_.__reset(__storage_.__begin(), __storage_.__buffer_size);
451  }
452
453  _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
454    // A __flush to the direct writer happens in the following occasions:
455    // - The format function has written the maximum number of allowed code
456    //   units. At this point it's no longer valid to write to this writer. So
457    //   switch to the internal storage. This internal storage doesn't need to
458    //   be written anywhere so the __flush for that storage writes no output.
459    // - Like above, but the next "mass write" operation would overflow the
460    //   buffer. In that case the buffer is pre-emptively switched. The still
461    //   valid code units will be written separately.
462    // - The format_to_n function is finished. In this case there's no need to
463    //   switch the buffer, but for simplicity the buffers are still switched.
464    // When the __max_size <= 0 the constructor already switched the buffers.
465    if (__size_ == 0 && __ptr != __storage_.__begin()) {
466      __writer_.__flush(__ptr, __n);
467      __output_.__reset(__storage_.__begin(), __storage_.__buffer_size);
468    } else if (__size_ < __max_size_) {
469      // Copies a part of the internal buffer to the output up to n characters.
470      // See __output_buffer<_CharT>::__flush_on_overflow for more information.
471      _Size __s = std::min(_Size(__n), __max_size_ - __size_);
472      std::copy_n(__ptr, __s, __writer_.__out_it());
473      __writer_.__flush(__ptr, __s);
474    }
475
476    __size_ += __n;
477  }
478
479protected:
480  __internal_storage<_CharT> __storage_;
481  __output_buffer<_CharT> __output_;
482  __writer_direct<_OutIt, _CharT> __writer_;
483
484  _Size __max_size_;
485  _Size __size_{0};
486};
487
488/// The buffer that counts and limits the number of insertions.
489template <class _OutIt, __fmt_char_type _CharT>
490  requires(output_iterator<_OutIt, const _CharT&>)
491struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final
492    : public __format_to_n_buffer_base< _OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>> {
493  using _Base = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>;
494  using _Size = iter_difference_t<_OutIt>;
495
496public:
497  _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __max_size)
498      : _Base(std::move(__out_it), __max_size) {}
499  _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return this->__output_.__make_output_iterator(); }
500
501  _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && {
502    this->__output_.__flush();
503    return {std::move(this->__writer_).__out_it(), this->__size_};
504  }
505};
506
507// A dynamically growing buffer intended to be used for retargeting a context.
508//
509// P2286 Formatting ranges adds range formatting support. It allows the user to
510// specify the minimum width for the entire formatted range.  The width of the
511// range is not known until the range is formatted. Formatting is done to an
512// output_iterator so there's no guarantee it would be possible to add the fill
513// to the front of the output. Instead the range is formatted to a temporary
514// buffer and that buffer is formatted as a string.
515//
516// There is an issue with that approach, the format context used in
517// std::formatter<T>::format contains the output iterator used as part of its
518// type. So using this output iterator means there needs to be a new format
519// context and the format arguments need to be retargeted to the new context.
520// This retargeting is done by a basic_format_context specialized for the
521// __iterator of this container.
522//
523// This class uses its own buffer management, since using vector
524// would lead to a circular include with formatter for vector<bool>.
525template <__fmt_char_type _CharT>
526class _LIBCPP_TEMPLATE_VIS __retarget_buffer {
527  using _Alloc = allocator<_CharT>;
528
529public:
530  using value_type = _CharT;
531
532  struct __iterator {
533    using difference_type = ptrdiff_t;
534    using value_type      = _CharT;
535
536    _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(__retarget_buffer& __buffer)
537        : __buffer_(std::addressof(__buffer)) {}
538    _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(const _CharT& __c) {
539      __buffer_->push_back(__c);
540      return *this;
541    }
542    _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(_CharT&& __c) {
543      __buffer_->push_back(__c);
544      return *this;
545    }
546
547    _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator*() { return *this; }
548    _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { return *this; }
549    _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { return *this; }
550    __retarget_buffer* __buffer_;
551  };
552
553  __retarget_buffer(const __retarget_buffer&)            = delete;
554  __retarget_buffer& operator=(const __retarget_buffer&) = delete;
555
556  _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) {
557    // When the initial size is very small a lot of resizes happen
558    // when elements added. So use a hard-coded minimum size.
559    //
560    // Note a size < 2 will not work
561    // - 0 there is no buffer, while push_back requires 1 empty element.
562    // - 1 multiplied by the grow factor is 1 and thus the buffer never
563    //   grows.
564    auto __result = std::__allocate_at_least(__alloc_, std::max(__size_hint, 256 / sizeof(_CharT)));
565    __ptr_        = __result.ptr;
566    __capacity_   = __result.count;
567  }
568
569  _LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() {
570    ranges::destroy_n(__ptr_, __size_);
571    allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
572  }
573
574  _LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; }
575
576  _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) {
577    std::construct_at(__ptr_ + __size_, __c);
578    ++__size_;
579
580    if (__size_ == __capacity_)
581      __grow_buffer();
582  }
583
584  template <__fmt_char_type _InCharT>
585  _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) {
586    size_t __n = __str.size();
587    if (__size_ + __n >= __capacity_)
588      // Push_back requires the buffer to have room for at least one character.
589      __grow_buffer(__size_ + __n + 1);
590
591    std::uninitialized_copy_n(__str.data(), __n, __ptr_ + __size_);
592    __size_ += __n;
593  }
594
595  template <contiguous_iterator _Iterator,
596            class _UnaryOperation,
597            __fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type>
598  _LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) {
599    _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range");
600
601    size_t __n = static_cast<size_t>(__last - __first);
602    if (__size_ + __n >= __capacity_)
603      // Push_back requires the buffer to have room for at least one character.
604      __grow_buffer(__size_ + __n + 1);
605
606    std::uninitialized_default_construct_n(__ptr_ + __size_, __n);
607    std::transform(__first, __last, __ptr_ + __size_, std::move(__operation));
608    __size_ += __n;
609  }
610
611  _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) {
612    if (__size_ + __n >= __capacity_)
613      // Push_back requires the buffer to have room for at least one character.
614      __grow_buffer(__size_ + __n + 1);
615
616    std::uninitialized_fill_n(__ptr_ + __size_, __n, __value);
617    __size_ += __n;
618  }
619
620  _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, __size_}; }
621
622private:
623  _LIBCPP_HIDE_FROM_ABI void __grow_buffer() { __grow_buffer(__capacity_ * 1.6); }
624
625  _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) {
626    _LIBCPP_ASSERT_INTERNAL(__capacity > __capacity_, "the buffer must grow");
627    auto __result = std::__allocate_at_least(__alloc_, __capacity);
628    auto __guard  = std::__make_exception_guard([&] {
629      allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count);
630    });
631    // This shouldn't throw, but just to be safe. Note that at -O1 this
632    // guard is optimized away so there is no runtime overhead.
633    std::uninitialized_move_n(__ptr_, __size_, __result.ptr);
634    __guard.__complete();
635    ranges::destroy_n(__ptr_, __size_);
636    allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
637
638    __ptr_      = __result.ptr;
639    __capacity_ = __result.count;
640  }
641  _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_;
642  _CharT* __ptr_;
643  size_t __capacity_;
644  size_t __size_{0};
645};
646
647} // namespace __format
648
649#endif //_LIBCPP_STD_VER >= 20
650
651_LIBCPP_END_NAMESPACE_STD
652
653_LIBCPP_POP_MACROS
654
655#endif // _LIBCPP___FORMAT_BUFFER_H
656