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