Home | Namespaces | Hierarchy | Alphabetical List | Class list | Files | Namespace Members | Class members | File members

irrArray.h

Go to the documentation of this file.
00001 // Copyright (C) 2002-2008 Nikolaus Gebhardt
00002 // This file is part of the "Irrlicht Engine" and the "irrXML" project.
00003 // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
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); //new T[new_size];
00074                 allocated = new_size;
00075 
00076                 // copy old data
00077                 s32 end = used < new_size ? used : new_size;
00078 
00079                 for (s32 i=0; i<end; ++i)
00080                 {
00081                         // data[i] = old_data[i];
00082                         allocator.construct(&data[i], old_data[i]);
00083                 }
00084 
00085                 // destruct old data
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); //delete [] old_data;
00093         }
00094 
00095 
00097 
00099         void push_back(const T& element)
00100         {
00101                 if (used + 1 > allocated)
00102                 {
00103                         // reallocate(used * 2 +1);
00104                         // this doesn't work if the element is in the same array. So
00105                         // we'll copy the element first to be sure we'll get no data
00106                         // corruption
00107 
00108                         T e(element);
00109                         reallocate(used * 2 +1); // increase data block
00110 
00111                         allocator.construct(&data[used++], e); // data[used++] = e; // push_back
00112                 }
00113                 else
00114                 {
00115                         //data[used++] = element;
00116                         // instead of using this here, we copy it the safe way:
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) // access violation
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]); // data[i] = data[i-1];
00153                 }
00154 
00155                 if (used > index)
00156                         allocator.destruct(&data[index]);
00157                 allocator.construct(&data[index], element); // 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); // delete [] 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); // delete [] 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); // delete [] data;
00224                 }
00225 
00226                 //if (allocated < other.allocated)
00227                 if (other.allocated == 0)
00228                         data = 0;
00229                 else
00230                         data = allocator.allocate(other.allocated); // new T[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]); // 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) // access violation
00265 
00266                 return data[index];
00267         }
00268 
00269 
00271         const T& operator [](u32 index) const
00272         {
00273                 _IRR_DEBUG_BREAK_IF(index>=used) // access violation
00274 
00275                 return data[index];
00276         }
00277 
00278 
00280         T& getLast()
00281         {
00282                 _IRR_DEBUG_BREAK_IF(!used) // access violation
00283 
00284                 return data[used-1];
00285         }
00286 
00287 
00289         const T& getLast() const
00290         {
00291                 _IRR_DEBUG_BREAK_IF(!used) // access violation
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                 // this last line equals to:
00400                 // " while((element != array[m]) && left<=right);"
00401                 // but we only want to use the '<' operator.
00402                 // the same in next line, it is "(element == array[m])"
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) // access violation
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]); // 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) // access violation
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]); // 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 } // end namespace core
00509 } // end namespace irr
00510 
00511 
00512 #endif
00513 

The Irrlicht Engine
The Irrlicht Engine Documentation © 2003-2008 by Nikolaus Gebhardt. Generated on Sun Jun 1 07:59:08 2008 by Doxygen (1.4.2)