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___SPLIT_BUFFER 11#define _LIBCPP___SPLIT_BUFFER 12 13#include <__algorithm/max.h> 14#include <__algorithm/move.h> 15#include <__algorithm/move_backward.h> 16#include <__config> 17#include <__iterator/distance.h> 18#include <__iterator/iterator_traits.h> 19#include <__iterator/move_iterator.h> 20#include <__memory/allocate_at_least.h> 21#include <__memory/allocator.h> 22#include <__memory/allocator_traits.h> 23#include <__memory/compressed_pair.h> 24#include <__memory/pointer_traits.h> 25#include <__memory/swap_allocator.h> 26#include <__utility/forward.h> 27#include <__utility/move.h> 28#include <type_traits> 29 30#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 31# pragma GCC system_header 32#endif 33 34_LIBCPP_PUSH_MACROS 35#include <__undef_macros> 36 37 38_LIBCPP_BEGIN_NAMESPACE_STD 39 40// __split_buffer allocates a contiguous chunk of memory and stores objects in the range [__begin_, __end_). 41// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __end_cap_.first()). That allows 42// it to grow both in the front and back without having to move the data. 43 44template <class _Tp, class _Allocator = allocator<_Tp> > 45struct __split_buffer 46{ 47private: 48 __split_buffer(const __split_buffer&); 49 __split_buffer& operator=(const __split_buffer&); 50public: 51 typedef _Tp value_type; 52 typedef _Allocator allocator_type; 53 typedef __libcpp_remove_reference_t<allocator_type> __alloc_rr; 54 typedef allocator_traits<__alloc_rr> __alloc_traits; 55 typedef value_type& reference; 56 typedef const value_type& const_reference; 57 typedef typename __alloc_traits::size_type size_type; 58 typedef typename __alloc_traits::difference_type difference_type; 59 typedef typename __alloc_traits::pointer pointer; 60 typedef typename __alloc_traits::const_pointer const_pointer; 61 typedef pointer iterator; 62 typedef const_pointer const_iterator; 63 64 pointer __first_; 65 pointer __begin_; 66 pointer __end_; 67 __compressed_pair<pointer, allocator_type> __end_cap_; 68 69 typedef __add_lvalue_reference_t<allocator_type> __alloc_ref; 70 typedef __add_lvalue_reference_t<allocator_type> __alloc_const_ref; 71 72 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __alloc_rr& __alloc() _NOEXCEPT {return __end_cap_.second();} 73 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const __alloc_rr& __alloc() const _NOEXCEPT {return __end_cap_.second();} 74 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT {return __end_cap_.first();} 75 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT {return __end_cap_.first();} 76 77 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 78 __split_buffer() 79 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value); 80 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 81 explicit __split_buffer(__alloc_rr& __a); 82 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 83 explicit __split_buffer(const __alloc_rr& __a); 84 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); 85 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer(); 86 87 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c) 88 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value); 89 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); 90 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer& operator=(__split_buffer&& __c) 91 _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && 92 is_nothrow_move_assignable<allocator_type>::value) || 93 !__alloc_traits::propagate_on_container_move_assignment::value); 94 95 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {return __begin_;} 96 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {return __begin_;} 97 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {return __end_;} 98 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT {return __end_;} 99 100 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 101 void clear() _NOEXCEPT 102 {__destruct_at_end(__begin_);} 103 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const {return static_cast<size_type>(__end_ - __begin_);} 104 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const {return __end_ == __begin_;} 105 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const {return static_cast<size_type>(__end_cap() - __first_);} 106 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const {return static_cast<size_type>(__begin_ - __first_);} 107 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const {return static_cast<size_type>(__end_cap() - __end_);} 108 109 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() {return *__begin_;} 110 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const {return *__begin_;} 111 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() {return *(__end_ - 1);} 112 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const {return *(__end_ - 1);} 113 114 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); 115 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; 116 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(const_reference __x); 117 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x); 118 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x); 119 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x); 120 template <class... _Args> 121 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args); 122 123 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() {__destruct_at_begin(__begin_+1);} 124 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {__destruct_at_end(__end_-1);} 125 126 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n); 127 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x); 128 template <class _InputIter> 129 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> 130 __construct_at_end(_InputIter __first, _InputIter __last); 131 template <class _ForwardIterator> 132 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> 133 __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); 134 135 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin) 136 {__destruct_at_begin(__new_begin, is_trivially_destructible<value_type>());} 137 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 138 void __destruct_at_begin(pointer __new_begin, false_type); 139 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 140 void __destruct_at_begin(pointer __new_begin, true_type); 141 142 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 143 void __destruct_at_end(pointer __new_last) _NOEXCEPT 144 {__destruct_at_end(__new_last, false_type());} 145 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 146 void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT; 147 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 148 void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT; 149 150 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x) 151 _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| 152 __is_nothrow_swappable<__alloc_rr>::value); 153 154 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const; 155 156private: 157 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 158 void __move_assign_alloc(__split_buffer& __c, true_type) 159 _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) 160 { 161 __alloc() = _VSTD::move(__c.__alloc()); 162 } 163 164 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 165 void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT 166 {} 167 168 struct _ConstructTransaction { 169 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT 170 : __pos_(*__p), __end_(*__p + __n), __dest_(__p) { 171 } 172 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { 173 *__dest_ = __pos_; 174 } 175 pointer __pos_; 176 const pointer __end_; 177 private: 178 pointer *__dest_; 179 }; 180}; 181 182template <class _Tp, class _Allocator> 183_LIBCPP_CONSTEXPR_SINCE_CXX20 184bool 185__split_buffer<_Tp, _Allocator>::__invariants() const 186{ 187 if (__first_ == nullptr) 188 { 189 if (__begin_ != nullptr) 190 return false; 191 if (__end_ != nullptr) 192 return false; 193 if (__end_cap() != nullptr) 194 return false; 195 } 196 else 197 { 198 if (__begin_ < __first_) 199 return false; 200 if (__end_ < __begin_) 201 return false; 202 if (__end_cap() < __end_) 203 return false; 204 } 205 return true; 206} 207 208// Default constructs __n objects starting at __end_ 209// throws if construction throws 210// Precondition: __n > 0 211// Precondition: size() + __n <= capacity() 212// Postcondition: size() == size() + __n 213template <class _Tp, class _Allocator> 214_LIBCPP_CONSTEXPR_SINCE_CXX20 215void 216__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) 217{ 218 _ConstructTransaction __tx(&this->__end_, __n); 219 for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { 220 __alloc_traits::construct(this->__alloc(), _VSTD::__to_address(__tx.__pos_)); 221 } 222} 223 224// Copy constructs __n objects starting at __end_ from __x 225// throws if construction throws 226// Precondition: __n > 0 227// Precondition: size() + __n <= capacity() 228// Postcondition: size() == old size() + __n 229// Postcondition: [i] == __x for all i in [size() - __n, __n) 230template <class _Tp, class _Allocator> 231_LIBCPP_CONSTEXPR_SINCE_CXX20 232void 233__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) 234{ 235 _ConstructTransaction __tx(&this->__end_, __n); 236 for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { 237 __alloc_traits::construct(this->__alloc(), 238 _VSTD::__to_address(__tx.__pos_), __x); 239 } 240} 241 242template <class _Tp, class _Allocator> 243template <class _InputIter> 244_LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> 245__split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIter __last) 246{ 247 __alloc_rr& __a = this->__alloc(); 248 for (; __first != __last; ++__first) 249 { 250 if (__end_ == __end_cap()) 251 { 252 size_type __old_cap = __end_cap() - __first_; 253 size_type __new_cap = _VSTD::max<size_type>(2 * __old_cap, 8); 254 __split_buffer __buf(__new_cap, 0, __a); 255 for (pointer __p = __begin_; __p != __end_; ++__p, (void) ++__buf.__end_) 256 __alloc_traits::construct(__buf.__alloc(), 257 _VSTD::__to_address(__buf.__end_), _VSTD::move(*__p)); 258 swap(__buf); 259 } 260 __alloc_traits::construct(__a, _VSTD::__to_address(this->__end_), *__first); 261 ++this->__end_; 262 } 263} 264 265template <class _Tp, class _Allocator> 266template <class _ForwardIterator> 267_LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> 268__split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) 269{ 270 _ConstructTransaction __tx(&this->__end_, _VSTD::distance(__first, __last)); 271 for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void) ++__first) { 272 __alloc_traits::construct(this->__alloc(), 273 _VSTD::__to_address(__tx.__pos_), *__first); 274 } 275} 276 277template <class _Tp, class _Allocator> 278_LIBCPP_CONSTEXPR_SINCE_CXX20 279inline 280void 281__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) 282{ 283 while (__begin_ != __new_begin) 284 __alloc_traits::destroy(__alloc(), _VSTD::__to_address(__begin_++)); 285} 286 287template <class _Tp, class _Allocator> 288_LIBCPP_CONSTEXPR_SINCE_CXX20 289inline 290void 291__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type) 292{ 293 __begin_ = __new_begin; 294} 295 296template <class _Tp, class _Allocator> 297_LIBCPP_CONSTEXPR_SINCE_CXX20 298inline _LIBCPP_HIDE_FROM_ABI 299void 300__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT 301{ 302 while (__new_last != __end_) 303 __alloc_traits::destroy(__alloc(), _VSTD::__to_address(--__end_)); 304} 305 306template <class _Tp, class _Allocator> 307_LIBCPP_CONSTEXPR_SINCE_CXX20 308inline _LIBCPP_HIDE_FROM_ABI 309void 310__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type) _NOEXCEPT 311{ 312 __end_ = __new_last; 313} 314 315template <class _Tp, class _Allocator> 316_LIBCPP_CONSTEXPR_SINCE_CXX20 317__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a) 318 : __end_cap_(nullptr, __a) 319{ 320 if (__cap == 0) { 321 __first_ = nullptr; 322 } else { 323 auto __allocation = std::__allocate_at_least(__alloc(), __cap); 324 __first_ = __allocation.ptr; 325 __cap = __allocation.count; 326 } 327 __begin_ = __end_ = __first_ + __start; 328 __end_cap() = __first_ + __cap; 329} 330 331template <class _Tp, class _Allocator> 332_LIBCPP_CONSTEXPR_SINCE_CXX20 333inline 334__split_buffer<_Tp, _Allocator>::__split_buffer() 335 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) 336 : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __default_init_tag()) 337{ 338} 339 340template <class _Tp, class _Allocator> 341_LIBCPP_CONSTEXPR_SINCE_CXX20 342inline 343__split_buffer<_Tp, _Allocator>::__split_buffer(__alloc_rr& __a) 344 : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) 345{ 346} 347 348template <class _Tp, class _Allocator> 349_LIBCPP_CONSTEXPR_SINCE_CXX20 350inline 351__split_buffer<_Tp, _Allocator>::__split_buffer(const __alloc_rr& __a) 352 : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) 353{ 354} 355 356template <class _Tp, class _Allocator> 357_LIBCPP_CONSTEXPR_SINCE_CXX20 358__split_buffer<_Tp, _Allocator>::~__split_buffer() 359{ 360 clear(); 361 if (__first_) 362 __alloc_traits::deallocate(__alloc(), __first_, capacity()); 363} 364 365template <class _Tp, class _Allocator> 366_LIBCPP_CONSTEXPR_SINCE_CXX20 367__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c) 368 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value) 369 : __first_(_VSTD::move(__c.__first_)), 370 __begin_(_VSTD::move(__c.__begin_)), 371 __end_(_VSTD::move(__c.__end_)), 372 __end_cap_(_VSTD::move(__c.__end_cap_)) 373{ 374 __c.__first_ = nullptr; 375 __c.__begin_ = nullptr; 376 __c.__end_ = nullptr; 377 __c.__end_cap() = nullptr; 378} 379 380template <class _Tp, class _Allocator> 381_LIBCPP_CONSTEXPR_SINCE_CXX20 382__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a) 383 : __end_cap_(nullptr, __a) 384{ 385 if (__a == __c.__alloc()) 386 { 387 __first_ = __c.__first_; 388 __begin_ = __c.__begin_; 389 __end_ = __c.__end_; 390 __end_cap() = __c.__end_cap(); 391 __c.__first_ = nullptr; 392 __c.__begin_ = nullptr; 393 __c.__end_ = nullptr; 394 __c.__end_cap() = nullptr; 395 } 396 else 397 { 398 auto __allocation = std::__allocate_at_least(__alloc(), __c.size()); 399 __first_ = __allocation.ptr; 400 __begin_ = __end_ = __first_; 401 __end_cap() = __first_ + __allocation.count; 402 typedef move_iterator<iterator> _Ip; 403 __construct_at_end(_Ip(__c.begin()), _Ip(__c.end())); 404 } 405} 406 407template <class _Tp, class _Allocator> 408_LIBCPP_CONSTEXPR_SINCE_CXX20 409__split_buffer<_Tp, _Allocator>& 410__split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) 411 _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && 412 is_nothrow_move_assignable<allocator_type>::value) || 413 !__alloc_traits::propagate_on_container_move_assignment::value) 414{ 415 clear(); 416 shrink_to_fit(); 417 __first_ = __c.__first_; 418 __begin_ = __c.__begin_; 419 __end_ = __c.__end_; 420 __end_cap() = __c.__end_cap(); 421 __move_assign_alloc(__c, 422 integral_constant<bool, 423 __alloc_traits::propagate_on_container_move_assignment::value>()); 424 __c.__first_ = __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr; 425 return *this; 426} 427 428template <class _Tp, class _Allocator> 429_LIBCPP_CONSTEXPR_SINCE_CXX20 430void 431__split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x) 432 _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| 433 __is_nothrow_swappable<__alloc_rr>::value) 434{ 435 _VSTD::swap(__first_, __x.__first_); 436 _VSTD::swap(__begin_, __x.__begin_); 437 _VSTD::swap(__end_, __x.__end_); 438 _VSTD::swap(__end_cap(), __x.__end_cap()); 439 _VSTD::__swap_allocator(__alloc(), __x.__alloc()); 440} 441 442template <class _Tp, class _Allocator> 443_LIBCPP_CONSTEXPR_SINCE_CXX20 444void 445__split_buffer<_Tp, _Allocator>::reserve(size_type __n) 446{ 447 if (__n < capacity()) 448 { 449 __split_buffer<value_type, __alloc_rr&> __t(__n, 0, __alloc()); 450 __t.__construct_at_end(move_iterator<pointer>(__begin_), 451 move_iterator<pointer>(__end_)); 452 _VSTD::swap(__first_, __t.__first_); 453 _VSTD::swap(__begin_, __t.__begin_); 454 _VSTD::swap(__end_, __t.__end_); 455 _VSTD::swap(__end_cap(), __t.__end_cap()); 456 } 457} 458 459template <class _Tp, class _Allocator> 460_LIBCPP_CONSTEXPR_SINCE_CXX20 461void 462__split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT 463{ 464 if (capacity() > size()) 465 { 466#ifndef _LIBCPP_NO_EXCEPTIONS 467 try 468 { 469#endif // _LIBCPP_NO_EXCEPTIONS 470 __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __alloc()); 471 __t.__construct_at_end(move_iterator<pointer>(__begin_), 472 move_iterator<pointer>(__end_)); 473 __t.__end_ = __t.__begin_ + (__end_ - __begin_); 474 _VSTD::swap(__first_, __t.__first_); 475 _VSTD::swap(__begin_, __t.__begin_); 476 _VSTD::swap(__end_, __t.__end_); 477 _VSTD::swap(__end_cap(), __t.__end_cap()); 478#ifndef _LIBCPP_NO_EXCEPTIONS 479 } 480 catch (...) 481 { 482 } 483#endif // _LIBCPP_NO_EXCEPTIONS 484 } 485} 486 487template <class _Tp, class _Allocator> 488_LIBCPP_CONSTEXPR_SINCE_CXX20 489void 490__split_buffer<_Tp, _Allocator>::push_front(const_reference __x) 491{ 492 if (__begin_ == __first_) 493 { 494 if (__end_ < __end_cap()) 495 { 496 difference_type __d = __end_cap() - __end_; 497 __d = (__d + 1) / 2; 498 __begin_ = _VSTD::move_backward(__begin_, __end_, __end_ + __d); 499 __end_ += __d; 500 } 501 else 502 { 503 size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 504 __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc()); 505 __t.__construct_at_end(move_iterator<pointer>(__begin_), 506 move_iterator<pointer>(__end_)); 507 _VSTD::swap(__first_, __t.__first_); 508 _VSTD::swap(__begin_, __t.__begin_); 509 _VSTD::swap(__end_, __t.__end_); 510 _VSTD::swap(__end_cap(), __t.__end_cap()); 511 } 512 } 513 __alloc_traits::construct(__alloc(), _VSTD::__to_address(__begin_-1), __x); 514 --__begin_; 515} 516 517template <class _Tp, class _Allocator> 518_LIBCPP_CONSTEXPR_SINCE_CXX20 519void 520__split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) 521{ 522 if (__begin_ == __first_) 523 { 524 if (__end_ < __end_cap()) 525 { 526 difference_type __d = __end_cap() - __end_; 527 __d = (__d + 1) / 2; 528 __begin_ = _VSTD::move_backward(__begin_, __end_, __end_ + __d); 529 __end_ += __d; 530 } 531 else 532 { 533 size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 534 __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc()); 535 __t.__construct_at_end(move_iterator<pointer>(__begin_), 536 move_iterator<pointer>(__end_)); 537 _VSTD::swap(__first_, __t.__first_); 538 _VSTD::swap(__begin_, __t.__begin_); 539 _VSTD::swap(__end_, __t.__end_); 540 _VSTD::swap(__end_cap(), __t.__end_cap()); 541 } 542 } 543 __alloc_traits::construct(__alloc(), _VSTD::__to_address(__begin_-1), 544 _VSTD::move(__x)); 545 --__begin_; 546} 547 548template <class _Tp, class _Allocator> 549_LIBCPP_CONSTEXPR_SINCE_CXX20 550inline _LIBCPP_HIDE_FROM_ABI 551void 552__split_buffer<_Tp, _Allocator>::push_back(const_reference __x) 553{ 554 if (__end_ == __end_cap()) 555 { 556 if (__begin_ > __first_) 557 { 558 difference_type __d = __begin_ - __first_; 559 __d = (__d + 1) / 2; 560 __end_ = _VSTD::move(__begin_, __end_, __begin_ - __d); 561 __begin_ -= __d; 562 } 563 else 564 { 565 size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 566 __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc()); 567 __t.__construct_at_end(move_iterator<pointer>(__begin_), 568 move_iterator<pointer>(__end_)); 569 _VSTD::swap(__first_, __t.__first_); 570 _VSTD::swap(__begin_, __t.__begin_); 571 _VSTD::swap(__end_, __t.__end_); 572 _VSTD::swap(__end_cap(), __t.__end_cap()); 573 } 574 } 575 __alloc_traits::construct(__alloc(), _VSTD::__to_address(__end_), __x); 576 ++__end_; 577} 578 579template <class _Tp, class _Allocator> 580_LIBCPP_CONSTEXPR_SINCE_CXX20 581void 582__split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) 583{ 584 if (__end_ == __end_cap()) 585 { 586 if (__begin_ > __first_) 587 { 588 difference_type __d = __begin_ - __first_; 589 __d = (__d + 1) / 2; 590 __end_ = _VSTD::move(__begin_, __end_, __begin_ - __d); 591 __begin_ -= __d; 592 } 593 else 594 { 595 size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 596 __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc()); 597 __t.__construct_at_end(move_iterator<pointer>(__begin_), 598 move_iterator<pointer>(__end_)); 599 _VSTD::swap(__first_, __t.__first_); 600 _VSTD::swap(__begin_, __t.__begin_); 601 _VSTD::swap(__end_, __t.__end_); 602 _VSTD::swap(__end_cap(), __t.__end_cap()); 603 } 604 } 605 __alloc_traits::construct(__alloc(), _VSTD::__to_address(__end_), 606 _VSTD::move(__x)); 607 ++__end_; 608} 609 610template <class _Tp, class _Allocator> 611template <class... _Args> 612_LIBCPP_CONSTEXPR_SINCE_CXX20 613void 614__split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) 615{ 616 if (__end_ == __end_cap()) 617 { 618 if (__begin_ > __first_) 619 { 620 difference_type __d = __begin_ - __first_; 621 __d = (__d + 1) / 2; 622 __end_ = _VSTD::move(__begin_, __end_, __begin_ - __d); 623 __begin_ -= __d; 624 } 625 else 626 { 627 size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 628 __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc()); 629 __t.__construct_at_end(move_iterator<pointer>(__begin_), 630 move_iterator<pointer>(__end_)); 631 _VSTD::swap(__first_, __t.__first_); 632 _VSTD::swap(__begin_, __t.__begin_); 633 _VSTD::swap(__end_, __t.__end_); 634 _VSTD::swap(__end_cap(), __t.__end_cap()); 635 } 636 } 637 __alloc_traits::construct(__alloc(), _VSTD::__to_address(__end_), 638 _VSTD::forward<_Args>(__args)...); 639 ++__end_; 640} 641 642template <class _Tp, class _Allocator> 643_LIBCPP_CONSTEXPR_SINCE_CXX20 644inline _LIBCPP_HIDE_FROM_ABI 645void 646swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) 647 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) 648{ 649 __x.swap(__y); 650} 651 652_LIBCPP_END_NAMESPACE_STD 653 654_LIBCPP_POP_MACROS 655 656#endif // _LIBCPP___SPLIT_BUFFER 657