Nebula
Loading...
Searching...
No Matches
ringbuffer.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
14#include "core/types.h"
15#include "util/array.h"
16
17//------------------------------------------------------------------------------
18namespace Util
19{
20template <class TYPE> class RingBuffer
21{
22public:
34 void operator=(const RingBuffer<TYPE>& rhs);
38 TYPE& operator[](IndexT index) const;
39
41 void SetCapacity(SizeT newCapacity);
43 SizeT Capacity() const;
45 SizeT Size() const;
47 void Add(const TYPE& elm);
49 bool IsEmpty() const;
51 void Reset();
53 TYPE& Front() const;
55 TYPE& Back() const;
59 TYPE* GetBuffer();
61 const TYPE* GetBuffer() const;
62
63private:
67 void Delete();
69 void Copy(const RingBuffer<TYPE>& src);
70
75 TYPE* elements;
76};
77
78//------------------------------------------------------------------------------
81template<class TYPE> void
83{
84 #if NEBULA_BOUNDSCHECKS
85 n_assert(0 == this->elements);
86 n_assert(c > 0);
87 #endif
88 this->capacity = c;
89 this->size = 0;
90 this->baseIndex = 0;
91 this->headIndex = 0;
92 this->elements = new TYPE[c];
93}
94
95//------------------------------------------------------------------------------
98template<class TYPE> void
100{
101 this->capacity = 0;
102 this->size = 0;
103 this->baseIndex = 0;
104 this->headIndex = 0;
105 if (0 != this->elements)
106 {
107 delete[] this->elements;
108 this->elements = 0;
109 }
110}
111
112//------------------------------------------------------------------------------
115template<class TYPE> void
117{
118 #if NEBULA_BOUNDSCHECKS
119 n_assert(0 == this->elements);
120 #endif
121 this->Allocate(rhs.capacity);
122 this->size = rhs.size;
123 this->baseIndex = rhs.baseIndex;
124 this->headIndex = rhs.headIndex;
125 IndexT i;
126 for (i = 0; i < rhs.Size(); i++)
127 {
128 (*this)[i] = rhs[i];
129 }
130}
131
132//------------------------------------------------------------------------------
135template<class TYPE>
137 capacity(0),
138 size(0),
139 baseIndex(0),
140 headIndex(0),
141 elements(0)
142{
143 // empty
144}
145
146//------------------------------------------------------------------------------
149template<class TYPE>
151 elements(0)
152{
153 this->Allocate(c);
154}
155
156//------------------------------------------------------------------------------
159template<class TYPE>
161 elements(0)
162{
163 if (rhs.size > 0)
164 this->Copy(rhs);
165}
166
167//------------------------------------------------------------------------------
170template<class TYPE>
172{
173 this->size = rhs.size;
174 this->capacity = rhs.capacity;
175 this->headIndex = rhs.headIndex;
176 this->baseIndex = rhs.baseIndex;
177 this->elements = rhs.elements;
178
179 rhs.size = 0;
180 rhs.capacity = 0;
181 rhs.headIndex = 0;
182 rhs.baseIndex = 0;
183 rhs.elements = nullptr;
184}
185
186//------------------------------------------------------------------------------
189template<class TYPE>
191{
192 this->Delete();
193}
194
195//------------------------------------------------------------------------------
198template<class TYPE> void
200{
201 this->Delete();
202 if (rhs.capacity > 0)
203 this->Copy(rhs);
204}
205
206//------------------------------------------------------------------------------
209template<class TYPE> void
211{
212 this->size = rhs.size;
213 this->capacity = rhs.capacity;
214 this->headIndex = rhs.headIndex;
215 this->baseIndex = rhs.baseIndex;
216 this->elements = rhs.elements;
217
218 rhs.size = 0;
219 rhs.capacity = 0;
220 rhs.headIndex = 0;
221 rhs.baseIndex = 0;
222 rhs.elements = nullptr;
223}
224
225//------------------------------------------------------------------------------
228template<class TYPE> TYPE&
230{
231 #if NEBULA_BOUNDSCHECKS
232 n_assert(this->elements && (index < this->size));
233 #endif
234 IndexT absIndex = index + this->baseIndex;
235 if (absIndex >= this->capacity)
236 {
237 // wrap-around
238 absIndex -= this->capacity;
239 }
240 return this->elements[absIndex];
241}
242
243//------------------------------------------------------------------------------
246template<class TYPE> TYPE&
248{
249 return (*this)[0];
250}
251
252//------------------------------------------------------------------------------
255template<class TYPE> TYPE&
257{
258 #if NEBULA_BOUNDSCHECKS
259 n_assert(this->size > 0);
260 #endif
261 return (*this)[this->size - 1];
262}
263
264//------------------------------------------------------------------------------
267template<class TYPE> bool
269{
270 return (0 == this->size);
271}
272
273//------------------------------------------------------------------------------
276template<class TYPE> void
278{
279 this->size = 0;
280 this->baseIndex = 0;
281 this->headIndex = 0;
282}
283
284//------------------------------------------------------------------------------
287template<class TYPE> void
289{
290 this->Delete();
291 this->Allocate(newCapacity);
292}
293
294//------------------------------------------------------------------------------
297template<class TYPE> SizeT
299{
300 return this->capacity;
301}
302
303//------------------------------------------------------------------------------
306template<class TYPE> SizeT
308{
309 return this->size;
310}
311
312//------------------------------------------------------------------------------
315template<class TYPE> void
316RingBuffer<TYPE>::Add(const TYPE& elm)
317{
318 #if NEBULA_BOUNDSCHECKS
319 n_assert(0 != this->elements);
320 #endif
321
322 // write new element
323 this->elements[this->headIndex++] = elm;
324
325 // check if head index should wrap around
326 if (this->headIndex >= this->capacity)
327 {
328 this->headIndex = 0;
329 }
330
331 // if we are full, we need to advance the base index
332 if (this->size == this->capacity)
333 {
334 this->baseIndex++;
335 if (this->baseIndex >= this->capacity)
336 {
337 // wraparound base index
338 this->baseIndex = 0;
339 }
340 }
341 else
342 {
343 // not full yet, increment size member
344 this->size++;
345 }
346}
347
348//------------------------------------------------------------------------------
351template<class TYPE> Array<TYPE>
353{
354 Array<TYPE> result(this->size, 0);
355 IndexT i;
356 for (i = 0; i < this->size; i++)
357 {
358 result.Append((*this)[i]);
359 }
360 return result;
361}
362
363//------------------------------------------------------------------------------
366template<class TYPE>
367TYPE*
369{
370 n_assert(this->elements);
371 return this->elements;
372}
373
374//------------------------------------------------------------------------------
377template<class TYPE>
378const TYPE*
380{
381 n_assert(this->elements);
382 return this->elements;
383}
384
385} // namespace Util
386//------------------------------------------------------------------------------
Nebula's dynamic array class.
Definition array.h:60
void Append(const TYPE &first, const ELEM_TYPE &... elements)
Append multiple elements to the end of the array.
Definition array.h:1334
A ring buffer stores up to a maximum number of elements in a circular fashion.
Definition ringbuffer.h:21
~RingBuffer()
destructor
Definition ringbuffer.h:190
void SetCapacity(SizeT newCapacity)
set capacity (clear previous content)
Definition ringbuffer.h:288
IndexT baseIndex
Definition ringbuffer.h:73
TYPE & Back() const
return reference to last element
Definition ringbuffer.h:256
RingBuffer(const RingBuffer< TYPE > &rhs)
copy constructor
Definition ringbuffer.h:160
TYPE * GetBuffer()
get real linear underlying buffer
Definition ringbuffer.h:368
void Add(const TYPE &elm)
add an element to the ring buffer
Definition ringbuffer.h:316
SizeT capacity
Definition ringbuffer.h:71
RingBuffer()
default constructor
Definition ringbuffer.h:136
void Reset()
reset ring buffer, just reset the head/base indices without calling destructors
Definition ringbuffer.h:277
RingBuffer(SizeT capacity)
constructor with size
Definition ringbuffer.h:150
void operator=(RingBuffer< TYPE > &&rhs)
mover operator
Definition ringbuffer.h:210
void Copy(const RingBuffer< TYPE > &src)
copy content
Definition ringbuffer.h:116
RingBuffer(RingBuffer< TYPE > &&rhs)
move constructor
Definition ringbuffer.h:171
TYPE & operator[](IndexT index) const
index operator
Definition ringbuffer.h:229
Array< TYPE > AsArray() const
return all values as array
Definition ringbuffer.h:352
TYPE & Front() const
return reference to first element
Definition ringbuffer.h:247
bool IsEmpty() const
return true if ring buffer is empty
Definition ringbuffer.h:268
SizeT size
Definition ringbuffer.h:72
void operator=(const RingBuffer< TYPE > &rhs)
assignment operator
Definition ringbuffer.h:199
void Delete()
delete content
Definition ringbuffer.h:99
TYPE * elements
Definition ringbuffer.h:75
IndexT headIndex
Definition ringbuffer.h:74
void Allocate(SizeT capacity)
allocate element buffer
Definition ringbuffer.h:82
SizeT Size() const
get number of elements in ring buffer
Definition ringbuffer.h:307
const TYPE * GetBuffer() const
get real linear underlying buffer
Definition ringbuffer.h:379
SizeT Capacity() const
get capacity
Definition ringbuffer.h:298
#define n_assert(exp)
Definition debug.h:50
A pinned array is an array which manages its own virtual memory.
Definition String.cs:6
int SizeT
Definition types.h:49
int IndexT
Definition types.h:48