xref: /openbsd-src/gnu/llvm/libcxx/include/__split_buffer (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
146035553Spatrick// -*- C++ -*-
2*4bdff4beSrobert//===----------------------------------------------------------------------===//
3*4bdff4beSrobert//
4*4bdff4beSrobert// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*4bdff4beSrobert// See https://llvm.org/LICENSE.txt for license information.
6*4bdff4beSrobert// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*4bdff4beSrobert//
8*4bdff4beSrobert//===----------------------------------------------------------------------===//
946035553Spatrick
10*4bdff4beSrobert#ifndef _LIBCPP___SPLIT_BUFFER
11*4bdff4beSrobert#define _LIBCPP___SPLIT_BUFFER
12*4bdff4beSrobert
13*4bdff4beSrobert#include <__algorithm/max.h>
14*4bdff4beSrobert#include <__algorithm/move.h>
15*4bdff4beSrobert#include <__algorithm/move_backward.h>
1646035553Spatrick#include <__config>
17*4bdff4beSrobert#include <__iterator/distance.h>
18*4bdff4beSrobert#include <__iterator/iterator_traits.h>
19*4bdff4beSrobert#include <__iterator/move_iterator.h>
20*4bdff4beSrobert#include <__memory/allocate_at_least.h>
21*4bdff4beSrobert#include <__memory/allocator.h>
22*4bdff4beSrobert#include <__memory/allocator_traits.h>
23*4bdff4beSrobert#include <__memory/compressed_pair.h>
24*4bdff4beSrobert#include <__memory/pointer_traits.h>
25*4bdff4beSrobert#include <__memory/swap_allocator.h>
2676d0caaeSpatrick#include <__utility/forward.h>
27*4bdff4beSrobert#include <__utility/move.h>
2876d0caaeSpatrick#include <type_traits>
2946035553Spatrick
3046035553Spatrick#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
3146035553Spatrick#  pragma GCC system_header
3246035553Spatrick#endif
3346035553Spatrick
3446035553Spatrick_LIBCPP_PUSH_MACROS
3546035553Spatrick#include <__undef_macros>
3646035553Spatrick
3746035553Spatrick
3846035553Spatrick_LIBCPP_BEGIN_NAMESPACE_STD
3946035553Spatrick
40*4bdff4beSrobert// __split_buffer allocates a contiguous chunk of memory and stores objects in the range [__begin_, __end_).
41*4bdff4beSrobert// It has uninitialized memory in the ranges  [__first_, __begin_) and [__end_, __end_cap_.first()). That allows
42*4bdff4beSrobert// it to grow both in the front and back without having to move the data.
4346035553Spatrick
4446035553Spatricktemplate <class _Tp, class _Allocator = allocator<_Tp> >
4546035553Spatrickstruct __split_buffer
4646035553Spatrick{
4746035553Spatrickprivate:
4846035553Spatrick    __split_buffer(const __split_buffer&);
4946035553Spatrick    __split_buffer& operator=(const __split_buffer&);
5046035553Spatrickpublic:
5146035553Spatrick    typedef _Tp                                             value_type;
5246035553Spatrick    typedef _Allocator                                      allocator_type;
53*4bdff4beSrobert    typedef __libcpp_remove_reference_t<allocator_type>     __alloc_rr;
5446035553Spatrick    typedef allocator_traits<__alloc_rr>                    __alloc_traits;
5546035553Spatrick    typedef value_type&                                     reference;
5646035553Spatrick    typedef const value_type&                               const_reference;
5746035553Spatrick    typedef typename __alloc_traits::size_type              size_type;
5846035553Spatrick    typedef typename __alloc_traits::difference_type        difference_type;
5946035553Spatrick    typedef typename __alloc_traits::pointer                pointer;
6046035553Spatrick    typedef typename __alloc_traits::const_pointer          const_pointer;
6146035553Spatrick    typedef pointer                                         iterator;
6246035553Spatrick    typedef const_pointer                                   const_iterator;
6346035553Spatrick
6446035553Spatrick    pointer                                         __first_;
6546035553Spatrick    pointer                                         __begin_;
6646035553Spatrick    pointer                                         __end_;
6746035553Spatrick    __compressed_pair<pointer, allocator_type> __end_cap_;
6846035553Spatrick
69*4bdff4beSrobert    typedef __add_lvalue_reference_t<allocator_type> __alloc_ref;
70*4bdff4beSrobert    typedef __add_lvalue_reference_t<allocator_type> __alloc_const_ref;
7146035553Spatrick
72*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __alloc_rr&           __alloc() _NOEXCEPT         {return __end_cap_.second();}
73*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const __alloc_rr&     __alloc() const _NOEXCEPT   {return __end_cap_.second();}
74*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer&              __end_cap() _NOEXCEPT       {return __end_cap_.first();}
75*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer&        __end_cap() const _NOEXCEPT {return __end_cap_.first();}
7646035553Spatrick
77*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
7846035553Spatrick    __split_buffer()
7946035553Spatrick        _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value);
80*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
8146035553Spatrick    explicit __split_buffer(__alloc_rr& __a);
82*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
8346035553Spatrick    explicit __split_buffer(const __alloc_rr& __a);
84*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a);
85*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer();
8646035553Spatrick
87*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c)
8846035553Spatrick        _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
89*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const __alloc_rr& __a);
90*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer& operator=(__split_buffer&& __c)
9146035553Spatrick        _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
9246035553Spatrick                is_nothrow_move_assignable<allocator_type>::value) ||
9346035553Spatrick               !__alloc_traits::propagate_on_container_move_assignment::value);
9446035553Spatrick
95*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI       iterator begin() _NOEXCEPT       {return __begin_;}
96*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {return __begin_;}
97*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI       iterator end() _NOEXCEPT         {return __end_;}
98*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT   {return __end_;}
9946035553Spatrick
100*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
10146035553Spatrick    void clear() _NOEXCEPT
10246035553Spatrick        {__destruct_at_end(__begin_);}
103*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const {return static_cast<size_type>(__end_ - __begin_);}
104*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty()     const {return __end_ == __begin_;}
105*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const {return static_cast<size_type>(__end_cap() - __first_);}
106*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const {return static_cast<size_type>(__begin_ - __first_);}
107*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const {return static_cast<size_type>(__end_cap() - __end_);}
10846035553Spatrick
109*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI       reference front()       {return *__begin_;}
110*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const {return *__begin_;}
111*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI       reference back()        {return *(__end_ - 1);}
112*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const  {return *(__end_ - 1);}
11346035553Spatrick
114*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
115*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
116*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(const_reference __x);
117*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x);
118*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x);
119*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x);
12046035553Spatrick    template <class... _Args>
121*4bdff4beSrobert        _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args);
12246035553Spatrick
123*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() {__destruct_at_begin(__begin_+1);}
124*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {__destruct_at_end(__end_-1);}
12546035553Spatrick
126*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n);
127*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x);
12846035553Spatrick    template <class _InputIter>
129*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value>
13046035553Spatrick        __construct_at_end(_InputIter __first, _InputIter __last);
13146035553Spatrick    template <class _ForwardIterator>
132*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value>
13346035553Spatrick        __construct_at_end(_ForwardIterator __first, _ForwardIterator __last);
13446035553Spatrick
135*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin)
13646035553Spatrick        {__destruct_at_begin(__new_begin, is_trivially_destructible<value_type>());}
137*4bdff4beSrobert        _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
13846035553Spatrick        void __destruct_at_begin(pointer __new_begin, false_type);
139*4bdff4beSrobert        _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
14046035553Spatrick        void __destruct_at_begin(pointer __new_begin, true_type);
14146035553Spatrick
142*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
14346035553Spatrick    void __destruct_at_end(pointer __new_last) _NOEXCEPT
14446035553Spatrick        {__destruct_at_end(__new_last, false_type());}
145*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
14646035553Spatrick        void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT;
147*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
14846035553Spatrick        void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT;
14946035553Spatrick
150*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x)
15146035553Spatrick        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value||
15246035553Spatrick                   __is_nothrow_swappable<__alloc_rr>::value);
15346035553Spatrick
154*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
15546035553Spatrick
15646035553Spatrickprivate:
157*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
15846035553Spatrick    void __move_assign_alloc(__split_buffer& __c, true_type)
15946035553Spatrick        _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
16046035553Spatrick        {
16146035553Spatrick            __alloc() = _VSTD::move(__c.__alloc());
16246035553Spatrick        }
16346035553Spatrick
164*4bdff4beSrobert    _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
16546035553Spatrick    void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT
16646035553Spatrick        {}
16746035553Spatrick
16846035553Spatrick    struct _ConstructTransaction {
169*4bdff4beSrobert      _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT
17046035553Spatrick      : __pos_(*__p), __end_(*__p + __n), __dest_(__p) {
17146035553Spatrick      }
172*4bdff4beSrobert      _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
17346035553Spatrick        *__dest_ = __pos_;
17446035553Spatrick      }
17546035553Spatrick      pointer __pos_;
17646035553Spatrick     const pointer __end_;
17746035553Spatrick    private:
17846035553Spatrick     pointer *__dest_;
17946035553Spatrick    };
18046035553Spatrick};
18146035553Spatrick
18246035553Spatricktemplate <class _Tp, class _Allocator>
183*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
18446035553Spatrickbool
18546035553Spatrick__split_buffer<_Tp, _Allocator>::__invariants() const
18646035553Spatrick{
18746035553Spatrick    if (__first_ == nullptr)
18846035553Spatrick    {
18946035553Spatrick        if (__begin_ != nullptr)
19046035553Spatrick            return false;
19146035553Spatrick        if (__end_ != nullptr)
19246035553Spatrick            return false;
19346035553Spatrick        if (__end_cap() != nullptr)
19446035553Spatrick            return false;
19546035553Spatrick    }
19646035553Spatrick    else
19746035553Spatrick    {
19846035553Spatrick        if (__begin_ < __first_)
19946035553Spatrick            return false;
20046035553Spatrick        if (__end_ < __begin_)
20146035553Spatrick            return false;
20246035553Spatrick        if (__end_cap() < __end_)
20346035553Spatrick            return false;
20446035553Spatrick    }
20546035553Spatrick    return true;
20646035553Spatrick}
20746035553Spatrick
20846035553Spatrick//  Default constructs __n objects starting at __end_
20946035553Spatrick//  throws if construction throws
21046035553Spatrick//  Precondition:  __n > 0
21146035553Spatrick//  Precondition:  size() + __n <= capacity()
21246035553Spatrick//  Postcondition:  size() == size() + __n
21346035553Spatricktemplate <class _Tp, class _Allocator>
214*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
21546035553Spatrickvoid
21646035553Spatrick__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n)
21746035553Spatrick{
21846035553Spatrick    _ConstructTransaction __tx(&this->__end_, __n);
21946035553Spatrick    for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
22046035553Spatrick        __alloc_traits::construct(this->__alloc(), _VSTD::__to_address(__tx.__pos_));
22146035553Spatrick    }
22246035553Spatrick}
22346035553Spatrick
22446035553Spatrick//  Copy constructs __n objects starting at __end_ from __x
22546035553Spatrick//  throws if construction throws
22646035553Spatrick//  Precondition:  __n > 0
22746035553Spatrick//  Precondition:  size() + __n <= capacity()
22846035553Spatrick//  Postcondition:  size() == old size() + __n
22946035553Spatrick//  Postcondition:  [i] == __x for all i in [size() - __n, __n)
23046035553Spatricktemplate <class _Tp, class _Allocator>
231*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
23246035553Spatrickvoid
23346035553Spatrick__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x)
23446035553Spatrick{
23546035553Spatrick    _ConstructTransaction __tx(&this->__end_, __n);
23646035553Spatrick    for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
23746035553Spatrick        __alloc_traits::construct(this->__alloc(),
23846035553Spatrick            _VSTD::__to_address(__tx.__pos_), __x);
23946035553Spatrick    }
24046035553Spatrick}
24146035553Spatrick
24246035553Spatricktemplate <class _Tp, class _Allocator>
24346035553Spatricktemplate <class _InputIter>
244*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value>
24546035553Spatrick__split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIter __last)
24646035553Spatrick{
24746035553Spatrick    __alloc_rr& __a = this->__alloc();
24846035553Spatrick    for (; __first != __last; ++__first)
24946035553Spatrick    {
25046035553Spatrick        if (__end_ == __end_cap())
25146035553Spatrick        {
25246035553Spatrick            size_type __old_cap = __end_cap() - __first_;
25346035553Spatrick            size_type __new_cap = _VSTD::max<size_type>(2 * __old_cap, 8);
25446035553Spatrick            __split_buffer __buf(__new_cap, 0, __a);
255*4bdff4beSrobert            for (pointer __p = __begin_; __p != __end_; ++__p, (void) ++__buf.__end_)
25646035553Spatrick                __alloc_traits::construct(__buf.__alloc(),
25746035553Spatrick                        _VSTD::__to_address(__buf.__end_), _VSTD::move(*__p));
25846035553Spatrick            swap(__buf);
25946035553Spatrick        }
26046035553Spatrick        __alloc_traits::construct(__a, _VSTD::__to_address(this->__end_), *__first);
26146035553Spatrick        ++this->__end_;
26246035553Spatrick    }
26346035553Spatrick}
26446035553Spatrick
26546035553Spatricktemplate <class _Tp, class _Allocator>
26646035553Spatricktemplate <class _ForwardIterator>
267*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value>
26846035553Spatrick__split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last)
26946035553Spatrick{
27076d0caaeSpatrick    _ConstructTransaction __tx(&this->__end_, _VSTD::distance(__first, __last));
271*4bdff4beSrobert    for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void) ++__first) {
27246035553Spatrick        __alloc_traits::construct(this->__alloc(),
27346035553Spatrick            _VSTD::__to_address(__tx.__pos_), *__first);
27446035553Spatrick    }
27546035553Spatrick}
27646035553Spatrick
27746035553Spatricktemplate <class _Tp, class _Allocator>
278*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
27946035553Spatrickinline
28046035553Spatrickvoid
28146035553Spatrick__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type)
28246035553Spatrick{
28346035553Spatrick    while (__begin_ != __new_begin)
28476d0caaeSpatrick        __alloc_traits::destroy(__alloc(), _VSTD::__to_address(__begin_++));
28546035553Spatrick}
28646035553Spatrick
28746035553Spatricktemplate <class _Tp, class _Allocator>
288*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
28946035553Spatrickinline
29046035553Spatrickvoid
29146035553Spatrick__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type)
29246035553Spatrick{
29346035553Spatrick    __begin_ = __new_begin;
29446035553Spatrick}
29546035553Spatrick
29646035553Spatricktemplate <class _Tp, class _Allocator>
297*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
298*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI
29946035553Spatrickvoid
30046035553Spatrick__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT
30146035553Spatrick{
30246035553Spatrick    while (__new_last != __end_)
30376d0caaeSpatrick        __alloc_traits::destroy(__alloc(), _VSTD::__to_address(--__end_));
30446035553Spatrick}
30546035553Spatrick
30646035553Spatricktemplate <class _Tp, class _Allocator>
307*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
308*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI
30946035553Spatrickvoid
31046035553Spatrick__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type) _NOEXCEPT
31146035553Spatrick{
31246035553Spatrick    __end_ = __new_last;
31346035553Spatrick}
31446035553Spatrick
31546035553Spatricktemplate <class _Tp, class _Allocator>
316*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
31746035553Spatrick__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
31846035553Spatrick    : __end_cap_(nullptr, __a)
31946035553Spatrick{
320*4bdff4beSrobert    if (__cap == 0) {
321*4bdff4beSrobert        __first_ = nullptr;
322*4bdff4beSrobert    } else {
323*4bdff4beSrobert        auto __allocation = std::__allocate_at_least(__alloc(), __cap);
324*4bdff4beSrobert        __first_ = __allocation.ptr;
325*4bdff4beSrobert        __cap = __allocation.count;
326*4bdff4beSrobert    }
32746035553Spatrick    __begin_ = __end_ = __first_ + __start;
32846035553Spatrick    __end_cap() = __first_ + __cap;
32946035553Spatrick}
33046035553Spatrick
33146035553Spatricktemplate <class _Tp, class _Allocator>
332*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
33346035553Spatrickinline
33446035553Spatrick__split_buffer<_Tp, _Allocator>::__split_buffer()
33546035553Spatrick    _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
33646035553Spatrick    : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __default_init_tag())
33746035553Spatrick{
33846035553Spatrick}
33946035553Spatrick
34046035553Spatricktemplate <class _Tp, class _Allocator>
341*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
34246035553Spatrickinline
34346035553Spatrick__split_buffer<_Tp, _Allocator>::__split_buffer(__alloc_rr& __a)
34446035553Spatrick    : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a)
34546035553Spatrick{
34646035553Spatrick}
34746035553Spatrick
34846035553Spatricktemplate <class _Tp, class _Allocator>
349*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
35046035553Spatrickinline
35146035553Spatrick__split_buffer<_Tp, _Allocator>::__split_buffer(const __alloc_rr& __a)
35246035553Spatrick    : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a)
35346035553Spatrick{
35446035553Spatrick}
35546035553Spatrick
35646035553Spatricktemplate <class _Tp, class _Allocator>
357*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
35846035553Spatrick__split_buffer<_Tp, _Allocator>::~__split_buffer()
35946035553Spatrick{
36046035553Spatrick    clear();
36146035553Spatrick    if (__first_)
36246035553Spatrick        __alloc_traits::deallocate(__alloc(), __first_, capacity());
36346035553Spatrick}
36446035553Spatrick
36546035553Spatricktemplate <class _Tp, class _Allocator>
366*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
36746035553Spatrick__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c)
36846035553Spatrick    _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
36946035553Spatrick    : __first_(_VSTD::move(__c.__first_)),
37046035553Spatrick      __begin_(_VSTD::move(__c.__begin_)),
37146035553Spatrick      __end_(_VSTD::move(__c.__end_)),
37246035553Spatrick      __end_cap_(_VSTD::move(__c.__end_cap_))
37346035553Spatrick{
37446035553Spatrick    __c.__first_ = nullptr;
37546035553Spatrick    __c.__begin_ = nullptr;
37646035553Spatrick    __c.__end_ = nullptr;
37746035553Spatrick    __c.__end_cap() = nullptr;
37846035553Spatrick}
37946035553Spatrick
38046035553Spatricktemplate <class _Tp, class _Allocator>
381*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
38246035553Spatrick__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
38346035553Spatrick    : __end_cap_(nullptr, __a)
38446035553Spatrick{
38546035553Spatrick    if (__a == __c.__alloc())
38646035553Spatrick    {
38746035553Spatrick        __first_ = __c.__first_;
38846035553Spatrick        __begin_ = __c.__begin_;
38946035553Spatrick        __end_ = __c.__end_;
39046035553Spatrick        __end_cap() = __c.__end_cap();
39146035553Spatrick        __c.__first_ = nullptr;
39246035553Spatrick        __c.__begin_ = nullptr;
39346035553Spatrick        __c.__end_ = nullptr;
39446035553Spatrick        __c.__end_cap() = nullptr;
39546035553Spatrick    }
39646035553Spatrick    else
39746035553Spatrick    {
398*4bdff4beSrobert        auto __allocation = std::__allocate_at_least(__alloc(), __c.size());
399*4bdff4beSrobert        __first_ = __allocation.ptr;
40046035553Spatrick        __begin_ = __end_ = __first_;
401*4bdff4beSrobert        __end_cap() = __first_ + __allocation.count;
40246035553Spatrick        typedef move_iterator<iterator> _Ip;
40346035553Spatrick        __construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
40446035553Spatrick    }
40546035553Spatrick}
40646035553Spatrick
40746035553Spatricktemplate <class _Tp, class _Allocator>
408*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
40946035553Spatrick__split_buffer<_Tp, _Allocator>&
41046035553Spatrick__split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c)
41146035553Spatrick    _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
41246035553Spatrick                is_nothrow_move_assignable<allocator_type>::value) ||
41346035553Spatrick               !__alloc_traits::propagate_on_container_move_assignment::value)
41446035553Spatrick{
41546035553Spatrick    clear();
41646035553Spatrick    shrink_to_fit();
41746035553Spatrick    __first_ = __c.__first_;
41846035553Spatrick    __begin_ = __c.__begin_;
41946035553Spatrick    __end_ = __c.__end_;
42046035553Spatrick    __end_cap() = __c.__end_cap();
42146035553Spatrick    __move_assign_alloc(__c,
42246035553Spatrick        integral_constant<bool,
42346035553Spatrick                          __alloc_traits::propagate_on_container_move_assignment::value>());
42446035553Spatrick    __c.__first_ = __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr;
42546035553Spatrick    return *this;
42646035553Spatrick}
42746035553Spatrick
42846035553Spatricktemplate <class _Tp, class _Allocator>
429*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
43046035553Spatrickvoid
43146035553Spatrick__split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x)
43246035553Spatrick        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value||
43346035553Spatrick                   __is_nothrow_swappable<__alloc_rr>::value)
43446035553Spatrick{
43546035553Spatrick    _VSTD::swap(__first_, __x.__first_);
43646035553Spatrick    _VSTD::swap(__begin_, __x.__begin_);
43746035553Spatrick    _VSTD::swap(__end_, __x.__end_);
43846035553Spatrick    _VSTD::swap(__end_cap(), __x.__end_cap());
43976d0caaeSpatrick    _VSTD::__swap_allocator(__alloc(), __x.__alloc());
44046035553Spatrick}
44146035553Spatrick
44246035553Spatricktemplate <class _Tp, class _Allocator>
443*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
44446035553Spatrickvoid
44546035553Spatrick__split_buffer<_Tp, _Allocator>::reserve(size_type __n)
44646035553Spatrick{
44746035553Spatrick    if (__n < capacity())
44846035553Spatrick    {
44946035553Spatrick        __split_buffer<value_type, __alloc_rr&> __t(__n, 0, __alloc());
45046035553Spatrick        __t.__construct_at_end(move_iterator<pointer>(__begin_),
45146035553Spatrick                               move_iterator<pointer>(__end_));
45246035553Spatrick        _VSTD::swap(__first_, __t.__first_);
45346035553Spatrick        _VSTD::swap(__begin_, __t.__begin_);
45446035553Spatrick        _VSTD::swap(__end_, __t.__end_);
45546035553Spatrick        _VSTD::swap(__end_cap(), __t.__end_cap());
45646035553Spatrick    }
45746035553Spatrick}
45846035553Spatrick
45946035553Spatricktemplate <class _Tp, class _Allocator>
460*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
46146035553Spatrickvoid
46246035553Spatrick__split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT
46346035553Spatrick{
46446035553Spatrick    if (capacity() > size())
46546035553Spatrick    {
46646035553Spatrick#ifndef _LIBCPP_NO_EXCEPTIONS
46746035553Spatrick        try
46846035553Spatrick        {
46946035553Spatrick#endif // _LIBCPP_NO_EXCEPTIONS
47046035553Spatrick            __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __alloc());
47146035553Spatrick            __t.__construct_at_end(move_iterator<pointer>(__begin_),
47246035553Spatrick                                   move_iterator<pointer>(__end_));
47346035553Spatrick            __t.__end_ = __t.__begin_ + (__end_ - __begin_);
47446035553Spatrick            _VSTD::swap(__first_, __t.__first_);
47546035553Spatrick            _VSTD::swap(__begin_, __t.__begin_);
47646035553Spatrick            _VSTD::swap(__end_, __t.__end_);
47746035553Spatrick            _VSTD::swap(__end_cap(), __t.__end_cap());
47846035553Spatrick#ifndef _LIBCPP_NO_EXCEPTIONS
47946035553Spatrick        }
48046035553Spatrick        catch (...)
48146035553Spatrick        {
48246035553Spatrick        }
48346035553Spatrick#endif // _LIBCPP_NO_EXCEPTIONS
48446035553Spatrick    }
48546035553Spatrick}
48646035553Spatrick
48746035553Spatricktemplate <class _Tp, class _Allocator>
488*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
48946035553Spatrickvoid
49046035553Spatrick__split_buffer<_Tp, _Allocator>::push_front(const_reference __x)
49146035553Spatrick{
49246035553Spatrick    if (__begin_ == __first_)
49346035553Spatrick    {
49446035553Spatrick        if (__end_ < __end_cap())
49546035553Spatrick        {
49646035553Spatrick            difference_type __d = __end_cap() - __end_;
49746035553Spatrick            __d = (__d + 1) / 2;
49846035553Spatrick            __begin_ = _VSTD::move_backward(__begin_, __end_, __end_ + __d);
49946035553Spatrick            __end_ += __d;
50046035553Spatrick        }
50146035553Spatrick        else
50246035553Spatrick        {
503*4bdff4beSrobert            size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
50446035553Spatrick            __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc());
50546035553Spatrick            __t.__construct_at_end(move_iterator<pointer>(__begin_),
50646035553Spatrick                                   move_iterator<pointer>(__end_));
50746035553Spatrick            _VSTD::swap(__first_, __t.__first_);
50846035553Spatrick            _VSTD::swap(__begin_, __t.__begin_);
50946035553Spatrick            _VSTD::swap(__end_, __t.__end_);
51046035553Spatrick            _VSTD::swap(__end_cap(), __t.__end_cap());
51146035553Spatrick        }
51246035553Spatrick    }
51346035553Spatrick    __alloc_traits::construct(__alloc(), _VSTD::__to_address(__begin_-1), __x);
51446035553Spatrick    --__begin_;
51546035553Spatrick}
51646035553Spatrick
51746035553Spatricktemplate <class _Tp, class _Allocator>
518*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
51946035553Spatrickvoid
52046035553Spatrick__split_buffer<_Tp, _Allocator>::push_front(value_type&& __x)
52146035553Spatrick{
52246035553Spatrick    if (__begin_ == __first_)
52346035553Spatrick    {
52446035553Spatrick        if (__end_ < __end_cap())
52546035553Spatrick        {
52646035553Spatrick            difference_type __d = __end_cap() - __end_;
52746035553Spatrick            __d = (__d + 1) / 2;
52846035553Spatrick            __begin_ = _VSTD::move_backward(__begin_, __end_, __end_ + __d);
52946035553Spatrick            __end_ += __d;
53046035553Spatrick        }
53146035553Spatrick        else
53246035553Spatrick        {
533*4bdff4beSrobert            size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
53446035553Spatrick            __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc());
53546035553Spatrick            __t.__construct_at_end(move_iterator<pointer>(__begin_),
53646035553Spatrick                                   move_iterator<pointer>(__end_));
53746035553Spatrick            _VSTD::swap(__first_, __t.__first_);
53846035553Spatrick            _VSTD::swap(__begin_, __t.__begin_);
53946035553Spatrick            _VSTD::swap(__end_, __t.__end_);
54046035553Spatrick            _VSTD::swap(__end_cap(), __t.__end_cap());
54146035553Spatrick        }
54246035553Spatrick    }
54346035553Spatrick    __alloc_traits::construct(__alloc(), _VSTD::__to_address(__begin_-1),
54446035553Spatrick            _VSTD::move(__x));
54546035553Spatrick    --__begin_;
54646035553Spatrick}
54746035553Spatrick
54846035553Spatricktemplate <class _Tp, class _Allocator>
549*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
550*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI
55146035553Spatrickvoid
55246035553Spatrick__split_buffer<_Tp, _Allocator>::push_back(const_reference __x)
55346035553Spatrick{
55446035553Spatrick    if (__end_ == __end_cap())
55546035553Spatrick    {
55646035553Spatrick        if (__begin_ > __first_)
55746035553Spatrick        {
55846035553Spatrick            difference_type __d = __begin_ - __first_;
55946035553Spatrick            __d = (__d + 1) / 2;
56046035553Spatrick            __end_ = _VSTD::move(__begin_, __end_, __begin_ - __d);
56146035553Spatrick            __begin_ -= __d;
56246035553Spatrick        }
56346035553Spatrick        else
56446035553Spatrick        {
565*4bdff4beSrobert            size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
56646035553Spatrick            __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc());
56746035553Spatrick            __t.__construct_at_end(move_iterator<pointer>(__begin_),
56846035553Spatrick                                   move_iterator<pointer>(__end_));
56946035553Spatrick            _VSTD::swap(__first_, __t.__first_);
57046035553Spatrick            _VSTD::swap(__begin_, __t.__begin_);
57146035553Spatrick            _VSTD::swap(__end_, __t.__end_);
57246035553Spatrick            _VSTD::swap(__end_cap(), __t.__end_cap());
57346035553Spatrick        }
57446035553Spatrick    }
57546035553Spatrick    __alloc_traits::construct(__alloc(), _VSTD::__to_address(__end_), __x);
57646035553Spatrick    ++__end_;
57746035553Spatrick}
57846035553Spatrick
57946035553Spatricktemplate <class _Tp, class _Allocator>
580*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
58146035553Spatrickvoid
58246035553Spatrick__split_buffer<_Tp, _Allocator>::push_back(value_type&& __x)
58346035553Spatrick{
58446035553Spatrick    if (__end_ == __end_cap())
58546035553Spatrick    {
58646035553Spatrick        if (__begin_ > __first_)
58746035553Spatrick        {
58846035553Spatrick            difference_type __d = __begin_ - __first_;
58946035553Spatrick            __d = (__d + 1) / 2;
59046035553Spatrick            __end_ = _VSTD::move(__begin_, __end_, __begin_ - __d);
59146035553Spatrick            __begin_ -= __d;
59246035553Spatrick        }
59346035553Spatrick        else
59446035553Spatrick        {
595*4bdff4beSrobert            size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
59646035553Spatrick            __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc());
59746035553Spatrick            __t.__construct_at_end(move_iterator<pointer>(__begin_),
59846035553Spatrick                                   move_iterator<pointer>(__end_));
59946035553Spatrick            _VSTD::swap(__first_, __t.__first_);
60046035553Spatrick            _VSTD::swap(__begin_, __t.__begin_);
60146035553Spatrick            _VSTD::swap(__end_, __t.__end_);
60246035553Spatrick            _VSTD::swap(__end_cap(), __t.__end_cap());
60346035553Spatrick        }
60446035553Spatrick    }
60546035553Spatrick    __alloc_traits::construct(__alloc(), _VSTD::__to_address(__end_),
60646035553Spatrick            _VSTD::move(__x));
60746035553Spatrick    ++__end_;
60846035553Spatrick}
60946035553Spatrick
61046035553Spatricktemplate <class _Tp, class _Allocator>
61146035553Spatricktemplate <class... _Args>
612*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
61346035553Spatrickvoid
61446035553Spatrick__split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args)
61546035553Spatrick{
61646035553Spatrick    if (__end_ == __end_cap())
61746035553Spatrick    {
61846035553Spatrick        if (__begin_ > __first_)
61946035553Spatrick        {
62046035553Spatrick            difference_type __d = __begin_ - __first_;
62146035553Spatrick            __d = (__d + 1) / 2;
62246035553Spatrick            __end_ = _VSTD::move(__begin_, __end_, __begin_ - __d);
62346035553Spatrick            __begin_ -= __d;
62446035553Spatrick        }
62546035553Spatrick        else
62646035553Spatrick        {
627*4bdff4beSrobert            size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
62846035553Spatrick            __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc());
62946035553Spatrick            __t.__construct_at_end(move_iterator<pointer>(__begin_),
63046035553Spatrick                                   move_iterator<pointer>(__end_));
63146035553Spatrick            _VSTD::swap(__first_, __t.__first_);
63246035553Spatrick            _VSTD::swap(__begin_, __t.__begin_);
63346035553Spatrick            _VSTD::swap(__end_, __t.__end_);
63446035553Spatrick            _VSTD::swap(__end_cap(), __t.__end_cap());
63546035553Spatrick        }
63646035553Spatrick    }
63746035553Spatrick    __alloc_traits::construct(__alloc(), _VSTD::__to_address(__end_),
63846035553Spatrick                              _VSTD::forward<_Args>(__args)...);
63946035553Spatrick    ++__end_;
64046035553Spatrick}
64146035553Spatrick
64246035553Spatricktemplate <class _Tp, class _Allocator>
643*4bdff4beSrobert_LIBCPP_CONSTEXPR_SINCE_CXX20
644*4bdff4beSrobertinline _LIBCPP_HIDE_FROM_ABI
64546035553Spatrickvoid
64646035553Spatrickswap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y)
64746035553Spatrick        _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
64846035553Spatrick{
64946035553Spatrick    __x.swap(__y);
65046035553Spatrick}
65146035553Spatrick
65246035553Spatrick_LIBCPP_END_NAMESPACE_STD
65346035553Spatrick
65446035553Spatrick_LIBCPP_POP_MACROS
65546035553Spatrick
656*4bdff4beSrobert#endif // _LIBCPP___SPLIT_BUFFER
657