master
  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.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.h>
 33#include <__memory/allocator_traits.h>
 34#include <__memory/construct_at.h>
 35#include <__memory/destroy.h>
 36#include <__memory/uninitialized_algorithms.h>
 37#include <__type_traits/add_pointer.h>
 38#include <__type_traits/conditional.h>
 39#include <__utility/exception_guard.h>
 40#include <__utility/move.h>
 41#include <stdexcept>
 42#include <string_view>
 43
 44#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 45#  pragma GCC system_header
 46#endif
 47
 48_LIBCPP_PUSH_MACROS
 49#include <__undef_macros>
 50
 51_LIBCPP_BEGIN_NAMESPACE_STD
 52
 53#if _LIBCPP_STD_VER >= 20
 54
 55namespace __format {
 56
 57// A helper to limit the total size of code units written.
 58class _LIBCPP_HIDE_FROM_ABI __max_output_size {
 59public:
 60  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __max_output_size(size_t __max_size) : __max_size_{__max_size} {}
 61
 62  // This function adjusts the size of a (bulk) write operations. It ensures the
 63  // number of code units written by a __output_buffer never exceeds
 64  // __max_size_ code units.
 65  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __write_request(size_t __code_units) {
 66    size_t __result =
 67        __code_units_written_ < __max_size_ ? std::min(__code_units, __max_size_ - __code_units_written_) : 0;
 68    __code_units_written_ += __code_units;
 69    return __result;
 70  }
 71
 72  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __code_units_written() const noexcept { return __code_units_written_; }
 73
 74private:
 75  size_t __max_size_;
 76  // The code units that would have been written if there was no limit.
 77  // format_to_n returns this value.
 78  size_t __code_units_written_{0};
 79};
 80
 81/// A "buffer" that handles writing to the proper iterator.
 82///
 83/// This helper is used together with the @ref back_insert_iterator to offer
 84/// type-erasure for the formatting functions. This reduces the number to
 85/// template instantiations.
 86///
 87/// The design is the following:
 88/// - There is an external object that connects the buffer to the output.
 89/// - This buffer object:
 90///   - inherits publicly from this class.
 91///   - has a static or dynamic buffer.
 92///   - has a static member function to make space in its buffer write
 93///     operations. This can be done by increasing the size of the internal
 94///     buffer or by writing the contents of the buffer to the output iterator.
 95///
 96///     This member function is a constructor argument, so its name is not
 97///     fixed. The code uses the name __prepare_write.
 98/// - The number of output code units can be limited by a __max_output_size
 99///   object. This is used in format_to_n This object:
100///   - Contains the maximum number of code units to be written.
101///   - Contains the number of code units that are requested to be written.
102///     This number is returned to the user of format_to_n.
103///   - The write functions call the object's __request_write member function.
104///     This function:
105///     - Updates the number of code units that are requested to be written.
106///     - Returns the number of code units that can be written without
107///       exceeding the maximum number of code units to be written.
108///
109/// Documentation for the buffer usage members:
110/// - __ptr_
111///   The start of the buffer.
112/// - __capacity_
113///   The number of code units that can be written. This means
114///   [__ptr_, __ptr_ + __capacity_) is a valid range to write to.
115/// - __size_
116///   The number of code units written in the buffer. The next code unit will
117///   be written at __ptr_ + __size_. This __size_ may NOT contain the total
118///   number of code units written by the __output_buffer. Whether or not it
119///   does depends on the sub-class used. Typically the total number of code
120///   units written is not interesting. It is interesting for format_to_n which
121///   has its own way to track this number.
122///
123/// Documentation for the modifying buffer operations:
124/// The subclasses have a function with the following signature:
125///
126///   static void __prepare_write(
127///     __output_buffer<_CharT>& __buffer, size_t __code_units);
128///
129/// This function is called when a write function writes more code units than
130/// the buffer's available space. When an __max_output_size object is provided
131/// the number of code units is the number of code units returned from
132/// __max_output_size::__request_write function.
133///
134/// - The __buffer contains *this. Since the class containing this function
135///   inherits from __output_buffer it's safe to cast it to the subclass being
136///   used.
137/// - The __code_units is the number of code units the caller will write + 1.
138///   - This value does not take the available space of the buffer into account.
139///   - The push_back function is more efficient when writing before resizing,
140///     this means the buffer should always have room for one code unit. Hence
141///     the + 1 is the size.
142/// - When the function returns there is room for at least one additional code
143///   unit. There is no requirement there is room for __code_units code units:
144///   - The class has some "bulk" operations. For example, __copy which copies
145///     the contents of a basic_string_view to the output. If the sub-class has
146///     a fixed size buffer the size of the basic_string_view may be larger
147///     than the buffer. In that case it's impossible to honor the requested
148///     size.
149///   - When the buffer has room for at least one code unit the function may be
150///     a no-op.
151/// - When the function makes space for more code units it uses one for these
152///   functions to signal the change:
153///   - __buffer_flushed()
154///     - This function is typically used for a fixed sized buffer.
155///     - The current contents of [__ptr_, __ptr_ + __size_) have been
156///       processed.
157///     - __ptr_ remains unchanged.
158///     - __capacity_ remains unchanged.
159///     - __size_ will be set to 0.
160///   - __buffer_moved(_CharT* __ptr, size_t __capacity)
161///     - This function is typically used for a dynamic sized buffer. There the
162///       location of the buffer changes due to reallocations.
163///     - __ptr_ will be set to __ptr. (This value may be the old value of
164///       __ptr_).
165///     - __capacity_ will be set to __capacity. (This value may be the old
166///       value of __capacity_).
167///     - __size_ remains unchanged,
168///     - The range [__ptr, __ptr + __size_) contains the original data of the
169///       range [__ptr_, __ptr_ + __size_).
170///
171/// The push_back function expects a valid buffer and a capacity of at least 1.
172/// This means:
173/// - The class is constructed with a valid buffer,
174/// - __buffer_moved is called with a valid buffer is used before the first
175///   write operation,
176/// - no write function is ever called, or
177/// - the class is constructed with a __max_output_size object with __max_size 0.
178///
179/// The latter option allows formatted_size to use the output buffer without
180/// ever writing anything to the buffer.
181template <__fmt_char_type _CharT>
182class __output_buffer {
183public:
184  using value_type _LIBCPP_NODEBUG           = _CharT;
185  using __prepare_write_type _LIBCPP_NODEBUG = void (*)(__output_buffer<_CharT>&, size_t);
186
187  [[nodiscard]]
188  _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, __prepare_write_type __function)
189      : __output_buffer{__ptr, __capacity, __function, nullptr} {}
190
191  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(
192      _CharT* __ptr, size_t __capacity, __prepare_write_type __function, __max_output_size* __max_output_size)
193      : __ptr_(__ptr), __capacity_(__capacity), __prepare_write_(__function), __max_output_size_(__max_output_size) {}
194
195  _LIBCPP_HIDE_FROM_ABI void __buffer_flushed() { __size_ = 0; }
196
197  _LIBCPP_HIDE_FROM_ABI void __buffer_moved(_CharT* __ptr, size_t __capacity) {
198    __ptr_      = __ptr;
199    __capacity_ = __capacity;
200  }
201
202  _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return std::back_insert_iterator{*this}; }
203
204  // Used in std::back_insert_iterator.
205  _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) {
206    if (__max_output_size_ && __max_output_size_->__write_request(1) == 0)
207      return;
208
209    _LIBCPP_ASSERT_INTERNAL(
210        __ptr_ && __size_ < __capacity_ && __available() >= 1, "attempted to write outside the buffer");
211
212    __ptr_[__size_++] = __c;
213
214    // Profiling showed flushing after adding is more efficient than flushing
215    // when entering the function.
216    if (__size_ == __capacity_)
217      __prepare_write(0);
218  }
219
220  /// Copies the input __str to the buffer.
221  ///
222  /// Since some of the input is generated by std::to_chars, there needs to be a
223  /// conversion when _CharT is wchar_t.
224  template <__fmt_char_type _InCharT>
225  _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) {
226    // When the underlying iterator is a simple iterator the __capacity_ is
227    // infinite. For a string or container back_inserter it isn't. This means
228    // that adding a large string to the buffer can cause some overhead. In that
229    // case a better approach could be:
230    // - flush the buffer
231    // - container.append(__str.begin(), __str.end());
232    // The same holds true for the fill.
233    // For transform it might be slightly harder, however the use case for
234    // transform is slightly less common; it converts hexadecimal values to
235    // upper case. For integral these strings are short.
236    // TODO FMT Look at the improvements above.
237    size_t __n = __str.size();
238    if (__max_output_size_) {
239      __n = __max_output_size_->__write_request(__n);
240      if (__n == 0)
241        return;
242    }
243
244    const _InCharT* __first = __str.data();
245    do {
246      __prepare_write(__n);
247      size_t __chunk = std::min(__n, __available());
248      std::copy_n(__first, __chunk, std::addressof(__ptr_[__size_]));
249      __size_ += __chunk;
250      __first += __chunk;
251      __n -= __chunk;
252    } while (__n);
253  }
254
255  /// A std::transform wrapper.
256  ///
257  /// Like @ref __copy it may need to do type conversion.
258  template <contiguous_iterator _Iterator,
259            class _UnaryOperation,
260            __fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type>
261  _LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) {
262    _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range");
263
264    size_t __n = static_cast<size_t>(__last - __first);
265    if (__max_output_size_) {
266      __n = __max_output_size_->__write_request(__n);
267      if (__n == 0)
268        return;
269    }
270
271    do {
272      __prepare_write(__n);
273      size_t __chunk = std::min(__n, __available());
274      std::transform(__first, __first + __chunk, std::addressof(__ptr_[__size_]), __operation);
275      __size_ += __chunk;
276      __first += __chunk;
277      __n -= __chunk;
278    } while (__n);
279  }
280
281  /// A \c fill_n wrapper.
282  _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) {
283    if (__max_output_size_) {
284      __n = __max_output_size_->__write_request(__n);
285      if (__n == 0)
286        return;
287    }
288
289    do {
290      __prepare_write(__n);
291      size_t __chunk = std::min(__n, __available());
292      std::fill_n(std::addressof(__ptr_[__size_]), __chunk, __value);
293      __size_ += __chunk;
294      __n -= __chunk;
295    } while (__n);
296  }
297
298  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __capacity() const { return __capacity_; }
299  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __size() const { return __size_; }
300
301private:
302  _CharT* __ptr_;
303  size_t __capacity_;
304  size_t __size_{0};
305  void (*__prepare_write_)(__output_buffer<_CharT>&, size_t);
306  __max_output_size* __max_output_size_;
307
308  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __available() const { return __capacity_ - __size_; }
309
310  _LIBCPP_HIDE_FROM_ABI void __prepare_write(size_t __code_units) {
311    // Always have space for one additional code unit. This is a precondition of the push_back function.
312    __code_units += 1;
313    if (__available() < __code_units)
314      __prepare_write_(*this, __code_units + 1);
315  }
316};
317
318template <class _OutIt, class _CharT>
319concept __enable_direct_output =
320    __fmt_char_type<_CharT> &&
321    (same_as<_OutIt, _CharT*>
322     // TODO(hardening): the following check might not apply to hardened iterators and might need to be wrapped in an
323     // `#ifdef`.
324     || same_as<_OutIt, __wrap_iter<_CharT*>>);
325
326/// Concept to see whether a \a _Container is insertable.
327///
328/// The concept is used to validate whether multiple calls to a
329/// \ref back_insert_iterator can be replace by a call to \c _Container::insert.
330///
331/// \note a \a _Container needs to opt-in to the concept by specializing
332/// \ref __enable_insertable.
333template <class _Container>
334concept __insertable =
335    __enable_insertable<_Container> && __fmt_char_type<typename _Container::value_type> &&
336    requires(_Container& __t,
337             add_pointer_t<typename _Container::value_type> __first,
338             add_pointer_t<typename _Container::value_type> __last) { __t.insert(__t.end(), __first, __last); };
339
340/// Extract the container type of a \ref back_insert_iterator.
341template <class _It>
342struct __back_insert_iterator_container {
343  using type _LIBCPP_NODEBUG = void;
344};
345
346template <__insertable _Container>
347struct __back_insert_iterator_container<back_insert_iterator<_Container>> {
348  using type _LIBCPP_NODEBUG = _Container;
349};
350
351// A dynamically growing buffer.
352template <__fmt_char_type _CharT>
353class __allocating_buffer : public __output_buffer<_CharT> {
354public:
355  __allocating_buffer(const __allocating_buffer&)            = delete;
356  __allocating_buffer& operator=(const __allocating_buffer&) = delete;
357
358  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __allocating_buffer() : __allocating_buffer{nullptr} {}
359
360  [[nodiscard]]
361  _LIBCPP_HIDE_FROM_ABI explicit __allocating_buffer(__max_output_size* __max_output_size)
362      : __output_buffer<_CharT>{__small_buffer_, __buffer_size_, __prepare_write, __max_output_size} {}
363
364  _LIBCPP_HIDE_FROM_ABI ~__allocating_buffer() {
365    if (__ptr_ != __small_buffer_)
366      _Alloc{}.deallocate(__ptr_, this->__capacity());
367  }
368
369  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, this->__size()}; }
370
371private:
372  using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>;
373
374  // Since allocating is expensive the class has a small internal buffer. When
375  // its capacity is exceeded a dynamic buffer will be allocated.
376  static constexpr size_t __buffer_size_ = 256;
377  _CharT __small_buffer_[__buffer_size_];
378
379  _CharT* __ptr_{__small_buffer_};
380
381  _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) {
382    if (__capacity < __buffer_size_)
383      return;
384
385    _LIBCPP_ASSERT_INTERNAL(__capacity > this->__capacity(), "the buffer must grow");
386
387    // _CharT is an implicit lifetime type so can be used without explicit
388    // construction or destruction.
389    _Alloc __alloc;
390    auto __result = std::__allocate_at_least(__alloc, __capacity);
391    std::copy_n(__ptr_, this->__size(), __result.ptr);
392    if (__ptr_ != __small_buffer_)
393      __alloc.deallocate(__ptr_, this->__capacity());
394
395    __ptr_ = __result.ptr;
396    this->__buffer_moved(__ptr_, __result.count);
397  }
398
399  _LIBCPP_HIDE_FROM_ABI void __prepare_write(size_t __size_hint) {
400    __grow_buffer(std::max<size_t>(this->__capacity() + __size_hint, this->__capacity() * 1.6));
401  }
402
403  _LIBCPP_HIDE_FROM_ABI static void __prepare_write(__output_buffer<_CharT>& __buffer, size_t __size_hint) {
404    static_cast<__allocating_buffer<_CharT>&>(__buffer).__prepare_write(__size_hint);
405  }
406};
407
408// A buffer that directly writes to the underlying buffer.
409template <class _OutIt, __fmt_char_type _CharT>
410class __direct_iterator_buffer : public __output_buffer<_CharT> {
411public:
412  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it)
413      : __direct_iterator_buffer{__out_it, nullptr} {}
414
415  [[nodiscard]]
416  _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size)
417      : __output_buffer<_CharT>{std::__unwrap_iter(__out_it), __buffer_size, __prepare_write, __max_output_size},
418        __out_it_(__out_it) {}
419
420  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return __out_it_ + this->__size(); }
421
422private:
423  // The function format_to expects a buffer large enough for the output. The
424  // function format_to_n has its own helper class that restricts the number of
425  // write options. So this function class can pretend to have an infinite
426  // buffer.
427  static constexpr size_t __buffer_size = -1;
428
429  _OutIt __out_it_;
430
431  _LIBCPP_HIDE_FROM_ABI static void
432  __prepare_write([[maybe_unused]] __output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) {
433    std::__throw_length_error("__direct_iterator_buffer");
434  }
435};
436
437// A buffer that writes its output to the end of a container.
438template <class _OutIt, __fmt_char_type _CharT>
439class __container_inserter_buffer : public __output_buffer<_CharT> {
440public:
441  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it)
442      : __container_inserter_buffer{__out_it, nullptr} {}
443
444  [[nodiscard]]
445  _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it, __max_output_size* __max_output_size)
446      : __output_buffer<_CharT>{__small_buffer_, __buffer_size, __prepare_write, __max_output_size},
447        __container_{__out_it.__get_container()} {}
448
449  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && {
450    __container_->insert(__container_->end(), __small_buffer_, __small_buffer_ + this->__size());
451    return std::back_inserter(*__container_);
452  }
453
454private:
455  typename __back_insert_iterator_container<_OutIt>::type* __container_;
456
457  // This class uses a fixed size buffer and appends the elements in
458  // __buffer_size chunks. An alternative would be to use an allocating buffer
459  // and append the output in a single write operation. Benchmarking showed no
460  // performance difference.
461  static constexpr size_t __buffer_size = 256;
462  _CharT __small_buffer_[__buffer_size];
463
464  _LIBCPP_HIDE_FROM_ABI void __prepare_write() {
465    __container_->insert(__container_->end(), __small_buffer_, __small_buffer_ + this->__size());
466    this->__buffer_flushed();
467  }
468
469  _LIBCPP_HIDE_FROM_ABI static void
470  __prepare_write(__output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) {
471    static_cast<__container_inserter_buffer<_OutIt, _CharT>&>(__buffer).__prepare_write();
472  }
473};
474
475// A buffer that writes to an iterator.
476//
477// Unlike the __container_inserter_buffer this class' performance does benefit
478// from allocating and then inserting.
479template <class _OutIt, __fmt_char_type _CharT>
480class __iterator_buffer : public __allocating_buffer<_CharT> {
481public:
482  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it)
483      : __allocating_buffer<_CharT>{}, __out_it_{std::move(__out_it)} {}
484
485  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size)
486      : __allocating_buffer<_CharT>{__max_output_size}, __out_it_{std::move(__out_it)} {}
487
488  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && {
489    return std::ranges::copy(this->__view(), std::move(__out_it_)).out;
490  }
491
492private:
493  _OutIt __out_it_;
494};
495
496// Selects the type of the buffer used for the output iterator.
497template <class _OutIt, __fmt_char_type _CharT>
498class __buffer_selector {
499  using _Container _LIBCPP_NODEBUG = __back_insert_iterator_container<_OutIt>::type;
500
501public:
502  using type _LIBCPP_NODEBUG =
503      conditional_t<!same_as<_Container, void>,
504                    __container_inserter_buffer<_OutIt, _CharT>,
505                    conditional_t<__enable_direct_output<_OutIt, _CharT>,
506                                  __direct_iterator_buffer<_OutIt, _CharT>,
507                                  __iterator_buffer<_OutIt, _CharT>>>;
508};
509
510// A buffer that counts and limits the number of insertions.
511template <class _OutIt, __fmt_char_type _CharT>
512class __format_to_n_buffer : private __buffer_selector<_OutIt, _CharT>::type {
513public:
514  using _Base _LIBCPP_NODEBUG = __buffer_selector<_OutIt, _CharT>::type;
515
516  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_to_n_buffer(_OutIt __out_it, iter_difference_t<_OutIt> __n)
517      : _Base{std::move(__out_it), std::addressof(__max_output_size_)},
518        __max_output_size_{__n < 0 ? size_t{0} : static_cast<size_t>(__n)} {}
519
520  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return _Base::__make_output_iterator(); }
521
522  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && {
523    return {static_cast<_Base&&>(*this).__out_it(),
524            static_cast<iter_difference_t<_OutIt>>(__max_output_size_.__code_units_written())};
525  }
526
527private:
528  __max_output_size __max_output_size_;
529};
530
531// A buffer that counts the number of insertions.
532//
533// Since formatted_size only needs to know the size, the output itself is
534// discarded.
535template <__fmt_char_type _CharT>
536class __formatted_size_buffer : private __output_buffer<_CharT> {
537public:
538  using _Base _LIBCPP_NODEBUG = __output_buffer<_CharT>;
539
540  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __formatted_size_buffer()
541      : _Base{nullptr, 0, __prepare_write, std::addressof(__max_output_size_)} {}
542
543  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return _Base::__make_output_iterator(); }
544
545  // This function does not need to be r-value qualified, however this is
546  // consistent with similar objects.
547  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __result() && { return __max_output_size_.__code_units_written(); }
548
549private:
550  __max_output_size __max_output_size_{0};
551
552  _LIBCPP_HIDE_FROM_ABI static void
553  __prepare_write([[maybe_unused]] __output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) {
554    // Note this function does not satisfy the requirement of giving a 1 code unit buffer.
555    _LIBCPP_ASSERT_INTERNAL(
556        false, "Since __max_output_size_.__max_size_ == 0 there should never be call to this function.");
557  }
558};
559
560// A dynamically growing buffer intended to be used for retargeting a context.
561//
562// P2286 Formatting ranges adds range formatting support. It allows the user to
563// specify the minimum width for the entire formatted range.  The width of the
564// range is not known until the range is formatted. Formatting is done to an
565// output_iterator so there's no guarantee it would be possible to add the fill
566// to the front of the output. Instead the range is formatted to a temporary
567// buffer and that buffer is formatted as a string.
568//
569// There is an issue with that approach, the format context used in
570// std::formatter<T>::format contains the output iterator used as part of its
571// type. So using this output iterator means there needs to be a new format
572// context and the format arguments need to be retargeted to the new context.
573// This retargeting is done by a basic_format_context specialized for the
574// __iterator of this container.
575//
576// This class uses its own buffer management, since using vector
577// would lead to a circular include with formatter for vector<bool>.
578template <__fmt_char_type _CharT>
579class __retarget_buffer {
580  using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>;
581
582public:
583  using value_type _LIBCPP_NODEBUG = _CharT;
584
585  struct __iterator {
586    using difference_type _LIBCPP_NODEBUG = ptrdiff_t;
587    using value_type _LIBCPP_NODEBUG      = _CharT;
588
589    _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(__retarget_buffer& __buffer)
590        : __buffer_(std::addressof(__buffer)) {}
591    _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(const _CharT& __c) {
592      __buffer_->push_back(__c);
593      return *this;
594    }
595    _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(_CharT&& __c) {
596      __buffer_->push_back(__c);
597      return *this;
598    }
599
600    _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator*() { return *this; }
601    _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { return *this; }
602    _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { return *this; }
603    __retarget_buffer* __buffer_;
604  };
605
606  __retarget_buffer(const __retarget_buffer&)            = delete;
607  __retarget_buffer& operator=(const __retarget_buffer&) = delete;
608
609  _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) {
610    // When the initial size is very small a lot of resizes happen
611    // when elements added. So use a hard-coded minimum size.
612    //
613    // Note a size < 2 will not work
614    // - 0 there is no buffer, while push_back requires 1 empty element.
615    // - 1 multiplied by the grow factor is 1 and thus the buffer never
616    //   grows.
617    auto __result = std::__allocate_at_least(__alloc_, std::max(__size_hint, 256 / sizeof(_CharT)));
618    __ptr_        = __result.ptr;
619    __capacity_   = __result.count;
620  }
621
622  _LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() {
623    std::destroy_n(__ptr_, __size_);
624    allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
625  }
626
627  _LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; }
628
629  _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) {
630    std::construct_at(__ptr_ + __size_, __c);
631    ++__size_;
632
633    if (__size_ == __capacity_)
634      __grow_buffer();
635  }
636
637  template <__fmt_char_type _InCharT>
638  _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) {
639    size_t __n = __str.size();
640    if (__size_ + __n >= __capacity_)
641      // Push_back requires the buffer to have room for at least one character.
642      __grow_buffer(__size_ + __n + 1);
643
644    std::uninitialized_copy_n(__str.data(), __n, __ptr_ + __size_);
645    __size_ += __n;
646  }
647
648  template <contiguous_iterator _Iterator,
649            class _UnaryOperation,
650            __fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type>
651  _LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) {
652    _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range");
653
654    size_t __n = static_cast<size_t>(__last - __first);
655    if (__size_ + __n >= __capacity_)
656      // Push_back requires the buffer to have room for at least one character.
657      __grow_buffer(__size_ + __n + 1);
658
659    std::uninitialized_default_construct_n(__ptr_ + __size_, __n);
660    std::transform(__first, __last, __ptr_ + __size_, std::move(__operation));
661    __size_ += __n;
662  }
663
664  _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) {
665    if (__size_ + __n >= __capacity_)
666      // Push_back requires the buffer to have room for at least one character.
667      __grow_buffer(__size_ + __n + 1);
668
669    std::uninitialized_fill_n(__ptr_ + __size_, __n, __value);
670    __size_ += __n;
671  }
672
673  _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, __size_}; }
674
675private:
676  _LIBCPP_HIDE_FROM_ABI void __grow_buffer() { __grow_buffer(__capacity_ * 1.6); }
677
678  _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) {
679    _LIBCPP_ASSERT_INTERNAL(__capacity > __capacity_, "the buffer must grow");
680    auto __result = std::__allocate_at_least(__alloc_, __capacity);
681    auto __guard  = std::__make_exception_guard([&] {
682      allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count);
683    });
684    // This shouldn't throw, but just to be safe. Note that at -O1 this
685    // guard is optimized away so there is no runtime overhead.
686    std::uninitialized_move_n(__ptr_, __size_, __result.ptr);
687    __guard.__complete();
688    std::destroy_n(__ptr_, __size_);
689    allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
690
691    __ptr_      = __result.ptr;
692    __capacity_ = __result.count;
693  }
694  _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_;
695  _CharT* __ptr_;
696  size_t __capacity_;
697  size_t __size_{0};
698};
699
700} // namespace __format
701
702#endif // _LIBCPP_STD_VER >= 20
703
704_LIBCPP_END_NAMESPACE_STD
705
706_LIBCPP_POP_MACROS
707
708#endif // _LIBCPP___FORMAT_BUFFER_H