|
|
|
|
@@ -47,7 +47,7 @@ _LIBCPP_PUSH_MACROS
|
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
|
|
|
|
|
|
// __split_buffer allocates a contiguous chunk of memory and stores objects in the range [__begin_, __end_).
|
|
|
|
|
// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __end_cap_.first()). That allows
|
|
|
|
|
// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __cap_). That allows
|
|
|
|
|
// it to grow both in the front and back without having to move the data.
|
|
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator = allocator<_Tp> >
|
|
|
|
|
@@ -78,20 +78,20 @@ public:
|
|
|
|
|
pointer __first_;
|
|
|
|
|
pointer __begin_;
|
|
|
|
|
pointer __end_;
|
|
|
|
|
_LIBCPP_COMPRESSED_PAIR(pointer, __end_cap_, allocator_type, __alloc_);
|
|
|
|
|
_LIBCPP_COMPRESSED_PAIR(pointer, __cap_, allocator_type, __alloc_);
|
|
|
|
|
|
|
|
|
|
__split_buffer(const __split_buffer&) = delete;
|
|
|
|
|
__split_buffer& operator=(const __split_buffer&) = delete;
|
|
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer()
|
|
|
|
|
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
|
|
|
|
|
: __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr) {}
|
|
|
|
|
: __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr) {}
|
|
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a)
|
|
|
|
|
: __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr), __alloc_(__a) {}
|
|
|
|
|
: __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr), __alloc_(__a) {}
|
|
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a)
|
|
|
|
|
: __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr), __alloc_(__a) {}
|
|
|
|
|
: __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr), __alloc_(__a) {}
|
|
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
|
|
|
|
|
__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a);
|
|
|
|
|
@@ -123,7 +123,7 @@ public:
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __end_ == __begin_; }
|
|
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const {
|
|
|
|
|
return static_cast<size_type>(__end_cap_ - __first_);
|
|
|
|
|
return static_cast<size_type>(__cap_ - __first_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const {
|
|
|
|
|
@@ -131,7 +131,7 @@ public:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const {
|
|
|
|
|
return static_cast<size_type>(__end_cap_ - __end_);
|
|
|
|
|
return static_cast<size_type>(__cap_ - __end_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__begin_; }
|
|
|
|
|
@@ -215,14 +215,14 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __split_buffer<_Tp, _Allocator>::__invariants
|
|
|
|
|
return false;
|
|
|
|
|
if (__end_ != nullptr)
|
|
|
|
|
return false;
|
|
|
|
|
if (__end_cap_ != nullptr)
|
|
|
|
|
if (__cap_ != nullptr)
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
if (__begin_ < __first_)
|
|
|
|
|
return false;
|
|
|
|
|
if (__end_ < __begin_)
|
|
|
|
|
return false;
|
|
|
|
|
if (__end_cap_ < __end_)
|
|
|
|
|
if (__cap_ < __end_)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
@@ -262,8 +262,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
|
|
|
|
__split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) {
|
|
|
|
|
__alloc_rr& __a = __alloc_;
|
|
|
|
|
for (; __first != __last; ++__first) {
|
|
|
|
|
if (__end_ == __end_cap_) {
|
|
|
|
|
size_type __old_cap = __end_cap_ - __first_;
|
|
|
|
|
if (__end_ == __cap_) {
|
|
|
|
|
size_type __old_cap = __cap_ - __first_;
|
|
|
|
|
size_type __new_cap = std::max<size_type>(2 * __old_cap, 8);
|
|
|
|
|
__split_buffer __buf(__new_cap, 0, __a);
|
|
|
|
|
for (pointer __p = __begin_; __p != __end_; ++__p, (void)++__buf.__end_)
|
|
|
|
|
@@ -320,7 +320,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
|
|
__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
|
|
|
|
|
: __end_cap_(nullptr), __alloc_(__a) {
|
|
|
|
|
: __cap_(nullptr), __alloc_(__a) {
|
|
|
|
|
if (__cap == 0) {
|
|
|
|
|
__first_ = nullptr;
|
|
|
|
|
} else {
|
|
|
|
|
@@ -329,7 +329,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __sta
|
|
|
|
|
__cap = __allocation.count;
|
|
|
|
|
}
|
|
|
|
|
__begin_ = __end_ = __first_ + __start;
|
|
|
|
|
__end_cap_ = __first_ + __cap;
|
|
|
|
|
__cap_ = __first_ + __cap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
|
@@ -345,32 +345,32 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__
|
|
|
|
|
: __first_(std::move(__c.__first_)),
|
|
|
|
|
__begin_(std::move(__c.__begin_)),
|
|
|
|
|
__end_(std::move(__c.__end_)),
|
|
|
|
|
__end_cap_(std::move(__c.__end_cap_)),
|
|
|
|
|
__cap_(std::move(__c.__cap_)),
|
|
|
|
|
__alloc_(std::move(__c.__alloc_)) {
|
|
|
|
|
__c.__first_ = nullptr;
|
|
|
|
|
__c.__begin_ = nullptr;
|
|
|
|
|
__c.__end_ = nullptr;
|
|
|
|
|
__c.__end_cap_ = nullptr;
|
|
|
|
|
__c.__first_ = nullptr;
|
|
|
|
|
__c.__begin_ = nullptr;
|
|
|
|
|
__c.__end_ = nullptr;
|
|
|
|
|
__c.__cap_ = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
|
|
__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
|
|
|
|
|
: __end_cap_(nullptr), __alloc_(__a) {
|
|
|
|
|
: __cap_(nullptr), __alloc_(__a) {
|
|
|
|
|
if (__a == __c.__alloc_) {
|
|
|
|
|
__first_ = __c.__first_;
|
|
|
|
|
__begin_ = __c.__begin_;
|
|
|
|
|
__end_ = __c.__end_;
|
|
|
|
|
__end_cap_ = __c.__end_cap_;
|
|
|
|
|
__c.__first_ = nullptr;
|
|
|
|
|
__c.__begin_ = nullptr;
|
|
|
|
|
__c.__end_ = nullptr;
|
|
|
|
|
__c.__end_cap_ = nullptr;
|
|
|
|
|
__first_ = __c.__first_;
|
|
|
|
|
__begin_ = __c.__begin_;
|
|
|
|
|
__end_ = __c.__end_;
|
|
|
|
|
__cap_ = __c.__cap_;
|
|
|
|
|
__c.__first_ = nullptr;
|
|
|
|
|
__c.__begin_ = nullptr;
|
|
|
|
|
__c.__end_ = nullptr;
|
|
|
|
|
__c.__cap_ = nullptr;
|
|
|
|
|
} else {
|
|
|
|
|
auto __allocation = std::__allocate_at_least(__alloc_, __c.size());
|
|
|
|
|
__first_ = __allocation.ptr;
|
|
|
|
|
__begin_ = __end_ = __first_;
|
|
|
|
|
__end_cap_ = __first_ + __allocation.count;
|
|
|
|
|
__cap_ = __first_ + __allocation.count;
|
|
|
|
|
typedef move_iterator<iterator> _Ip;
|
|
|
|
|
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
|
|
|
|
|
}
|
|
|
|
|
@@ -384,12 +384,12 @@ __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c)
|
|
|
|
|
!__alloc_traits::propagate_on_container_move_assignment::value) {
|
|
|
|
|
clear();
|
|
|
|
|
shrink_to_fit();
|
|
|
|
|
__first_ = __c.__first_;
|
|
|
|
|
__begin_ = __c.__begin_;
|
|
|
|
|
__end_ = __c.__end_;
|
|
|
|
|
__end_cap_ = __c.__end_cap_;
|
|
|
|
|
__first_ = __c.__first_;
|
|
|
|
|
__begin_ = __c.__begin_;
|
|
|
|
|
__end_ = __c.__end_;
|
|
|
|
|
__cap_ = __c.__cap_;
|
|
|
|
|
__move_assign_alloc(__c, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());
|
|
|
|
|
__c.__first_ = __c.__begin_ = __c.__end_ = __c.__end_cap_ = nullptr;
|
|
|
|
|
__c.__first_ = __c.__begin_ = __c.__end_ = __c.__cap_ = nullptr;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -399,7 +399,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::swap(__split
|
|
|
|
|
std::swap(__first_, __x.__first_);
|
|
|
|
|
std::swap(__begin_, __x.__begin_);
|
|
|
|
|
std::swap(__end_, __x.__end_);
|
|
|
|
|
std::swap(__end_cap_, __x.__end_cap_);
|
|
|
|
|
std::swap(__cap_, __x.__cap_);
|
|
|
|
|
std::__swap_allocator(__alloc_, __x.__alloc_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -415,7 +415,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi
|
|
|
|
|
std::swap(__first_, __t.__first_);
|
|
|
|
|
std::swap(__begin_, __t.__begin_);
|
|
|
|
|
std::swap(__end_, __t.__end_);
|
|
|
|
|
std::swap(__end_cap_, __t.__end_cap_);
|
|
|
|
|
std::swap(__cap_, __t.__cap_);
|
|
|
|
|
#if _LIBCPP_HAS_EXCEPTIONS
|
|
|
|
|
} catch (...) {
|
|
|
|
|
}
|
|
|
|
|
@@ -427,19 +427,19 @@ template <class _Tp, class _Allocator>
|
|
|
|
|
template <class... _Args>
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_front(_Args&&... __args) {
|
|
|
|
|
if (__begin_ == __first_) {
|
|
|
|
|
if (__end_ < __end_cap_) {
|
|
|
|
|
difference_type __d = __end_cap_ - __end_;
|
|
|
|
|
if (__end_ < __cap_) {
|
|
|
|
|
difference_type __d = __cap_ - __end_;
|
|
|
|
|
__d = (__d + 1) / 2;
|
|
|
|
|
__begin_ = std::move_backward(__begin_, __end_, __end_ + __d);
|
|
|
|
|
__end_ += __d;
|
|
|
|
|
} else {
|
|
|
|
|
size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap_ - __first_), 1);
|
|
|
|
|
size_type __c = std::max<size_type>(2 * static_cast<size_t>(__cap_ - __first_), 1);
|
|
|
|
|
__split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc_);
|
|
|
|
|
__t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
|
|
|
|
|
std::swap(__first_, __t.__first_);
|
|
|
|
|
std::swap(__begin_, __t.__begin_);
|
|
|
|
|
std::swap(__end_, __t.__end_);
|
|
|
|
|
std::swap(__end_cap_, __t.__end_cap_);
|
|
|
|
|
std::swap(__cap_, __t.__cap_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
__alloc_traits::construct(__alloc_, std::__to_address(__begin_ - 1), std::forward<_Args>(__args)...);
|
|
|
|
|
@@ -449,20 +449,20 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_fron
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
|
template <class... _Args>
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
|
|
|
|
|
if (__end_ == __end_cap_) {
|
|
|
|
|
if (__end_ == __cap_) {
|
|
|
|
|
if (__begin_ > __first_) {
|
|
|
|
|
difference_type __d = __begin_ - __first_;
|
|
|
|
|
__d = (__d + 1) / 2;
|
|
|
|
|
__end_ = std::move(__begin_, __end_, __begin_ - __d);
|
|
|
|
|
__begin_ -= __d;
|
|
|
|
|
} else {
|
|
|
|
|
size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap_ - __first_), 1);
|
|
|
|
|
size_type __c = std::max<size_type>(2 * static_cast<size_t>(__cap_ - __first_), 1);
|
|
|
|
|
__split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc_);
|
|
|
|
|
__t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
|
|
|
|
|
std::swap(__first_, __t.__first_);
|
|
|
|
|
std::swap(__begin_, __t.__begin_);
|
|
|
|
|
std::swap(__end_, __t.__end_);
|
|
|
|
|
std::swap(__end_cap_, __t.__end_cap_);
|
|
|
|
|
std::swap(__cap_, __t.__cap_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
__alloc_traits::construct(__alloc_, std::__to_address(__end_), std::forward<_Args>(__args)...);
|
|
|
|
|
|