47 template <
typename T, std::
size_t SegmentSize = 64,
typename Alloc = std::allocator<T> >
57 typedef typename std::allocator_traits<allocator_type>::pointer
pointer;
58 typedef typename std::allocator_traits<allocator_type>::const_pointer
const_pointer;
59 typedef typename std::allocator_traits<allocator_type>::size_type
size_type;
60 typedef typename std::allocator_traits<allocator_type>::difference_type
difference_type;
83 typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<node> node_allocator_type;
92 typedef typename segmented_array ::value_type
value_type;
94 typedef typename segmented_array ::pointer
pointer;
95 typedef typename segmented_array ::size_type
size_type;
96 typedef typename segmented_array ::reference
reference;
100 iContainer(), iNode(), iContainerPosition(), iSegmentPosition()
104 iContainer(aOther.iContainer), iNode(aOther.iNode), iContainerPosition(aOther.iContainerPosition), iSegmentPosition(aOther.iSegmentPosition)
109 iContainer = aOther.iContainer;
110 iNode = aOther.iNode;
111 iContainerPosition = aOther.iContainerPosition;
112 iSegmentPosition = aOther.iSegmentPosition;
117 iContainer(&aContainer), iNode(nullptr), iContainerPosition(aContainerPosition), iSegmentPosition(0)
119 iNode = iContainer->find_node(aContainerPosition, iSegmentPosition);
121 *
this = iContainer->
end();
124 iContainer(&aContainer), iNode(aNode), iContainerPosition(aContainerPosition), iSegmentPosition(aSegmentPosition)
131 ++iContainerPosition;
132 if (++iSegmentPosition ==
static_cast<node*
>(iNode)->segment().
size())
134 if (iNode != iContainer->back_node())
136 iNode =
static_cast<node*
>(iNode->next());
137 iSegmentPosition = 0;
145 --iContainerPosition;
146 if (iSegmentPosition-- == 0)
148 iNode =
static_cast<node*
>(iNode->previous());
149 iSegmentPosition =
static_cast<node*
>(iNode)->segment().
size() - 1;
156 --iContainerPosition;
157 if (iSegmentPosition == 0)
159 iNode =
static_cast<node*
>(iNode->previous());
160 iSegmentPosition =
static_cast<node*
>(iNode)->segment().
size() - 1;
173 else if (iNode ==
nullptr || aDifference >=
static_cast<difference_type>(segment().
size() - iSegmentPosition))
174 *
this =
iterator(*iContainer, iContainerPosition + aDifference);
177 iContainerPosition += aDifference;
178 iSegmentPosition += aDifference;
187 *
this =
iterator(*iContainer, iContainerPosition - aDifference);
190 iContainerPosition -= aDifference;
191 iSegmentPosition -= aDifference;
201 bool operator==(
const iterator& aOther)
const {
return iContainerPosition == aOther.iContainerPosition; }
202 bool operator!=(
const iterator& aOther)
const {
return iContainerPosition != aOther.iContainerPosition; }
203 bool operator<(
const iterator& aOther)
const {
return iContainerPosition < aOther.iContainerPosition; }
204 bool operator<=(
const iterator& aOther)
const {
return iContainerPosition <= aOther.iContainerPosition; }
205 bool operator>(
const iterator& aOther)
const {
return iContainerPosition > aOther.iContainerPosition; }
206 bool operator>=(
const iterator& aOther)
const {
return iContainerPosition >= aOther.iContainerPosition; }
209 segment_type& segment()
const {
return iNode->segment(); }
231 iContainer(), iNode(), iContainerPosition(), iSegmentPosition()
235 iContainer(aOther.iContainer), iNode(aOther.iNode), iContainerPosition(aOther.iContainerPosition), iSegmentPosition(aOther.iSegmentPosition)
239 iContainer(aOther.iContainer), iNode(aOther.iNode), iContainerPosition(aOther.iContainerPosition), iSegmentPosition(aOther.iSegmentPosition)
244 iContainer = aOther.iContainer;
245 iNode = aOther.iNode;
246 iContainerPosition = aOther.iContainerPosition;
247 iSegmentPosition = aOther.iSegmentPosition;
252 iContainer = aOther.iContainer;
253 iNode = aOther.iNode;
254 iContainerPosition = aOther.iContainerPosition;
255 iSegmentPosition = aOther.iSegmentPosition;
260 iContainer(&aContainer), iNode(nullptr), iContainerPosition(aContainerPosition), iSegmentPosition(0)
262 iNode = iContainer->find_node(aContainerPosition, iSegmentPosition);
264 *
this = iContainer->
end();
267 iContainer(&aContainer), iNode(aNode), iContainerPosition(aContainerPosition), iSegmentPosition(aSegmentPosition)
274 ++iContainerPosition;
275 if (++iSegmentPosition ==
static_cast<node*
>(iNode)->segment().
size())
277 if (iNode != iContainer->back_node())
279 iNode =
static_cast<node*
>(iNode->next());
280 iSegmentPosition = 0;
288 --iContainerPosition;
289 if (iSegmentPosition-- == 0)
291 iNode =
static_cast<node*
>(iNode->previous());
292 iSegmentPosition =
static_cast<node*
>(iNode)->segment().
size() - 1;
299 --iContainerPosition;
300 if (iSegmentPosition == 0)
302 iNode =
static_cast<node*
>(iNode->previous());
303 iSegmentPosition =
static_cast<node*
>(iNode)->segment().
size() - 1;
316 else if (iNode ==
nullptr || aDifference >=
static_cast<difference_type>(segment().
size() - iSegmentPosition))
317 *
this =
const_iterator(*iContainer, iContainerPosition + aDifference);
320 iContainerPosition += aDifference;
321 iSegmentPosition += aDifference;
330 *
this =
const_iterator(*iContainer, iContainerPosition - aDifference);
333 iContainerPosition -= aDifference;
334 iSegmentPosition -= aDifference;
352 segment_type& segment()
const {
return iNode->segment(); }
365 iAllocator{ aAllocator }, iSize{ 0 }
369 iAllocator{ aAllocator }, iSize{ 0 }
373 template <
typename InputIterator>
374 segmented_array(InputIterator aFirst, InputIterator aLast,
const Alloc& aAllocator = Alloc()) :
375 iAllocator{ aAllocator }, iSize{ 0 }
380 iAllocator{ aAllocator }, iSize{ 0 }
386 iAllocator{
std::move(aOther.iAllocator) }, iSize{ aOther.iSize }
402 newContents.
swap(*
this);
457 return cbegin() + (&aValue - &(*this)[0]);
461 return citer(aValue);
465 return begin() + (&aValue - &(*this)[0]);
487 template <
typename... Args>
494 return *(
begin() + aIndex);
498 return *(
begin() + aIndex);
500 template <
class InputIterator>
501 typename std::enable_if<!std::is_integral<InputIterator>::value,
iterator>::type
504 return do_insert(aPosition, aFirst, aLast);
508 auto pos = aPosition.iContainerPosition;
511 aPosition =
insert(aPosition, &aValue, &aValue+1);
517 template <
typename... Args>
520 auto pos = aPosition.iContainerPosition;
524 auto const& temp =
value_type{ std::forward<Args>(aArguments)... };
525 aPosition =
insert(aPosition, &temp, &temp + 1);
543 template <
typename... Args>
548 template <
typename... Args>
555 if (
size() < aNewSize)
562 erase(aPosition, aPosition + 1);
563 return iterator{*
this, aPosition.iContainerPosition};
568 return iterator{*
this, aFirst.iNode, aFirst.iContainerPosition, aFirst.iSegmentPosition};
570 if (aFirst.iNode == aLast.iNode)
572 segmentFirst.
erase(segmentFirst.
begin() + aFirst.iSegmentPosition, segmentFirst.
begin() + aLast.iSegmentPosition);
573 iSize -= (aLast.iSegmentPosition - aFirst.iSegmentPosition);
574 aFirst.iNode->set_size(aFirst.iNode->size() - (aLast.iSegmentPosition - aFirst.iSegmentPosition));
575 if (segmentFirst.
empty())
576 free_node(aFirst.iNode);
581 for (node* inbetweenNode =
static_cast<node*
>(aFirst.iNode->next()); inbetweenNode != aLast.iNode;)
583 node* next =
static_cast<node*
>(inbetweenNode->next());
584 size_type inbetweenRemoved = inbetweenNode->segment().size();
585 free_node(inbetweenNode);
586 iSize -= inbetweenRemoved;
587 inbetweenNode = next;
589 size_type firstRemoved = segmentFirst.
size() - aFirst.iSegmentPosition;
590 size_type secondRemoved = aLast.iSegmentPosition;
591 segmentFirst.
erase(segmentFirst.
begin() + aFirst.iSegmentPosition, segmentFirst.
end());
592 segmentLast.
erase(segmentLast.
begin(), segmentLast.
begin() + aLast.iSegmentPosition);
593 if (segmentFirst.
empty())
594 free_node(aFirst.iNode);
596 aFirst.iNode->set_size(aFirst.iNode->size() - firstRemoved);
597 iSize -= firstRemoved;
598 if (segmentLast.
empty())
599 free_node(aLast.iNode);
601 aLast.iNode->set_size(aLast.iNode->size() - secondRemoved);
602 iSize -= secondRemoved;
604 return iterator{*
this, aFirst.iContainerPosition};
617 std::swap(iAllocator, aOther.iAllocator);
622 template <
class InputIterator>
623 typename std::enable_if<!std::is_same<typename std::iterator_traits<InputIterator>::iterator_category, std::input_iterator_tag>::value,
iterator>::type
624 do_insert(
const_iterator aPosition, InputIterator aFirst, InputIterator aLast)
628 return iterator{*
this, aPosition.iNode, aPosition.iContainerPosition, aPosition.iSegmentPosition};
629 node* before = aPosition.iNode;
630 node* after = aPosition.iNode ?
static_cast<node*
>(aPosition.iNode->next()) : nullptr;
631 node* lastNode = aPosition.iNode;
632 if (aPosition.iNode !=
nullptr && count <=
static_cast<node*
>(aPosition.iNode)->segment().available())
634 segment_type& segment =
static_cast<node*
>(aPosition.iNode)->segment();
635 segment.insert(segment.begin() + aPosition.iSegmentPosition, aFirst, aLast);
637 aPosition.iNode->set_size(aPosition.iNode->size() + count);
641 lastNode = allocate_space(aPosition, count);
642 if (aPosition.iNode ==
nullptr)
644 segment_type& segment = aPosition.iNode->segment();
645 typename segment_type::const_iterator tailEnd = segment.end();
646 typename segment_type::const_iterator tailStart = tailEnd - (segment.size() - aPosition.iSegmentPosition);
647 if (tailStart != tailEnd)
649 lastNode->segment().insert(lastNode->segment().begin(), tailStart, tailEnd);
650 lastNode->set_size(lastNode->size() + (tailEnd - tailStart));
651 aPosition.iNode->set_size(aPosition.iNode->size() - (tailEnd - tailStart));
652 segment.erase(tailStart, tailEnd);
654 for (node* nextNode = aPosition.iNode; count > 0 && nextNode != lastNode; nextNode =
static_cast<node*
>(nextNode->next()))
656 size_type addCount = std::min(count, nextNode->segment().available());
659 InputIterator stop = aFirst;
661 nextNode->segment().insert(nextNode->segment().begin() + (nextNode == aPosition.iNode ? aPosition.iSegmentPosition : 0), aFirst, stop);
665 nextNode->set_size(nextNode->size() + addCount);
670 InputIterator stop = aFirst;
672 lastNode->segment().insert(lastNode->segment().begin() + (lastNode == aPosition.iNode ? aPosition.iSegmentPosition : 0), aFirst, stop);
673 lastNode->set_size(lastNode->size() + count);
677 size_type index = aPosition.iContainerPosition - aPosition.iSegmentPosition;
678 for (node* newNode = aPosition.iNode;; newNode =
static_cast<node*
>(newNode->next()))
680 if (newNode != before && newNode != after)
684 index += newNode->segment().size();
685 if (newNode == lastNode)
688 if (aPosition.iSegmentPosition != aPosition.iNode->segment().size())
689 return iterator{*
this, aPosition.iNode, aPosition.iContainerPosition, aPosition.iSegmentPosition};
691 return iterator{*
this,
static_cast<node*
>(aPosition.iNode->next()), aPosition.iContainerPosition, 0};
693 template <
class InputIterator>
694 typename std::enable_if<std::is_same<typename std::iterator_traits<InputIterator>::iterator_category, std::input_iterator_tag>::value, iterator>::type
695 do_insert(const_iterator aPosition, InputIterator aFirst, InputIterator aLast)
697 auto pos = aPosition.iContainerPosition;
698 while (aFirst != aLast)
700 aPosition =
insert(aPosition, 1, *aFirst++);
703 return iterator{*
this, pos};
709 aSegmentPosition = aContainerPosition - nodeIndex;
712 node* allocate_space(const_iterator aPosition,
size_type aCount)
715 return aPosition.iNode;
717 aCount -= std::min(aCount, (aPosition.iNode->segment().available()));
719 return aPosition.iNode;
720 node* lastNode =
nullptr;
721 if (aCount > 0 && aPosition.iNode && aPosition.iNode->next() !=
nullptr && aCount <=
static_cast<node*
>(aPosition.iNode->next())->segment().available())
723 lastNode =
static_cast<node*
>(aPosition.iNode->next());
724 aCount -= std::min(aCount, lastNode->segment().available());
726 node* nextNode = aPosition.iNode;
728 aCount -= std::min(aCount, (nextNode = allocate_node(nextNode))->segment().available());
729 if (aPosition.iNode ==
nullptr)
731 segment_type& segment = aPosition.iNode->segment();
732 if (aPosition.iSegmentPosition < segment.size() && nextNode->segment().available() < segment.size() - aPosition.iSegmentPosition)
733 lastNode = allocate_node(nextNode);
734 return lastNode ? lastNode : nextNode;
736 node* allocate_node(node* aAfter)
738 node* newNode = std::allocator_traits<node_allocator_type>::allocate(iAllocator, 1);
741 std::allocator_traits<node_allocator_type>::construct(iAllocator, newNode, node());
745 std::allocator_traits<node_allocator_type>::deallocate(iAllocator, newNode, 1);
748 if (aAfter ==
nullptr)
755 newNode->set_previous(aAfter);
756 if (aAfter->next() !=
nullptr)
758 newNode->set_next(aAfter->next());
759 aAfter->next()->set_previous(newNode);
761 aAfter->set_next(newNode);
767 void free_node(node* aNode)
772 aNode->next()->set_previous(aNode->previous());
773 if (aNode->previous())
774 aNode->previous()->set_next(aNode->next());
781 std::allocator_traits<node_allocator_type>::destroy(iAllocator, aNode);
782 std::allocator_traits<node_allocator_type>::deallocate(iAllocator, aNode, 1);
786 node_allocator_type iAllocator;
790 template <
typename T, std::
size_t SegmentSize,
typename Alloc>
796 template <
typename T, std::
size_t SegmentSize,
typename Alloc>
799 return !(lhs == rhs);
node * find_node(size_type aPosition, size_type &aNodeIndex) const
node * front_node() const
void insert_node(node *aNode, size_type aPosition)
void set_front_node(node *aFront)
void delete_node(node *aNode)
void swap(array_tree &aOther)
void set_back_node(node *aBack)
bool operator!=(const const_iterator &aOther) const
segmented_array::size_type size_type
const_iterator operator++(int)
const_iterator & operator--()
const_iterator & operator++()
const_pointer operator->() const
friend difference_type operator-(const const_iterator &aLhs, const const_iterator &aRhs)
const_iterator & operator+=(difference_type aDifference)
std::random_access_iterator_tag iterator_category
const_iterator & operator=(const const_iterator &aOther)
const_iterator operator--(int)
const_iterator(const typename segmented_array::iterator &aOther)
bool operator>=(const const_iterator &aOther) const
bool operator<(const const_iterator &aOther) const
bool operator>(const const_iterator &aOther) const
const_iterator(const const_iterator &aOther)
segmented_array::const_reference reference
bool operator<=(const const_iterator &aOther) const
const_reference operator*() const
const_reference operator[](difference_type aDifference) const
const_iterator operator-(difference_type aDifference) const
const_iterator & operator=(const typename segmented_array::iterator &aOther)
bool operator==(const const_iterator &aOther) const
segmented_array::value_type value_type
segmented_array::difference_type difference_type
const_iterator & operator-=(difference_type aDifference)
segmented_array::const_pointer pointer
const_iterator operator+(difference_type aDifference) const
iterator & operator+=(difference_type aDifference)
bool operator<(const iterator &aOther) const
segmented_array::difference_type difference_type
segmented_array::reference reference
bool operator<=(const iterator &aOther) const
bool operator>(const iterator &aOther) const
iterator(const iterator &aOther)
bool operator>=(const iterator &aOther) const
bool operator!=(const iterator &aOther) const
difference_type operator-(const iterator &aOther) const
iterator operator+(difference_type aDifference) const
segmented_array::size_type size_type
segmented_array::pointer pointer
iterator & operator-=(difference_type aDifference)
reference operator*() const
pointer operator->() const
segmented_array::value_type value_type
iterator operator-(difference_type aDifference) const
bool operator==(const iterator &aOther) const
reference operator[](difference_type aDifference) const
iterator & operator=(const iterator &aOther)
std::random_access_iterator_tag iterator_category
iterator emplace_insert(const_iterator aPosition, size_type aCount, Args &&... aArguments)
std::enable_if<!std::is_integral< InputIterator >::value, iterator >::type insert(const_iterator aPosition, InputIterator aFirst, InputIterator aLast)
segmented_array(const size_type aCount, const value_type &aValue, const Alloc &aAllocator=Alloc())
segmented_array & operator=(segmented_array &&aOther)
iterator erase(const_iterator aFirst, const_iterator aLast)
const_reference back() const
void push_back(const value_type &aValue)
segmented_array(const Alloc &aAllocator=Alloc())
void push_front(const value_type &aValue)
void emplace_back(Args &&... aArguments)
segmented_array(segmented_array &&aOther)
std::allocator_traits< allocator_type >::size_type size_type
std::allocator_traits< allocator_type >::difference_type difference_type
const_reverse_iterator rend() const
segmented_array & operator=(const segmented_array &aOther)
const_reference front() const
void emplace_front(Args &&... aArguments)
const_iterator citer(const value_type &aValue) const
const_iterator end() const
const_iterator cbegin() const
std::reverse_iterator< const_iterator > const_reverse_iterator
const_reference operator[](size_type aIndex) const
reference operator[](size_type aIndex)
void resize(std::size_t aNewSize, const value_type &aValue=value_type{})
std::allocator_traits< allocator_type >::pointer pointer
const_iterator cend() const
value_type const & const_reference
reverse_iterator rbegin()
segmented_array(const segmented_array &aOther, const Alloc &aAllocator=Alloc())
iterator erase(const_iterator aPosition)
iterator iter(const value_type &aValue)
void swap(segmented_array &aOther)
const_reverse_iterator rbegin() const
std::allocator_traits< allocator_type >::const_pointer const_pointer
std::reverse_iterator< iterator > reverse_iterator
iterator insert(const_iterator aPosition, const value_type &aValue)
segmented_array(InputIterator aFirst, InputIterator aLast, const Alloc &aAllocator=Alloc())
const_iterator iter(const value_type &aValue) const
const_iterator begin() const
iterator emplace_insert(const_iterator aPosition, Args &&... aArguments)
iterator insert(const_iterator aPosition, size_type aCount, const value_type &aValue)
iterator erase(const_iterator position)
const_iterator begin() const
const_iterator end() const
void swap(plf::hive< element_type, allocator_type > &a, plf::hive< element_type, allocator_type > &b) noexcept(std::allocator_traits< allocator_type >::propagate_on_container_swap::value||std::allocator_traits< allocator_type >::is_always_equal::value)
iterator_traits< it_type >::difference_type distance(const it_type first, const it_type last)
void advance(it_type &it, const distance_type distance)