Array.inl
Go to the documentation of this file.00001 //*** Array.inl *** 00002 00003 #include "Debug.h" 00004 00005 //*** Constructor *** 00006 00007 template <class TYPE> 00008 Array<TYPE>::Array(int initialCapacity): 00009 initialCapacity_(initialCapacity), 00010 capacity_(initialCapacity), 00011 itemCount_(0), 00012 items_(0) 00013 { 00014 } 00015 00016 00017 //*** Copy Constructor *** 00018 00019 template <class TYPE> 00020 Array<TYPE>::Array(const Array<TYPE>& arrayToCopy ): 00021 initialCapacity_(arrayToCopy.initialCapacity_), 00022 capacity_(arrayToCopy.capacity_), 00023 itemCount_(arrayToCopy.itemCount_), 00024 items_(0) 00025 { 00026 if (!arrayToCopy.items_) 00027 { 00028 return; 00029 } 00030 00031 items_=new TYPE[capacity_]; 00032 00033 Assert(items_,"Couldn't allocate memory for array"); 00034 if (!items_) 00035 { 00036 FatalError("Allocation failed when allocating memory for an array"); 00037 } 00038 00039 // Copy each item of the other array 00040 for (int i=0; i<itemCount_; i++) 00041 { 00042 items_[i]=arrayToCopy.items_[i]; 00043 } 00044 } 00045 00046 00047 //*** Assignment operator *** 00048 00049 00050 template <class TYPE> 00051 const Array<TYPE>& Array<TYPE>::operator =(const Array<TYPE>& arrayToCopy) 00052 { 00053 if (items_) 00054 { 00055 delete[] items_; 00056 items_=0; 00057 } 00058 00059 initialCapacity_=arrayToCopy.initialCapacity_; 00060 capacity_=arrayToCopy.capacity_; 00061 itemCount_=arrayToCopy.itemCount_; 00062 00063 if (arrayToCopy.items_) 00064 { 00065 items_=new TYPE[capacity_]; 00066 00067 Assert(items_,"Couldn't allocate memory for array"); 00068 if (!items_) 00069 { 00070 FatalError("Allocation failed when allocating memory for array"); 00071 } 00072 00073 // Copy each item of the other array 00074 for (int i=0; i<itemCount_; i++) 00075 { 00076 items_[i]=arrayToCopy.items_[i]; 00077 } 00078 } 00079 00080 return *this; 00081 } 00082 00083 00084 //*** Destructor *** 00085 00086 template <class TYPE> 00087 Array<TYPE>::~Array() 00088 { 00089 // Free memory used by the array 00090 if (items_) 00091 { 00092 delete[] items_; 00093 items_=0; 00094 } 00095 } 00096 00097 00098 //*** Add *** 00099 00100 template <class TYPE> 00101 TYPE& Array<TYPE>::Add(const TYPE& item) 00102 { 00103 // Check if the array is full 00104 if (!items_ || itemCount_>=capacity_) 00105 { 00106 int newCapacity=capacity_; 00107 if (itemCount_>=capacity_) 00108 { 00109 newCapacity*=2; 00110 } 00111 // Create a new array with twice the size 00112 TYPE* newItems=new TYPE[newCapacity]; 00113 Assert(newItems,"Couldn't allocate memory for array"); 00114 if (!newItems) 00115 { 00116 FatalError("Allocation failed when allocating memory for array"); 00117 } 00118 00119 // Copy each item from the old array to the new one 00120 for (int i=0; i<itemCount_; i++) 00121 { 00122 newItems[i]=items_[i]; 00123 } 00124 00125 // Delete the old array 00126 if (items_) 00127 { 00128 delete[] items_; 00129 items_=0; 00130 } 00131 00132 // Store the pointer to the new array instead of the old 00133 items_=newItems; 00134 00135 // Increase the maximum number of items 00136 capacity_=newCapacity; 00137 } 00138 00139 // Set the item 00140 items_[itemCount_]=item; 00141 TYPE& returnValue=items_[itemCount_]; 00142 itemCount_++; 00143 return returnValue; 00144 } 00145 00146 00147 //*** InsertBefore (index) *** 00148 00149 template <class TYPE> 00150 void Array<TYPE>::InsertBefore(const TYPE& item,int index) 00151 { 00152 Assert(index>=0 && index<itemCount_,"Index out of range"); 00153 if (index<0 || index>=itemCount_) 00154 { 00155 return; 00156 } 00157 00158 // Make room 00159 Add(item); 00160 00161 // If there were already items in the array, they need to be shifted 00162 if (itemCount_>1) 00163 { 00164 // Shift existing items 00165 for (int i=itemCount_-1; i>index; i--) 00166 { 00167 items_[i]=items_[i-1]; 00168 } 00169 00170 // Insert the new item at the specified index 00171 items_[index]=item; 00172 } 00173 } 00174 00175 00176 //*** InsertBefore (iterator) *** 00177 00178 template <class TYPE> 00179 void Array<TYPE>::InsertBefore(const TYPE& item, const ArrayIterator<TYPE>& insertBefore) 00180 { 00181 // Find index 00182 int index=insertBefore.GetCurrentIndex(); 00183 Assert(index>=0 && index<itemCount_,"Iterator out of bounds"); 00184 if (index>=0 && index<itemCount_) 00185 { 00186 // Insert the item 00187 InsertBefore(item,index); 00188 } 00189 } 00190 00191 00192 //*** InsertAfter (index) *** 00193 00194 template <class TYPE> 00195 void Array<TYPE>::InsertAfter(const TYPE& item,int index) 00196 { 00197 Assert(index>=0 && index<itemCount_,"Index out of range"); 00198 if (index<0 || index>=itemCount_) 00199 { 00200 return; 00201 } 00202 00203 // Make room 00204 Add(item); 00205 00206 // We're actually interested in the item AFTER the specified index 00207 index++; 00208 00209 // If there were already items in the array, they need to be shifted 00210 if (itemCount_>1) 00211 { 00212 // Shift existing items 00213 for (int i=itemCount_-1; i>index; i--) 00214 { 00215 items_[i]=items_[i-1]; 00216 } 00217 00218 // Insert the new item at the specified index 00219 items_[index]=item; 00220 } 00221 } 00222 00223 00224 //*** InsertAfter (iterator) *** 00225 00226 template <class TYPE> 00227 void Array<TYPE>::InsertAfter(const TYPE& item, const ArrayIterator<TYPE>& insertAfter) 00228 { 00229 int index=insertAfter.GetCurrentIndex(); 00230 Assert(index>=0 && index<itemCount_,"Iterator out of bounds"); 00231 if (index>=0 && index<itemCount_) 00232 { 00233 // Insert the item 00234 InsertAfter(item,index); 00235 } 00236 } 00237 00238 00239 //*** RemoveLast *** 00240 00241 template <class TYPE> 00242 void Array<TYPE>::RemoveLast() 00243 { 00244 Assert(items_ && itemCount_>0,"No items to remove"); 00245 if (!items_ || itemCount_==0) 00246 { 00247 return; 00248 } 00249 00250 // Do not downsize array - performance is more important than memory 00251 // and chances are that we will soon be adding a new item anyway 00252 itemCount_--; 00253 } 00254 00255 00256 //*** Remove (index) *** 00257 00258 template <class TYPE> 00259 void Array<TYPE>::Remove(int index) 00260 { 00261 Assert(items_ && index>=0 && index<itemCount_,"Index out of range"); 00262 if (!items_ || index<0 || index>=itemCount_) 00263 { 00264 return; 00265 } 00266 00267 // If the item to remove is the last item, just decrease the number of items and return 00268 if (index==itemCount_-1) 00269 { 00270 itemCount_--; 00271 return; 00272 } 00273 00274 // Move items after the item to be removed 00275 for (int i=index; i<itemCount_-1; i++) 00276 { 00277 items_[i]=items_[i+1]; 00278 } 00279 00280 // Decrease the total number of items 00281 itemCount_--; 00282 } 00283 00284 00285 //*** Remove (iterator) *** 00286 00287 template <class TYPE> 00288 void Array<TYPE>::Remove(const ArrayIterator<TYPE>& iterator) 00289 { 00290 int index=iterator.GetCurrentIndex(); 00291 Assert(index>=0 && index<itemCount_,"Iterator out of bounds"); 00292 if (index>=0 && index<itemCount_) 00293 { 00294 // Remove the item 00295 Remove(index); 00296 } 00297 } 00298 00299 00300 //*** GetItemCount *** 00301 00302 template <class TYPE> 00303 int Array<TYPE>::GetItemCount() const 00304 { 00305 return itemCount_; 00306 } 00307 00308 00309 //*** Get (index) *** 00310 00311 template <class TYPE> 00312 TYPE& Array<TYPE>::Get(int index) const 00313 { 00314 Assert(items_ && index>=0 && index<itemCount_,"Index out of range"); 00315 if (!items_ || index<0 || index>=itemCount_) 00316 { 00317 static TYPE defaultValue; 00318 return defaultValue; 00319 } 00320 00321 return items_[index]; 00322 } 00323 00324 00325 //*** Get (iterator) *** 00326 00327 template <class TYPE> 00328 TYPE& Array<TYPE>::Get(const ArrayIterator<TYPE>& iterator) const 00329 { 00330 int index=iterator.GetCurrentIndex(); 00331 Assert(items_ && index>=0 && index<itemCount_,"Iterator out of bounds"); 00332 if (!items_ || index<0 || index>=itemCount_) 00333 { 00334 static TYPE defaultValue; 00335 return defaultValue; 00336 } 00337 00338 return items_[index]; 00339 } 00340 00341 00342 //*** Set (index) *** 00343 00344 template <class TYPE> 00345 void Array<TYPE>::Set(int index, const TYPE& item) 00346 { 00347 Assert(index>=0,"Index out of range"); 00348 if (index<0) 00349 { 00350 return; 00351 } 00352 00353 // Check if we are indexing outside of the currently allocated range 00354 if (!items_ || index>=capacity_) 00355 { 00356 // Double the storage space 00357 int newCapacity=capacity_; 00358 00359 // Keep doubling until we have enough 00360 while (newCapacity<index) 00361 { 00362 newCapacity*=2; 00363 } 00364 00365 // Create a new array with the new size 00366 TYPE* newItems=new TYPE[newCapacity]; 00367 Assert(newItems,"Couldn't allocate memory for array"); 00368 if (!newItems) 00369 { 00370 FatalError("Allocation failed when allocating memory for array"); 00371 } 00372 00373 // Copy each item from the old array to the new one 00374 for (int i=0; i<itemCount_; i++) 00375 { 00376 newItems[i]=items_[i]; 00377 } 00378 00379 // Delete the old array 00380 if (items_) 00381 { 00382 delete[] items_; 00383 items_=0; 00384 } 00385 00386 // Store pointer to the new array 00387 items_=newItems; 00388 00389 // Store the new value for maximum number of items 00390 capacity_=newCapacity; 00391 } 00392 00393 // If we set an item outside of the currently used range, change the 00394 // currently used range to reflect this 00395 if (index>=itemCount_) 00396 { 00397 itemCount_=index+1; 00398 } 00399 00400 Assert(items_ && index>=0 && index<capacity_,"Index out of range"); 00401 00402 // Set the item 00403 if (items_ && index>=0 && index<capacity_) 00404 { 00405 items_[index]=item; 00406 } 00407 } 00408 00409 00410 //*** Set (iterator) *** 00411 00412 template <class TYPE> 00413 void Array<TYPE>::Set(const ArrayIterator<TYPE>& iterator, const TYPE& item) 00414 { 00415 int index=iterator.GetCurrentIndex(); 00416 Assert(index>=0,"Iterator out of bounds"); 00417 if (index>=0) 00418 { 00419 Set(index,item); 00420 } 00421 } 00422 00423 00424 //*** GetCapacity *** 00425 00426 template <class TYPE> 00427 int Array<TYPE>::GetCapacity() const 00428 { 00429 return capacity_; 00430 } 00431 00432 00433 //*** SetCapacity *** 00434 00435 template <class TYPE> 00436 void Array<TYPE>::SetCapacity(int capacity) 00437 { 00438 Assert(capacity>0,"Invalid capacity"); 00439 if (capacity<=0) 00440 { 00441 return; 00442 } 00443 00444 if (itemCount_>capacity) 00445 { 00446 itemCount_=capacity; 00447 } 00448 00449 if (items_) 00450 { 00451 // Create a new array with the new size 00452 TYPE* newItems=new TYPE[capacity]; 00453 Assert(newItems,"Couldn't allocate memory for array"); 00454 if (!newItems) 00455 { 00456 FatalError("Allocation failed when allocating memory for array"); 00457 } 00458 00459 // Copy each item from the old array to the new one 00460 for (int i=0; i<itemCount_; i++) 00461 { 00462 newItems[i]=items_[i]; 00463 } 00464 00465 // Delete the old array 00466 delete[] items_; 00467 00468 // Store pointer to the new array 00469 items_=newItems; 00470 } 00471 00472 00473 // Store the new value for maximum number of items 00474 capacity_=capacity; 00475 } 00476 00477 00478 //*** Clear *** 00479 00480 template <class TYPE> 00481 void Array<TYPE>::Clear(bool releaseMemory) 00482 { 00483 // Clear used range 00484 itemCount_=0; 00485 00486 // Free allocated memory if requested 00487 if (releaseMemory) 00488 { 00489 // Free the memory 00490 if (items_) 00491 { 00492 delete[] items_; 00493 items_=0; 00494 } 00495 00496 // Reset to initial size 00497 capacity_=initialCapacity_; 00498 00499 } 00500 } 00501 00502 00503 //*** ItemExists *** 00504 00505 template <class TYPE> 00506 bool Array<TYPE>::ItemExists(const TYPE& item) const 00507 { 00508 for (int i=0; i<itemCount_; i++) 00509 { 00510 if (items_[i]==item) 00511 { 00512 return true; 00513 } 00514 } 00515 00516 return false; 00517 } 00518 00519 00520 00521 //*** GetPointer *** 00522 00523 template <class TYPE> 00524 TYPE* Array<TYPE>::GetPointer() const 00525 { 00526 // Return the raw pointer to array memory, which might be dangerous, but that's the callers responsibility 00527 return items_; 00528 }
Reproduction/republishing of any material on this site without permission is strictly prohibited.
