neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
segmented_array.hpp
Go to the documentation of this file.
1/*
2* segmented_array.hpp
3*
4* Copyright (c) 2007 Leigh Johnston.
5*
6* All rights reserved.
7*
8* Redistribution and use in source and binary forms, with or without
9* modification, are permitted provided that the following conditions are
10* met:
11*
12* * Redistributions of source code must retain the above copyright
13* notice, this list of conditions and the following disclaimer.
14*
15* * Redistributions in binary form must reproduce the above copyright
16* notice, this list of conditions and the following disclaimer in the
17* documentation and/or other materials provided with the distribution.
18*
19* * Neither the name of Leigh Johnston nor the names of any
20* other contributors to this software may be used to endorse or
21* promote products derived from this software without specific prior
22* written permission.
23*
24* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35*/
36
37#pragma once
38
39#include <neolib/neolib.hpp>
40#include <memory>
41#include <iterator>
44
45namespace neolib
46{
47 template <typename T, std::size_t SegmentSize = 64, typename Alloc = std::allocator<T> >
48 class segmented_array : private array_tree<Alloc>
49 {
52 public:
53 typedef T value_type;
54 typedef Alloc allocator_type;
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;
61 private:
63 class node : public base_type::node
64 {
65 public:
66 node()
67 {
68 }
69
70 public:
71 const segment_type& segment() const
72 {
73 return iSegment;
74 }
75 segment_type& segment()
76 {
77 return iSegment;
78 }
79
80 private:
81 segment_type iSegment;
82 };
83 typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<node> node_allocator_type;
84 public:
86 {
87 friend class segmented_array;
89
90 public:
91 typedef std::random_access_iterator_tag iterator_category;
92 typedef typename segmented_array ::value_type value_type;
93 typedef typename segmented_array ::difference_type difference_type;
94 typedef typename segmented_array ::pointer pointer;
95 typedef typename segmented_array ::size_type size_type;
96 typedef typename segmented_array ::reference reference;
97
98 public:
100 iContainer(), iNode(), iContainerPosition(), iSegmentPosition()
101 {
102 }
103 iterator(const iterator& aOther) :
104 iContainer(aOther.iContainer), iNode(aOther.iNode), iContainerPosition(aOther.iContainerPosition), iSegmentPosition(aOther.iSegmentPosition)
105 {
106 }
108 {
109 iContainer = aOther.iContainer;
110 iNode = aOther.iNode;
111 iContainerPosition = aOther.iContainerPosition;
112 iSegmentPosition = aOther.iSegmentPosition;
113 return *this;
114 }
115 private:
116 iterator(segmented_array& aContainer, size_type aContainerPosition) :
117 iContainer(&aContainer), iNode(nullptr), iContainerPosition(aContainerPosition), iSegmentPosition(0)
118 {
119 iNode = iContainer->find_node(aContainerPosition, iSegmentPosition);
120 if (iNode->is_nil())
121 *this = iContainer->end();
122 }
123 iterator(segmented_array& aContainer, node* aNode, size_type aContainerPosition, size_type aSegmentPosition) :
124 iContainer(&aContainer), iNode(aNode), iContainerPosition(aContainerPosition), iSegmentPosition(aSegmentPosition)
125 {
126 }
127
128 public:
130 {
131 ++iContainerPosition;
132 if (++iSegmentPosition == static_cast<node*>(iNode)->segment().size())
133 {
134 if (iNode != iContainer->back_node())
135 {
136 iNode = static_cast<node*>(iNode->next());
137 iSegmentPosition = 0;
138 }
139 }
140 return *this;
141 }
142#ifndef _MSC_VER // Internal Compiler Error (VS2022)
144 {
145 --iContainerPosition;
146 if (iSegmentPosition-- == 0)
147 {
148 iNode = static_cast<node*>(iNode->previous());
149 iSegmentPosition = static_cast<node*>(iNode)->segment().size() - 1;
150 }
151 return *this;
152 }
153#else // Internal Compiler Error (VS2022) workaround
155 {
156 --iContainerPosition;
157 if (iSegmentPosition == 0)
158 {
159 iNode = static_cast<node*>(iNode->previous());
160 iSegmentPosition = static_cast<node*>(iNode)->segment().size() - 1;
161 }
162 else
163 --iSegmentPosition;
164 return *this;
165 }
166#endif
167 iterator operator++(int) { iterator ret(*this); operator++(); return ret; }
168 iterator operator--(int) { iterator ret(*this); operator--(); return ret; }
170 {
171 if (aDifference < 0)
172 return operator-=(-aDifference);
173 else if (iNode == nullptr || aDifference >= static_cast<difference_type>(segment().size() - iSegmentPosition))
174 *this = iterator(*iContainer, iContainerPosition + aDifference);
175 else
176 {
177 iContainerPosition += aDifference;
178 iSegmentPosition += aDifference;
179 }
180 return *this;
181 }
183 {
184 if (aDifference < 0)
185 return operator+=(-aDifference);
186 else if (aDifference > static_cast<difference_type>(iSegmentPosition))
187 *this = iterator(*iContainer, iContainerPosition - aDifference);
188 else
189 {
190 iContainerPosition -= aDifference;
191 iSegmentPosition -= aDifference;
192 }
193 return *this;
194 }
195 iterator operator+(difference_type aDifference) const { iterator result(*this); result += aDifference; return result; }
196 iterator operator-(difference_type aDifference) const { iterator result(*this); result -= aDifference; return result; }
197 reference operator[](difference_type aDifference) const { return *((*this) + aDifference); }
198 difference_type operator-(const iterator& aOther) const { return static_cast<difference_type>(iContainerPosition)-static_cast<difference_type>(aOther.iContainerPosition); }
199 reference operator*() const { return segment()[iSegmentPosition]; }
200 pointer operator->() const { return &operator*(); }
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; }
207
208 private:
209 segment_type& segment() const { return iNode->segment(); }
210
211 private:
212 segmented_array* iContainer;
213 node* iNode;
214 size_type iContainerPosition;
215 size_type iSegmentPosition;
216 };
218 {
219 friend class segmented_array;
220
221 public:
222 typedef std::random_access_iterator_tag iterator_category;
228
229 public:
231 iContainer(), iNode(), iContainerPosition(), iSegmentPosition()
232 {
233 }
235 iContainer(aOther.iContainer), iNode(aOther.iNode), iContainerPosition(aOther.iContainerPosition), iSegmentPosition(aOther.iSegmentPosition)
236 {
237 }
239 iContainer(aOther.iContainer), iNode(aOther.iNode), iContainerPosition(aOther.iContainerPosition), iSegmentPosition(aOther.iSegmentPosition)
240 {
241 }
243 {
244 iContainer = aOther.iContainer;
245 iNode = aOther.iNode;
246 iContainerPosition = aOther.iContainerPosition;
247 iSegmentPosition = aOther.iSegmentPosition;
248 return *this;
249 }
251 {
252 iContainer = aOther.iContainer;
253 iNode = aOther.iNode;
254 iContainerPosition = aOther.iContainerPosition;
255 iSegmentPosition = aOther.iSegmentPosition;
256 return *this;
257 }
258 private:
259 const_iterator(const segmented_array& aContainer, size_type aContainerPosition) :
260 iContainer(&aContainer), iNode(nullptr), iContainerPosition(aContainerPosition), iSegmentPosition(0)
261 {
262 iNode = iContainer->find_node(aContainerPosition, iSegmentPosition);
263 if (iNode->is_nil())
264 *this = iContainer->end();
265 }
266 const_iterator(const segmented_array& aContainer, node* aNode, size_type aContainerPosition, size_type aSegmentPosition) :
267 iContainer(&aContainer), iNode(aNode), iContainerPosition(aContainerPosition), iSegmentPosition(aSegmentPosition)
268 {
269 }
270
271 public:
273 {
274 ++iContainerPosition;
275 if (++iSegmentPosition == static_cast<node*>(iNode)->segment().size())
276 {
277 if (iNode != iContainer->back_node())
278 {
279 iNode = static_cast<node*>(iNode->next());
280 iSegmentPosition = 0;
281 }
282 }
283 return *this;
284 }
285#ifndef _MSC_VER // Internal Compiler Error (VS2022)
287 {
288 --iContainerPosition;
289 if (iSegmentPosition-- == 0)
290 {
291 iNode = static_cast<node*>(iNode->previous());
292 iSegmentPosition = static_cast<node*>(iNode)->segment().size() - 1;
293 }
294 return *this;
295 }
296#else // Internal Compiler Error (VS2022) workaround
298 {
299 --iContainerPosition;
300 if (iSegmentPosition == 0)
301 {
302 iNode = static_cast<node*>(iNode->previous());
303 iSegmentPosition = static_cast<node*>(iNode)->segment().size() - 1;
304 }
305 else
306 --iSegmentPosition;
307 return *this;
308 }
309#endif
310 const_iterator operator++(int) { const_iterator ret(*this); operator++(); return ret; }
311 const_iterator operator--(int) { const_iterator ret(*this); operator--(); return ret; }
313 {
314 if (aDifference < 0)
315 return operator-=(-aDifference);
316 else if (iNode == nullptr || aDifference >= static_cast<difference_type>(segment().size() - iSegmentPosition))
317 *this = const_iterator(*iContainer, iContainerPosition + aDifference);
318 else
319 {
320 iContainerPosition += aDifference;
321 iSegmentPosition += aDifference;
322 }
323 return *this;
324 }
326 {
327 if (aDifference < 0)
328 return operator+=(-aDifference);
329 else if (aDifference > static_cast<difference_type>(iSegmentPosition))
330 *this = const_iterator(*iContainer, iContainerPosition - aDifference);
331 else
332 {
333 iContainerPosition -= aDifference;
334 iSegmentPosition -= aDifference;
335 }
336 return *this;
337 }
338 const_iterator operator+(difference_type aDifference) const { const_iterator result(*this); result += aDifference; return result; }
339 const_iterator operator-(difference_type aDifference) const { const_iterator result(*this); result -= aDifference; return result; }
340 const_reference operator[](difference_type aDifference) const { return *((*this) + aDifference); }
341 friend difference_type operator-(const const_iterator& aLhs, const const_iterator& aRhs) { return static_cast<difference_type>(aLhs.iContainerPosition)-static_cast<difference_type>(aRhs.iContainerPosition); }
342 const_reference operator*() const { return segment()[iSegmentPosition]; }
343 const_pointer operator->() const { return &operator*(); }
344 bool operator==(const const_iterator& aOther) const { return iContainerPosition == aOther.iContainerPosition; }
345 bool operator!=(const const_iterator& aOther) const { return iContainerPosition != aOther.iContainerPosition; }
346 bool operator<(const const_iterator& aOther) const { return iContainerPosition < aOther.iContainerPosition; }
347 bool operator<=(const const_iterator& aOther) const { return iContainerPosition <= aOther.iContainerPosition; }
348 bool operator>(const const_iterator& aOther) const { return iContainerPosition > aOther.iContainerPosition; }
349 bool operator>=(const const_iterator& aOther) const { return iContainerPosition >= aOther.iContainerPosition; }
350
351 private:
352 segment_type& segment() const { return iNode->segment(); }
353
354 private:
355 const segmented_array* iContainer;
356 node* iNode;
357 size_type iContainerPosition;
358 size_type iSegmentPosition;
359 };
360 typedef std::reverse_iterator<iterator> reverse_iterator;
361 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
362
363 public:
364 segmented_array(const Alloc& aAllocator = Alloc()) :
365 iAllocator{ aAllocator }, iSize{ 0 }
366 {
367 }
368 segmented_array(const size_type aCount, const value_type& aValue, const Alloc& aAllocator = Alloc()) :
369 iAllocator{ aAllocator }, iSize{ 0 }
370 {
371 insert(begin(), aCount, aValue);
372 }
373 template <typename InputIterator>
374 segmented_array(InputIterator aFirst, InputIterator aLast, const Alloc& aAllocator = Alloc()) :
375 iAllocator{ aAllocator }, iSize{ 0 }
376 {
377 insert(begin(), aFirst, aLast);
378 }
379 segmented_array(const segmented_array& aOther, const Alloc& aAllocator = Alloc()) :
380 iAllocator{ aAllocator }, iSize{ 0 }
381 {
382 insert(begin(), aOther.begin(), aOther.end());
383 }
385 base_type{ std::move(aOther) },
386 iAllocator{ std::move(aOther.iAllocator) }, iSize{ aOther.iSize }
387 {
388 aOther.iSize = 0;
389 }
391 {
392 erase(begin(), end());
393 }
395 {
396 swap(aOther);
397 return *this;
398 }
400 {
401 segmented_array newContents(aOther);
402 newContents.swap(*this);
403 return *this;
404 }
405
406 public:
408 {
409 return iSize;
410 }
411 bool empty() const
412 {
413 return iSize == 0;
414 }
416 {
417 return const_iterator(*this, static_cast<node*>(base_type::front_node()), 0, 0);
418 }
420 {
421 return cbegin();
422 }
424 {
425 return const_iterator(*this, static_cast<node*>(base_type::back_node()), iSize, base_type::back_node() ? static_cast<node*>(base_type::back_node())->segment().size() : 0);
426 }
428 {
429 return cend();
430 }
432 {
433 return iterator(*this, static_cast<node*>(base_type::front_node()), 0, 0);
434 }
436 {
437 return iterator(*this, static_cast<node*>(base_type::back_node()), iSize, base_type::back_node() ? static_cast<node*>(base_type::back_node())->segment().size() : 0);
438 }
440 {
441 return const_reverse_iterator(end());
442 }
444 {
446 }
448 {
449 return reverse_iterator(end());
450 }
452 {
453 return reverse_iterator(begin());
454 }
455 const_iterator citer(const value_type& aValue) const
456 {
457 return cbegin() + (&aValue - &(*this)[0]);
458 }
459 const_iterator iter(const value_type& aValue) const
460 {
461 return citer(aValue);
462 }
463 iterator iter(const value_type& aValue)
464 {
465 return begin() + (&aValue - &(*this)[0]);
466 }
468 {
469 return *begin();
470 }
472 {
473 return *begin();
474 }
476 {
477 return *--end();
478 }
480 {
481 return *--end();
482 }
483 iterator insert(const_iterator aPosition, const value_type& aValue)
484 {
485 return insert(aPosition, static_cast<size_type>(1), aValue);
486 }
487 template <typename... Args>
488 iterator emplace_insert(const_iterator aPosition, Args&&... aArguments)
489 {
490 return emplace_insert(aPosition, static_cast<size_type>(1), std::forward<Args>(aArguments)...);
491 }
493 {
494 return *(begin() + aIndex);
495 }
497 {
498 return *(begin() + aIndex);
499 }
500 template <class InputIterator>
501 typename std::enable_if<!std::is_integral<InputIterator>::value, iterator>::type
502 insert(const_iterator aPosition, InputIterator aFirst, InputIterator aLast)
503 {
504 return do_insert(aPosition, aFirst, aLast);
505 }
506 iterator insert(const_iterator aPosition, size_type aCount, const value_type& aValue)
507 {
508 auto pos = aPosition.iContainerPosition;
509 while (aCount > 0)
510 {
511 aPosition = insert(aPosition, &aValue, &aValue+1);
512 ++aPosition;
513 --aCount;
514 }
515 return iterator{*this, pos};
516 }
517 template <typename... Args>
518 iterator emplace_insert(const_iterator aPosition, size_type aCount, Args&&... aArguments)
519 {
520 auto pos = aPosition.iContainerPosition;
521 while (aCount > 0)
522 {
523 // todo: shouldn't be creating a temporary for emplace
524 auto const& temp = value_type{ std::forward<Args>(aArguments)... };
525 aPosition = insert(aPosition, &temp, &temp + 1);
526 ++aPosition;
527 --aCount;
528 }
529 return iterator{ *this, pos };
530 }
531 void clear()
532 {
533 erase(begin(), end());
534 }
535 void push_front(const value_type& aValue)
536 {
537 insert(begin(), aValue);
538 }
539 void push_back(const value_type& aValue)
540 {
541 insert(end(), aValue);
542 }
543 template <typename... Args>
544 void emplace_front(Args&&... aArguments)
545 {
546 emplace_insert(begin(), std::forward<Args>(aArguments)...);
547 }
548 template <typename... Args>
549 void emplace_back(Args&&... aArguments)
550 {
551 emplace_insert(end(), std::forward<Args>(aArguments)...);
552 }
553 void resize(std::size_t aNewSize, const value_type& aValue = value_type{})
554 {
555 if (size() < aNewSize)
556 insert(end(), aNewSize - size(), aValue);
557 else
558 erase(begin() + aNewSize, end());
559 }
561 {
562 erase(aPosition, aPosition + 1);
563 return iterator{*this, aPosition.iContainerPosition};
564 }
566 {
567 if (aFirst == aLast)
568 return iterator{*this, aFirst.iNode, aFirst.iContainerPosition, aFirst.iSegmentPosition};
569 segment_type& segmentFirst = aFirst.iNode->segment();
570 if (aFirst.iNode == aLast.iNode)
571 {
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);
577 }
578 else
579 {
580 segment_type& segmentLast = aLast.iNode->segment();
581 for (node* inbetweenNode = static_cast<node*>(aFirst.iNode->next()); inbetweenNode != aLast.iNode;)
582 {
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;
588 }
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);
595 else
596 aFirst.iNode->set_size(aFirst.iNode->size() - firstRemoved);
597 iSize -= firstRemoved;
598 if (segmentLast.empty())
599 free_node(aLast.iNode);
600 else
601 aLast.iNode->set_size(aLast.iNode->size() - secondRemoved);
602 iSize -= secondRemoved;
603 }
604 return iterator{*this, aFirst.iContainerPosition};
605 }
607 {
608 erase(begin());
609 }
610 void pop_back()
611 {
612 erase(--end());
613 }
614 void swap(segmented_array& aOther)
615 {
616 base_type::swap(aOther);
617 std::swap(iAllocator, aOther.iAllocator);
618 std::swap(iSize, aOther.iSize);
619 }
620
621 private:
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)
625 {
626 size_type count = std::distance(aFirst, aLast);
627 if (count == 0)
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())
633 {
634 segment_type& segment = static_cast<node*>(aPosition.iNode)->segment();
635 segment.insert(segment.begin() + aPosition.iSegmentPosition, aFirst, aLast);
636 iSize += count;
637 aPosition.iNode->set_size(aPosition.iNode->size() + count);
638 }
639 else
640 {
641 lastNode = allocate_space(aPosition, count);
642 if (aPosition.iNode == nullptr)
643 aPosition = begin();
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)
648 {
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);
653 }
654 for (node* nextNode = aPosition.iNode; count > 0 && nextNode != lastNode; nextNode = static_cast<node*>(nextNode->next()))
655 {
656 size_type addCount = std::min(count, nextNode->segment().available());
657 if (addCount != 0)
658 {
659 InputIterator stop = aFirst;
660 std::advance(stop, addCount);
661 nextNode->segment().insert(nextNode->segment().begin() + (nextNode == aPosition.iNode ? aPosition.iSegmentPosition : 0), aFirst, stop);
662 aFirst = stop;
663 iSize += addCount;
664 count -= addCount;
665 nextNode->set_size(nextNode->size() + addCount);
666 }
667 }
668 if (count > 0)
669 {
670 InputIterator stop = aFirst;
671 std::advance(stop, count);
672 lastNode->segment().insert(lastNode->segment().begin() + (lastNode == aPosition.iNode ? aPosition.iSegmentPosition : 0), aFirst, stop);
673 lastNode->set_size(lastNode->size() + count);
674 iSize += count;
675 }
676 }
677 size_type index = aPosition.iContainerPosition - aPosition.iSegmentPosition;
678 for (node* newNode = aPosition.iNode;; newNode = static_cast<node*>(newNode->next()))
679 {
680 if (newNode != before && newNode != after)
681 {
682 base_type::insert_node(newNode, index);
683 }
684 index += newNode->segment().size();
685 if (newNode == lastNode)
686 break;
687 }
688 if (aPosition.iSegmentPosition != aPosition.iNode->segment().size()) // was not end
689 return iterator{*this, aPosition.iNode, aPosition.iContainerPosition, aPosition.iSegmentPosition};
690 else
691 return iterator{*this, static_cast<node*>(aPosition.iNode->next()), aPosition.iContainerPosition, 0};
692 }
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)
696 {
697 auto pos = aPosition.iContainerPosition;
698 while (aFirst != aLast)
699 {
700 aPosition = insert(aPosition, 1, *aFirst++);
701 ++aPosition;
702 }
703 return iterator{*this, pos};
704 }
705 node* find_node(size_type aContainerPosition, size_type& aSegmentPosition) const
706 {
707 size_type nodeIndex = 0;
708 node* result = static_cast<node*>(base_type::find_node(aContainerPosition, nodeIndex));
709 aSegmentPosition = aContainerPosition - nodeIndex;
710 return result;
711 }
712 node* allocate_space(const_iterator aPosition, size_type aCount)
713 {
714 if (aCount == 0)
715 return aPosition.iNode;
716 if (aPosition.iNode)
717 aCount -= std::min(aCount, (aPosition.iNode->segment().available()));
718 if (aCount == 0)
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())
722 {
723 lastNode = static_cast<node*>(aPosition.iNode->next());
724 aCount -= std::min(aCount, lastNode->segment().available());
725 }
726 node* nextNode = aPosition.iNode;
727 while (aCount > 0)
728 aCount -= std::min(aCount, (nextNode = allocate_node(nextNode))->segment().available());
729 if (aPosition.iNode == nullptr)
730 aPosition = begin();
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;
735 }
736 node* allocate_node(node* aAfter)
737 {
738 node* newNode = std::allocator_traits<node_allocator_type>::allocate(iAllocator, 1);
739 try
740 {
741 std::allocator_traits<node_allocator_type>::construct(iAllocator, newNode, node());
742 }
743 catch (...)
744 {
745 std::allocator_traits<node_allocator_type>::deallocate(iAllocator, newNode, 1);
746 throw;
747 }
748 if (aAfter == nullptr)
749 {
752 }
753 else
754 {
755 newNode->set_previous(aAfter);
756 if (aAfter->next() != nullptr)
757 {
758 newNode->set_next(aAfter->next());
759 aAfter->next()->set_previous(newNode);
760 }
761 aAfter->set_next(newNode);
762 if (base_type::back_node() == aAfter)
764 }
765 return newNode;
766 }
767 void free_node(node* aNode)
768 {
769 if (aNode)
770 {
771 if (aNode->next())
772 aNode->next()->set_previous(aNode->previous());
773 if (aNode->previous())
774 aNode->previous()->set_next(aNode->next());
775 if (base_type::back_node() == aNode)
776 base_type::set_back_node(aNode->previous());
777 if (base_type::front_node() == aNode)
778 base_type::set_front_node(aNode->next());
780 }
781 std::allocator_traits<node_allocator_type>::destroy(iAllocator, aNode);
782 std::allocator_traits<node_allocator_type>::deallocate(iAllocator, aNode, 1);
783 }
784
785 private:
786 node_allocator_type iAllocator;
787 size_type iSize;
788 };
789
790 template <typename T, std::size_t SegmentSize, typename Alloc>
792 {
793 return lhs.size() == rhs.size() && std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
794 }
795
796 template <typename T, std::size_t SegmentSize, typename Alloc>
798 {
799 return !(lhs == rhs);
800 }
801}
node * find_node(size_type aPosition, size_type &aNodeIndex) const
node * back_node() 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
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(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[](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::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
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)
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)
bool empty() const
Definition vecarray.hpp:439
iterator erase(const_iterator position)
Definition vecarray.hpp:514
const_iterator begin() const
Definition vecarray.hpp:430
size_type size() const
Definition vecarray.hpp:441
const_iterator end() const
Definition vecarray.hpp:433
Definition plf_hive.h:79
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)
Definition plf_hive.h:4776
iterator_traits< it_type >::difference_type distance(const it_type first, const it_type last)
Definition plf_hive.h:107
void advance(it_type &it, const distance_type distance)
Definition plf_hive.h:81