CppELib 1.7.0
Loading...
Searching...
No Matches
PreallocatedDeque.h
Go to the documentation of this file.
1#ifndef CONTAINER_PREALLOCATED_DEQUE_H_INCLUDED
2#define CONTAINER_PREALLOCATED_DEQUE_H_INCLUDED
3
4#include <cstddef>
5#ifndef CPPELIB_NO_STD_ITERATOR
6#include <iterator>
7#endif
9#include "private/TypeTraits.h"
10#include "private/Construct.h"
11#include "Assertion/Assertion.h"
12
13namespace Container {
14
15template <typename T>
16class PreallocatedDeque;
17
21template <typename T, typename Ref, typename Ptr, typename DeqPtr>
23public:
24 typedef T value_type;
25 typedef std::size_t size_type;
26 typedef std::ptrdiff_t difference_type;
29 typedef Ref reference;
30 typedef const Ref const_reference;
31 typedef Ptr pointer;
32 typedef const Ptr const_pointer;
33#ifndef CPPELIB_NO_STD_ITERATOR
34 typedef std::random_access_iterator_tag iterator_category;
35#endif
36
37 PreallocatedDeque_iterator() : m_deq(0), m_idx(0U) {}
38
39 PreallocatedDeque_iterator(const iterator& x) : m_deq(x.m_deq), m_idx(x.m_idx) {}
40
42 {
43 m_deq = x.m_deq;
44 m_idx = x.m_idx;
45 return *this;
46 }
47
49 {
50 DEBUG_ASSERT(m_deq != 0);
51 if (n < 0) {
52 return operator-=(-n);
53 }
54
55 const size_type un = static_cast<size_type>(n);
56 m_idx = m_deq->next_idx(m_idx, un);
57 return *this;
58 }
59
61 {
63 return tmp += n;
64 }
65
67 {
68 DEBUG_ASSERT(m_deq != 0);
69 if (n < 0) {
70 return operator+=(-n);
71 }
72
73 const size_type un = static_cast<size_type>(n);
74 m_idx = m_deq->prev_idx(m_idx, un);
75 return *this;
76 }
77
79 {
80 DEBUG_ASSERT(m_deq != 0);
81 DEBUG_ASSERT(m_deq == x.m_deq);
82 if (*this >= x) {
83 return static_cast<difference_type>(m_deq->distance_idx(x.m_idx, m_idx));
84 }
85 return -static_cast<difference_type>(m_deq->distance_idx(m_idx, x.m_idx));
86 }
87
89 {
91 return tmp -= n;
92 }
93
98
100 {
101 return operator-=(1);
102 }
103
105 {
106 PreallocatedDeque_iterator tmp = *this;
107 ++*this;
108 return tmp;
109 }
110
112 {
113 PreallocatedDeque_iterator tmp = *this;
114 --*this;
115 return tmp;
116 }
117
119 {
120 DEBUG_ASSERT(m_deq != 0);
121 return m_deq->m_buf[m_idx];
122 }
123
125 {
126 DEBUG_ASSERT(m_deq != 0);
127 return &m_deq->m_buf[m_idx];
128 }
129
131 {
132 return *(*this + n);
133 }
134
136 {
137 return (m_deq == x.m_deq) && (m_idx == x.m_idx);
138 }
139
141 {
142 return !(*this == x);
143 }
144
146 {
147 DEBUG_ASSERT(m_deq != 0);
148 DEBUG_ASSERT(m_deq == x.m_deq);
149 return
150 m_deq->distance_idx(m_deq->m_begin, m_idx) <
151 m_deq->distance_idx(x.m_deq->m_begin, x.m_idx);
152 }
153
155 {
156 return x < *this;
157 }
158
160 {
161 return !(x < *this);
162 }
163
165 {
166 return !(*this < x);
167 }
168
169private:
170 template <typename U>
171 friend class PreallocatedDeque;
172
173 template <typename U, typename RefX, typename PtrX, typename DeqPtrX>
175
176 DeqPtr m_deq;
177 size_type m_idx;
178
179 PreallocatedDeque_iterator(DeqPtr deq, size_type idx) : m_deq(deq), m_idx(idx) {}
180};
181
182template <typename T, typename Ref, typename Ptr, typename DeqPtr>
183PreallocatedDeque_iterator<T, Ref, Ptr, DeqPtr>
185{
186 return x + n;
187}
188
199template <typename T>
201public:
202 typedef T value_type;
203 typedef std::size_t size_type;
204 typedef std::ptrdiff_t difference_type;
210 typedef const value_type* const_pointer;
211#ifndef CPPELIB_NO_STD_ITERATOR
212 typedef std::reverse_iterator<iterator> reverse_iterator;
213 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
214#endif
215
216private:
217 T* m_buf;
218 size_type m_buf_size;
219 size_type m_begin;
220 size_type m_end;
221
222 class BadAlloc : public Container::BadAlloc {
223 public:
224 BadAlloc() : Container::BadAlloc() {}
225 const char* what() const CPPELIB_CONTAINER_NOEXCEPT
226 {
227 return "PreallocatedDeque::BadAlloc";
228 }
229 };
230
232
233public:
239 : m_buf(0), m_buf_size(0U), m_begin(0U), m_end(0U)
240 {}
241
249 : m_buf(static_cast<T*>(preallocated_buffer)), m_buf_size(buffer_size), m_begin(0U), m_end(0U)
250 {
251 }
252
258 {
259 destroy_range(begin(), end());
260 }
261
271 {
272 if (m_buf != 0) {
273 return;
274 }
275 m_buf = static_cast<T*>(preallocated_buffer);
276 m_buf_size = buffer_size;
277 }
278
280 {
281 if (this != &x) {
282 assign(x.begin(), x.end());
283 }
284 return *this;
285 }
286
288 {
289 return distance_idx(m_begin, m_end);
290 }
291
293 {
294 return (m_buf_size / sizeof(T)) - 1U;
295 }
296
298 {
299 return max_size() - size();
300 }
301
302 bool empty() const
303 {
304 return m_begin == m_end;
305 }
306
307 bool full() const
308 {
309 return size() == max_size();
310 }
311
312 void clear()
313 {
314 destroy_range(begin(), end());
315 m_end = m_begin;
316 }
317
319 {
320 return *(begin() + idx);
321 }
322
324 {
325 return *(begin() + idx);
326 }
327
329 {
330 if (idx >= size()) {
331 CPPELIB_CONTAINER_THROW(OutOfRange("PreallocatedDeque::at"));
332 }
333 return *(begin() + idx);
334 }
335
337 {
338 if (idx >= size()) {
339 CPPELIB_CONTAINER_THROW(OutOfRange("PreallocatedDeque::at"));
340 }
341 return *(begin() + idx);
342 }
343
345 {
346 return iterator(this, m_begin);
347 }
348
350 {
351 return const_iterator(this, m_begin);
352 }
353
355 {
356 return iterator(this, m_end);
357 }
358
360 {
361 return const_iterator(this, m_end);
362 }
363
364#ifndef CPPELIB_NO_STD_ITERATOR
366 {
367 return reverse_iterator(end());
368 }
369
371 {
372 return const_reverse_iterator(end());
373 }
374
376 {
377 return reverse_iterator(begin());
378 }
379
381 {
383 }
384#endif
385
387 {
389 return *begin();
390 }
391
393 {
395 return *begin();
396 }
397
399 {
401 return *(end() - 1);
402 }
403
405 {
407 return *(end() - 1);
408 }
409
410 void resize(size_type n, const T& data = T())
411 {
412 if (size() >= n) {
413 destroy_range(begin() + n, end());
414 m_end = prev_idx(m_end, size() - n);
415 return;
416 }
417
418 if (max_size() < n) {
419 CPPELIB_CONTAINER_THROW(BadAlloc());
420 }
421 const size_type rest = n - size();
422 for (size_type i = 0U; i < rest; ++i) {
423 push_back(data);
424 }
425 }
426
427 void push_back(const T& data)
428 {
429 if (full()) {
430 CPPELIB_CONTAINER_THROW(BadAlloc());
431 }
432 construct(&*end(), data);
433 m_end = next_idx(m_end);
434 }
435
436 void pop_back()
437 {
439 destroy(&*(end() - 1));
440 m_end = prev_idx(m_end);
441 }
442
443 void push_front(const T& data)
444 {
445 if (full()) {
446 CPPELIB_CONTAINER_THROW(BadAlloc());
447 }
448 construct(&*(begin() - 1), data);
449 m_begin = prev_idx(m_begin);
450 }
451
453 {
455 destroy(&*begin());
456 m_begin = next_idx(m_begin);
457 }
458
459 void assign(size_type n, const T& data)
460 {
461 if (max_size() < n) {
462 CPPELIB_CONTAINER_THROW(BadAlloc());
463 }
464 clear();
465 resize(n, data);
466 }
467
468 template <typename InputIterator>
470 {
471 size_type n = 0U;
472 for (InputIterator i = first; i != last; ++i) {
473 ++n;
474 }
475 if (max_size() < n) {
476 CPPELIB_CONTAINER_THROW(BadAlloc());
477 }
478 clear();
479 for (; first != last; ++first) {
481 }
482 }
483
485 {
486 DEBUG_ASSERT((begin() <= pos) && (pos <= end()));
487 return insert_n(pos, 1U, data);
488 }
489
490 void insert(iterator pos, size_type n, const T& data)
491 {
492 DEBUG_ASSERT((begin() <= pos) && (pos <= end()));
493 insert_n(pos, n, data);
494 }
495
496 template <typename InputIterator>
498 {
499 DEBUG_ASSERT((begin() <= pos) && (pos <= end()));
501 insert_dispatch(pos, first, last, Integral());
502 }
503
505 {
506 DEBUG_ASSERT((begin() <= pos) && (pos < end()));
507 return erase(pos, pos + 1);
508 }
509
511 {
513 DEBUG_ASSERT((begin() <= first) && (first < end()));
514 DEBUG_ASSERT((begin() <= last) && (last <= end()));
515 const size_type n = static_cast<size_type>(last - first);
516 if ((first - begin()) >= (end() - last)) {
517 // move the end side
518 for (iterator i = last; i != end(); ++i) {
519 *(i - n) = *i;
520 }
521 destroy_range(end() - n, end());
522 m_end = prev_idx(m_end, n);
523 return first;
524 } else {
525 // move the begin side
526 iterator stop = begin() - 1;
527 for (iterator i = first - 1; i != stop; --i) {
528 *(i + n) = *i;
529 }
530 destroy_range(begin(), begin() + n);
531 m_begin = next_idx(m_begin, n);
532 return last;
533 }
534 }
535
536private:
537 template <typename U, typename Ref, typename Ptr, typename DeqPtr>
539
540 template <typename U>
542
543 size_type num_elems_in_buf() const
544 {
545 return m_buf_size / sizeof(T);
546 }
547
548 size_type next_idx(size_type idx, size_type un = 1U) const
549 {
550 if (idx + un < num_elems_in_buf()) {
551 return idx + un;
552 }
553 // wraparound
554 return idx + un - num_elems_in_buf();
555 }
556
557 size_type prev_idx(size_type idx, size_type un = 1U) const
558 {
559 if (idx >= un) {
560 return idx - un;
561 }
562 // wraparound
563 return num_elems_in_buf() + idx - un;
564 }
565
566 size_type distance_idx(size_type first_idx, size_type last_idx) const
567 {
568 if (first_idx <= last_idx) {
569 return last_idx - first_idx;
570 }
571 // wraparound
572 return num_elems_in_buf() - first_idx + last_idx;
573 }
574
575 template <typename Integer>
576 void insert_dispatch(iterator pos, Integer n, Integer data, TrueType)
577 {
578 insert_n(pos, static_cast<size_type>(n), static_cast<T>(data));
579 }
580
581 template <typename InputIterator>
583 {
584 insert_range(pos, first, last);
585 }
586
587 iterator insert_n(iterator pos, size_type n, const T& data)
588 {
589 if (available_size() < n) {
590 CPPELIB_CONTAINER_THROW(BadAlloc());
591 }
592
593 if ((size() / 2U) < static_cast<size_type>(pos - begin())) {
594 // move the end side
596 iterator old_end = end();
597 if (num_elems_pos_to_end > n) {
598 for (size_type i = 0U; i < n; ++i) {
599 construct(&*end());
600 m_end = next_idx(m_end);
601 }
602 for (iterator it = old_end - 1; it != pos - 1; --it) {
603 *(it + n) = *it;
604 }
605 for (iterator it = pos; it != pos + n; ++it) {
606 *it = data;
607 }
608 } else {
609 for (size_type i = 0U; i < n - num_elems_pos_to_end; ++i) {
610 construct(&*end(), data);
611 m_end = next_idx(m_end);
612 }
613 for (iterator it = pos; it != pos + num_elems_pos_to_end; ++it) {
614 construct(&*end(), *it);
615 m_end = next_idx(m_end);
616 }
617 for (iterator it = pos; it != old_end; ++it) {
618 *it = data;
619 }
620 }
621 return pos;
622 } else {
623 // move the begin side
626 if (num_elems_beg_to_pos > n) {
627 for (size_type i = 0U; i < n; ++i) {
628 construct(&*(begin() - 1));
629 m_begin = prev_idx(m_begin);
630 }
631 for (iterator it = old_begin; it != pos; ++it) {
632 *(it - n) = *it;
633 }
634 for (iterator it = pos - n; it != pos; ++it) {
635 *it = data;
636 }
637 } else {
638 for (size_type i = 0U; i < n - num_elems_beg_to_pos; ++i) {
639 construct(&*(begin() - 1), data);
640 m_begin = prev_idx(m_begin);
641 }
642 for (iterator it = pos - 1; it != old_begin - 1; --it) {
643 construct(&*(begin() - 1), *it);
644 m_begin = prev_idx(m_begin);
645 }
646 for (iterator it = old_begin; it != pos; ++it) {
647 *it = data;
648 }
649 }
650 return pos - n;
651 }
652 }
653
654 template <typename InputIterator>
655 void insert_range(iterator pos, InputIterator first, InputIterator last)
656 {
657 size_type n = 0U;
658 for (InputIterator i = first; i != last; ++i) {
659 ++n;
660 }
661 if (available_size() < n) {
662 CPPELIB_CONTAINER_THROW(BadAlloc());
663 }
664
665 if ((size() / 2U) < static_cast<size_type>(pos - begin())) {
666 // move the end side
668 iterator old_end = end();
669 if (num_elems_pos_to_end > n) {
670 for (size_type i = 0U; i < n; ++i) {
671 construct(&*end());
672 m_end = next_idx(m_end);
673 }
674 for (iterator it = old_end - 1; it != pos - 1; --it) {
675 *(it + n) = *it;
676 }
677 for (; first != last; ++pos, ++first) {
678 *pos = *first;
679 }
680 } else {
682 for (size_type i = 0U; i < num_elems_pos_to_end; ++i) {
683 ++mid;
684 }
685 for (size_type i = 0U; i < n - num_elems_pos_to_end; ++i) {
686 construct(&*end(), *mid);
687 ++mid;
688 m_end = next_idx(m_end);
689 }
690 for (iterator it = pos; it != pos + num_elems_pos_to_end; ++it) {
691 construct(&*end(), *it);
692 m_end = next_idx(m_end);
693 }
694 for (iterator it = pos; it != old_end; ++it, ++first) {
695 *it = *first;
696 }
697 }
698 } else {
699 // move the begin side
702 if (num_elems_beg_to_pos > n) {
703 for (size_type i = 0U; i < n; ++i) {
704 construct(&*(begin() - 1));
705 m_begin = prev_idx(m_begin);
706 }
707 for (iterator it = old_begin; it != pos; ++it) {
708 *(it - n) = *it;
709 }
710 for (iterator it = pos - n; it != pos; ++it, ++first) {
711 *it = *first;
712 }
713 } else {
715 for (size_type i = 0U; i < n - num_elems_beg_to_pos; ++i) {
716 ++mid;
717 }
719 for (size_type i = 0U; i < n - num_elems_beg_to_pos; ++i) {
720 construct(&*(begin() - 1), *--p);
721 m_begin = prev_idx(m_begin);
722 }
723 for (iterator it = pos - 1; it != old_begin - 1; --it) {
724 construct(&*(begin() - 1), *it);
725 m_begin = prev_idx(m_begin);
726 }
727 for (iterator it = old_begin; it != pos; ++it, ++mid) {
728 *it = *mid;
729 }
730 }
731 }
732 }
733
734};
735
736template <typename T>
738{
739 if (x.max_size() != y.max_size()) {
740 return false;
741 }
742 if (x.size() != y.size()) {
743 return false;
744 }
745 for (std::size_t i = 0U; i < x.size(); ++i) {
746 if (!(x[i] == y[i])) {
747 return false;
748 }
749 }
750 return true;
751}
752
753template <typename T>
755{
756 return !(x == y);
757}
758
759}
760
761#endif // CONTAINER_PREALLOCATED_DEQUE_H_INCLUDED
#define DEBUG_ASSERT(x)
The same as CHECK_ASSERT() macro.
Definition Assertion.h:39
Definition ContainerException.h:34
Definition ContainerException.h:23
Random-access iterator used as PreallocatedDeque<T>::iterator or PreallocatedDeque<T>::const_iterator...
Definition PreallocatedDeque.h:22
PreallocatedDeque_iterator operator--(int)
Definition PreallocatedDeque.h:111
Ref reference
Definition PreallocatedDeque.h:29
bool operator>(const PreallocatedDeque_iterator &x) const
Definition PreallocatedDeque.h:154
Ptr pointer
Definition PreallocatedDeque.h:31
PreallocatedDeque_iterator operator+(difference_type n) const
Definition PreallocatedDeque.h:60
const Ref const_reference
Definition PreallocatedDeque.h:30
friend class PreallocatedDeque_iterator
Definition PreallocatedDeque.h:174
PreallocatedDeque_iterator & operator=(const iterator &x)
Definition PreallocatedDeque.h:41
PreallocatedDeque_iterator & operator+=(difference_type n)
Definition PreallocatedDeque.h:48
PreallocatedDeque_iterator operator-(difference_type n) const
Definition PreallocatedDeque.h:88
PreallocatedDeque_iterator(const iterator &x)
Definition PreallocatedDeque.h:39
bool operator<=(const PreallocatedDeque_iterator &x) const
Definition PreallocatedDeque.h:159
bool operator>=(const PreallocatedDeque_iterator &x) const
Definition PreallocatedDeque.h:164
const Ptr const_pointer
Definition PreallocatedDeque.h:32
PreallocatedDeque_iterator()
Definition PreallocatedDeque.h:37
pointer operator->() const
Definition PreallocatedDeque.h:124
difference_type operator-(const PreallocatedDeque_iterator &x) const
Definition PreallocatedDeque.h:78
reference operator[](difference_type n) const
Definition PreallocatedDeque.h:130
PreallocatedDeque_iterator & operator-=(difference_type n)
Definition PreallocatedDeque.h:66
std::ptrdiff_t difference_type
Definition PreallocatedDeque.h:26
PreallocatedDeque_iterator & operator++()
Definition PreallocatedDeque.h:94
PreallocatedDeque_iterator & operator--()
Definition PreallocatedDeque.h:99
bool operator!=(const PreallocatedDeque_iterator &x) const
Definition PreallocatedDeque.h:140
bool operator<(const PreallocatedDeque_iterator &x) const
Definition PreallocatedDeque.h:145
std::size_t size_type
Definition PreallocatedDeque.h:25
reference operator*() const
Definition PreallocatedDeque.h:118
PreallocatedDeque_iterator< T, const T &, const T *, const PreallocatedDeque< T > * > const_iterator
Definition PreallocatedDeque.h:28
bool operator==(const PreallocatedDeque_iterator &x) const
Definition PreallocatedDeque.h:135
PreallocatedDeque_iterator< T, T &, T *, PreallocatedDeque< T > * > iterator
Definition PreallocatedDeque.h:27
T value_type
Definition PreallocatedDeque.h:24
PreallocatedDeque_iterator operator++(int)
Definition PreallocatedDeque.h:104
std::random_access_iterator_tag iterator_category
Definition PreallocatedDeque.h:34
STL-like deque container using pre-allocated buffer.
Definition PreallocatedDeque.h:200
T value_type
Definition PreallocatedDeque.h:202
const value_type & const_reference
Definition PreallocatedDeque.h:208
PreallocatedDeque_iterator< T, const T &, const T *, const PreallocatedDeque * > const_iterator
Definition PreallocatedDeque.h:206
size_type available_size() const
Definition PreallocatedDeque.h:297
reverse_iterator rend()
Definition PreallocatedDeque.h:375
void assign(size_type n, const T &data)
Definition PreallocatedDeque.h:459
void resize(size_type n, const T &data=T())
Definition PreallocatedDeque.h:410
const value_type * const_pointer
Definition PreallocatedDeque.h:210
iterator erase(iterator first, iterator last)
Definition PreallocatedDeque.h:510
const_iterator begin() const
Definition PreallocatedDeque.h:349
PreallocatedDeque & operator=(const PreallocatedDeque &x)
Definition PreallocatedDeque.h:279
void insert(iterator pos, InputIterator first, InputIterator last)
Definition PreallocatedDeque.h:497
bool full() const
Definition PreallocatedDeque.h:307
void push_front(const T &data)
Definition PreallocatedDeque.h:443
const_reference back() const
Definition PreallocatedDeque.h:404
friend bool operator==(const PreallocatedDeque< U > &x, const PreallocatedDeque< U > &y)
reverse_iterator rbegin()
Definition PreallocatedDeque.h:365
std::reverse_iterator< iterator > reverse_iterator
Definition PreallocatedDeque.h:212
iterator begin()
Definition PreallocatedDeque.h:344
void push_back(const T &data)
Definition PreallocatedDeque.h:427
std::ptrdiff_t difference_type
Definition PreallocatedDeque.h:204
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition PreallocatedDeque.h:213
size_type max_size() const
Definition PreallocatedDeque.h:292
void pop_back()
Definition PreallocatedDeque.h:436
PreallocatedDeque_iterator< T, T &, T *, PreallocatedDeque * > iterator
Definition PreallocatedDeque.h:205
value_type * pointer
Definition PreallocatedDeque.h:209
const_reverse_iterator rbegin() const
Definition PreallocatedDeque.h:370
void assign(InputIterator first, InputIterator last)
Definition PreallocatedDeque.h:469
const_reference operator[](size_type idx) const
Definition PreallocatedDeque.h:323
iterator erase(iterator pos)
Definition PreallocatedDeque.h:504
const_reference front() const
Definition PreallocatedDeque.h:392
~PreallocatedDeque()
Destructor.
Definition PreallocatedDeque.h:257
iterator insert(iterator pos, const T &data)
Definition PreallocatedDeque.h:484
size_type size() const
Definition PreallocatedDeque.h:287
std::size_t size_type
Definition PreallocatedDeque.h:203
const_reference at(size_type idx) const
Definition PreallocatedDeque.h:336
reference front()
Definition PreallocatedDeque.h:386
reference at(size_type idx)
Definition PreallocatedDeque.h:328
const_reverse_iterator rend() const
Definition PreallocatedDeque.h:380
bool empty() const
Definition PreallocatedDeque.h:302
iterator end()
Definition PreallocatedDeque.h:354
void init(void *preallocated_buffer, size_type buffer_size)
Initialize.
Definition PreallocatedDeque.h:270
reference back()
Definition PreallocatedDeque.h:398
PreallocatedDeque(void *preallocated_buffer, size_type buffer_size)
Constructor.
Definition PreallocatedDeque.h:248
value_type & reference
Definition PreallocatedDeque.h:207
void clear()
Definition PreallocatedDeque.h:312
void insert(iterator pos, size_type n, const T &data)
Definition PreallocatedDeque.h:490
reference operator[](size_type idx)
Definition PreallocatedDeque.h:318
void pop_front()
Definition PreallocatedDeque.h:452
PreallocatedDeque()
Default constructor.
Definition PreallocatedDeque.h:238
const_iterator end() const
Definition PreallocatedDeque.h:359
Definition Array.h:10
FixedDeque_iterator< T, Ref, Ptr, DeqPtr, MaxSize > operator+(std::ptrdiff_t n, const FixedDeque_iterator< T, Ref, Ptr, DeqPtr, MaxSize > &x)
Definition FixedDeque.h:184
bool operator==(const Array< T, Size > &x, const Array< T, Size > &y)
Definition Array.h:160
bool operator!=(const Array< T, Size > &x, const Array< T, Size > &y)
Definition Array.h:171