Nirtcpp 2.1.0
Nirtcpp is a high-performance c++ graphics engine.
Loading...
Searching...
No Matches
irrArray.hpp
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine" and the "irrXML" project.
3// For conditions of distribution and use, see copyright notice in nirtcpp/nirtcpp.hpp and nirtcpp/irrXML.hpp
4
5#ifndef NIRT_ARRAY_HPP_INCLUDED
6#define NIRT_ARRAY_HPP_INCLUDED
7
8#include <nirtcpp/core/engine/nirt_types.hpp>
9#include <nirtcpp/core/engine/heapsort.hpp>
10#include <nirtcpp/core/engine/irrAllocator.hpp>
11#include <nirtcpp/core/engine/irrMath.hpp>
12
13namespace nirt
14{
15namespace core
16{
17
19
21template <class T, typename TAlloc = irrAllocator<T> >
22class array
23{
24
25public:
26
28 array() : data(0), allocated(0), used(0),
29 strategy(ALLOC_STRATEGY_DOUBLE), free_when_destroyed(true), is_sorted(true)
30 {
31 }
32
33
35
36 explicit array(u32 start_count) : data(0), allocated(0), used(0),
37 strategy(ALLOC_STRATEGY_DOUBLE),
38 free_when_destroyed(true), is_sorted(true)
39 {
41 }
42
43
45 array(const array<T, TAlloc>& other) : data(0)
46 {
47 *this = other;
48 }
49
50
52
55 {
56 clear();
57 }
58
59
61
67 {
68 if (allocated==new_size)
69 return;
70 if (!canShrink && (new_size < allocated))
71 return;
72
73 T* old_data = data;
74
75 data = allocator.allocate(new_size); //new T[new_size];
76 allocated = new_size;
77
78 // copy old data
79 const s32 end = used < new_size ? used : new_size;
80
81 for (s32 i=0; i<end; ++i)
82 {
83 // data[i] = old_data[i];
84 allocator.construct(&data[i], old_data[i]);
85 }
86
87 // destruct old data
88 for (u32 j=0; j<used; ++j)
89 allocator.destruct(&old_data[j]);
90
91 if (allocated < used)
92 used = allocated;
93
94 allocator.deallocate(old_data); //delete [] old_data;
95 }
96
97
99
102 void setAllocStrategy ( eAllocStrategy newStrategy = ALLOC_STRATEGY_DOUBLE )
103 {
104 strategy = newStrategy;
105 }
106
107
109
111 void push_back(const T& element)
112 {
113 insert(element, used);
114 }
115
116
118
122 void push_front(const T& element)
123 {
125 }
126
127
129
132 void insert(const T& element, u32 index=0)
133 {
134 NIRT_DEBUG_BREAK_IF(index>used) // access violation
135
136 if (used + 1 > allocated)
137 {
138 // this doesn't work if the element is in the same
139 // array. So we'll copy the element first to be sure
140 // we'll get no data corruption
141 const T e(element);
142
143 // increase data block
145 switch ( strategy )
146 {
147 case ALLOC_STRATEGY_DOUBLE:
149 break;
150 default:
151 case ALLOC_STRATEGY_SAFE:
152 newAlloc = used + 1;
153 break;
154 }
156
157 // move array content and construct new element
158 // first move end one up
159 for (u32 i=used; i>index; --i)
160 {
161 if (i<used)
162 allocator.destruct(&data[i]);
163 allocator.construct(&data[i], data[i-1]); // data[i] = data[i-1];
164 }
165 // then add new element
166 if (used > index)
167 allocator.destruct(&data[index]);
168 allocator.construct(&data[index], e); // data[index] = e;
169 }
170 else
171 {
172 // element inserted not at end
173 if ( used > index )
174 {
175 // create one new element at the end
176 allocator.construct(&data[used], data[used-1]);
177
178 // move the rest of the array content
179 for (u32 i=used-1; i>index; --i)
180 {
181 data[i] = data[i-1];
182 }
183 // insert the new element
184 data[index] = element;
185 }
186 else
187 {
188 // insert the new element to the end
189 allocator.construct(&data[index], element);
190 }
191 }
192 // set to false as we don't know if we have the comparison operators
193 is_sorted = false;
194 ++used;
195 }
196
197
199 void clear()
200 {
201 if (free_when_destroyed)
202 {
203 for (u32 i=0; i<used; ++i)
204 allocator.destruct(&data[i]);
205
206 allocator.deallocate(data); // delete [] data;
207 }
208 data = 0;
209 used = 0;
210 allocated = 0;
211 is_sorted = true;
212 }
213
214
216
225 {
226 clear();
227 data = newPointer;
228 allocated = size;
229 used = size;
230 is_sorted = _is_sorted;
231 free_when_destroyed=_free_when_destroyed;
232 }
233
235
242 void set_data(const T* newData, u32 newSize, bool newDataIsSorted=false, bool canShrink=false)
243 {
246 for ( u32 i=0; i<newSize; ++i)
247 {
248 data[i] = newData[i];
249 }
250 is_sorted = newDataIsSorted;
251 }
252
254
257 bool equals(const T* otherData, u32 size) const
258 {
259 if (used != size)
260 return false;
261
262 for (u32 i=0; i<size; ++i)
263 if (data[i] != otherData[i])
264 return false;
265 return true;
266 }
267
268
269
271
279 {
280 free_when_destroyed = f;
281 }
282
283
285
289 {
290 if (allocated < usedNow)
292
293 used = usedNow;
294 }
295
298 {
299 if (this == &other)
300 return *this;
301 strategy = other.strategy;
302
303 // (TODO: we could probably avoid re-allocations of data when (allocated < other.allocated)
304
305 if (data)
306 clear();
307
308 used = other.used;
309 free_when_destroyed = true;
310 is_sorted = other.is_sorted;
311 allocated = other.allocated;
312
313 if (other.allocated == 0)
314 {
315 data = 0;
316 }
317 else
318 {
319 data = allocator.allocate(other.allocated); // new T[other.allocated];
320
321 for (u32 i=0; i<other.used; ++i)
322 allocator.construct(&data[i], other.data[i]); // data[i] = other.data[i];
323 }
324
325 return *this;
326 }
327
328
331 {
332 return equals(other.const_pointer(), other.size());
333 }
334
335
338 {
339 return !(*this==other);
340 }
341
342
345 {
346 NIRT_DEBUG_BREAK_IF(index>=used) // access violation
347
348 return data[index];
349 }
350
351
353 const T& operator [](u32 index) const
354 {
355 NIRT_DEBUG_BREAK_IF(index>=used) // access violation
356
357 return data[index];
358 }
359
360
363 {
364 NIRT_DEBUG_BREAK_IF(!used) // access violation
365
366 return data[used-1];
367 }
368
369
371 const T& getLast() const
372 {
373 NIRT_DEBUG_BREAK_IF(!used) // access violation
374
375 return data[used-1];
376 }
377
378
380
382 {
383 return data;
384 }
385
386
388
389 const T* const_pointer() const
390 {
391 return data;
392 }
393
394
396
397 u32 size() const
398 {
399 return used;
400 }
401
402
404
407 {
408 return allocated;
409 }
410
411
413
414 bool empty() const
415 {
416 return used == 0;
417 }
418
419
421
423 void sort()
424 {
425 if (!is_sorted && used>1)
426 heapsort(data, used);
427 is_sorted = true;
428 }
429
430
432
439 {
440 sort();
441 return binary_search(element, 0, used-1);
442 }
443
444
446
452 {
453 if (is_sorted)
454 return binary_search(element, 0, used-1);
455 else
456 return linear_search(element);
457 }
458
459
461
467 {
468 if (!used)
469 return -1;
470
471 s32 m;
472
473 do
474 {
475 m = (left+right)>>1;
476
477 if (element < data[m])
478 right = m - 1;
479 else
480 left = m + 1;
481
482 } while((element < data[m] || data[m] < element) && left<=right);
483 // this last line equals to:
484 // " while((element != array[m]) && left<=right);"
485 // but we only want to use the '<' operator.
486 // the same in next line, it is "(element == array[m])"
487
488
489 if (!(element < data[m]) && !(data[m] < element))
490 return m;
491
492 return -1;
493 }
494
495
498
505 {
506 sort();
507 s32 index = binary_search(element, 0, used-1);
508 if ( index < 0 )
509 return index;
510
511 // The search can be somewhere in the middle of the set
512 // look linear previous and past the index
513 last = index;
514
515 while ( index > 0 && !(element < data[index - 1]) && !(data[index - 1] < element) )
516 {
517 index -= 1;
518 }
519 // look linear up
520 while ( last < (s32) used - 1 && !(element < data[last + 1]) && !(data[last + 1] < element) )
521 {
522 last += 1;
523 }
524
525 return index;
526 }
527
528
530
535 template <class E>
537 {
538 for (u32 i=0; i<used; ++i)
539 if (data[i] == element)
540 return (s32)i;
541
542 return -1;
543 }
544
545
547
552 template <class E>
554 {
555 for (s32 i=used-1; i>=0; --i)
556 if (data[i] == element)
557 return i;
558
559 return -1;
560 }
561
562
564
567 void erase(u32 index)
568 {
569 NIRT_DEBUG_BREAK_IF(index>=used) // access violation
570
571 for (u32 i=index+1; i<used; ++i)
572 {
573 allocator.destruct(&data[i-1]);
574 allocator.construct(&data[i-1], data[i]); // data[i-1] = data[i];
575 }
576
577 allocator.destruct(&data[used-1]);
578
579 --used;
580 }
581
582
584
588 void erase(u32 index, s32 count)
589 {
590 if (index>=used || count<1)
591 return;
592 if (index+count>used)
593 count = used-index;
594
595 u32 i;
596 for (i=index; i<index+count; ++i)
597 allocator.destruct(&data[i]);
598
599 for (i=index+count; i<used; ++i)
600 {
601 if (i-count >= index+count) // not already destructed before loop
602 allocator.destruct(&data[i-count]);
603
604 allocator.construct(&data[i-count], data[i]); // data[i-count] = data[i];
605
606 if (i >= used-count) // those which are not overwritten
607 allocator.destruct(&data[i]);
608 }
609
610 used-= count;
611 }
612
613
616 {
617 is_sorted = _is_sorted;
618 }
619
620
622
626 {
627 core::swap(data, other.data);
628 core::swap(allocated, other.allocated);
629 core::swap(used, other.used);
630 core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation
631 eAllocStrategy helper_strategy(strategy); // can't use core::swap with bitfields
632 strategy = other.strategy;
633 other.strategy = helper_strategy;
634 bool helper_free_when_destroyed(free_when_destroyed);
635 free_when_destroyed = other.free_when_destroyed;
636 other.free_when_destroyed = helper_free_when_destroyed;
637 bool helper_is_sorted(is_sorted);
638 is_sorted = other.is_sorted;
639 other.is_sorted = helper_is_sorted;
640 }
641
642 using allocator_type = TAlloc;
643 using value_type = T;
644 using size_type = u32;
645
646private:
647 T* data;
648 u32 allocated;
649 u32 used;
650 TAlloc allocator;
651 eAllocStrategy strategy:4;
652 bool free_when_destroyed:1;
653 bool is_sorted:1;
654};
655
656
657} // end namespace core
658} // end namespace nirt
659
660#endif
661
Axis aligned bounding box in 3d dimensional space.
Definition aabbox3d.hpp:22
Self reallocating template array (like stl vector) with additional features.
Definition irrArray.hpp:23
u32 size() const
Get number of occupied elements of the array.
Definition irrArray.hpp:397
u32 allocated_size() const
Get amount of memory allocated.
Definition irrArray.hpp:406
s32 binary_search(const T &element) const
Performs a binary search for an element if possible, returns -1 if not found.
Definition irrArray.hpp:451
void set_sorted(bool _is_sorted)
Sets if the array is sorted.
Definition irrArray.hpp:615
void insert(const T &element, u32 index=0)
Insert item into array at specified position.
Definition irrArray.hpp:132
const array< T, TAlloc > & operator=(const array< T, TAlloc > &other)
Assignment operator.
Definition irrArray.hpp:297
bool operator==(const array< T, TAlloc > &other) const
Equality operator.
Definition irrArray.hpp:330
void swap(array< T, TAlloc > &other)
Swap the content of this array container with the content of another array.
Definition irrArray.hpp:625
void push_back(const T &element)
Adds an element at back of array.
Definition irrArray.hpp:111
array(u32 start_count)
Constructs an array and allocates an initial chunk of memory.
Definition irrArray.hpp:36
T & getLast()
Gets last element.
Definition irrArray.hpp:362
void set_data(const T *newData, u32 newSize, bool newDataIsSorted=false, bool canShrink=false)
Set (copy) data from given memory block.
Definition irrArray.hpp:242
s32 linear_reverse_search(const E &element) const
Finds an element by searching linearly from array end to start.
Definition irrArray.hpp:553
void erase(u32 index, s32 count)
Erases some elements from the array.
Definition irrArray.hpp:588
s32 binary_search(const T &element)
Performs a binary search for an element, returns -1 if not found.
Definition irrArray.hpp:438
void erase(u32 index)
Erases an element from the array.
Definition irrArray.hpp:567
void reallocate(u32 new_size, bool canShrink=true)
Reallocates the array, make it bigger or smaller.
Definition irrArray.hpp:66
array(const array< T, TAlloc > &other)
Copy constructor.
Definition irrArray.hpp:45
const T * const_pointer() const
Gets a const pointer to the array.
Definition irrArray.hpp:389
void push_front(const T &element)
Adds an element at the front of the array.
Definition irrArray.hpp:122
bool empty() const
Check if array is empty.
Definition irrArray.hpp:414
T * pointer()
Gets a pointer to the array.
Definition irrArray.hpp:381
void set_used(u32 usedNow)
Sets the size of the array and allocates new elements if necessary.
Definition irrArray.hpp:288
~array()
Destructor.
Definition irrArray.hpp:54
array()
Default constructor for empty array.
Definition irrArray.hpp:28
const T & getLast() const
Gets last element.
Definition irrArray.hpp:371
void sort()
Sorts the array using heapsort.
Definition irrArray.hpp:423
bool operator!=(const array< T, TAlloc > &other) const
Inequality operator.
Definition irrArray.hpp:337
void setAllocStrategy(eAllocStrategy newStrategy=ALLOC_STRATEGY_DOUBLE)
set a new allocation strategy
Definition irrArray.hpp:102
T & operator[](u32 index)
Direct access operator.
Definition irrArray.hpp:344
void set_pointer(T *newPointer, u32 size, bool _is_sorted=false, bool _free_when_destroyed=true)
Sets pointer to new array, using this as new workspace.
Definition irrArray.hpp:224
s32 binary_search(const T &element, s32 left, s32 right) const
Performs a binary search for an element, returns -1 if not found.
Definition irrArray.hpp:466
void set_free_when_destroyed(bool f)
Sets if the array should delete the memory it uses upon destruction.
Definition irrArray.hpp:278
s32 linear_search(const E &element) const
Finds an element by searching linearly from array start to end.
Definition irrArray.hpp:536
bool equals(const T *otherData, u32 size) const
Compare if given data block is identical to the data in our array.
Definition irrArray.hpp:257
s32 binary_search_multi(const T &element, s32 &last)
Definition irrArray.hpp:504
void clear()
Clears the array and deletes all allocated memory.
Definition irrArray.hpp:199
eAllocStrategy
defines an allocation strategy (used only by nirt::array so far)
Definition irrAllocator.hpp:113
void heapsort(T *array_, s32 size)
Sorts an array with size 'size' using heapsort.
Definition heapsort.hpp:41
void swap(T1 &a, T2 &b)
swaps the content of the passed parameters
Definition irrMath.hpp:175
As of Nirtcpp 1.6, position2d is a synonym for vector2d.
Definition vector3d.hpp:11
signed int s32
32 bit signed variable.
Definition irrTypes.hpp:72
unsigned int u32
32 bit unsigned variable.
Definition irrTypes.hpp:64

Nirtcpp    @cppfx.xyz

Utxcpp    utx::print