qafContainer.h

00001 /* 
00002 ** Qaf Framework 1.2
00003 ** June 2006
00004 ** 
00005 ** Pedro Luchini de Moraes, Public Domain - Free Lunch Code
00006 */
00007 
00008 #ifndef QAF_UTIL_CONTAINER_H
00009 #define QAF_UTIL_CONTAINER_H
00010 
00011 #include <math.h>
00012 #include <stdexcept>
00013 #include <stdlib.h>
00014 
00015 
00016 namespace qaf {
00017 
00041     template <typename T>
00042     class Container {
00043     public:
00047         Container () {
00048             // No elements yet:
00049             count = 0;
00050             
00051             // Start with a capacity of 1:
00052             capacity = 1;
00053             data = new T[1];
00054         }
00055         
00059         Container ( const T * elems, int _count ) {
00060             count = _count;
00061             capacity = _count;
00062             data = new T[count];
00063             
00064             for ( int i = 0; i < count; i++ )
00065                 data[i] = elems[i];
00066         }
00067         
00072         Container ( const Container & orig ) {
00073             count    = orig.count;
00074             capacity = orig.capacity;
00075             data     = new T[capacity];
00076             
00077             for ( int i = 0; i < count; i++ )
00078                 data[i] = orig.data[i];
00079         }
00080         
00084         inline Container & operator = ( const Container & other ) {
00085             reserve( other.count );
00086             
00087             for ( int i = 0; i < other.count; i++ )
00088                 data[i] = other.data[i];
00089             
00090             count = other.count;
00091             
00092             return (*this);
00093         }
00094         
00095         
00100         inline void add ( const T & elem ) {
00101             // Ensure we've got room for the new element:
00102             reserve( count + 1 );
00103             
00104             // Store the new element:
00105             data[count] = elem;
00106             
00107             count++;
00108         }
00109         
00119         inline void add ( int index, const T & elem ) {
00120             // Check for index validity:
00121             if ( index < 0 || index > count )
00122                 throw std::out_of_range("Container index out of range");
00123             
00124             // Ensure we've got room for the new element:
00125             reserve( count + 1 );
00126             
00127             // Shift everyone from "index" onwards to higher indices:
00128             for ( int i = count; i > index; i-- )
00129                 data[i] = data[i - 1];
00130             
00131             // Store the new element:
00132             data[index] = elem;
00133             count++;
00134         }
00135         
00142         inline int indexOf ( const T & elem ) const {
00143             for ( int i = 0; i < count; i++ )
00144                 if ( data[i] == elem )
00145                     return i;
00146             
00147             return -1;
00148         }
00149         
00159         inline void remove ( int index ) {
00160             // Check for index validity:
00161             if ( index < 0 || index >= count )
00162                 throw std::out_of_range("Container index out of range");
00163             
00164             // Shift everyone from "index + 1" onwards to lower indices:
00165             for ( int i = index; i < count - 1; i++ )
00166                 data[i] = data[i + 1];
00167             
00168             // One less element:
00169             count--;
00170         }
00171         
00178         inline bool removeFirst ( const T & elem ) {
00179             int index = indexOf( elem );
00180             
00181             if ( index == -1 )
00182                 return false;
00183             else {
00184                 remove( index );
00185                 return true;
00186             }
00187         }
00188         
00195         inline bool removeAll ( const T & elem ) {
00196             bool foundIt = false;
00197             
00198             for ( int i = count - 1; i >= 0; i-- ) {
00199                 if ( data[i] == elem ) {
00200                     remove( i );
00201                     foundIt = true;
00202                 }
00203             }
00204             
00205             return foundIt;
00206         }
00207         
00211         inline void removeAll () {
00212             count = 0;
00213         }
00214         
00218         inline int getCount () const {
00219             return count;
00220         }
00221         
00232         inline const T & operator[] ( int index ) const {
00233             // Check for index validity:
00234             if ( index < 0 || index >= count )
00235                 throw std::out_of_range("Container index out of range");
00236             
00237             return data[index];
00238         }
00239         
00250         inline T & operator[] ( int index ) {
00251             // Check for index validity:
00252             if ( index < 0 || index >= count )
00253                 throw std::out_of_range("Container index out of range");
00254             
00255             return data[index];
00256         }
00257         
00262         inline const T & elem ( int index ) const {
00263             return operator[]( index );
00264         }
00265         
00270         inline T & elem ( int index ) {
00271             return operator[]( index );
00272         }
00273         
00278         inline const T & tail () const {
00279             return operator[]( count - 1 );
00280         }
00281         
00282         
00287         inline T & tail () {
00288             return operator[]( count - 1 );
00289         }
00290         
00291         
00298         inline const T * getData () const {
00299             return data;
00300         }
00301         
00311         inline void toBeginning ( int index ) {
00312             // Check for index validity:
00313             if ( index < 0 || index >= count )
00314                 throw std::out_of_range("Container index out of range");
00315             
00316             // Ignore if the object is already at the head of the Container:
00317             if ( index == 0 )
00318                 return;
00319             
00320             // The element being moved:
00321             T elem = data[index];
00322             
00323             // Shift everyone towards the end:
00324             for ( int i = index; i >= 1; i-- )
00325                 data[i] = data[i - 1];
00326             
00327             // Place the element at index 0:
00328             data[0] = elem;
00329         }
00330         
00340         inline void toEnd ( int index ) {
00341             // Check for index validity:
00342             if ( index < 0 || index >= count )
00343                 throw std::out_of_range("Container index out of range");
00344             
00345             // Ignore if the object is already at the tail of the Container:
00346             if ( index == count - 1 )
00347                 return;
00348             
00349             // The element being moved:
00350             T elem = data[index];
00351             
00352             // Shift everyone towards the beginning:
00353             for ( int i = index + 1; i < count; i++ )
00354                 data[i - 1] = data[i];
00355             
00356             // Place the element at index "count - 1":
00357             data[count - 1] = elem;
00358         }
00359         
00364         inline void swap ( int i, int j ) {
00365             // Check for index validity:
00366             if ( i < 0 || i >= count ||
00367                  j < 0 || j >= count )
00368                 throw std::out_of_range("Container index out of range");
00369             
00370             // Nothing to do if the indices are the same:
00371             if ( i == j )
00372                 return;
00373             
00374             T tmp = data[j];
00375             data[j] = data[i];
00376             data[i] = tmp;
00377         }
00378         
00379         
00383         virtual ~Container () {
00384             delete[] data;
00385         }
00386         
00387     private:
00388         T * data;
00389         int capacity;
00390         int count;
00391         
00392         // Ensures the container's capacity will be "size" or larger.
00393         void reserve ( int size ) {
00394             if ( capacity < size ) {
00395                 // Increase capacity in steps of 125%, until it's large enough.
00396                 do {
00397                     capacity = (int) ceil( capacity * 1.25 );
00398                 } while ( capacity < size );
00399                 
00400                 // Allocate new storage space:
00401                 T * newData = new T[capacity];
00402                 
00403                 // Copy data to the new storage space:
00404                 for ( int i = 0; i < count; i++ )
00405                     newData[i] = data[i];
00406                 
00407                 // Replace old data:
00408                 delete[] data;
00409                 data = newData;
00410             }
00411         }
00412     };
00413 
00414 }
00415 
00416 #endif

Generated on Sun Mar 25 12:32:12 2007 for Qaf Framework by  doxygen 1.5.1-p1