File indexing completed on 2026-05-03 08:13:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___CXX03___FORMAT_BUFFER_H
0011 #define _LIBCPP___CXX03___FORMAT_BUFFER_H
0012
0013 #include <__cxx03/__algorithm/copy_n.h>
0014 #include <__cxx03/__algorithm/fill_n.h>
0015 #include <__cxx03/__algorithm/max.h>
0016 #include <__cxx03/__algorithm/min.h>
0017 #include <__cxx03/__algorithm/ranges_copy_n.h>
0018 #include <__cxx03/__algorithm/transform.h>
0019 #include <__cxx03/__algorithm/unwrap_iter.h>
0020 #include <__cxx03/__concepts/same_as.h>
0021 #include <__cxx03/__config>
0022 #include <__cxx03/__format/concepts.h>
0023 #include <__cxx03/__format/enable_insertable.h>
0024 #include <__cxx03/__format/format_to_n_result.h>
0025 #include <__cxx03/__iterator/back_insert_iterator.h>
0026 #include <__cxx03/__iterator/concepts.h>
0027 #include <__cxx03/__iterator/incrementable_traits.h>
0028 #include <__cxx03/__iterator/iterator_traits.h>
0029 #include <__cxx03/__iterator/wrap_iter.h>
0030 #include <__cxx03/__memory/addressof.h>
0031 #include <__cxx03/__memory/allocate_at_least.h>
0032 #include <__cxx03/__memory/allocator_traits.h>
0033 #include <__cxx03/__memory/construct_at.h>
0034 #include <__cxx03/__memory/ranges_construct_at.h>
0035 #include <__cxx03/__memory/uninitialized_algorithms.h>
0036 #include <__cxx03/__type_traits/add_pointer.h>
0037 #include <__cxx03/__type_traits/conditional.h>
0038 #include <__cxx03/__utility/exception_guard.h>
0039 #include <__cxx03/__utility/move.h>
0040 #include <__cxx03/cstddef>
0041 #include <__cxx03/string_view>
0042
0043 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0044 # pragma GCC system_header
0045 #endif
0046
0047 _LIBCPP_PUSH_MACROS
0048 #include <__cxx03/__undef_macros>
0049
0050 _LIBCPP_BEGIN_NAMESPACE_STD
0051
0052 #if _LIBCPP_STD_VER >= 20
0053
0054 namespace __format {
0055
0056
0057
0058
0059
0060
0061 template <__fmt_char_type _CharT>
0062 class _LIBCPP_TEMPLATE_VIS __output_buffer {
0063 public:
0064 using value_type = _CharT;
0065
0066 template <class _Tp>
0067 _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, _Tp* __obj)
0068 : __ptr_(__ptr),
0069 __capacity_(__capacity),
0070 __flush_([](_CharT* __p, size_t __n, void* __o) { static_cast<_Tp*>(__o)->__flush(__p, __n); }),
0071 __obj_(__obj) {}
0072
0073 _LIBCPP_HIDE_FROM_ABI void __reset(_CharT* __ptr, size_t __capacity) {
0074 __ptr_ = __ptr;
0075 __capacity_ = __capacity;
0076 }
0077
0078 _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return std::back_insert_iterator{*this}; }
0079
0080
0081 _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) {
0082 __ptr_[__size_++] = __c;
0083
0084
0085
0086 if (__size_ == __capacity_)
0087 __flush();
0088 }
0089
0090
0091
0092
0093
0094 template <__fmt_char_type _InCharT>
0095 _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) {
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 size_t __n = __str.size();
0108
0109 __flush_on_overflow(__n);
0110 if (__n < __capacity_) {
0111 std::copy_n(__str.data(), __n, std::addressof(__ptr_[__size_]));
0112 __size_ += __n;
0113 return;
0114 }
0115
0116
0117
0118 _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow");
0119 const _InCharT* __first = __str.data();
0120 do {
0121 size_t __chunk = std::min(__n, __capacity_);
0122 std::copy_n(__first, __chunk, std::addressof(__ptr_[__size_]));
0123 __size_ = __chunk;
0124 __first += __chunk;
0125 __n -= __chunk;
0126 __flush();
0127 } while (__n);
0128 }
0129
0130
0131
0132
0133 template <contiguous_iterator _Iterator,
0134 class _UnaryOperation,
0135 __fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type>
0136 _LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) {
0137 _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range");
0138
0139 size_t __n = static_cast<size_t>(__last - __first);
0140 __flush_on_overflow(__n);
0141 if (__n < __capacity_) {
0142 std::transform(__first, __last, std::addressof(__ptr_[__size_]), std::move(__operation));
0143 __size_ += __n;
0144 return;
0145 }
0146
0147
0148
0149 _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow");
0150 do {
0151 size_t __chunk = std::min(__n, __capacity_);
0152 std::transform(__first, __first + __chunk, std::addressof(__ptr_[__size_]), __operation);
0153 __size_ = __chunk;
0154 __first += __chunk;
0155 __n -= __chunk;
0156 __flush();
0157 } while (__n);
0158 }
0159
0160
0161 _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) {
0162 __flush_on_overflow(__n);
0163 if (__n < __capacity_) {
0164 std::fill_n(std::addressof(__ptr_[__size_]), __n, __value);
0165 __size_ += __n;
0166 return;
0167 }
0168
0169
0170
0171 _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow");
0172 do {
0173 size_t __chunk = std::min(__n, __capacity_);
0174 std::fill_n(std::addressof(__ptr_[__size_]), __chunk, __value);
0175 __size_ = __chunk;
0176 __n -= __chunk;
0177 __flush();
0178 } while (__n);
0179 }
0180
0181 _LIBCPP_HIDE_FROM_ABI void __flush() {
0182 __flush_(__ptr_, __size_, __obj_);
0183 __size_ = 0;
0184 }
0185
0186 private:
0187 _CharT* __ptr_;
0188 size_t __capacity_;
0189 size_t __size_{0};
0190 void (*__flush_)(_CharT*, size_t, void*);
0191 void* __obj_;
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 _LIBCPP_HIDE_FROM_ABI void __flush_on_overflow(size_t __n) {
0227 if (__size_ + __n >= __capacity_)
0228 __flush();
0229 }
0230 };
0231
0232
0233
0234
0235
0236 template <__fmt_char_type _CharT>
0237 class _LIBCPP_TEMPLATE_VIS __internal_storage {
0238 public:
0239 _LIBCPP_HIDE_FROM_ABI _CharT* __begin() { return __buffer_; }
0240
0241 static constexpr size_t __buffer_size = 256 / sizeof(_CharT);
0242
0243 private:
0244 _CharT __buffer_[__buffer_size];
0245 };
0246
0247
0248
0249
0250
0251
0252 template <__fmt_char_type _CharT>
0253 class _LIBCPP_TEMPLATE_VIS __direct_storage {};
0254
0255 template <class _OutIt, class _CharT>
0256 concept __enable_direct_output =
0257 __fmt_char_type<_CharT> &&
0258 (same_as<_OutIt, _CharT*>
0259
0260
0261 || same_as<_OutIt, __wrap_iter<_CharT*>>);
0262
0263
0264 template <class _OutIt, __fmt_char_type _CharT>
0265 class _LIBCPP_TEMPLATE_VIS __writer_direct {
0266 public:
0267 _LIBCPP_HIDE_FROM_ABI explicit __writer_direct(_OutIt __out_it) : __out_it_(__out_it) {}
0268
0269 _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() { return __out_it_; }
0270
0271 _LIBCPP_HIDE_FROM_ABI void __flush(_CharT*, size_t __n) {
0272
0273
0274 __out_it_ += __n;
0275 }
0276
0277 private:
0278 _OutIt __out_it_;
0279 };
0280
0281
0282 template <class _OutIt, __fmt_char_type _CharT>
0283 class _LIBCPP_TEMPLATE_VIS __writer_iterator {
0284 public:
0285 _LIBCPP_HIDE_FROM_ABI explicit __writer_iterator(_OutIt __out_it) : __out_it_{std::move(__out_it)} {}
0286
0287 _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return std::move(__out_it_); }
0288
0289 _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
0290 __out_it_ = std::ranges::copy_n(__ptr, __n, std::move(__out_it_)).out;
0291 }
0292
0293 private:
0294 _OutIt __out_it_;
0295 };
0296
0297
0298
0299
0300
0301
0302
0303
0304 template <class _Container>
0305 concept __insertable =
0306 __enable_insertable<_Container> && __fmt_char_type<typename _Container::value_type> &&
0307 requires(_Container& __t,
0308 add_pointer_t<typename _Container::value_type> __first,
0309 add_pointer_t<typename _Container::value_type> __last) { __t.insert(__t.end(), __first, __last); };
0310
0311
0312 template <class _It>
0313 struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container {
0314 using type = void;
0315 };
0316
0317 template <__insertable _Container>
0318 struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container<back_insert_iterator<_Container>> {
0319 using type = _Container;
0320 };
0321
0322
0323 template <class _Container>
0324 class _LIBCPP_TEMPLATE_VIS __writer_container {
0325 public:
0326 using _CharT = typename _Container::value_type;
0327
0328 _LIBCPP_HIDE_FROM_ABI explicit __writer_container(back_insert_iterator<_Container> __out_it)
0329 : __container_{__out_it.__get_container()} {}
0330
0331 _LIBCPP_HIDE_FROM_ABI auto __out_it() { return std::back_inserter(*__container_); }
0332
0333 _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
0334 __container_->insert(__container_->end(), __ptr, __ptr + __n);
0335 }
0336
0337 private:
0338 _Container* __container_;
0339 };
0340
0341
0342 template <class _OutIt, class _CharT>
0343 class _LIBCPP_TEMPLATE_VIS __writer_selector {
0344 using _Container = typename __back_insert_iterator_container<_OutIt>::type;
0345
0346 public:
0347 using type =
0348 conditional_t<!same_as<_Container, void>,
0349 __writer_container<_Container>,
0350 conditional_t<__enable_direct_output<_OutIt, _CharT>,
0351 __writer_direct<_OutIt, _CharT>,
0352 __writer_iterator<_OutIt, _CharT>>>;
0353 };
0354
0355
0356 template <class _OutIt, __fmt_char_type _CharT>
0357 requires(output_iterator<_OutIt, const _CharT&>)
0358 class _LIBCPP_TEMPLATE_VIS __format_buffer {
0359 using _Storage =
0360 conditional_t<__enable_direct_output<_OutIt, _CharT>, __direct_storage<_CharT>, __internal_storage<_CharT>>;
0361
0362 public:
0363 _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it)
0364 requires(same_as<_Storage, __internal_storage<_CharT>>)
0365 : __output_(__storage_.__begin(), __storage_.__buffer_size, this), __writer_(std::move(__out_it)) {}
0366
0367 _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it)
0368 requires(same_as<_Storage, __direct_storage<_CharT>>)
0369 : __output_(std::__unwrap_iter(__out_it), size_t(-1), this), __writer_(std::move(__out_it)) {}
0370
0371 _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return __output_.__make_output_iterator(); }
0372
0373 _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { __writer_.__flush(__ptr, __n); }
0374
0375 _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && {
0376 __output_.__flush();
0377 return std::move(__writer_).__out_it();
0378 }
0379
0380 private:
0381 _LIBCPP_NO_UNIQUE_ADDRESS _Storage __storage_;
0382 __output_buffer<_CharT> __output_;
0383 typename __writer_selector<_OutIt, _CharT>::type __writer_;
0384 };
0385
0386
0387
0388
0389
0390 template <__fmt_char_type _CharT>
0391 class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer {
0392 public:
0393 _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return __output_.__make_output_iterator(); }
0394
0395 _LIBCPP_HIDE_FROM_ABI void __flush(const _CharT*, size_t __n) { __size_ += __n; }
0396
0397 _LIBCPP_HIDE_FROM_ABI size_t __result() && {
0398 __output_.__flush();
0399 return __size_;
0400 }
0401
0402 private:
0403 __internal_storage<_CharT> __storage_;
0404 __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this};
0405 size_t __size_{0};
0406 };
0407
0408
0409 template <class _OutIt, __fmt_char_type _CharT, bool>
0410 requires(output_iterator<_OutIt, const _CharT&>)
0411 struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base {
0412 using _Size = iter_difference_t<_OutIt>;
0413
0414 public:
0415 _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size)
0416 : __writer_(std::move(__out_it)), __max_size_(std::max(_Size(0), __max_size)) {}
0417
0418 _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
0419 if (_Size(__size_) <= __max_size_)
0420 __writer_.__flush(__ptr, std::min(_Size(__n), __max_size_ - __size_));
0421 __size_ += __n;
0422 }
0423
0424 protected:
0425 __internal_storage<_CharT> __storage_;
0426 __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this};
0427 typename __writer_selector<_OutIt, _CharT>::type __writer_;
0428
0429 _Size __max_size_;
0430 _Size __size_{0};
0431 };
0432
0433
0434
0435
0436
0437
0438
0439 template <class _OutIt, __fmt_char_type _CharT>
0440 requires(output_iterator<_OutIt, const _CharT&>)
0441 class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base<_OutIt, _CharT, true> {
0442 using _Size = iter_difference_t<_OutIt>;
0443
0444 public:
0445 _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size)
0446 : __output_(std::__unwrap_iter(__out_it), __max_size, this),
0447 __writer_(std::move(__out_it)),
0448 __max_size_(__max_size) {
0449 if (__max_size <= 0) [[unlikely]]
0450 __output_.__reset(__storage_.__begin(), __storage_.__buffer_size);
0451 }
0452
0453 _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) {
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465 if (__size_ == 0 && __ptr != __storage_.__begin()) {
0466 __writer_.__flush(__ptr, __n);
0467 __output_.__reset(__storage_.__begin(), __storage_.__buffer_size);
0468 } else if (__size_ < __max_size_) {
0469
0470
0471 _Size __s = std::min(_Size(__n), __max_size_ - __size_);
0472 std::copy_n(__ptr, __s, __writer_.__out_it());
0473 __writer_.__flush(__ptr, __s);
0474 }
0475
0476 __size_ += __n;
0477 }
0478
0479 protected:
0480 __internal_storage<_CharT> __storage_;
0481 __output_buffer<_CharT> __output_;
0482 __writer_direct<_OutIt, _CharT> __writer_;
0483
0484 _Size __max_size_;
0485 _Size __size_{0};
0486 };
0487
0488
0489 template <class _OutIt, __fmt_char_type _CharT>
0490 requires(output_iterator<_OutIt, const _CharT&>)
0491 struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final
0492 : public __format_to_n_buffer_base< _OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>> {
0493 using _Base = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>;
0494 using _Size = iter_difference_t<_OutIt>;
0495
0496 public:
0497 _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __max_size)
0498 : _Base(std::move(__out_it), __max_size) {}
0499 _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return this->__output_.__make_output_iterator(); }
0500
0501 _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && {
0502 this->__output_.__flush();
0503 return {std::move(this->__writer_).__out_it(), this->__size_};
0504 }
0505 };
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525 template <__fmt_char_type _CharT>
0526 class _LIBCPP_TEMPLATE_VIS __retarget_buffer {
0527 using _Alloc = allocator<_CharT>;
0528
0529 public:
0530 using value_type = _CharT;
0531
0532 struct __iterator {
0533 using difference_type = ptrdiff_t;
0534 using value_type = _CharT;
0535
0536 _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(__retarget_buffer& __buffer)
0537 : __buffer_(std::addressof(__buffer)) {}
0538 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(const _CharT& __c) {
0539 __buffer_->push_back(__c);
0540 return *this;
0541 }
0542 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(_CharT&& __c) {
0543 __buffer_->push_back(__c);
0544 return *this;
0545 }
0546
0547 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator*() { return *this; }
0548 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { return *this; }
0549 _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { return *this; }
0550 __retarget_buffer* __buffer_;
0551 };
0552
0553 __retarget_buffer(const __retarget_buffer&) = delete;
0554 __retarget_buffer& operator=(const __retarget_buffer&) = delete;
0555
0556 _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) {
0557
0558
0559
0560
0561
0562
0563
0564 auto __result = std::__allocate_at_least(__alloc_, std::max(__size_hint, 256 / sizeof(_CharT)));
0565 __ptr_ = __result.ptr;
0566 __capacity_ = __result.count;
0567 }
0568
0569 _LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() {
0570 ranges::destroy_n(__ptr_, __size_);
0571 allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
0572 }
0573
0574 _LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; }
0575
0576 _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) {
0577 std::construct_at(__ptr_ + __size_, __c);
0578 ++__size_;
0579
0580 if (__size_ == __capacity_)
0581 __grow_buffer();
0582 }
0583
0584 template <__fmt_char_type _InCharT>
0585 _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) {
0586 size_t __n = __str.size();
0587 if (__size_ + __n >= __capacity_)
0588
0589 __grow_buffer(__size_ + __n + 1);
0590
0591 std::uninitialized_copy_n(__str.data(), __n, __ptr_ + __size_);
0592 __size_ += __n;
0593 }
0594
0595 template <contiguous_iterator _Iterator,
0596 class _UnaryOperation,
0597 __fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type>
0598 _LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) {
0599 _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range");
0600
0601 size_t __n = static_cast<size_t>(__last - __first);
0602 if (__size_ + __n >= __capacity_)
0603
0604 __grow_buffer(__size_ + __n + 1);
0605
0606 std::uninitialized_default_construct_n(__ptr_ + __size_, __n);
0607 std::transform(__first, __last, __ptr_ + __size_, std::move(__operation));
0608 __size_ += __n;
0609 }
0610
0611 _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) {
0612 if (__size_ + __n >= __capacity_)
0613
0614 __grow_buffer(__size_ + __n + 1);
0615
0616 std::uninitialized_fill_n(__ptr_ + __size_, __n, __value);
0617 __size_ += __n;
0618 }
0619
0620 _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, __size_}; }
0621
0622 private:
0623 _LIBCPP_HIDE_FROM_ABI void __grow_buffer() { __grow_buffer(__capacity_ * 1.6); }
0624
0625 _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) {
0626 _LIBCPP_ASSERT_INTERNAL(__capacity > __capacity_, "the buffer must grow");
0627 auto __result = std::__allocate_at_least(__alloc_, __capacity);
0628 auto __guard = std::__make_exception_guard([&] {
0629 allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count);
0630 });
0631
0632
0633 std::uninitialized_move_n(__ptr_, __size_, __result.ptr);
0634 __guard.__complete();
0635 ranges::destroy_n(__ptr_, __size_);
0636 allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
0637
0638 __ptr_ = __result.ptr;
0639 __capacity_ = __result.count;
0640 }
0641 _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_;
0642 _CharT* __ptr_;
0643 size_t __capacity_;
0644 size_t __size_{0};
0645 };
0646
0647 }
0648
0649 #endif
0650
0651 _LIBCPP_END_NAMESPACE_STD
0652
0653 _LIBCPP_POP_MACROS
0654
0655 #endif