00001
00002
00003
00004
00005 #ifndef __IRR_ARRAY_H_INCLUDED__
00006 #define __IRR_ARRAY_H_INCLUDED__
00007
00008 #include "irrTypes.h"
00009 #include "heapsort.h"
00010 #include "irrAllocator.h"
00011
00012 namespace irr
00013 {
00014 namespace core
00015 {
00016
00018
00020 template <class T, typename TAlloc = irrAllocator<T> >
00021 class array
00022 {
00023
00024 public:
00025
00027 array()
00028 : data(0), allocated(0), used(0),
00029 free_when_destroyed(true), is_sorted(true)
00030 {
00031 }
00032
00034
00035 array(u32 start_count)
00036 : data(0), allocated(0), used(0),
00037 free_when_destroyed(true), is_sorted(true)
00038 {
00039 reallocate(start_count);
00040 }
00041
00042
00044 array(const array<T>& other)
00045 : data(0)
00046 {
00047 *this = other;
00048 }
00049
00050
00051
00053
00055 ~array()
00056 {
00057 if (free_when_destroyed)
00058 {
00059 for (u32 i=0; i<used; ++i)
00060 allocator.destruct(&data[i]);
00061
00062 allocator.deallocate(data);
00063 }
00064 }
00065
00066
00068
00069 void reallocate(u32 new_size)
00070 {
00071 T* old_data = data;
00072
00073 data = allocator.allocate(new_size);
00074 allocated = new_size;
00075
00076
00077 s32 end = used < new_size ? used : new_size;
00078
00079 for (s32 i=0; i<end; ++i)
00080 {
00081
00082 allocator.construct(&data[i], old_data[i]);
00083 }
00084
00085
00086 for (u32 j=0; j<used; ++j)
00087 allocator.destruct(&old_data[j]);
00088
00089 if (allocated < used)
00090 used = allocated;
00091
00092 allocator.deallocate(old_data);
00093 }
00094
00095
00097
00099 void push_back(const T& element)
00100 {
00101 if (used + 1 > allocated)
00102 {
00103
00104
00105
00106
00107
00108 T e(element);
00109 reallocate(used * 2 +1);
00110
00111 allocator.construct(&data[used++], e);
00112 }
00113 else
00114 {
00115
00116
00117 allocator.construct(&data[used++], element);
00118 }
00119
00120 is_sorted = false;
00121 }
00122
00123
00125
00129 void push_front(const T& element)
00130 {
00131 insert(element);
00132 }
00133
00134
00136
00141 void insert(const T& element, u32 index=0)
00142 {
00143 _IRR_DEBUG_BREAK_IF(index>used)
00144
00145 if (used + 1 > allocated)
00146 reallocate(used +1);
00147
00148 for (u32 i=used; i>index; --i)
00149 {
00150 if (i<used)
00151 allocator.destruct(&data[i]);
00152 allocator.construct(&data[i], data[i-1]);
00153 }
00154
00155 if (used > index)
00156 allocator.destruct(&data[index]);
00157 allocator.construct(&data[index], element);
00158 is_sorted = false;
00159 ++used;
00160 }
00161
00162
00164 void clear()
00165 {
00166 for (u32 i=0; i<used; ++i)
00167 allocator.destruct(&data[i]);
00168
00169 allocator.deallocate(data);
00170 data = 0;
00171 used = 0;
00172 allocated = 0;
00173 is_sorted = true;
00174 }
00175
00176
00178
00180 void set_pointer(T* newPointer, u32 size)
00181 {
00182 for (u32 i=0; i<used; ++i)
00183 allocator.destruct(&data[i]);
00184
00185 allocator.deallocate(data);
00186 data = newPointer;
00187 allocated = size;
00188 used = size;
00189 is_sorted = false;
00190 }
00191
00192
00194
00196 void set_free_when_destroyed(bool f)
00197 {
00198 free_when_destroyed = f;
00199 }
00200
00201
00203
00206 void set_used(u32 usedNow)
00207 {
00208 if (allocated < usedNow)
00209 reallocate(usedNow);
00210
00211 used = usedNow;
00212 }
00213
00214
00216 void operator=(const array<T>& other)
00217 {
00218 if (data)
00219 {
00220 for (u32 i=0; i<used; ++i)
00221 allocator.destruct(&data[i]);
00222
00223 allocator.deallocate(data);
00224 }
00225
00226
00227 if (other.allocated == 0)
00228 data = 0;
00229 else
00230 data = allocator.allocate(other.allocated);
00231
00232 used = other.used;
00233 free_when_destroyed = other.free_when_destroyed;
00234 is_sorted = other.is_sorted;
00235 allocated = other.allocated;
00236
00237 for (u32 i=0; i<other.used; ++i)
00238 allocator.construct(&data[i], other.data[i]);
00239 }
00240
00241
00243 bool operator == (const array<T>& other) const
00244 {
00245 if (used != other.used)
00246 return false;
00247
00248 for (u32 i=0; i<other.used; ++i)
00249 if (data[i] != other[i])
00250 return false;
00251 return true;
00252 }
00253
00255 bool operator != (const array<T>& other) const
00256 {
00257 return !(*this==other);
00258 }
00259
00260
00262 T& operator [](u32 index)
00263 {
00264 _IRR_DEBUG_BREAK_IF(index>=used)
00265
00266 return data[index];
00267 }
00268
00269
00271 const T& operator [](u32 index) const
00272 {
00273 _IRR_DEBUG_BREAK_IF(index>=used)
00274
00275 return data[index];
00276 }
00277
00278
00280 T& getLast()
00281 {
00282 _IRR_DEBUG_BREAK_IF(!used)
00283
00284 return data[used-1];
00285 }
00286
00287
00289 const T& getLast() const
00290 {
00291 _IRR_DEBUG_BREAK_IF(!used)
00292
00293 return data[used-1];
00294 }
00295
00296
00298
00299 T* pointer()
00300 {
00301 return data;
00302 }
00303
00304
00306
00307 const T* const_pointer() const
00308 {
00309 return data;
00310 }
00311
00312
00314
00315 u32 size() const
00316 {
00317 return used;
00318 }
00319
00320
00322
00324 u32 allocated_size() const
00325 {
00326 return allocated;
00327 }
00328
00329
00331
00332 bool empty() const
00333 {
00334 return used == 0;
00335 }
00336
00337
00339
00341 void sort()
00342 {
00343 if (is_sorted || used<2)
00344 return;
00345
00346 heapsort(data, used);
00347 is_sorted = true;
00348 }
00349
00350
00352
00357 s32 binary_search(const T& element)
00358 {
00359 sort();
00360 return binary_search(element, 0, used-1);
00361 }
00362
00363
00365
00369 s32 binary_search_const(const T& element) const
00370 {
00371 return binary_search(element, 0, used-1);
00372 }
00373
00374
00376
00381 s32 binary_search(const T& element, s32 left, s32 right) const
00382 {
00383 if (!used)
00384 return -1;
00385
00386 s32 m;
00387
00388 do
00389 {
00390 m = (left+right)>>1;
00391
00392 if (element < data[m])
00393 right = m - 1;
00394 else
00395 left = m + 1;
00396
00397 } while((element < data[m] || data[m] < element) && left<=right);
00398
00399
00400
00401
00402
00403
00404 if (!(element < data[m]) && !(data[m] < element))
00405 return m;
00406
00407 return -1;
00408 }
00409
00410
00412
00417 s32 linear_search(const T& element) const
00418 {
00419 for (u32 i=0; i<used; ++i)
00420 if (element == data[i])
00421 return (s32)i;
00422
00423 return -1;
00424 }
00425
00426
00428
00433 s32 linear_reverse_search(const T& element) const
00434 {
00435 for (s32 i=used-1; i>=0; --i)
00436 if (data[i] == element)
00437 return i;
00438
00439 return -1;
00440 }
00441
00442
00444
00447 void erase(u32 index)
00448 {
00449 _IRR_DEBUG_BREAK_IF(index>=used)
00450
00451 for (u32 i=index+1; i<used; ++i)
00452 {
00453 allocator.destruct(&data[i-1]);
00454 allocator.construct(&data[i-1], data[i]);
00455 }
00456
00457 allocator.destruct(&data[used-1]);
00458
00459 --used;
00460 }
00461
00462
00464
00468 void erase(u32 index, s32 count)
00469 {
00470 _IRR_DEBUG_BREAK_IF(index>=used || count<1 || index+count>used)
00471
00472 u32 i;
00473 for (i=index; i<index+count; ++i)
00474 allocator.destruct(&data[i]);
00475
00476 for (i=index+count; i<used; ++i)
00477 {
00478 if (i > index+count)
00479 allocator.destruct(&data[i-count]);
00480
00481 allocator.construct(&data[i-count], data[i]);
00482
00483 if (i >= used-count)
00484 allocator.destruct(&data[i]);
00485 }
00486
00487 used-= count;
00488 }
00489
00490
00492 void set_sorted(bool _is_sorted)
00493 {
00494 is_sorted = _is_sorted;
00495 }
00496
00497 private:
00498
00499 T* data;
00500 u32 allocated;
00501 u32 used;
00502 bool free_when_destroyed;
00503 bool is_sorted;
00504 TAlloc allocator;
00505 };
00506
00507
00508 }
00509 }
00510
00511
00512 #endif
00513