00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef LEGOPARR_H
00020 #define LEGOPARR_H
00021
00022
00023
00024
00025
00026 #include "globals.H"
00027 #include "legoErr.H"
00028
00029
00030
00031
00032
00033 #ifndef __STRING_H
00034 #include <string.h>
00035 #endif
00036
00037 #ifndef __STDLIB_H
00038 #include <stdlib.h>
00039 #endif
00040
00041 #ifndef MAX_UNSIGNED
00042 #define MAX_UNSIGNED ((unsigned) -1)
00043 #endif
00044
00045 template <class T> class legoPSet;
00046 template <class T> class legoPArrItr;
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 template <class T> class legoPArr {
00067
00068 protected:
00069
00070 T *data;
00071 unsigned _size,_delta;
00072 unsigned count;
00073 int shouldDelete;
00074
00075
00076 void Expand(unsigned newSize);
00077 void Shrink();
00078
00079
00080 unsigned ComputeSize(unsigned sz)
00081 {
00082 if ((_delta != 0) && (sz % _delta != 0))
00083 return (((sz + _delta) / _delta) * _delta);
00084 else
00085 return sz;
00086 };
00087
00088 public:
00089 friend legoPSet<T>;
00090
00091
00092 legoPArr();
00093
00094
00095 legoPArr(unsigned size,unsigned delta = 4);
00096
00097
00098 virtual ~legoPArr()
00099 {
00100
00101 PEmpty();
00102 }
00103
00104
00105 legoPArr(const legoPArr<T>& a,unsigned delta = LARGE_INTVAL);
00106 const legoPArr<T>& operator = (const legoPArr<T>& a);
00107
00108
00109 int operator == (const legoPArr<T>& a);
00110 int operator != (const legoPArr<T>& a)
00111 { return !(*this == a); };
00112
00113
00114 T& operator [] (unsigned index)
00115 {
00116 if (data == NULL)
00117 LegoFatal ("legoPArr operator []", "Container %x is uninitialized.",
00118 this);
00119 if (index >= count)
00120 LegoFatal ("legoPArr operator []", "Index given is %d, but container "
00121 "%x only has %d items.", index, this, count);
00122
00123 return data[index];
00124 };
00125
00126 const T& operator [] (unsigned index) const
00127 {
00128 if (data == NULL)
00129 LegoFatal ("legoPArr operator []", "Container %x is uninitialized.",
00130 this);
00131 if (index < count)
00132 LegoFatal ("legoPArr operator []", "Index given is %d, but container "
00133 "%x only has %d items.", index, this, count);
00134
00135 return data[index];
00136 };
00137
00138
00139 unsigned AddItem(T item);
00140 void Insert(T item, unsigned index, unsigned count = 1);
00141
00142
00143 void Replace(T item, unsigned index);
00144
00145
00146 void DestroyItem(unsigned index);
00147
00148
00149 virtual unsigned Search(T item, unsigned first, unsigned last,
00150 int direction = +1) const;
00151 unsigned Search(T item, int direction = +1) const
00152 {
00153 if ( count == 0 ) { return MAX_UNSIGNED; }
00154 return Search(item, 0, count-1, direction);
00155 };
00156
00157
00158 void SetCount(unsigned newCount);
00159
00160
00161 unsigned GetCount() const { return count; };
00162
00163
00164 int IsEmpty() const { return count == 0; };
00165
00166
00167 int IsFull() const
00168 { return (_delta == 0) && (count == _size); };
00169
00170
00171 unsigned GetSize() const { return _size; };
00172 unsigned GetDelta() const { return _delta; };
00173
00174
00175 void SetDelta(unsigned delta);
00176
00177
00178 void SetSize(unsigned newSize);
00179
00180
00181 void Empty();
00182
00183
00184 void PEmpty();
00185
00186
00187 int Valid() const { return (data != NULL); };
00188
00189
00190 int IsOwner() const { return shouldDelete; }
00191
00192 private:
00193
00194 friend class legoPArrItr<T>;
00195 };
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 template <class T> class legoPArrItr {
00206
00207 protected:
00208
00209 const legoPArr<T> *a;
00210 unsigned cursor,lower,upper;
00211
00212 public:
00213
00214
00215 legoPArrItr()
00216 { a = NULL; cursor = lower = upper = 0; };
00217
00218
00219 legoPArrItr(const legoPArr<T>& arr)
00220 { a = &arr; Restart(0,arr.GetCount()); };
00221
00222
00223 legoPArrItr(const legoPArr<T>& arr, unsigned start, unsigned stop)
00224 { a = &arr; Restart(start,stop); };
00225
00226
00227 const legoPArrItr<T>& operator = (const legoPArr<T>& arr)
00228 { a = &arr; Restart(0,arr.GetCount());
00229 return *this;
00230 };
00231
00232
00233 const legoPArrItr<T>& operator = (const legoPArrItr<T>& i)
00234 { a = i.a; Restart(i.lower,i.upper);
00235 return *this;
00236 };
00237
00238
00239 operator int () { return cursor < upper; };
00240
00241
00242 T node()
00243 {
00244 if (cursor >= upper)
00245 LegoFatal ("LegoPArrItr::node", "Cursor out of range.");
00246
00247 return (*a)[cursor];
00248 };
00249
00250
00251 T operator ++ ()
00252 { if (++cursor < upper) return (*a)[cursor];
00253 else return (*a)[upper-1];
00254 };
00255
00256
00257 T operator ++ (int)
00258 { if (cursor < upper) return (*a)[cursor++];
00259 else return (*a)[upper-1];
00260 };
00261
00262
00263 void Restart() { Restart(lower,upper); };
00264
00265
00266 void Restart(unsigned start,unsigned stop)
00267 { cursor = lower = start; upper = stop; };
00268 };
00269
00270
00271
00272
00273
00274
00275
00276
00277 template <class T> unsigned legoPArr<T>::AddItem(T item)
00278
00279
00280
00281
00282
00283
00284
00285 {
00286
00287 if (!Valid())
00288 LegoFatal ("legoPArr::AddItem", "Container %x is uninitialized.",
00289 this);
00290
00291 if (count == _size) Expand(count+1);
00292 if (count >= _size)
00293 LegoFatal ("legoPArr::AddItem", "Expansion of container %x "
00294 "failed!", this);
00295
00296 if (Valid()) {
00297 data[count++] = item;
00298 return 1;
00299 }
00300 else { return 0; }
00301 }
00302
00303 template <class T> void legoPArr<T>::SetCount(unsigned newCount)
00304
00305
00306
00307
00308
00309
00310
00311 {
00312 SetSize(newCount);
00313 count = newCount;
00314 }
00315
00316 template <class T>
00317 void legoPArr<T>::Replace(T item, unsigned index)
00318
00319
00320
00321
00322
00323
00324
00325 {
00326 if (!Valid())
00327 LegoFatal ("legoPArr::AddItem", "Container %x is uninitialized.",
00328 this);
00329
00330 if (index >= count)
00331 LegoFatal ("legoPArr::Replace", "Index given is %d, but container "
00332 "%x only has %d items.", index, this, count);
00333
00334 if (shouldDelete)
00335 delete data[index];
00336 data[index] = item;
00337 }
00338
00339 template <class T> legoPArr<T>::legoPArr()
00340 : _size(4), _delta(4), count(0)
00341
00342
00343
00344
00345
00346 {
00347
00348 shouldDelete = true;
00349 data = new T[_size];
00350
00351 }
00352
00353 template <class T> legoPArr<T>::legoPArr(unsigned size,unsigned delta)
00354 : _delta(delta), count(0)
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 {
00366
00367 shouldDelete = true;
00368 _size = ComputeSize(size);
00369 data = new T[_size];
00370
00371 }
00372
00373 template <class T> legoPArr<T>::legoPArr(const legoPArr<T>& a,
00374 unsigned delta = LARGE_INTVAL)
00375 : count(a.count)
00376
00377
00378
00379
00380
00381
00382 {
00383
00384 shouldDelete = false;
00385 if (!(a.Valid()))
00386 LegoFatal ("legoPArr::legoPArr [copy constructor]",
00387 "Original container %x is uninitialized.", a);
00388
00389 _delta = (delta == LARGE_INTVAL) ? a._delta : delta;
00390 _size = ComputeSize(a._size);
00391 data = new T[_size];
00392 if (Valid())
00393 memcpy(data,a.data,count * sizeof(T));
00394 }
00395
00396 template <class T> const legoPArr<T>& legoPArr<T>::operator = (const legoPArr<T>& a)
00397
00398
00399
00400
00401
00402
00403
00404 {
00405
00406
00407
00408 if (!Valid())
00409 LegoFatal ("LegoPArr operator =", "Container %x (dest.) is "
00410 "uninitialized.", this);
00411 if (!(a.Valid()))
00412 LegoFatal ("LegoPArr operator =", "Source container is "
00413 "uninitialized.");
00414
00415 if (data != a.data) {
00416 PEmpty();
00417 shouldDelete = false;
00418 _size = a._size;
00419 _delta = a._delta;
00420 count = a.count;
00421 delete [] data;
00422 data = new T[_size];
00423 if (Valid())
00424 memcpy(data,a.data,count * sizeof(T));
00425 }
00426 return *this;
00427 }
00428
00429 template <class T> int legoPArr<T>::operator == (const legoPArr<T>& a)
00430
00431
00432
00433
00434
00435
00436
00437 {
00438 if (!Valid())
00439 LegoFatal ("LegoPArr operator ==", "Container %x (first) is "
00440 "uninitialized.", this);
00441 if (!(a.Valid()))
00442 LegoFatal ("LegoPArr operator ==", "Second container is "
00443 "uninitialized.");
00444
00445 if (count != a.count)
00446 return 0;
00447 T *p = data, *pa = a.data;
00448 for (unsigned i = 0; i < count; i++)
00449 if (!(*p++ == *pa++))
00450 return 0;
00451 return 1;
00452 }
00453
00454 template <class T> void legoPArr<T>::Insert(T item,
00455 unsigned index, unsigned aCount)
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 {
00468 if (!Valid())
00469 LegoFatal ("legoPArr::Insert", "Container %x is uninitialized.",
00470 this);
00471
00472
00473 if (index > count)
00474 LegoFatal ("legoPArr::Insert", "Index given is %d, but container "
00475 "%x only has %d items.", index, this, count);
00476
00477 if (count+aCount > _size) Expand(count+aCount);
00478
00479
00480
00481 if (Valid()) {
00482 memmove(&data[index+aCount],&data[index],(count-index) * sizeof(T));
00483 for (unsigned i = 0; i < aCount; i++)
00484 data[index+i] = item;
00485 count += aCount;
00486 }
00487 }
00488
00489 template <class T> unsigned legoPArr<T>::Search(T item,
00490 unsigned first, unsigned last, int direction) const
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 {
00504 if (!Valid())
00505 LegoFatal ("legoPArr::Search", "Container %x is uninitialized.",
00506 this);
00507
00508
00509 if (count <= first || count <= last)
00510 LegoFatal ("legoPArr::Search", "Search indices given are %d to %d, but "
00511 "container %x only has %d items.", first, last, this, count);
00512
00513
00514 if (direction != -1 && direction != +1)
00515 {
00516 LegoNonFatal ("legoPArr::Search", "Direction specified was %d, should "
00517 "be either +1 or -1. Defaulting to forward search.",
00518 direction);
00519 direction = +1;
00520 }
00521
00522
00523 if (direction == +1) {
00524 T *p = &data[first];
00525 for (unsigned i = first; i <= last; i++) {
00526
00527 if (*(p++) == item) return i;
00528 }
00529 }
00530 else {
00531 T *p = &data[last];
00532 for (unsigned i = last; i >= first; i--)
00533 { if (*(p--) == item) return i; }
00534 }
00535
00536 return MAX_UNSIGNED;
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 template <class T> void legoPArr<T>::Expand(unsigned newSize)
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 {
00568 if (!Valid())
00569 LegoFatal ("legoPArr::Expand", "Container %x is uninitialized.",
00570 this);
00571
00572
00573 if (_delta == 0)
00574 return;
00575
00576 if (newSize < count)
00577 {
00578 LegoNonFatal ("legoPArr::Expand", "New size %d is smaller than "
00579 "current count %d of container %x. Skipping expansion.",
00580 newSize, count, this);
00581 return;
00582 }
00583
00584
00585 T *temp = new T[_size = ComputeSize(newSize)];
00586
00587
00588
00589 if (temp != NULL)
00590 {
00591 memcpy(temp,data,count * sizeof(T));
00592 delete[] data;
00593 }
00594 else
00595 {
00596 LegoNonFatal ("legoPArr::Expand", "Expansion failed.");
00597 temp = data;
00598 }
00599 data = temp;
00600 }
00601
00602 template <class T> void legoPArr<T>::Shrink()
00603
00604
00605
00606
00607
00608 {
00609 if (!Valid())
00610 LegoFatal ("legoPArr::Shrink", "Container %x is uninitialized.",
00611 this);
00612
00613
00614 if (_delta == 0)
00615 return;
00616
00617
00618
00619
00620 if ((_size - count) > (_delta + _delta/2) && (_size > _delta)) {
00621 T *temp = new T[_size = ComputeSize(_size - _delta)];
00622 if (temp != NULL)
00623 {
00624 memcpy(temp, data, count * sizeof(T));
00625 delete [] data;
00626 }
00627 else
00628 {
00629 LegoNonFatal("legoPArr::Shrink", "Shrinking failed.");
00630 temp = data;
00631 }
00632 data = temp;
00633 }
00634 }
00635
00636 template <class T> void legoPArr<T>::SetDelta(unsigned delta)
00637
00638
00639
00640
00641
00642
00643 {
00644 if (delta >= _delta) {
00645 _delta = delta;
00646 Expand(_size);
00647 }
00648 else {
00649 _delta = delta;
00650 Shrink();
00651 }
00652 }
00653
00654 template <class T> void legoPArr<T>::SetSize(unsigned newSize)
00655
00656
00657
00658
00659
00660
00661
00662 {
00663 if (_delta == 0) return;
00664
00665 Empty();
00666 Expand(newSize);
00667 }
00668
00669 template <class T> void legoPArr<T>::Empty()
00670
00671
00672
00673
00674 {
00675 count = 0;
00676 Shrink();
00677 }
00678
00679 template <class T> void legoPArr<T>::PEmpty()
00680
00681
00682
00683
00684
00685 {
00686 if (shouldDelete) {
00687 for (unsigned i = 0; i < count; i++)
00688 delete data[i];
00689 }
00690 Empty();
00691 }
00692
00693 template <class T> void legoPArr<T>::DestroyItem(unsigned index)
00694
00695
00696
00697
00698
00699
00700
00701
00702 {
00703 if (!Valid())
00704 LegoFatal ("legoPArr::DestroyItem", "Container %x is uninitialized.",
00705 this);
00706
00707 if (index >= count)
00708 LegoFatal ("legoPArr::DestroyItem", "Index given is %d, but "
00709 "container %x only has %d items.", index, this, count);
00710
00711
00712
00713
00714 if (shouldDelete)
00715 delete data[index];
00716 count--;
00717 memmove(&data[index],&data[index+1],(count-index) * sizeof(T));
00718 Shrink();
00719 }
00720
00721 #endif // LEGOPARR_H