xref: /freebsd/contrib/llvm-project/libcxx/include/__cxx03/__split_buffer (revision 700637cbb5e582861067a11aaca4d053546871d2)
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