include/df/array.hpp

00001 //Array template
00002 
00003 //Array uses MemFree()/MemReAlloc() to manage data.
00004 //DF/4.3.2 : New data elements created with ReAlloc() will be zeroed out
00005 //         : For some simple classes this should be enough
00006 //For complex data types (classes) use List instead (new/delete are used)
00007 
00008 template <class DATA>
00009 class Array : virtual public SystemCode {
00010   _PROTECTED_:
00011     //private data
00012     DATA* Data;
00013     uint32 G;  //Granularity (min # elements to alloc/free at a time)
00014     //default = 1
00015     uint32 A;  //currently alloced (if G>1)
00016     void _qsort_asc(DATA* b, int left, int right);
00017     void _qsort_dec(DATA* b, int left, int right);
00018   public:
00019     uint32 flgs;  //user definable flags
00020     //constructor
00021     void ctor();           //easily callable CTOR
00022     Array() {ctor();}      //zero size array (dynamic)
00023     Array(uint32 size);    //preset array size (still dynamic)
00024     //dtor
00025     ~Array() {
00026       if (Data) MemFree(Data);
00027     }
00028     //public data
00029     uint32 Count;          //# of elements in array
00030     uint32 Offset;         //current Offset for Insert(), Delete(), etc.
00031     BOOL Eol;              //is Offset past end of list?
00032     //public members
00033     void ReAlloc(uint32 size);   //set # of elements
00034     DATA &Insert(DATA x, BOOL _inc = TRUE);
00035     DATA &Insert(DATA *x, BOOL _inc = TRUE) { return Insert(*x, _inc); }
00036     DATA &Insert();
00037     BOOL Delete();             //may fail if no more Data to delete
00038     BOOL Set(DATA x, BOOL _inc = TRUE);
00039     BOOL Set(DATA *x, BOOL _inc = TRUE) { return Set(*x, _inc); }
00040     BOOL Get(DATA &x, BOOL _inc = TRUE);
00041     BOOL Get(DATA *&x, BOOL _inc = TRUE);
00042     int Find(DATA x);    //find Offset of object (-1 = not found)
00043     int Find(DATA *x) { return Find(*x);}
00044     void Sort(BOOL asc = TRUE);
00045     //seeking members
00046     BOOL Seek(int32 Offset, int fromwhere); //SEEK_SET, SEEK_END, or SEEK_CUR
00047     //operators
00048     DATA &operator [](int);
00049     DATA &operator =(DATA);  //set data @ current iterator (Offset)
00050     //optz
00051     void SetGranularity(uint32 size);  //can only be called when list is empty
00052 };
00053 
00054 template <class DATA>
00055 DATA &Array<DATA>::operator [](int idx) {
00056   if (idx >= Count) SystemCode::RaiseException(ERR_ASSERT);
00057   return Data[idx];
00058 }
00059 
00060 template <class DATA>
00061 DATA &Array<DATA>::operator =(DATA x) {
00062   if (Eol) SystemCode::RaiseException(ERR_ASSERT);
00063   Set(x, FALSE);
00064   return Data[Offset];
00065 }
00066 
00067 template <class DATA>
00068 void Array<DATA>::ctor() {
00069   Eol = TRUE;
00070   Offset = 0;
00071   Count = 0;
00072   G = 1;
00073   Data = (DATA*)NULL;
00074 }
00075 
00076 template <class DATA>
00077 Array<DATA>::Array(uint32 size) {
00078   ctor();
00079   if (!size) return;
00080   Count = size;
00081   Eol = FALSE;  
00082   Data = (DATA*) SystemCode::MemAlloc(size * sizeof(DATA));  //Note:G=1
00083 }
00084 
00085 //Insert DATA at Offset
00086 template <class DATA>
00087 DATA &Array<DATA>::Insert(DATA x, BOOL _inc) {
00088   int retOffset = Offset;
00089   Count++;
00090   ReAlloc(Count);
00091   if (Eol) {
00092     //insert object at end
00093     Eol = FALSE;  //Offset no longer beyond end
00094   } else {
00095     //shift PTRs below Offset (inserting new PTR)
00096     memcpy(Data + (Offset + 1), Data + Offset, (Count - 1 - Offset) * sizeof(DATA));
00097   }
00098   Data[Offset] = x;
00099   if (_inc) {
00100     Offset++;
00101     if (Offset == Count) Eol = TRUE;
00102   }
00103   return Data[retOffset];
00104 }
00105 
00106 //Insert uninit DATA at Offset
00107 template <class DATA>
00108 DATA &Array<DATA>::Insert() {
00109   uint32 retOffset = Offset;
00110   Count++;
00111   ReAlloc(Count);
00112   if (Eol) {
00113     //insert object at end
00114     Eol = FALSE;  //Offset no longer beyond end
00115   } else {
00116     //shift DATA below Offset (inserting new DATA)
00117     memcpy(Data + (Offset + 1), Data + Offset, (Count - 1 - Offset) * sizeof(DATA));
00118   }
00119   Offset++;
00120   if (Offset == Count) Eol = TRUE;
00121   return Data[retOffset];
00122 }
00123 
00124 //Deletes DATA at Offset
00125 template <class DATA>
00126 BOOL Array<DATA>::Delete() {
00127   if (Eol) return FALSE;  //Eol or no list
00128   //delete object at Offset
00129   memcpy(Data + Offset, Data + (Offset + 1), (Count - 1 - Offset) * sizeof(DATA));
00130   Count--;
00131   if (Offset == Count) (Eol) = TRUE;
00132   ReAlloc(Count);
00133   return TRUE;
00134 }
00135 
00136 //Sets object at Offset and then increments Offset
00137 template <class DATA>
00138 BOOL Array<DATA>::Set(DATA x, BOOL _inc) {
00139   if (Eol) return FALSE;
00140   Data[Offset] = x;
00141   if (_inc) {
00142     Offset++;
00143     if (Offset == Count) Eol = TRUE;
00144   }
00145   return TRUE;
00146 }
00147 
00148 //Gets object at Offset and then increments Offset
00149 template <class DATA>
00150 BOOL Array<DATA>::Get(DATA &x, BOOL _inc) {
00151   if (Eol) return FALSE;
00152   x = Data[Offset];
00153   if (_inc) {
00154     Offset++;
00155     if (Offset == Count) Eol = TRUE;
00156   }
00157   return TRUE;
00158 }
00159 
00160 //Gets object at Offset and then increments Offset
00161 template <class DATA>
00162 BOOL Array<DATA>::Get(DATA *&x, BOOL _inc) {
00163   if (Eol) return FALSE;
00164   x = &Data[Offset];
00165   if (_inc) {
00166     Offset++;
00167     if (Offset == Count) Eol = TRUE;
00168   }
00169   return TRUE;
00170 }
00171 
00172 //Seek thru list (fast!)
00173 template <class DATA>
00174 BOOL Array<DATA>::Seek(int32 _Offset, int fromwhere) {
00175   // fromwhere = SEEK_SET, SEEK_END, or SEEK_CUR
00176   // check 1st if list is empty
00177   if (!Count) return FALSE;
00178   switch (fromwhere) {
00179     case SEEK_SET:
00180       (Offset) = 0;
00181       (Eol) = FALSE;
00182       break;
00183     case SEEK_END:
00184       Offset = Count;
00185       Eol = TRUE;
00186       break;
00187     case SEEK_CUR:
00188       break;
00189     default:
00190       SystemCode::RaiseException(ERR_BADARGS);
00191   }
00192   if (_Offset == 0) return TRUE;
00193   if (_Offset < 0) {
00194     //reverse seeking
00195     _Offset *= -1; //abs()
00196     if (Offset < _Offset) {
00197       Offset = 0;
00198       Eol = FALSE;     //Count > 0
00199       return FALSE;  //seek too much
00200     }
00201     Offset -= _Offset;
00202     Eol = FALSE;
00203     return TRUE;  //seek OK
00204   }
00205   //forward seeking
00206   Offset += _Offset;
00207   if (Offset > Count) {
00208     Offset = Count;
00209     Eol = TRUE;
00210     return FALSE;  //seek too far
00211   }
00212   if (Offset == Count) Eol = TRUE; // else Eol=FALSE;
00213   return !Eol;
00214 }
00215 
00216 template <class DATA>
00217 int Array<DATA>::Find(DATA x) {
00218   //find Offset of object (-1 = not found)
00219   int idx = 0;
00220   while (idx < Count) {
00221     if (Data[idx] == x) return idx;
00222     idx++;
00223   }
00224   return ( -1);  //not found
00225 }
00226 
00227 template <class DATA>
00228 void Array<DATA>::ReAlloc(uint32 size) {
00229   uint32 D;  //desired (after granularity applied)
00230   uint32 OldCount = Count;
00231   if (!size) {
00232     MemFree(Data);
00233     Data = (DATA*)NULL;
00234     Offset = 0;
00235     Count = 0;
00236     A = 0;  //DF/0.5.1 : Bugfix
00237     Eol = TRUE;
00238     return;
00239   }
00240   Count = size;
00241   if (Offset >= Count) {
00242     Offset = Count;
00243     Eol = TRUE;
00244   }
00245   if (G > 1) {
00246     D = (size / G);
00247     if ((D * G) != size) D++;
00248     if (A != D) {
00249       A = D;
00250       Data = (DATA*)SystemCode::MemReAlloc((PTR)Data, A * G * sizeof(DATA));
00251     }
00252   } else {
00253     Data = (DATA*)SystemCode::MemReAlloc((PTR)Data, Count * sizeof(DATA));
00254   }
00255   if (OldCount < Count) SystemCode::memset(((uint8*)Data) + (OldCount * sizeof(DATA)), 0, (Count - OldCount) * sizeof(DATA));
00256 }
00257 
00258 template <class DATA>
00259 void Array<DATA>::SetGranularity(uint32 size) {
00260   if (Count) return;  //failed
00261   G = size;
00262   A = 0;
00263 }
00264 
00265 template <class DATA>
00266 void Array<DATA>::Sort(BOOL asc) {
00267   if (asc) _qsort_asc(Data, 0, Count - 1); else _qsort_dec(Data, 0, Count - 1);
00268 }
00269 
00270 template <class DATA>
00271 void Array<DATA>::_qsort_asc(DATA *b, int left, int right) {
00272   int i, j;
00273   BOOL finish;
00274   DATA p, tmp;
00275   if (right > left) {
00276     i = left;
00277     j = right;
00278     p = b[left];
00279     finish = FALSE;
00280     while (!finish) {
00281       do { i++;} while ((b[i] <= p) && (i <= right));
00282     while ((b[j] >= p) && (j > left)) {j--;}
00283       if (j < i)
00284         finish = TRUE;
00285       else {
00286         tmp = b[i];b[i] = b[j];b[j] = tmp;
00287       }
00288     } //while
00289     tmp = b[left];
00290     b[left] = b[j];
00291     b[j] = tmp;
00292     _qsort_asc(b, left, j - 1);
00293     _qsort_asc(b, i, right);
00294   } //if
00295   return;
00296 }
00297 
00298 template <class DATA>
00299 void Array<DATA>::_qsort_dec(DATA *b, int left, int right) {
00300   int i, j;
00301   BOOL finish;
00302   DATA p, tmp;
00303   if (right > left) {
00304     i = left;
00305     j = right;
00306     p = b[left];
00307     finish = FALSE;
00308     while (!finish) {
00309       do { i++;} while ((b[i] >= p) && (i <= right));
00310     while ((b[j] <= p) && (j > left)) {j--;}
00311       if (j < i)
00312         finish = TRUE;
00313       else {
00314         tmp = b[i];b[i] = b[j];b[j] = tmp;
00315       }
00316     } //while
00317     tmp = b[left];
00318     b[left] = b[j];
00319     b[j] = tmp;
00320     _qsort_dec(b, left, j - 1);
00321     _qsort_dec(b, i, right);
00322   } //if
00323   return;
00324 }

Generated on Mon Mar 5 09:49:13 2007 for DigiForce by  doxygen 1.4.7