Vital
Loading...
Searching...
No Matches
circular_queue.h
Go to the documentation of this file.
1#pragma once
2
3#include "common.h"
4#include <cstddef>
5#include <memory>
6
7namespace vital {
8
31 template<class T>
33 public:
34
41 class iterator {
42 public:
50 iterator(T* pointer, T* front, T* end) : pointer_(pointer), front_(front), end_(end) { }
51
56 if (pointer_ == end_)
58 else
59 pointer_++;
60 }
61
66 if (pointer_ == front_)
67 pointer_ = end_;
68 else
69 pointer_--;
70 }
71
73 iterator iter = *this;
74 increment();
75 return iter;
76 }
77
79 iterator iter = *this;
80 increment();
81 return iter;
82 }
83
85 iterator iter = *this;
86 decrement();
87 return iter;
88 }
89
91 iterator iter = *this;
92 decrement();
93 return iter;
94 }
95
97 return *pointer_;
98 }
99
101 return pointer_;
102 }
103
105 return pointer_;
106 }
107
109 return pointer_ == rhs.pointer_;
110 }
111
113 return pointer_ != rhs.pointer_;
114 }
115
116 protected:
120 };
121
130 CircularQueue(int capacity) : capacity_(capacity + 1), start_(0), end_(0) {
131 data_ = std::make_unique<T[]>(capacity_);
132 }
133
140 capacity_ = other.capacity_;
141 data_ = std::make_unique<T[]>(capacity_);
142 memcpy(data_.get(), other.data_.get(), capacity_ * sizeof(T));
143 start_ = other.start_;
144 end_ = other.end_;
145 }
146
150 CircularQueue() : data_(nullptr), capacity_(0), start_(0), end_(0) { }
151
159 void reserve(int capacity) {
160 int new_capacity = capacity + 1;
161 if (new_capacity < capacity_)
162 return;
163
164 std::unique_ptr<T[]> tmp = std::make_unique<T[]>(new_capacity);
165
166 if (capacity_) {
167 end_ = size();
168 for (int i = 0; i < end_; ++i)
169 tmp[i] = std::move(at(i));
170 }
171
172 data_ = std::move(tmp);
173 capacity_ = new_capacity;
174 start_ = 0;
175 }
176
185 force_inline void assign(int num, T value) {
186 if (num > capacity_)
187 reserve(num);
188
189 for (int i = 0; i < num; ++i)
190 data_[i] = value;
191
192 start_ = 0;
193 end_ = num;
194 }
195
202 force_inline T& at(std::size_t index) {
203 VITAL_ASSERT(index >= 0 && index < size());
204 return data_[(start_ + static_cast<int>(index)) % capacity_];
205 }
206
207 force_inline T& operator[](std::size_t index) {
208 return at(index);
209 }
210
211 force_inline const T& operator[](std::size_t index) const {
212 return at(index);
213 }
214
220 force_inline void push_back(T entry) {
221 data_[end_] = std::move(entry);
222 end_ = (end_ + 1) % capacity_;
223 VITAL_ASSERT(end_ != start_);
224 }
225
232 VITAL_ASSERT(end_ != start_);
233 end_ = (end_ - 1 + capacity_) % capacity_;
234 return data_[end_];
235 }
236
242 force_inline void push_front(T entry) {
243 start_ = (start_ - 1 + capacity_) % capacity_;
244 data_[start_] = entry;
245 VITAL_ASSERT(end_ != start_);
246 }
247
254 VITAL_ASSERT(end_ != start_);
255 int last = start_;
256 start_ = (start_ + 1) % capacity_;
257 return data_[last];
258 }
259
267 force_inline void removeAt(int index) {
268 VITAL_ASSERT(end_ != start_);
269 int i = (index + start_) % capacity_;
270 end_ = (end_ - 1 + capacity_) % capacity_;
271 while (i != end_) {
272 int next = (i + 1) % capacity_;
273 data_[i] = data_[next];
274 i = next;
275 }
276 }
277
283 force_inline void remove(T entry) {
284 for (int i = start_; i != end_; i = (i + 1) % capacity_) {
285 if (data_[i] == entry) {
286 removeAt((i - start_ + capacity_) % capacity_);
287 return;
288 }
289 }
290 }
291
297 void removeAll(T entry) {
298 for (int i = start_; i != end_; i = (i + 1) % capacity_) {
299 if (data_[i] == entry) {
300 removeAt((i - start_ + capacity_) % capacity_);
301 i--;
302 }
303 }
304 }
305
311 template<int(*compare)(T, T)>
312 void sort() {
313 int total = size();
314 for (int i = 1; i < total; ++i) {
315 T value = at(i);
316 int j = i - 1;
317 for (; j >= 0 && compare(at(j), value) < 0; --j)
318 at(j + 1) = at(j);
319
320 at(j + 1) = value;
321 }
322 }
323
329 void ensureSpace(int space = 2) {
330 if (size() + space >= capacity())
331 reserve(capacity_ + std::max(capacity_, space));
332 }
333
339 void ensureCapacity(int min_capacity) {
340 if (min_capacity >= capacity())
341 reserve(capacity_ + std::max(capacity_, min_capacity));
342 }
343
351 int index = static_cast<int>(iter.get() - data_.get());
352 removeAt((index - start_ + capacity_) % capacity_);
353 return iter;
354 }
355
362 int count(T entry) const {
363 int number = 0;
364 for (int i = start_; i != end_; i = (i + 1) % capacity_) {
365 if (data_[i] == entry)
366 number++;
367 }
368 return number;
369 }
370
377 bool contains(T entry) const {
378 for (int i = start_; i != end_; i = (i + 1) % capacity_) {
379 if (data_[i] == entry)
380 return true;
381 }
382 return false;
383 }
384
389 start_ = 0;
390 end_ = 0;
391 }
392
396 force_inline T front() const {
397 return data_[start_];
398 }
399
403 force_inline T back() const {
404 return data_[(end_ - 1 + capacity_) % capacity_];
405 }
406
410 force_inline int size() const {
411 VITAL_ASSERT(capacity_ > 0);
412 return (end_ - start_ + capacity_) % capacity_;
413 }
414
418 force_inline int capacity() const {
419 return capacity_ - 1;
420 }
421
426 return iterator(data_.get() + start_, data_.get(), data_.get() + (capacity_ - 1));
427 }
428
433 return iterator(data_.get() + end_, data_.get(), data_.get() + (capacity_ - 1));
434 }
435
436 private:
437 std::unique_ptr<T[]> data_;
438 int capacity_;
439 int start_;
440 int end_;
441 };
442} // namespace vital
A forward and backward iterator for iterating over the elements in the CircularQueue.
Definition circular_queue.h:41
T * end_
Definition circular_queue.h:119
force_inline T & operator*()
Definition circular_queue.h:96
force_inline void decrement()
Moves the iterator to the previous element.
Definition circular_queue.h:65
force_inline void increment()
Moves the iterator to the next element.
Definition circular_queue.h:55
force_inline T * get()
Definition circular_queue.h:104
T * pointer_
Definition circular_queue.h:117
T * front_
Definition circular_queue.h:118
force_inline iterator operator--()
Definition circular_queue.h:84
force_inline iterator operator++()
Definition circular_queue.h:72
iterator(T *pointer, T *front, T *end)
Constructs an iterator.
Definition circular_queue.h:50
force_inline const iterator operator--(int i)
Definition circular_queue.h:90
force_inline bool operator==(const iterator &rhs)
Definition circular_queue.h:108
force_inline const iterator operator++(int i)
Definition circular_queue.h:78
force_inline bool operator!=(const iterator &rhs)
Definition circular_queue.h:112
force_inline T * operator->()
Definition circular_queue.h:100
A generic circular buffer (FIFO) data structure that allows adding and removing elements efficiently.
Definition circular_queue.h:32
force_inline T pop_back()
Pops an element from the back of the queue.
Definition circular_queue.h:231
void removeAll(T entry)
Removes all occurrences of a given element.
Definition circular_queue.h:297
force_inline int capacity() const
Returns the maximum number of elements the queue can hold.
Definition circular_queue.h:418
int count(T entry) const
Counts how many times entry appears in the queue.
Definition circular_queue.h:362
force_inline T back() const
Returns the element at the back of the queue.
Definition circular_queue.h:403
CircularQueue(int capacity)
Constructs a CircularQueue with a given capacity.
Definition circular_queue.h:130
force_inline void remove(T entry)
Removes the first occurrence of an element if found.
Definition circular_queue.h:283
force_inline int size() const
Returns the current number of elements in the queue.
Definition circular_queue.h:410
force_inline T front() const
Returns the element at the front of the queue.
Definition circular_queue.h:396
force_inline const T & operator[](std::size_t index) const
Definition circular_queue.h:211
CircularQueue(const CircularQueue &other)
Copy constructor.
Definition circular_queue.h:139
CircularQueue()
Default constructor creates an empty queue with no capacity.
Definition circular_queue.h:150
void reserve(int capacity)
Ensures that the queue has at least the given capacity.
Definition circular_queue.h:159
force_inline void removeAt(int index)
Removes an element at a given index.
Definition circular_queue.h:267
force_inline T & at(std::size_t index)
Accesses an element by index in the queue.
Definition circular_queue.h:202
force_inline iterator end() const
Returns an iterator to the past-the-end element of the queue.
Definition circular_queue.h:432
bool contains(T entry) const
Checks if the queue contains a given element.
Definition circular_queue.h:377
force_inline iterator begin() const
Returns an iterator to the first element of the queue.
Definition circular_queue.h:425
force_inline T & operator[](std::size_t index)
Definition circular_queue.h:207
force_inline void clear()
Clears all elements in the queue.
Definition circular_queue.h:388
void sort()
Sorts the elements according to a compare function.
Definition circular_queue.h:312
force_inline void push_back(T entry)
Pushes an element to the back of the queue.
Definition circular_queue.h:220
force_inline void assign(int num, T value)
Assigns num elements with a given value.
Definition circular_queue.h:185
force_inline T pop_front()
Pops an element from the front of the queue.
Definition circular_queue.h:253
void ensureCapacity(int min_capacity)
Ensures the queue has at least min_capacity total capacity.
Definition circular_queue.h:339
void ensureSpace(int space=2)
Ensures that there is at least space extra capacity beyond the current size.
Definition circular_queue.h:329
force_inline iterator erase(iterator &iter)
Erases the element at the iterator position and returns an iterator to the next element.
Definition circular_queue.h:350
force_inline void push_front(T entry)
Pushes an element to the front of the queue.
Definition circular_queue.h:242
#define VITAL_ASSERT(x)
Definition common.h:11
#define force_inline
Definition common.h:23
Contains classes and functions used within the Vital synthesizer framework.