neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
tag_array.hpp
Go to the documentation of this file.
1/*
2* tag_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 Tag, typename T, std::size_t ArraySize = 16, std::size_t VectorSize = 256, typename Alloc = std::allocator<T> >
48 class tag_array : private neolib::array_tree<Alloc>
49 {
51 public:
52 typedef T value_type;
55 typedef Alloc allocator_type;
56 typedef typename std::allocator_traits<allocator_type>::pointer pointer;
57 typedef typename std::allocator_traits<allocator_type>::const_pointer const_pointer;
58 typedef typename std::allocator_traits<allocator_type>::size_type size_type;
59 typedef typename std::allocator_traits<allocator_type>::difference_type difference_type;
60 private:
61 class node : public base_type::node
62 {
63 public:
64 typedef typename Tag::template rebind<node>::type tag_type;
65 class data : public neolib::vecarray<T, ArraySize, VectorSize, neolib::nocheck>
66 {
67 public:
68 data(node& aNode, const tag_type& aTag) :
69 iTag(aNode, aTag)
70 {
71 }
72 public:
73 const tag_type& tag() const
74 {
75 return iTag;
76 }
77 private:
78 tag_type iTag;
79 };
80 typedef data segment_type;
81 public:
82 node(const tag_type& aTag) :
83 iSegment(*this, aTag)
84 {
85 }
86 public:
87 const segment_type& segment() const
88 {
89 return iSegment;
90 }
91 segment_type& segment()
92 {
93 return iSegment;
94 }
95 private:
96 segment_type iSegment;
97 };
98 public:
99 typedef typename node::tag_type tag_type;
100 private:
101 typedef typename node::segment_type segment_type;
102 typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<node> node_allocator_type;
103 public:
105 {
106 friend class tag_array;
108
109 public:
110 typedef std::random_access_iterator_tag iterator_category;
115
116 public:
118 iContainer(), iNode(), iContainerPosition(), iSegmentPosition()
119 {
120 }
121 iterator(const iterator& aOther) :
122 iContainer(aOther.iContainer), iNode(aOther.iNode), iContainerPosition(aOther.iContainerPosition), iSegmentPosition(aOther.iSegmentPosition)
123 {
124 }
126 {
127 iContainer = aOther.iContainer;
128 iNode = aOther.iNode;
129 iContainerPosition = aOther.iContainerPosition;
130 iSegmentPosition = aOther.iSegmentPosition;
131 return *this;
132 }
133 private:
134 iterator(tag_array& aContainer, size_type aContainerPosition) :
135 iContainer(&aContainer), iNode(0), iContainerPosition(aContainerPosition), iSegmentPosition(0)
136 {
137 iNode = iContainer->find_node(aContainerPosition, iSegmentPosition);
138 if (iNode->is_nil())
139 *this = iContainer->end();
140 }
141 iterator(tag_array& aContainer, node* aNode, size_type aContainerPosition, size_type aSegmentPosition) :
142 iContainer(&aContainer), iNode(aNode), iContainerPosition(aContainerPosition), iSegmentPosition(aSegmentPosition)
143 {
144 }
145
146 public:
148 {
149 ++iContainerPosition;
150 if (++iSegmentPosition == static_cast<node*>(iNode)->segment().size())
151 {
152 if (iNode != iContainer->back_node())
153 {
154 iNode = static_cast<node*>(iNode->next());
155 iSegmentPosition = 0;
156 }
157 }
158 return *this;
159 }
161 {
162 --iContainerPosition;
163 if (iSegmentPosition-- == 0)
164 {
165 iNode = static_cast<node*>(iNode->previous());
166 iSegmentPosition = static_cast<node*>(iNode)->segment().size() - 1;
167 }
168 return *this;
169 }
170 iterator operator++(int) { iterator ret(*this); operator++(); return ret; }
171 iterator operator--(int) { iterator ret(*this); operator--(); return ret; }
173 {
174 if (aDifference < 0)
175 return operator-=(-aDifference);
176 else if (iNode == nullptr || aDifference >= static_cast<difference_type>(segment().size() - iSegmentPosition))
177 *this = iterator(*iContainer, iContainerPosition + aDifference);
178 else
179 {
180 iContainerPosition += aDifference;
181 iSegmentPosition += aDifference;
182 }
183 return *this;
184 }
186 {
187 if (aDifference < 0)
188 return operator+=(-aDifference);
189 else if (aDifference > static_cast<difference_type>(iSegmentPosition))
190 *this = iterator(*iContainer, iContainerPosition - aDifference);
191 else
192 {
193 iContainerPosition -= aDifference;
194 iSegmentPosition -= aDifference;
195 }
196 return *this;
197 }
198 iterator operator+(difference_type aDifference) const { iterator result(*this); result += aDifference; return result; }
199 iterator operator-(difference_type aDifference) const { iterator result(*this); result -= aDifference; return result; }
200 reference operator[](difference_type aDifference) const { return *((*this) + aDifference); }
201 difference_type operator-(const iterator& aOther) const { return static_cast<difference_type>(iContainerPosition)-static_cast<difference_type>(aOther.iContainerPosition); }
202 reference operator*() const { return segment()[iSegmentPosition]; }
203 pointer operator->() const { return &operator*(); }
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 bool operator<=(const iterator& aOther) const { return iContainerPosition <= aOther.iContainerPosition; }
208 bool operator>(const iterator& aOther) const { return iContainerPosition > aOther.iContainerPosition; }
209 bool operator>=(const iterator& aOther) const { return iContainerPosition >= aOther.iContainerPosition; }
210
211 private:
212 segment_type& segment() const { return iNode->segment(); }
213
214 private:
215 tag_array* iContainer;
216 node* iNode;
217 size_type iContainerPosition;
218 size_type iSegmentPosition;
219 };
221 {
222 friend class tag_array;
223
224 public:
225 typedef std::random_access_iterator_tag iterator_category;
230
231 public:
233 iContainer(), iNode(), iContainerPosition(), iSegmentPosition()
234 {
235 }
237 iContainer(aOther.iContainer), iNode(aOther.iNode), iContainerPosition(aOther.iContainerPosition), iSegmentPosition(aOther.iSegmentPosition)
238 {
239 }
240 const_iterator(const typename tag_array::iterator& aOther) :
241 iContainer(aOther.iContainer), iNode(aOther.iNode), iContainerPosition(aOther.iContainerPosition), iSegmentPosition(aOther.iSegmentPosition)
242 {
243 }
245 {
246 iContainer = aOther.iContainer;
247 iNode = aOther.iNode;
248 iContainerPosition = aOther.iContainerPosition;
249 iSegmentPosition = aOther.iSegmentPosition;
250 return *this;
251 }
253 {
254 iContainer = aOther.iContainer;
255 iNode = aOther.iNode;
256 iContainerPosition = aOther.iContainerPosition;
257 iSegmentPosition = aOther.iSegmentPosition;
258 return *this;
259 }
260 private:
261 const_iterator(const tag_array& aContainer, size_type aContainerPosition) :
262 iContainer(&aContainer), iNode(nullptr), iContainerPosition(aContainerPosition), iSegmentPosition(0)
263 {
264 iNode = iContainer->find_node(aContainerPosition, iSegmentPosition);
265 if (iNode->is_nil())
266 *this = iContainer->end();
267 }
268 const_iterator(const tag_array& aContainer, node* aNode, size_type aContainerPosition, size_type aSegmentPosition) :
269 iContainer(&aContainer), iNode(aNode), iContainerPosition(aContainerPosition), iSegmentPosition(aSegmentPosition)
270 {
271 }
272
273 public:
275 {
276 ++iContainerPosition;
277 if (++iSegmentPosition == static_cast<node*>(iNode)->segment().size())
278 {
279 if (iNode != iContainer->back_node())
280 {
281 iNode = static_cast<node*>(iNode->next());
282 iSegmentPosition = 0;
283 }
284 }
285 return *this;
286 }
288 {
289 --iContainerPosition;
290 if (iSegmentPosition-- == 0)
291 {
292 iNode = static_cast<node*>(iNode->previous());
293 iSegmentPosition = static_cast<node*>(iNode)->segment().size() - 1;
294 }
295 return *this;
296 }
297 const_iterator operator++(int) { const_iterator ret(*this); operator++(); return ret; }
298 const_iterator operator--(int) { const_iterator ret(*this); operator--(); return ret; }
300 {
301 if (aDifference < 0)
302 return operator-=(-aDifference);
303 else if (iNode == nullptr || aDifference >= static_cast<difference_type>(segment().size() - iSegmentPosition))
304 *this = const_iterator(*iContainer, iContainerPosition + aDifference);
305 else
306 {
307 iContainerPosition += aDifference;
308 iSegmentPosition += aDifference;
309 }
310 return *this;
311 }
313 {
314 if (aDifference < 0)
315 return operator+=(-aDifference);
316 else if (aDifference > static_cast<difference_type>(iSegmentPosition))
317 *this = const_iterator(*iContainer, iContainerPosition - aDifference);
318 else
319 {
320 iContainerPosition -= aDifference;
321 iSegmentPosition -= aDifference;
322 }
323 return *this;
324 }
325 const_iterator operator+(difference_type aDifference) const { const_iterator result(*this); result += aDifference; return result; }
326 const_iterator operator-(difference_type aDifference) const { const_iterator result(*this); result -= aDifference; return result; }
327 const_reference operator[](difference_type aDifference) const { return *((*this) + aDifference); }
328 difference_type operator-(const const_iterator& aOther) const { return static_cast<difference_type>(iContainerPosition)-static_cast<difference_type>(aOther.iContainerPosition); }
329 const_reference operator*() const { return segment()[iSegmentPosition]; }
330 const_pointer operator->() const { return &operator*(); }
331 bool operator==(const const_iterator& aOther) const { return iContainerPosition == aOther.iContainerPosition; }
332 bool operator!=(const const_iterator& aOther) const { return iContainerPosition != aOther.iContainerPosition; }
333 bool operator<(const const_iterator& aOther) const { return iContainerPosition < aOther.iContainerPosition; }
334 bool operator<=(const const_iterator& aOther) const { return iContainerPosition <= aOther.iContainerPosition; }
335 bool operator>(const const_iterator& aOther) const { return iContainerPosition > aOther.iContainerPosition; }
336 bool operator>=(const const_iterator& aOther) const { return iContainerPosition >= aOther.iContainerPosition; }
337
338 private:
339 segment_type& segment() const { return iNode->segment(); }
340
341 private:
342 const tag_array* iContainer;
343 node* iNode;
344 size_type iContainerPosition;
345 size_type iSegmentPosition;
346 };
347 typedef std::reverse_iterator<iterator> reverse_iterator;
348 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
349
350 public:
351 tag_array(const Alloc& aAllocator = Alloc()) :
352 iAllocator(aAllocator), iSize(0)
353 {
354 }
355 tag_array(const tag_type& aTag, const size_type aCount, const value_type& aValue, const Alloc& aAllocator = Alloc()) :
356 iAllocator(aAllocator), iSize(0)
357 {
358 insert(aTag, begin(), aCount, aValue);
359 }
360 template <typename InputIterator>
361 tag_array(const tag_type& aTag, InputIterator aFirst, InputIterator aLast, const Alloc& aAllocator = Alloc()) :
362 iAllocator(aAllocator), iSize(0)
363 {
364 insert(aTag, begin(), aFirst, aLast);
365 }
367 {
368 erase(begin(), end());
369 }
370 public:
372 {
373 clear();
374 insert(begin(), aRhs.begin(), aRhs.end());
375 return *this;
376 }
377 public:
378 bool operator==(const tag_array& aRhs) const
379 {
380 return size() == aRhs.size() && std::equal(begin(), end(), aRhs.begin(), aRhs.end());
381 }
382 bool operator!=(const tag_array& aRhs) const
383 {
384 return !(*this == aRhs);
385 }
386 public:
388 {
389 return iSize;
390 }
391 bool empty() const
392 {
393 return iSize == 0;
394 }
396 {
397 return const_iterator(*this, static_cast<node*>(base_type::front_node()), 0, 0);
398 }
400 {
401 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);
402 }
404 {
405 return iterator(*this, static_cast<node*>(base_type::front_node()), 0, 0);
406 }
408 {
409 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);
410 }
412 {
413 return const_reverse_iterator(end());
414 }
416 {
418 }
420 {
421 return reverse_iterator(end());
422 }
424 {
425 return reverse_iterator(begin());
426 }
428 {
429 return *begin();
430 }
432 {
433 return *begin();
434 }
436 {
437 return *--end();
438 }
440 {
441 return *--end();
442 }
443 iterator insert(const tag_type& aTag, const_iterator aPosition, const value_type& aValue)
444 {
445 return insert(aTag, aPosition, 1, aValue);
446 }
448 {
449 return *(begin() + aIndex);
450 }
452 {
453 return *(begin() + aIndex);
454 }
456 {
457 auto pos = aPosition.iContainerPosition;
458 while (aFirst != aLast)
459 {
460 aPosition = insert(aFirst.segment().tag(), aPosition, 1, *aFirst++);
461 ++aPosition;
462 }
463 return iterator(*this, pos);
464 }
465 template <class InputIterator>
466 typename std::enable_if<!std::is_integral<InputIterator>::value, iterator>::type
467 insert(const tag_type& aTag, const_iterator aPosition, InputIterator aFirst, InputIterator aLast)
468 {
469 return do_insert(aTag, aPosition, aFirst, aLast);
470 }
471 iterator insert(const tag_type& aTag, const_iterator aPosition, size_type aCount, const value_type& aValue)
472 {
473 auto pos = aPosition.iContainerPosition;
474 while (aCount > 0)
475 {
476 aPosition = insert(aTag, aPosition, &aValue, &aValue+1);
477 ++aPosition;
478 --aCount;
479 }
480 return iterator(*this, pos);
481 }
482 void clear()
483 {
484 erase(begin(), end());
485 }
486 void push_front(const tag_type& aTag, const value_type& aValue)
487 {
488 insert(aTag, begin(), aValue);
489 }
490 void push_back(const tag_type& aTag, const value_type& aValue)
491 {
492 insert(aTag, end(), aValue);
493 }
495 {
496 erase(aPosition, aPosition + 1);
497 return iterator(*this, aPosition.iContainerPosition);
498 }
500 {
501 if (aFirst == aLast)
502 return iterator(*this, aFirst.iNode, aFirst.iContainerPosition, aFirst.iSegmentPosition);
503 segment_type& segmentFirst = aFirst.iNode->segment();
504 if (aFirst.iNode == aLast.iNode)
505 {
506 segmentFirst.erase(segmentFirst.begin() + aFirst.iSegmentPosition, segmentFirst.begin() + aLast.iSegmentPosition);
507 iSize -= (aLast.iSegmentPosition - aFirst.iSegmentPosition);
508 aFirst.iNode->set_size(aFirst.iNode->size() - (aLast.iSegmentPosition - aFirst.iSegmentPosition));
509 if (segmentFirst.empty())
510 free_node(aFirst.iNode);
511 }
512 else
513 {
514 segment_type& segmentLast = aLast.iNode->segment();
515 for (node* inbetweenNode = static_cast<node*>(aFirst.iNode->next()); inbetweenNode != aLast.iNode;)
516 {
517 node* next = static_cast<node*>(inbetweenNode->next());
518 size_type inbetweenRemoved = inbetweenNode->segment().size();
519 free_node(inbetweenNode);
520 iSize -= inbetweenRemoved;
521 inbetweenNode = next;
522 }
523 size_type firstRemoved = segmentFirst.size() - aFirst.iSegmentPosition;
524 size_type secondRemoved = aLast.iSegmentPosition;
525 segmentFirst.erase(segmentFirst.begin() + aFirst.iSegmentPosition, segmentFirst.end());
526 segmentLast.erase(segmentLast.begin(), segmentLast.begin() + aLast.iSegmentPosition);
527 if (segmentFirst.empty())
528 free_node(aFirst.iNode);
529 else
530 aFirst.iNode->set_size(aFirst.iNode->size() - firstRemoved);
531 iSize -= firstRemoved;
532 if (segmentLast.empty())
533 free_node(aLast.iNode);
534 else
535 aLast.iNode->set_size(aLast.iNode->size() - secondRemoved);
536 iSize -= secondRemoved;
537 }
538 return iterator(*this, aFirst.iContainerPosition);
539 }
541 {
542 erase(begin());
543 }
544 void pop_back()
545 {
546 erase(--end());
547 }
548 void swap(tag_array& aOther)
549 {
550 base_type::swap(aOther);
551 std::swap(iAllocator, aOther.iAllocator);
552 std::swap(iSize, aOther.iSize);
553 }
554 const tag_type& tag(const_iterator aWhere) const
555 {
556 return aWhere.segment().tag();
557 }
558
559 private:
560 template <class InputIterator>
561 typename std::enable_if<!std::is_same<typename std::iterator_traits<InputIterator>::iterator_category, std::input_iterator_tag>::value, iterator>::type
562 do_insert(const tag_type& aTag, const_iterator aPosition, InputIterator aFirst, InputIterator aLast)
563 {
564 size_type count = std::distance(aFirst, aLast);
565 if (count == 0)
566 return iterator(*this, aPosition.iNode, aPosition.iContainerPosition, aPosition.iSegmentPosition);
567 if (aPosition.iNode != nullptr && static_cast<node*>(aPosition.iNode)->segment().tag() != aTag &&
568 aPosition.iNode->previous() != nullptr && static_cast<node*>(aPosition.iNode->previous())->segment().tag() == aTag &&
569 static_cast<node*>(aPosition.iNode->previous())->segment().available() >= count &&
570 aPosition.iSegmentPosition == 0)
571 {
572 aPosition.iNode = static_cast<node*>(aPosition.iNode->previous());
573 aPosition.iSegmentPosition = aPosition.iNode->segment().size();
574 }
575 node* before = aPosition.iNode;
576 node* after = aPosition.iNode ? static_cast<node*>(aPosition.iNode->next()) : nullptr;
577 node* lastNode = aPosition.iNode;
578 if (aPosition.iNode != nullptr && count <= static_cast<node*>(aPosition.iNode)->segment().available() && static_cast<node*>(aPosition.iNode)->segment().tag() == aTag)
579 {
580 segment_type& segment = static_cast<node*>(aPosition.iNode)->segment();
581 segment.insert(segment.begin() + aPosition.iSegmentPosition, aFirst, aLast);
582 iSize += count;
583 aPosition.iNode->set_size(aPosition.iNode->size() + count);
584 }
585 else
586 {
587 lastNode = allocate_space(aTag, aPosition, count);
588 if (aPosition.iNode == nullptr)
589 aPosition = begin();
590 segment_type& segment = aPosition.iNode->segment();
591 typename segment_type::const_iterator tailEnd = segment.end();
592 typename segment_type::const_iterator tailStart = tailEnd - (segment.size() - aPosition.iSegmentPosition);
593 if (tailStart != tailEnd)
594 {
595 lastNode->segment().insert(lastNode->segment().begin(), tailStart, tailEnd);
596 lastNode->set_size(lastNode->size() + (tailEnd - tailStart));
597 aPosition.iNode->set_size(aPosition.iNode->size() - (tailEnd - tailStart));
598 segment.erase(tailStart, tailEnd);
599 }
600 for (node* nextNode = segment.tag() == aTag ? aPosition.iNode : static_cast<node*>(aPosition.iNode->next()); count > 0 && nextNode != lastNode; nextNode = static_cast<node*>(nextNode->next()))
601 {
602 size_type addCount = std::min(count, nextNode->segment().available());
603 if (addCount != 0)
604 {
605 InputIterator stop = aFirst;
606 std::advance(stop, addCount);
607 nextNode->segment().insert(nextNode->segment().begin() + (nextNode == aPosition.iNode ? aPosition.iSegmentPosition : 0), aFirst, stop);
608 aFirst = stop;
609 iSize += addCount;
610 count -= addCount;
611 nextNode->set_size(nextNode->size() + addCount);
612 }
613 }
614 if (count > 0)
615 {
616 InputIterator stop = aFirst;
617 std::advance(stop, count);
618 lastNode->segment().insert(lastNode->segment().begin() + (lastNode == aPosition.iNode ? aPosition.iSegmentPosition : 0), aFirst, stop);
619 lastNode->set_size(lastNode->size() + count);
620 iSize += count;
621 }
622 }
623 size_type index = aPosition.iContainerPosition - aPosition.iSegmentPosition;
624 for (node* newNode = aPosition.iNode;; newNode = static_cast<node*>(newNode->next()))
625 {
626 if (newNode != before && newNode != after)
627 base_type::insert_node(newNode, index);
628 index += newNode->segment().size();
629 if (newNode == lastNode)
630 break;
631 }
632 if (aPosition.iNode->segment().empty())
633 {
634 auto insertionPoint = iterator(*this, static_cast<node*>(aPosition.iNode->next()), aPosition.iContainerPosition, 0);
635 free_node(aPosition.iNode);
636 return insertionPoint;
637 }
638 else if (aPosition.iSegmentPosition != aPosition.iNode->segment().size()) // was not end
639 return iterator(*this, aPosition.iNode, aPosition.iContainerPosition, aPosition.iSegmentPosition);
640 else
641 return iterator(*this, static_cast<node*>(aPosition.iNode->next()), aPosition.iContainerPosition, 0);
642 }
643 template <class InputIterator>
644 typename std::enable_if<std::is_same<typename std::iterator_traits<InputIterator>::iterator_category, std::input_iterator_tag>::value, iterator>::type
645 do_insert(const tag_type& aTag, const_iterator aPosition, InputIterator aFirst, InputIterator aLast)
646 {
647 auto pos = aPosition.iContainerPosition;
648 while (aFirst != aLast)
649 {
650 aPosition = insert(aTag, aPosition, 1, *aFirst++);
651 ++aPosition;
652 }
653 return iterator(*this, pos);
654 }
655 node* find_node(size_type aContainerPosition, size_type& aSegmentPosition) const
656 {
657 size_type nodeIndex = 0;
658 node* result = static_cast<node*>(base_type::find_node(aContainerPosition, nodeIndex));
659 aSegmentPosition = aContainerPosition - nodeIndex;
660 return result;
661 }
662 node* allocate_space(const tag_type& aTag, const_iterator aPosition, size_type aCount)
663 {
664 if (aCount == 0)
665 return aPosition.iNode;
666 if (aPosition.iNode && aPosition.iNode->segment().tag() == aTag)
667 aCount -= std::min(aCount, (aPosition.iNode->segment().available()));
668 if (aCount == 0)
669 return aPosition.iNode;
670 node* lastNode = nullptr;
671 if (aCount > 0 && aPosition.iNode && aPosition.iNode->next() != nullptr && aCount <= static_cast<node*>(aPosition.iNode->next())->segment().available() && static_cast<node*>(aPosition.iNode->next())->segment().tag() == aTag)
672 {
673 if (aPosition.iNode->segment().tag() == aTag || aPosition.iSegmentPosition == aPosition.iNode->segment().size())
674 {
675 lastNode = static_cast<node*>(aPosition.iNode->next());
676 aCount -= std::min(aCount, lastNode->segment().available());
677 }
678 }
679 node* nextNode = aPosition.iNode;
680 while (aCount > 0)
681 aCount -= std::min(aCount, (nextNode = allocate_node(aTag, nextNode))->segment().available());
682 if (aPosition.iNode == nullptr)
683 aPosition = begin();
684 segment_type& segment = aPosition.iNode->segment();
685 if (aPosition.iSegmentPosition < segment.size() && (nextNode->segment().available() < segment.size() - aPosition.iSegmentPosition || segment.tag() != aTag))
686 lastNode = allocate_node(segment.tag(), nextNode);
687 return lastNode ? lastNode : nextNode;
688 }
689 node* allocate_node(const tag_type& aTag, node* aAfter)
690 {
691 node* newNode = iAllocator.allocate(1);
692 std::allocator_traits<decltype(iAllocator)>::construct(iAllocator, newNode, node(aTag));
693 if (aAfter == nullptr)
694 {
697 }
698 else
699 {
700 newNode->set_previous(aAfter);
701 if (aAfter->next() != nullptr)
702 {
703 newNode->set_next(aAfter->next());
704 aAfter->next()->set_previous(newNode);
705 }
706 aAfter->set_next(newNode);
707 if (base_type::back_node() == aAfter)
709 }
710 return newNode;
711 }
712 void free_node(node* aNode)
713 {
714 if (aNode)
715 {
716 if (aNode->next())
717 aNode->next()->set_previous(aNode->previous());
718 if (aNode->previous())
719 aNode->previous()->set_next(aNode->next());
720 if (base_type::back_node() == aNode)
721 base_type::set_back_node(aNode->previous());
722 if (base_type::front_node() == aNode)
723 base_type::set_front_node(aNode->next());
725 }
726 std::allocator_traits<decltype(iAllocator)>::destroy(iAllocator, aNode);
727 iAllocator.deallocate(aNode, 1);
728 }
729
730 private:
731 node_allocator_type iAllocator;
732 size_type iSize;
733 };
734}
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
difference_type operator-(const const_iterator &aOther) const
const_iterator & operator+=(difference_type aDifference)
bool operator!=(const const_iterator &aOther) const
tag_array::const_pointer pointer
tag_array::difference_type difference_type
const_iterator & operator-=(difference_type aDifference)
const_iterator(const typename tag_array::iterator &aOther)
const_iterator operator-(difference_type aDifference) const
bool operator==(const const_iterator &aOther) const
const_reference operator[](difference_type aDifference) const
const_reference operator*() const
bool operator>=(const const_iterator &aOther) const
const_iterator(const const_iterator &aOther)
const_iterator operator+(difference_type aDifference) const
tag_array::value_type value_type
tag_array::const_reference reference
std::random_access_iterator_tag iterator_category
bool operator<=(const const_iterator &aOther) const
bool operator>(const const_iterator &aOther) const
const_iterator & operator=(const typename tag_array::iterator &aOther)
const_iterator & operator=(const const_iterator &aOther)
const_pointer operator->() const
reference operator*() const
tag_array::reference reference
bool operator>(const iterator &aOther) const
iterator & operator=(const iterator &aOther)
iterator(const iterator &aOther)
bool operator<(const iterator &aOther) const
reference operator[](difference_type aDifference) const
iterator & operator-=(difference_type aDifference)
iterator operator-(difference_type aDifference) const
tag_array::difference_type difference_type
iterator & operator+=(difference_type aDifference)
difference_type operator-(const iterator &aOther) const
bool operator>=(const iterator &aOther) const
tag_array::value_type value_type
bool operator!=(const iterator &aOther) const
tag_array::pointer pointer
bool operator==(const iterator &aOther) const
iterator operator+(difference_type aDifference) const
std::random_access_iterator_tag iterator_category
bool operator<=(const iterator &aOther) const
const tag_type & tag() const
Definition tag_array.hpp:73
data(node &aNode, const tag_type &aTag)
Definition tag_array.hpp:68
node::tag_type tag_type
Definition tag_array.hpp:99
std::enable_if<!std::is_integral< InputIterator >::value, iterator >::type insert(const tag_type &aTag, const_iterator aPosition, InputIterator aFirst, InputIterator aLast)
void push_front(const tag_type &aTag, const value_type &aValue)
const_iterator end() const
const_reference operator[](size_type aIndex) const
reverse_iterator rbegin()
const_reverse_iterator rbegin() const
const_reference front() const
reference operator[](size_type aIndex)
std::allocator_traits< allocator_type >::size_type size_type
Definition tag_array.hpp:58
iterator erase(const_iterator aPosition)
tag_array(const tag_type &aTag, const size_type aCount, const value_type &aValue, const Alloc &aAllocator=Alloc())
void swap(tag_array &aOther)
reverse_iterator rend()
std::allocator_traits< allocator_type >::pointer pointer
Definition tag_array.hpp:56
size_type size() const
std::reverse_iterator< iterator > reverse_iterator
bool operator==(const tag_array &aRhs) const
const_reference back() const
tag_array(const Alloc &aAllocator=Alloc())
tag_array(const tag_type &aTag, InputIterator aFirst, InputIterator aLast, const Alloc &aAllocator=Alloc())
reference back()
const value_type & const_reference
Definition tag_array.hpp:54
iterator insert(const_iterator aPosition, const_iterator aFirst, const_iterator aLast)
iterator insert(const tag_type &aTag, const_iterator aPosition, size_type aCount, const value_type &aValue)
reference front()
bool empty() const
iterator insert(const tag_type &aTag, const_iterator aPosition, const value_type &aValue)
const_iterator begin() const
tag_array & operator=(const tag_array &aRhs)
const_reverse_iterator rend() const
std::allocator_traits< allocator_type >::const_pointer const_pointer
Definition tag_array.hpp:57
iterator erase(const_iterator aFirst, const_iterator aLast)
value_type & reference
Definition tag_array.hpp:53
void push_back(const tag_type &aTag, const value_type &aValue)
bool operator!=(const tag_array &aRhs) const
std::reverse_iterator< const_iterator > const_reverse_iterator
const tag_type & tag(const_iterator aWhere) const
std::allocator_traits< allocator_type >::difference_type difference_type
Definition tag_array.hpp:59
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
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