1*700637cbSDimitry Andric// -*- C++ -*- 2*700637cbSDimitry Andric//===----------------------------------------------------------------------===// 3*700637cbSDimitry Andric// 4*700637cbSDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*700637cbSDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 6*700637cbSDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*700637cbSDimitry Andric// 8*700637cbSDimitry Andric//===----------------------------------------------------------------------===// 9*700637cbSDimitry Andric 10*700637cbSDimitry Andric#ifndef _LIBCPP___CXX03___SPLIT_BUFFER 11*700637cbSDimitry Andric#define _LIBCPP___CXX03___SPLIT_BUFFER 12*700637cbSDimitry Andric 13*700637cbSDimitry Andric#include <__cxx03/__algorithm/max.h> 14*700637cbSDimitry Andric#include <__cxx03/__algorithm/move.h> 15*700637cbSDimitry Andric#include <__cxx03/__algorithm/move_backward.h> 16*700637cbSDimitry Andric#include <__cxx03/__config> 17*700637cbSDimitry Andric#include <__cxx03/__iterator/distance.h> 18*700637cbSDimitry Andric#include <__cxx03/__iterator/iterator_traits.h> 19*700637cbSDimitry Andric#include <__cxx03/__iterator/move_iterator.h> 20*700637cbSDimitry Andric#include <__cxx03/__memory/allocate_at_least.h> 21*700637cbSDimitry Andric#include <__cxx03/__memory/allocator.h> 22*700637cbSDimitry Andric#include <__cxx03/__memory/allocator_traits.h> 23*700637cbSDimitry Andric#include <__cxx03/__memory/compressed_pair.h> 24*700637cbSDimitry Andric#include <__cxx03/__memory/pointer_traits.h> 25*700637cbSDimitry Andric#include <__cxx03/__memory/swap_allocator.h> 26*700637cbSDimitry Andric#include <__cxx03/__type_traits/add_lvalue_reference.h> 27*700637cbSDimitry Andric#include <__cxx03/__type_traits/conditional.h> 28*700637cbSDimitry Andric#include <__cxx03/__type_traits/enable_if.h> 29*700637cbSDimitry Andric#include <__cxx03/__type_traits/integral_constant.h> 30*700637cbSDimitry Andric#include <__cxx03/__type_traits/is_nothrow_assignable.h> 31*700637cbSDimitry Andric#include <__cxx03/__type_traits/is_nothrow_constructible.h> 32*700637cbSDimitry Andric#include <__cxx03/__type_traits/is_swappable.h> 33*700637cbSDimitry Andric#include <__cxx03/__type_traits/is_trivially_destructible.h> 34*700637cbSDimitry Andric#include <__cxx03/__type_traits/is_trivially_relocatable.h> 35*700637cbSDimitry Andric#include <__cxx03/__type_traits/remove_reference.h> 36*700637cbSDimitry Andric#include <__cxx03/__utility/forward.h> 37*700637cbSDimitry Andric#include <__cxx03/__utility/move.h> 38*700637cbSDimitry Andric#include <__cxx03/cstddef> 39*700637cbSDimitry Andric 40*700637cbSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 41*700637cbSDimitry Andric# pragma GCC system_header 42*700637cbSDimitry Andric#endif 43*700637cbSDimitry Andric 44*700637cbSDimitry Andric_LIBCPP_PUSH_MACROS 45*700637cbSDimitry Andric#include <__cxx03/__undef_macros> 46*700637cbSDimitry Andric 47*700637cbSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 48*700637cbSDimitry Andric 49*700637cbSDimitry Andric// __split_buffer allocates a contiguous chunk of memory and stores objects in the range [__begin_, __end_). 50*700637cbSDimitry Andric// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __end_cap_.first()). That allows 51*700637cbSDimitry Andric// it to grow both in the front and back without having to move the data. 52*700637cbSDimitry Andric 53*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator = allocator<_Tp> > 54*700637cbSDimitry Andricstruct __split_buffer { 55*700637cbSDimitry Andricpublic: 56*700637cbSDimitry Andric using value_type = _Tp; 57*700637cbSDimitry Andric using allocator_type = _Allocator; 58*700637cbSDimitry Andric using __alloc_rr = __libcpp_remove_reference_t<allocator_type>; 59*700637cbSDimitry Andric using __alloc_traits = allocator_traits<__alloc_rr>; 60*700637cbSDimitry Andric using reference = value_type&; 61*700637cbSDimitry Andric using const_reference = const value_type&; 62*700637cbSDimitry Andric using size_type = typename __alloc_traits::size_type; 63*700637cbSDimitry Andric using difference_type = typename __alloc_traits::difference_type; 64*700637cbSDimitry Andric using pointer = typename __alloc_traits::pointer; 65*700637cbSDimitry Andric using const_pointer = typename __alloc_traits::const_pointer; 66*700637cbSDimitry Andric using iterator = pointer; 67*700637cbSDimitry Andric using const_iterator = const_pointer; 68*700637cbSDimitry Andric 69*700637cbSDimitry Andric // A __split_buffer contains the following members which may be trivially relocatable: 70*700637cbSDimitry Andric // - pointer: may be trivially relocatable, so it's checked 71*700637cbSDimitry Andric // - allocator_type: may be trivially relocatable, so it's checked 72*700637cbSDimitry Andric // __split_buffer doesn't have any self-references, so it's trivially relocatable if its members are. 73*700637cbSDimitry Andric using __trivially_relocatable = __conditional_t< 74*700637cbSDimitry Andric __libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<allocator_type>::value, 75*700637cbSDimitry Andric __split_buffer, 76*700637cbSDimitry Andric void>; 77*700637cbSDimitry Andric 78*700637cbSDimitry Andric pointer __first_; 79*700637cbSDimitry Andric pointer __begin_; 80*700637cbSDimitry Andric pointer __end_; 81*700637cbSDimitry Andric __compressed_pair<pointer, allocator_type> __end_cap_; 82*700637cbSDimitry Andric 83*700637cbSDimitry Andric using __alloc_ref = __add_lvalue_reference_t<allocator_type>; 84*700637cbSDimitry Andric using __alloc_const_ref = __add_lvalue_reference_t<allocator_type>; 85*700637cbSDimitry Andric 86*700637cbSDimitry Andric __split_buffer(const __split_buffer&) = delete; 87*700637cbSDimitry Andric __split_buffer& operator=(const __split_buffer&) = delete; 88*700637cbSDimitry Andric 89*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI __split_buffer() 90*700637cbSDimitry Andric : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __default_init_tag()) {} 91*700637cbSDimitry Andric 92*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a) 93*700637cbSDimitry Andric : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) {} 94*700637cbSDimitry Andric 95*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a) 96*700637cbSDimitry Andric : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) {} 97*700637cbSDimitry Andric 98*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); 99*700637cbSDimitry Andric 100*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c); 101*700637cbSDimitry Andric 102*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); 103*700637cbSDimitry Andric 104*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI __split_buffer& operator=(__split_buffer&& __c); 105*700637cbSDimitry Andric 106*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI ~__split_buffer(); 107*700637cbSDimitry Andric 108*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI __alloc_rr& __alloc() _NOEXCEPT { return __end_cap_.second(); } 109*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const __alloc_rr& __alloc() const _NOEXCEPT { return __end_cap_.second(); } 110*700637cbSDimitry Andric 111*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT { return __end_cap_.first(); } 112*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT { return __end_cap_.first(); } 113*700637cbSDimitry Andric 114*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __begin_; } 115*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __begin_; } 116*700637cbSDimitry Andric 117*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __end_; } 118*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __end_; } 119*700637cbSDimitry Andric 120*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(__begin_); } 121*700637cbSDimitry Andric 122*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type size() const { return static_cast<size_type>(__end_ - __begin_); } 123*700637cbSDimitry Andric 124*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool empty() const { return __end_ == __begin_; } 125*700637cbSDimitry Andric 126*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type capacity() const { return static_cast<size_type>(__end_cap() - __first_); } 127*700637cbSDimitry Andric 128*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const { return static_cast<size_type>(__begin_ - __first_); } 129*700637cbSDimitry Andric 130*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const { return static_cast<size_type>(__end_cap() - __end_); } 131*700637cbSDimitry Andric 132*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI reference front() { return *__begin_; } 133*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *__begin_; } 134*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI reference back() { return *(__end_ - 1); } 135*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI const_reference back() const { return *(__end_ - 1); } 136*700637cbSDimitry Andric 137*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); 138*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; 139*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void push_front(const_reference __x); 140*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x); 141*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x); 142*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x); 143*700637cbSDimitry Andric 144*700637cbSDimitry Andric template <class... _Args> 145*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args); 146*700637cbSDimitry Andric 147*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void pop_front() { __destruct_at_begin(__begin_ + 1); } 148*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void pop_back() { __destruct_at_end(__end_ - 1); } 149*700637cbSDimitry Andric 150*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n); 151*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x); 152*700637cbSDimitry Andric 153*700637cbSDimitry Andric template <class _InputIter, __enable_if_t<__has_exactly_input_iterator_category<_InputIter>::value, int> = 0> 154*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __construct_at_end(_InputIter __first, _InputIter __last); 155*700637cbSDimitry Andric 156*700637cbSDimitry Andric template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> 157*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); 158*700637cbSDimitry Andric 159*700637cbSDimitry Andric template <class _Iterator, class _Sentinel> 160*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last); 161*700637cbSDimitry Andric 162*700637cbSDimitry Andric template <class _Iterator> 163*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __construct_at_end_with_size(_Iterator __first, size_type __n); 164*700637cbSDimitry Andric 165*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin) { 166*700637cbSDimitry Andric __destruct_at_begin(__new_begin, is_trivially_destructible<value_type>()); 167*700637cbSDimitry Andric } 168*700637cbSDimitry Andric 169*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, false_type); 170*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, true_type); 171*700637cbSDimitry Andric 172*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last) _NOEXCEPT { 173*700637cbSDimitry Andric __destruct_at_end(__new_last, false_type()); 174*700637cbSDimitry Andric } 175*700637cbSDimitry Andric 176*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT; 177*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT; 178*700637cbSDimitry Andric 179*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x); 180*700637cbSDimitry Andric 181*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __invariants() const; 182*700637cbSDimitry Andric 183*700637cbSDimitry Andricprivate: 184*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type) { 185*700637cbSDimitry Andric __alloc() = std::move(__c.__alloc()); 186*700637cbSDimitry Andric } 187*700637cbSDimitry Andric 188*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {} 189*700637cbSDimitry Andric 190*700637cbSDimitry Andric struct _ConstructTransaction { 191*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT 192*700637cbSDimitry Andric : __pos_(*__p), 193*700637cbSDimitry Andric __end_(*__p + __n), 194*700637cbSDimitry Andric __dest_(__p) {} 195*700637cbSDimitry Andric 196*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { *__dest_ = __pos_; } 197*700637cbSDimitry Andric 198*700637cbSDimitry Andric pointer __pos_; 199*700637cbSDimitry Andric const pointer __end_; 200*700637cbSDimitry Andric 201*700637cbSDimitry Andric private: 202*700637cbSDimitry Andric pointer* __dest_; 203*700637cbSDimitry Andric }; 204*700637cbSDimitry Andric}; 205*700637cbSDimitry Andric 206*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 207*700637cbSDimitry Andricbool __split_buffer<_Tp, _Allocator>::__invariants() const { 208*700637cbSDimitry Andric if (__first_ == nullptr) { 209*700637cbSDimitry Andric if (__begin_ != nullptr) 210*700637cbSDimitry Andric return false; 211*700637cbSDimitry Andric if (__end_ != nullptr) 212*700637cbSDimitry Andric return false; 213*700637cbSDimitry Andric if (__end_cap() != nullptr) 214*700637cbSDimitry Andric return false; 215*700637cbSDimitry Andric } else { 216*700637cbSDimitry Andric if (__begin_ < __first_) 217*700637cbSDimitry Andric return false; 218*700637cbSDimitry Andric if (__end_ < __begin_) 219*700637cbSDimitry Andric return false; 220*700637cbSDimitry Andric if (__end_cap() < __end_) 221*700637cbSDimitry Andric return false; 222*700637cbSDimitry Andric } 223*700637cbSDimitry Andric return true; 224*700637cbSDimitry Andric} 225*700637cbSDimitry Andric 226*700637cbSDimitry Andric// Default constructs __n objects starting at __end_ 227*700637cbSDimitry Andric// throws if construction throws 228*700637cbSDimitry Andric// Precondition: __n > 0 229*700637cbSDimitry Andric// Precondition: size() + __n <= capacity() 230*700637cbSDimitry Andric// Postcondition: size() == size() + __n 231*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 232*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) { 233*700637cbSDimitry Andric _ConstructTransaction __tx(&this->__end_, __n); 234*700637cbSDimitry Andric for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { 235*700637cbSDimitry Andric __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_)); 236*700637cbSDimitry Andric } 237*700637cbSDimitry Andric} 238*700637cbSDimitry Andric 239*700637cbSDimitry Andric// Copy constructs __n objects starting at __end_ from __x 240*700637cbSDimitry Andric// throws if construction throws 241*700637cbSDimitry Andric// Precondition: __n > 0 242*700637cbSDimitry Andric// Precondition: size() + __n <= capacity() 243*700637cbSDimitry Andric// Postcondition: size() == old size() + __n 244*700637cbSDimitry Andric// Postcondition: [i] == __x for all i in [size() - __n, __n) 245*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 246*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) { 247*700637cbSDimitry Andric _ConstructTransaction __tx(&this->__end_, __n); 248*700637cbSDimitry Andric for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { 249*700637cbSDimitry Andric __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), __x); 250*700637cbSDimitry Andric } 251*700637cbSDimitry Andric} 252*700637cbSDimitry Andric 253*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 254*700637cbSDimitry Andrictemplate <class _InputIter, __enable_if_t<__has_exactly_input_iterator_category<_InputIter>::value, int> > 255*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIter __last) { 256*700637cbSDimitry Andric __construct_at_end_with_sentinel(__first, __last); 257*700637cbSDimitry Andric} 258*700637cbSDimitry Andric 259*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 260*700637cbSDimitry Andrictemplate <class _Iterator, class _Sentinel> 261*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) { 262*700637cbSDimitry Andric __alloc_rr& __a = this->__alloc(); 263*700637cbSDimitry Andric for (; __first != __last; ++__first) { 264*700637cbSDimitry Andric if (__end_ == __end_cap()) { 265*700637cbSDimitry Andric size_type __old_cap = __end_cap() - __first_; 266*700637cbSDimitry Andric size_type __new_cap = std::max<size_type>(2 * __old_cap, 8); 267*700637cbSDimitry Andric __split_buffer __buf(__new_cap, 0, __a); 268*700637cbSDimitry Andric for (pointer __p = __begin_; __p != __end_; ++__p, (void)++__buf.__end_) 269*700637cbSDimitry Andric __alloc_traits::construct(__buf.__alloc(), std::__to_address(__buf.__end_), std::move(*__p)); 270*700637cbSDimitry Andric swap(__buf); 271*700637cbSDimitry Andric } 272*700637cbSDimitry Andric __alloc_traits::construct(__a, std::__to_address(this->__end_), *__first); 273*700637cbSDimitry Andric ++this->__end_; 274*700637cbSDimitry Andric } 275*700637cbSDimitry Andric} 276*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 277*700637cbSDimitry Andrictemplate <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > 278*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) { 279*700637cbSDimitry Andric __construct_at_end_with_size(__first, std::distance(__first, __last)); 280*700637cbSDimitry Andric} 281*700637cbSDimitry Andric 282*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 283*700637cbSDimitry Andrictemplate <class _ForwardIterator> 284*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) { 285*700637cbSDimitry Andric _ConstructTransaction __tx(&this->__end_, __n); 286*700637cbSDimitry Andric for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__first) { 287*700637cbSDimitry Andric __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), *__first); 288*700637cbSDimitry Andric } 289*700637cbSDimitry Andric} 290*700637cbSDimitry Andric 291*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 292*700637cbSDimitry Andricinline void __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) { 293*700637cbSDimitry Andric while (__begin_ != __new_begin) 294*700637cbSDimitry Andric __alloc_traits::destroy(__alloc(), std::__to_address(__begin_++)); 295*700637cbSDimitry Andric} 296*700637cbSDimitry Andric 297*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 298*700637cbSDimitry Andricinline void __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type) { 299*700637cbSDimitry Andric __begin_ = __new_begin; 300*700637cbSDimitry Andric} 301*700637cbSDimitry Andric 302*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 303*700637cbSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI void 304*700637cbSDimitry Andric__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT { 305*700637cbSDimitry Andric while (__new_last != __end_) 306*700637cbSDimitry Andric __alloc_traits::destroy(__alloc(), std::__to_address(--__end_)); 307*700637cbSDimitry Andric} 308*700637cbSDimitry Andric 309*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 310*700637cbSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI void 311*700637cbSDimitry Andric__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type) _NOEXCEPT { 312*700637cbSDimitry Andric __end_ = __new_last; 313*700637cbSDimitry Andric} 314*700637cbSDimitry Andric 315*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 316*700637cbSDimitry Andric__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a) 317*700637cbSDimitry Andric : __end_cap_(nullptr, __a) { 318*700637cbSDimitry Andric if (__cap == 0) { 319*700637cbSDimitry Andric __first_ = nullptr; 320*700637cbSDimitry Andric } else { 321*700637cbSDimitry Andric auto __allocation = std::__allocate_at_least(__alloc(), __cap); 322*700637cbSDimitry Andric __first_ = __allocation.ptr; 323*700637cbSDimitry Andric __cap = __allocation.count; 324*700637cbSDimitry Andric } 325*700637cbSDimitry Andric __begin_ = __end_ = __first_ + __start; 326*700637cbSDimitry Andric __end_cap() = __first_ + __cap; 327*700637cbSDimitry Andric} 328*700637cbSDimitry Andric 329*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 330*700637cbSDimitry Andric__split_buffer<_Tp, _Allocator>::~__split_buffer() { 331*700637cbSDimitry Andric clear(); 332*700637cbSDimitry Andric if (__first_) 333*700637cbSDimitry Andric __alloc_traits::deallocate(__alloc(), __first_, capacity()); 334*700637cbSDimitry Andric} 335*700637cbSDimitry Andric 336*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 337*700637cbSDimitry Andric__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c) 338*700637cbSDimitry Andric : __first_(std::move(__c.__first_)), 339*700637cbSDimitry Andric __begin_(std::move(__c.__begin_)), 340*700637cbSDimitry Andric __end_(std::move(__c.__end_)), 341*700637cbSDimitry Andric __end_cap_(std::move(__c.__end_cap_)) { 342*700637cbSDimitry Andric __c.__first_ = nullptr; 343*700637cbSDimitry Andric __c.__begin_ = nullptr; 344*700637cbSDimitry Andric __c.__end_ = nullptr; 345*700637cbSDimitry Andric __c.__end_cap() = nullptr; 346*700637cbSDimitry Andric} 347*700637cbSDimitry Andric 348*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 349*700637cbSDimitry Andric__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a) 350*700637cbSDimitry Andric : __end_cap_(nullptr, __a) { 351*700637cbSDimitry Andric if (__a == __c.__alloc()) { 352*700637cbSDimitry Andric __first_ = __c.__first_; 353*700637cbSDimitry Andric __begin_ = __c.__begin_; 354*700637cbSDimitry Andric __end_ = __c.__end_; 355*700637cbSDimitry Andric __end_cap() = __c.__end_cap(); 356*700637cbSDimitry Andric __c.__first_ = nullptr; 357*700637cbSDimitry Andric __c.__begin_ = nullptr; 358*700637cbSDimitry Andric __c.__end_ = nullptr; 359*700637cbSDimitry Andric __c.__end_cap() = nullptr; 360*700637cbSDimitry Andric } else { 361*700637cbSDimitry Andric auto __allocation = std::__allocate_at_least(__alloc(), __c.size()); 362*700637cbSDimitry Andric __first_ = __allocation.ptr; 363*700637cbSDimitry Andric __begin_ = __end_ = __first_; 364*700637cbSDimitry Andric __end_cap() = __first_ + __allocation.count; 365*700637cbSDimitry Andric typedef move_iterator<iterator> _Ip; 366*700637cbSDimitry Andric __construct_at_end(_Ip(__c.begin()), _Ip(__c.end())); 367*700637cbSDimitry Andric } 368*700637cbSDimitry Andric} 369*700637cbSDimitry Andric 370*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 371*700637cbSDimitry Andric__split_buffer<_Tp, _Allocator>& __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) { 372*700637cbSDimitry Andric clear(); 373*700637cbSDimitry Andric shrink_to_fit(); 374*700637cbSDimitry Andric __first_ = __c.__first_; 375*700637cbSDimitry Andric __begin_ = __c.__begin_; 376*700637cbSDimitry Andric __end_ = __c.__end_; 377*700637cbSDimitry Andric __end_cap() = __c.__end_cap(); 378*700637cbSDimitry Andric __move_assign_alloc(__c, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>()); 379*700637cbSDimitry Andric __c.__first_ = __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr; 380*700637cbSDimitry Andric return *this; 381*700637cbSDimitry Andric} 382*700637cbSDimitry Andric 383*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 384*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x) { 385*700637cbSDimitry Andric std::swap(__first_, __x.__first_); 386*700637cbSDimitry Andric std::swap(__begin_, __x.__begin_); 387*700637cbSDimitry Andric std::swap(__end_, __x.__end_); 388*700637cbSDimitry Andric std::swap(__end_cap(), __x.__end_cap()); 389*700637cbSDimitry Andric std::__swap_allocator(__alloc(), __x.__alloc()); 390*700637cbSDimitry Andric} 391*700637cbSDimitry Andric 392*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 393*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::reserve(size_type __n) { 394*700637cbSDimitry Andric if (__n < capacity()) { 395*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(__n, 0, __alloc()); 396*700637cbSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 397*700637cbSDimitry Andric std::swap(__first_, __t.__first_); 398*700637cbSDimitry Andric std::swap(__begin_, __t.__begin_); 399*700637cbSDimitry Andric std::swap(__end_, __t.__end_); 400*700637cbSDimitry Andric std::swap(__end_cap(), __t.__end_cap()); 401*700637cbSDimitry Andric } 402*700637cbSDimitry Andric} 403*700637cbSDimitry Andric 404*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 405*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { 406*700637cbSDimitry Andric if (capacity() > size()) { 407*700637cbSDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 408*700637cbSDimitry Andric try { 409*700637cbSDimitry Andric#endif // _LIBCPP_HAS_NO_EXCEPTIONS 410*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __alloc()); 411*700637cbSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 412*700637cbSDimitry Andric __t.__end_ = __t.__begin_ + (__end_ - __begin_); 413*700637cbSDimitry Andric std::swap(__first_, __t.__first_); 414*700637cbSDimitry Andric std::swap(__begin_, __t.__begin_); 415*700637cbSDimitry Andric std::swap(__end_, __t.__end_); 416*700637cbSDimitry Andric std::swap(__end_cap(), __t.__end_cap()); 417*700637cbSDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS 418*700637cbSDimitry Andric } catch (...) { 419*700637cbSDimitry Andric } 420*700637cbSDimitry Andric#endif // _LIBCPP_HAS_NO_EXCEPTIONS 421*700637cbSDimitry Andric } 422*700637cbSDimitry Andric} 423*700637cbSDimitry Andric 424*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 425*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) { 426*700637cbSDimitry Andric if (__begin_ == __first_) { 427*700637cbSDimitry Andric if (__end_ < __end_cap()) { 428*700637cbSDimitry Andric difference_type __d = __end_cap() - __end_; 429*700637cbSDimitry Andric __d = (__d + 1) / 2; 430*700637cbSDimitry Andric __begin_ = std::move_backward(__begin_, __end_, __end_ + __d); 431*700637cbSDimitry Andric __end_ += __d; 432*700637cbSDimitry Andric } else { 433*700637cbSDimitry Andric size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 434*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc()); 435*700637cbSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 436*700637cbSDimitry Andric std::swap(__first_, __t.__first_); 437*700637cbSDimitry Andric std::swap(__begin_, __t.__begin_); 438*700637cbSDimitry Andric std::swap(__end_, __t.__end_); 439*700637cbSDimitry Andric std::swap(__end_cap(), __t.__end_cap()); 440*700637cbSDimitry Andric } 441*700637cbSDimitry Andric } 442*700637cbSDimitry Andric __alloc_traits::construct(__alloc(), std::__to_address(__begin_ - 1), __x); 443*700637cbSDimitry Andric --__begin_; 444*700637cbSDimitry Andric} 445*700637cbSDimitry Andric 446*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 447*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) { 448*700637cbSDimitry Andric if (__begin_ == __first_) { 449*700637cbSDimitry Andric if (__end_ < __end_cap()) { 450*700637cbSDimitry Andric difference_type __d = __end_cap() - __end_; 451*700637cbSDimitry Andric __d = (__d + 1) / 2; 452*700637cbSDimitry Andric __begin_ = std::move_backward(__begin_, __end_, __end_ + __d); 453*700637cbSDimitry Andric __end_ += __d; 454*700637cbSDimitry Andric } else { 455*700637cbSDimitry Andric size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 456*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc()); 457*700637cbSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 458*700637cbSDimitry Andric std::swap(__first_, __t.__first_); 459*700637cbSDimitry Andric std::swap(__begin_, __t.__begin_); 460*700637cbSDimitry Andric std::swap(__end_, __t.__end_); 461*700637cbSDimitry Andric std::swap(__end_cap(), __t.__end_cap()); 462*700637cbSDimitry Andric } 463*700637cbSDimitry Andric } 464*700637cbSDimitry Andric __alloc_traits::construct(__alloc(), std::__to_address(__begin_ - 1), std::move(__x)); 465*700637cbSDimitry Andric --__begin_; 466*700637cbSDimitry Andric} 467*700637cbSDimitry Andric 468*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 469*700637cbSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI void __split_buffer<_Tp, _Allocator>::push_back(const_reference __x) { 470*700637cbSDimitry Andric if (__end_ == __end_cap()) { 471*700637cbSDimitry Andric if (__begin_ > __first_) { 472*700637cbSDimitry Andric difference_type __d = __begin_ - __first_; 473*700637cbSDimitry Andric __d = (__d + 1) / 2; 474*700637cbSDimitry Andric __end_ = std::move(__begin_, __end_, __begin_ - __d); 475*700637cbSDimitry Andric __begin_ -= __d; 476*700637cbSDimitry Andric } else { 477*700637cbSDimitry Andric size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 478*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc()); 479*700637cbSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 480*700637cbSDimitry Andric std::swap(__first_, __t.__first_); 481*700637cbSDimitry Andric std::swap(__begin_, __t.__begin_); 482*700637cbSDimitry Andric std::swap(__end_, __t.__end_); 483*700637cbSDimitry Andric std::swap(__end_cap(), __t.__end_cap()); 484*700637cbSDimitry Andric } 485*700637cbSDimitry Andric } 486*700637cbSDimitry Andric __alloc_traits::construct(__alloc(), std::__to_address(__end_), __x); 487*700637cbSDimitry Andric ++__end_; 488*700637cbSDimitry Andric} 489*700637cbSDimitry Andric 490*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 491*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) { 492*700637cbSDimitry Andric if (__end_ == __end_cap()) { 493*700637cbSDimitry Andric if (__begin_ > __first_) { 494*700637cbSDimitry Andric difference_type __d = __begin_ - __first_; 495*700637cbSDimitry Andric __d = (__d + 1) / 2; 496*700637cbSDimitry Andric __end_ = std::move(__begin_, __end_, __begin_ - __d); 497*700637cbSDimitry Andric __begin_ -= __d; 498*700637cbSDimitry Andric } else { 499*700637cbSDimitry Andric size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 500*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc()); 501*700637cbSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 502*700637cbSDimitry Andric std::swap(__first_, __t.__first_); 503*700637cbSDimitry Andric std::swap(__begin_, __t.__begin_); 504*700637cbSDimitry Andric std::swap(__end_, __t.__end_); 505*700637cbSDimitry Andric std::swap(__end_cap(), __t.__end_cap()); 506*700637cbSDimitry Andric } 507*700637cbSDimitry Andric } 508*700637cbSDimitry Andric __alloc_traits::construct(__alloc(), std::__to_address(__end_), std::move(__x)); 509*700637cbSDimitry Andric ++__end_; 510*700637cbSDimitry Andric} 511*700637cbSDimitry Andric 512*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 513*700637cbSDimitry Andrictemplate <class... _Args> 514*700637cbSDimitry Andricvoid __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) { 515*700637cbSDimitry Andric if (__end_ == __end_cap()) { 516*700637cbSDimitry Andric if (__begin_ > __first_) { 517*700637cbSDimitry Andric difference_type __d = __begin_ - __first_; 518*700637cbSDimitry Andric __d = (__d + 1) / 2; 519*700637cbSDimitry Andric __end_ = std::move(__begin_, __end_, __begin_ - __d); 520*700637cbSDimitry Andric __begin_ -= __d; 521*700637cbSDimitry Andric } else { 522*700637cbSDimitry Andric size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); 523*700637cbSDimitry Andric __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc()); 524*700637cbSDimitry Andric __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); 525*700637cbSDimitry Andric std::swap(__first_, __t.__first_); 526*700637cbSDimitry Andric std::swap(__begin_, __t.__begin_); 527*700637cbSDimitry Andric std::swap(__end_, __t.__end_); 528*700637cbSDimitry Andric std::swap(__end_cap(), __t.__end_cap()); 529*700637cbSDimitry Andric } 530*700637cbSDimitry Andric } 531*700637cbSDimitry Andric __alloc_traits::construct(__alloc(), std::__to_address(__end_), std::forward<_Args>(__args)...); 532*700637cbSDimitry Andric ++__end_; 533*700637cbSDimitry Andric} 534*700637cbSDimitry Andric 535*700637cbSDimitry Andrictemplate <class _Tp, class _Allocator> 536*700637cbSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) { 537*700637cbSDimitry Andric __x.swap(__y); 538*700637cbSDimitry Andric} 539*700637cbSDimitry Andric 540*700637cbSDimitry Andric_LIBCPP_END_NAMESPACE_STD 541*700637cbSDimitry Andric 542*700637cbSDimitry Andric_LIBCPP_POP_MACROS 543*700637cbSDimitry Andric 544*700637cbSDimitry Andric#endif // _LIBCPP___CXX03___SPLIT_BUFFER 545