10b57cec5SDimitry Andric// -*- C++ -*- 281ad6265SDimitry Andric//===----------------------------------------------------------------------===// 381ad6265SDimitry Andric// 481ad6265SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 581ad6265SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 681ad6265SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 781ad6265SDimitry Andric// 881ad6265SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 1081ad6265SDimitry Andric#ifndef _LIBCPP___SPLIT_BUFFER 1181ad6265SDimitry Andric#define _LIBCPP___SPLIT_BUFFER 1281ad6265SDimitry Andric 1381ad6265SDimitry Andric#include <__algorithm/max.h> 1481ad6265SDimitry Andric#include <__algorithm/move.h> 1581ad6265SDimitry Andric#include <__algorithm/move_backward.h> 160b57cec5SDimitry Andric#include <__config> 1781ad6265SDimitry Andric#include <__iterator/distance.h> 1881ad6265SDimitry Andric#include <__iterator/iterator_traits.h> 1981ad6265SDimitry Andric#include <__iterator/move_iterator.h> 20bdd1243dSDimitry Andric#include <__memory/allocate_at_least.h> 2181ad6265SDimitry Andric#include <__memory/allocator.h> 22bdd1243dSDimitry Andric#include <__memory/allocator_traits.h> 2381ad6265SDimitry Andric#include <__memory/compressed_pair.h> 24bdd1243dSDimitry Andric#include <__memory/pointer_traits.h> 25972a253aSDimitry Andric#include <__memory/swap_allocator.h> 260fca6ea1SDimitry Andric#include <__type_traits/conditional.h> 2706c3fb27SDimitry Andric#include <__type_traits/enable_if.h> 2806c3fb27SDimitry Andric#include <__type_traits/integral_constant.h> 290fca6ea1SDimitry Andric#include <__type_traits/is_nothrow_assignable.h> 300fca6ea1SDimitry Andric#include <__type_traits/is_nothrow_constructible.h> 31*700637cbSDimitry Andric#include <__type_traits/is_replaceable.h> 3206c3fb27SDimitry Andric#include <__type_traits/is_swappable.h> 3306c3fb27SDimitry Andric#include <__type_traits/is_trivially_destructible.h> 340fca6ea1SDimitry Andric#include <__type_traits/is_trivially_relocatable.h> 3506c3fb27SDimitry Andric#include <__type_traits/remove_reference.h> 36fe6060f1SDimitry Andric#include <__utility/forward.h> 37bdd1243dSDimitry Andric#include <__utility/move.h> 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 400b57cec5SDimitry Andric# pragma GCC system_header 410b57cec5SDimitry Andric#endif 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric_LIBCPP_PUSH_MACROS 440b57cec5SDimitry Andric#include <__undef_macros> 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 470b57cec5SDimitry Andric 48bdd1243dSDimitry Andric// __split_buffer allocates a contiguous chunk of memory and stores objects in the range [__begin_, __end_). 49*700637cbSDimitry Andric// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __cap_). That allows 50bdd1243dSDimitry Andric// it to grow both in the front and back without having to move the data. 51bdd1243dSDimitry Andric 520b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator = allocator<_Tp> > 53cb14a3feSDimitry Andricstruct __split_buffer { 540b57cec5SDimitry Andricpublic: 5506c3fb27SDimitry Andric using value_type = _Tp; 5606c3fb27SDimitry Andric using allocator_type = _Allocator; 57*700637cbSDimitry Andric using __alloc_rr _LIBCPP_NODEBUG = __libcpp_remove_reference_t<allocator_type>; 58*700637cbSDimitry Andric using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<__alloc_rr>; 5906c3fb27SDimitry Andric using reference = value_type&; 6006c3fb27SDimitry Andric using const_reference = const value_type&; 6106c3fb27SDimitry Andric using size_type = typename __alloc_traits::size_type; 6206c3fb27SDimitry Andric using difference_type = typename __alloc_traits::difference_type; 6306c3fb27SDimitry Andric using pointer = typename __alloc_traits::pointer; 6406c3fb27SDimitry Andric using const_pointer = typename __alloc_traits::const_pointer; 6506c3fb27SDimitry Andric using iterator = pointer; 6606c3fb27SDimitry Andric using const_iterator = const_pointer; 670b57cec5SDimitry Andric 680fca6ea1SDimitry Andric // A __split_buffer contains the following members which may be trivially relocatable: 690fca6ea1SDimitry Andric // - pointer: may be trivially relocatable, so it's checked 700fca6ea1SDimitry Andric // - allocator_type: may be trivially relocatable, so it's checked 710fca6ea1SDimitry Andric // __split_buffer doesn't have any self-references, so it's trivially relocatable if its members are. 72*700637cbSDimitry Andric using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t< 730fca6ea1SDimitry Andric __libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<allocator_type>::value, 740fca6ea1SDimitry Andric __split_buffer, 750fca6ea1SDimitry Andric void>; 76*700637cbSDimitry Andric using __replaceable _LIBCPP_NODEBUG = 77*700637cbSDimitry Andric __conditional_t<__is_replaceable_v<pointer> && __container_allocator_is_replaceable<__alloc_traits>::value, 78*700637cbSDimitry Andric __split_buffer, 79*700637cbSDimitry Andric void>; 800fca6ea1SDimitry Andric 810b57cec5SDimitry Andric pointer __first_; 820b57cec5SDimitry Andric pointer __begin_; 830b57cec5SDimitry Andric pointer __end_; 84*700637cbSDimitry Andric _LIBCPP_COMPRESSED_PAIR(pointer, __cap_, allocator_type, __alloc_); 850b57cec5SDimitry Andric 8606c3fb27SDimitry Andric __split_buffer(const __split_buffer&) = delete; 8706c3fb27SDimitry Andric __split_buffer& operator=(const __split_buffer&) = delete; 8806c3fb27SDimitry Andric 8906c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer() 9006c3fb27SDimitry Andric _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) 91*700637cbSDimitry Andric : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr) {} 9206c3fb27SDimitry Andric 9306c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a) 94*700637cbSDimitry Andric : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr), __alloc_(__a) {} 9506c3fb27SDimitry Andric 9606c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a) 97*700637cbSDimitry Andric : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr), __alloc_(__a) {} 980b57cec5SDimitry Andric 99bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI 10006c3fb27SDimitry Andric __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); 1010b57cec5SDimitry Andric 102bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c) 1030b57cec5SDimitry Andric _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value); 10406c3fb27SDimitry Andric 105bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); 10606c3fb27SDimitry Andric 107bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer& operator=(__split_buffer&& __c) 1080b57cec5SDimitry Andric _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && 1090b57cec5SDimitry Andric is_nothrow_move_assignable<allocator_type>::value) || 1100b57cec5SDimitry Andric !__alloc_traits::propagate_on_container_move_assignment::value); 1110b57cec5SDimitry Andric 11206c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer(); 11306c3fb27SDimitry Andric 114bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __begin_; } 115bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __begin_; } 11606c3fb27SDimitry Andric 117bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __end_; } 118bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __end_; } 1190b57cec5SDimitry Andric 12006c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(__begin_); } 12106c3fb27SDimitry Andric 12206c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const { 12306c3fb27SDimitry Andric return static_cast<size_type>(__end_ - __begin_); 12406c3fb27SDimitry Andric } 12506c3fb27SDimitry Andric 126bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __end_ == __begin_; } 12706c3fb27SDimitry Andric 12806c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const { 129*700637cbSDimitry Andric return static_cast<size_type>(__cap_ - __first_); 13006c3fb27SDimitry Andric } 13106c3fb27SDimitry Andric 13206c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const { 13306c3fb27SDimitry Andric return static_cast<size_type>(__begin_ - __first_); 13406c3fb27SDimitry Andric } 13506c3fb27SDimitry Andric 13606c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const { 137*700637cbSDimitry Andric return static_cast<size_type>(__cap_ - __end_); 13806c3fb27SDimitry Andric } 1390b57cec5SDimitry Andric 140bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__begin_; } 141bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *__begin_; } 142bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() { return *(__end_ - 1); } 143bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const { return *(__end_ - 1); } 1440b57cec5SDimitry Andric 145bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; 14606c3fb27SDimitry Andric 1470b57cec5SDimitry Andric template <class... _Args> 148*700637cbSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_front(_Args&&... __args); 149*700637cbSDimitry Andric template <class... _Args> 150bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args); 1510b57cec5SDimitry Andric 152bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() { __destruct_at_begin(__begin_ + 1); } 153bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() { __destruct_at_end(__end_ - 1); } 1540b57cec5SDimitry Andric 155bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n); 156bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x); 15706c3fb27SDimitry Andric 1585f757f3fSDimitry Andric template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> 159cb14a3feSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void 160cb14a3feSDimitry Andric __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); 1610b57cec5SDimitry Andric 16206c3fb27SDimitry Andric template <class _Iterator, class _Sentinel> 163cb14a3feSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void 164cb14a3feSDimitry Andric __construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last); 1650b57cec5SDimitry Andric 16606c3fb27SDimitry Andric template <class _Iterator> 167cb14a3feSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void 168cb14a3feSDimitry Andric __construct_at_end_with_size(_Iterator __first, size_type __n); 16906c3fb27SDimitry Andric 17006c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin) { 17106c3fb27SDimitry Andric __destruct_at_begin(__new_begin, is_trivially_destructible<value_type>()); 17206c3fb27SDimitry Andric } 17306c3fb27SDimitry Andric 17406c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, false_type); 17506c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, true_type); 17606c3fb27SDimitry Andric 17706c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last) _NOEXCEPT { 17806c3fb27SDimitry Andric __destruct_at_end(__new_last, false_type()); 17906c3fb27SDimitry Andric } 18006c3fb27SDimitry Andric 18106c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT; 18206c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT; 1830b57cec5SDimitry Andric 184bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x) 1850fca6ea1SDimitry Andric _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>); 1860b57cec5SDimitry Andric 187bdd1243dSDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andricprivate: 19006c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type) 19106c3fb27SDimitry Andric _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) { 192*700637cbSDimitry Andric __alloc_ = std::move(__c.__alloc_); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 19506c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {} 196e40139ffSDimitry Andric 197e40139ffSDimitry Andric struct _ConstructTransaction { 1980fca6ea1SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 1990fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT 20006c3fb27SDimitry Andric : __pos_(*__p), 20106c3fb27SDimitry Andric __end_(*__p + __n), 20206c3fb27SDimitry Andric __dest_(__p) {} 20306c3fb27SDimitry Andric 20406c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { *__dest_ = __pos_; } 20506c3fb27SDimitry Andric 206e40139ffSDimitry Andric pointer __pos_; 207e40139ffSDimitry Andric const pointer __end_; 20806c3fb27SDimitry Andric 209e40139ffSDimitry Andric private: 210e40139ffSDimitry Andric pointer* __dest_; 211e40139ffSDimitry Andric }; 2120b57cec5SDimitry Andric}; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 215cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 bool __split_buffer<_Tp, _Allocator>::__invariants() const { 216cb14a3feSDimitry Andric if (__first_ == nullptr) { 2170b57cec5SDimitry Andric if (__begin_ != nullptr) 2180b57cec5SDimitry Andric return false; 2190b57cec5SDimitry Andric if (__end_ != nullptr) 2200b57cec5SDimitry Andric return false; 221*700637cbSDimitry Andric if (__cap_ != nullptr) 2220b57cec5SDimitry Andric return false; 223cb14a3feSDimitry Andric } else { 2240b57cec5SDimitry Andric if (__begin_ < __first_) 2250b57cec5SDimitry Andric return false; 2260b57cec5SDimitry Andric if (__end_ < __begin_) 2270b57cec5SDimitry Andric return false; 228*700637cbSDimitry Andric if (__cap_ < __end_) 2290b57cec5SDimitry Andric return false; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric return true; 2320b57cec5SDimitry Andric} 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric// Default constructs __n objects starting at __end_ 2350b57cec5SDimitry Andric// throws if construction throws 2360b57cec5SDimitry Andric// Precondition: __n > 0 2370b57cec5SDimitry Andric// Precondition: size() + __n <= capacity() 2380b57cec5SDimitry Andric// Postcondition: size() == size() + __n 2390b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 240cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) { 241*700637cbSDimitry Andric _ConstructTransaction __tx(std::addressof(this->__end_), __n); 242e40139ffSDimitry Andric for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { 243*700637cbSDimitry Andric __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_)); 244e40139ffSDimitry Andric } 2450b57cec5SDimitry Andric} 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric// Copy constructs __n objects starting at __end_ from __x 2480b57cec5SDimitry Andric// throws if construction throws 2490b57cec5SDimitry Andric// Precondition: __n > 0 2500b57cec5SDimitry Andric// Precondition: size() + __n <= capacity() 2510b57cec5SDimitry Andric// Postcondition: size() == old size() + __n 2520b57cec5SDimitry Andric// Postcondition: [i] == __x for all i in [size() - __n, __n) 2530b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 254cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 void 255cb14a3feSDimitry Andric__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) { 256*700637cbSDimitry Andric _ConstructTransaction __tx(std::addressof(this->__end_), __n); 257e40139ffSDimitry Andric for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { 258*700637cbSDimitry Andric __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), __x); 259e40139ffSDimitry Andric } 2600b57cec5SDimitry Andric} 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 26306c3fb27SDimitry Andrictemplate <class _Iterator, class _Sentinel> 264cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 void 265cb14a3feSDimitry Andric__split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) { 266*700637cbSDimitry Andric __alloc_rr& __a = __alloc_; 267cb14a3feSDimitry Andric for (; __first != __last; ++__first) { 268*700637cbSDimitry Andric if (__end_ == __cap_) { 269*700637cbSDimitry Andric size_type __old_cap = __cap_ - __first_; 2705f757f3fSDimitry Andric size_type __new_cap = std::max<size_type>(2 * __old_cap, 8); 2710b57cec5SDimitry Andric __split_buffer __buf(__new_cap, 0, __a); 272349cc55cSDimitry Andric for (pointer __p = __begin_; __p != __end_; ++__p, (void)++__buf.__end_) 273*700637cbSDimitry Andric __alloc_traits::construct(__buf.__alloc_, std::__to_address(__buf.__end_), std::move(*__p)); 2740b57cec5SDimitry Andric swap(__buf); 2750b57cec5SDimitry Andric } 2765f757f3fSDimitry Andric __alloc_traits::construct(__a, std::__to_address(this->__end_), *__first); 2770b57cec5SDimitry Andric ++this->__end_; 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric} 28006c3fb27SDimitry Andrictemplate <class _Tp, class _Allocator> 2815f757f3fSDimitry Andrictemplate <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > 282cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 void 283cb14a3feSDimitry Andric__split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) { 28406c3fb27SDimitry Andric __construct_at_end_with_size(__first, std::distance(__first, __last)); 28506c3fb27SDimitry Andric} 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 2880b57cec5SDimitry Andrictemplate <class _ForwardIterator> 289cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 void 290cb14a3feSDimitry Andric__split_buffer<_Tp, _Allocator>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) { 291*700637cbSDimitry Andric _ConstructTransaction __tx(std::addressof(this->__end_), __n); 292349cc55cSDimitry Andric for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__first) { 293*700637cbSDimitry Andric __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), *__first); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric} 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 298cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void 299cb14a3feSDimitry Andric__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) { 3000b57cec5SDimitry Andric while (__begin_ != __new_begin) 301*700637cbSDimitry Andric __alloc_traits::destroy(__alloc_, std::__to_address(__begin_++)); 3020b57cec5SDimitry Andric} 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 305cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void 306cb14a3feSDimitry Andric__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type) { 3070b57cec5SDimitry Andric __begin_ = __new_begin; 3080b57cec5SDimitry Andric} 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 311cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void 312cb14a3feSDimitry Andric__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT { 3130b57cec5SDimitry Andric while (__new_last != __end_) 314*700637cbSDimitry Andric __alloc_traits::destroy(__alloc_, std::__to_address(--__end_)); 3150b57cec5SDimitry Andric} 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 318cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void 319cb14a3feSDimitry Andric__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type) _NOEXCEPT { 3200b57cec5SDimitry Andric __end_ = __new_last; 3210b57cec5SDimitry Andric} 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 324bdd1243dSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 3250b57cec5SDimitry Andric__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a) 326*700637cbSDimitry Andric : __cap_(nullptr), __alloc_(__a) { 32781ad6265SDimitry Andric if (__cap == 0) { 32881ad6265SDimitry Andric __first_ = nullptr; 32981ad6265SDimitry Andric } else { 330*700637cbSDimitry Andric auto __allocation = std::__allocate_at_least(__alloc_, __cap); 33181ad6265SDimitry Andric __first_ = __allocation.ptr; 33281ad6265SDimitry Andric __cap = __allocation.count; 33381ad6265SDimitry Andric } 3340b57cec5SDimitry Andric __begin_ = __end_ = __first_ + __start; 335*700637cbSDimitry Andric __cap_ = __first_ + __cap; 3360b57cec5SDimitry Andric} 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 339cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::~__split_buffer() { 3400b57cec5SDimitry Andric clear(); 3410b57cec5SDimitry Andric if (__first_) 342*700637cbSDimitry Andric __alloc_traits::deallocate(__alloc_, __first_, capacity()); 3430b57cec5SDimitry Andric} 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 346cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c) 3470b57cec5SDimitry Andric _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value) 3485f757f3fSDimitry Andric : __first_(std::move(__c.__first_)), 3495f757f3fSDimitry Andric __begin_(std::move(__c.__begin_)), 3505f757f3fSDimitry Andric __end_(std::move(__c.__end_)), 351*700637cbSDimitry Andric __cap_(std::move(__c.__cap_)), 352*700637cbSDimitry Andric __alloc_(std::move(__c.__alloc_)) { 3530b57cec5SDimitry Andric __c.__first_ = nullptr; 3540b57cec5SDimitry Andric __c.__begin_ = nullptr; 3550b57cec5SDimitry Andric __c.__end_ = nullptr; 356*700637cbSDimitry Andric __c.__cap_ = nullptr; 3570b57cec5SDimitry Andric} 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 360bdd1243dSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 3610b57cec5SDimitry Andric__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a) 362*700637cbSDimitry Andric : __cap_(nullptr), __alloc_(__a) { 363*700637cbSDimitry Andric if (__a == __c.__alloc_) { 3640b57cec5SDimitry Andric __first_ = __c.__first_; 3650b57cec5SDimitry Andric __begin_ = __c.__begin_; 3660b57cec5SDimitry Andric __end_ = __c.__end_; 367*700637cbSDimitry Andric __cap_ = __c.__cap_; 3680b57cec5SDimitry Andric __c.__first_ = nullptr; 3690b57cec5SDimitry Andric __c.__begin_ = nullptr; 3700b57cec5SDimitry Andric __c.__end_ = nullptr; 371*700637cbSDimitry Andric __c.__cap_ = nullptr; 372cb14a3feSDimitry Andric } else { 373*700637cbSDimitry Andric auto __allocation = std::__allocate_at_least(__alloc_, __c.size()); 37481ad6265SDimitry Andric __first_ = __allocation.ptr; 3750b57cec5SDimitry Andric __begin_ = __end_ = __first_; 376*700637cbSDimitry Andric __cap_ = __first_ + __allocation.count; 3770b57cec5SDimitry Andric typedef move_iterator<iterator> _Ip; 3780b57cec5SDimitry Andric __construct_at_end(_Ip(__c.begin()), _Ip(__c.end())); 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric} 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 383cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>& 3840b57cec5SDimitry Andric__split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) 3850b57cec5SDimitry Andric _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && 3860b57cec5SDimitry Andric is_nothrow_move_assignable<allocator_type>::value) || 387cb14a3feSDimitry Andric !__alloc_traits::propagate_on_container_move_assignment::value) { 3880b57cec5SDimitry Andric clear(); 3890b57cec5SDimitry Andric shrink_to_fit(); 3900b57cec5SDimitry Andric __first_ = __c.__first_; 3910b57cec5SDimitry Andric __begin_ = __c.__begin_; 3920b57cec5SDimitry Andric __end_ = __c.__end_; 393*700637cbSDimitry Andric __cap_ = __c.__cap_; 394cb14a3feSDimitry Andric __move_assign_alloc(__c, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>()); 395*700637cbSDimitry Andric __c.__first_ = __c.__begin_ = __c.__end_ = __c.__cap_ = nullptr; 3960b57cec5SDimitry Andric return *this; 3970b57cec5SDimitry Andric} 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 400cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x) 4010fca6ea1SDimitry Andric _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>) { 4025f757f3fSDimitry Andric std::swap(__first_, __x.__first_); 4035f757f3fSDimitry Andric std::swap(__begin_, __x.__begin_); 4045f757f3fSDimitry Andric std::swap(__end_, __x.__end_); 405*700637cbSDimitry Andric std::swap(__cap_, __x.__cap_); 406*700637cbSDimitry Andric std::__swap_allocator(__alloc_, __x.__alloc_); 4070b57cec5SDimitry Andric} 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 410cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { 411cb14a3feSDimitry Andric if (capacity() > size()) { 412*700637cbSDimitry Andric#if _LIBCPP_HAS_EXCEPTIONS 413cb14a3feSDimitry Andric try { 414*700637cbSDimitry Andric#endif // _LIBCPP_HAS_EXCEPTIONS 415*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __alloc_); 416*700637cbSDimitry Andric if (__t.capacity() < capacity()) { 417cb14a3feSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 4180b57cec5SDimitry Andric __t.__end_ = __t.__begin_ + (__end_ - __begin_); 4195f757f3fSDimitry Andric std::swap(__first_, __t.__first_); 4205f757f3fSDimitry Andric std::swap(__begin_, __t.__begin_); 4215f757f3fSDimitry Andric std::swap(__end_, __t.__end_); 422*700637cbSDimitry Andric std::swap(__cap_, __t.__cap_); 423*700637cbSDimitry Andric } 424*700637cbSDimitry Andric#if _LIBCPP_HAS_EXCEPTIONS 425cb14a3feSDimitry Andric } catch (...) { 4260b57cec5SDimitry Andric } 427*700637cbSDimitry Andric#endif // _LIBCPP_HAS_EXCEPTIONS 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric} 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 432*700637cbSDimitry Andrictemplate <class... _Args> 433*700637cbSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_front(_Args&&... __args) { 434cb14a3feSDimitry Andric if (__begin_ == __first_) { 435*700637cbSDimitry Andric if (__end_ < __cap_) { 436*700637cbSDimitry Andric difference_type __d = __cap_ - __end_; 4370b57cec5SDimitry Andric __d = (__d + 1) / 2; 4385f757f3fSDimitry Andric __begin_ = std::move_backward(__begin_, __end_, __end_ + __d); 4390b57cec5SDimitry Andric __end_ += __d; 440cb14a3feSDimitry Andric } else { 441*700637cbSDimitry Andric size_type __c = std::max<size_type>(2 * static_cast<size_type>(__cap_ - __first_), 1); 442*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc_); 443cb14a3feSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 4445f757f3fSDimitry Andric std::swap(__first_, __t.__first_); 4455f757f3fSDimitry Andric std::swap(__begin_, __t.__begin_); 4465f757f3fSDimitry Andric std::swap(__end_, __t.__end_); 447*700637cbSDimitry Andric std::swap(__cap_, __t.__cap_); 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric } 450*700637cbSDimitry Andric __alloc_traits::construct(__alloc_, std::__to_address(__begin_ - 1), std::forward<_Args>(__args)...); 4510b57cec5SDimitry Andric --__begin_; 4520b57cec5SDimitry Andric} 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 4550b57cec5SDimitry Andrictemplate <class... _Args> 456cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) { 457*700637cbSDimitry Andric if (__end_ == __cap_) { 458cb14a3feSDimitry Andric if (__begin_ > __first_) { 4590b57cec5SDimitry Andric difference_type __d = __begin_ - __first_; 4600b57cec5SDimitry Andric __d = (__d + 1) / 2; 4615f757f3fSDimitry Andric __end_ = std::move(__begin_, __end_, __begin_ - __d); 4620b57cec5SDimitry Andric __begin_ -= __d; 463cb14a3feSDimitry Andric } else { 464*700637cbSDimitry Andric size_type __c = std::max<size_type>(2 * static_cast<size_type>(__cap_ - __first_), 1); 465*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc_); 466cb14a3feSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 4675f757f3fSDimitry Andric std::swap(__first_, __t.__first_); 4685f757f3fSDimitry Andric std::swap(__begin_, __t.__begin_); 4695f757f3fSDimitry Andric std::swap(__end_, __t.__end_); 470*700637cbSDimitry Andric std::swap(__cap_, __t.__cap_); 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric } 473*700637cbSDimitry Andric __alloc_traits::construct(__alloc_, std::__to_address(__end_), std::forward<_Args>(__args)...); 4740b57cec5SDimitry Andric ++__end_; 4750b57cec5SDimitry Andric} 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andrictemplate <class _Tp, class _Allocator> 478cb14a3feSDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void 479cb14a3feSDimitry Andricswap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { 4800b57cec5SDimitry Andric __x.swap(__y); 4810b57cec5SDimitry Andric} 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric_LIBCPP_POP_MACROS 4860b57cec5SDimitry Andric 48781ad6265SDimitry Andric#endif // _LIBCPP___SPLIT_BUFFER 488