00001
00082 #ifndef INC_MI32_SIMPLEAR_H
00083 #define INC_MI32_SIMPLEAR_H
00084
00085 #ifndef INC_MI32_MEMALLOC_H
00086 #include <mi32/memalloc.h>
00087 #endif
00088
00089 #ifndef INC_MI32_SORT_H
00090 #include <mi32/sort.h>
00091 #endif
00092
00093 #ifndef INC_MI32_MEMBUF_H
00094 #include <mi32/membuf.h>
00095 #endif
00096
00097 #ifndef INC_MEMORY_H
00098 #ifndef GENERATING_DOXYGEN_OUTPUT
00099 #include <memory.h>
00100 #define INC_MEMORY_H
00101 #endif
00102 #endif
00103
00104 #ifndef INC_STRING_H
00105 #ifndef GENERATING_DOXYGEN_OUTPUT
00106 #include <string.h>
00107 #define INC_STRING_H
00108 #endif
00109 #endif
00110
00126
00127 template <class _CT> class SIMPLE_ARRAY {
00128 public:
00129
00131 SIMPLE_ARRAY (
00132 ):
00133 m_items(0),
00134 m_numitems(0),
00135 m_numalloc(0),
00136 m_RefCount(1)
00137 { }
00138
00140 SIMPLE_ARRAY (
00141 const SIMPLE_ARRAY<_CT>& rhs
00142 ):
00143 m_items(0),
00144 m_numitems(0),
00145 m_numalloc(0),
00146 m_RefCount(1)
00147 {
00148 if (rhs.m_numitems > 0) {
00149 MmAllocExc((void**)&m_items,rhs.m_numalloc*sizeof(_CT));
00150 m_numalloc = rhs.m_numalloc;
00151 memcpy(m_items,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00152 m_numitems = rhs.m_numitems;
00153 }
00154 }
00155
00157 ~SIMPLE_ARRAY (
00158 ) {
00159 if (m_items != 0) {
00160 free(m_items);
00161 m_numitems = 0;
00162 }
00163 }
00164
00167 SIMPLE_ARRAY<_CT>& operator= (
00168 const SIMPLE_ARRAY<_CT>& rhs
00169 ) {
00170 if (this != &rhs) {
00171 if (m_numalloc < rhs.m_numitems) {
00172 Free();
00173 MmAllocExc((void**)&m_items,rhs.m_numitems*sizeof(_CT));
00174 m_numalloc = rhs.m_numitems;
00175 }
00176 memcpy(m_items,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00177 m_numitems = rhs.m_numitems;
00178 }
00179 return (*this);
00180 }
00181
00183 bool operator== (
00184 const SIMPLE_ARRAY<_CT>& rhs
00185 ) const {
00186 if (m_numitems != rhs.m_numitems) return (false);
00187 if (m_numitems == 0) return (true);
00188 return (memcmp(m_items,rhs.m_items,m_numitems*sizeof(_CT)) == 0);
00189 }
00190
00192 bool operator!= (
00193 const SIMPLE_ARRAY<_CT>& rhs
00194 ) const {
00195 return (!operator==(rhs));
00196 }
00197
00199 operator const _CT*(
00200 ) const {
00201 return (m_items);
00202 }
00203
00205 operator _CT*(
00206 ) {
00207 return (m_items);
00208 }
00209
00212 template <typename _IDXTYPE> const _CT& operator[] (
00213 _IDXTYPE index
00214 ) const {
00215 return (m_items[index]);
00216 }
00217
00220 template <typename _IDXTYPE> _CT& operator[] (
00221 _IDXTYPE index
00222 ) {
00223 return (m_items[index]);
00224 }
00225
00227 void AddRef (
00228 ) { ++m_RefCount; }
00229
00231 ERRVALUE Append (
00232 const _CT& item
00233 ) {
00234 if (m_numitems >= m_numalloc) {
00235 ERRVALUE err;
00236 if ((err = Reserve(MAX(16,2*m_numitems))) < 0) return (err);
00237 }
00238 m_items[m_numitems++] = item;
00239 return (0);
00240 }
00241
00243 ERRVALUE Append (
00244 const _CT *items,
00245 unsigned numitems
00246 ) {
00247 ERRVALUE err;
00248 if ((err = Reserve(m_numitems+numitems)) < 0) return (err);
00249 memcpy(m_items+m_numitems,items,numitems*sizeof(_CT));
00250 m_numitems += numitems;
00251 return (0);
00252 }
00253
00255 ERRVALUE Append (
00256 const SIMPLE_ARRAY<_CT>& rhs
00257 ) {
00258 ERRVALUE err;
00259 if ((err = Reserve(m_numitems+rhs.m_numitems)) < 0) return (err);
00260 memcpy(m_items+m_numitems,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00261 m_numitems += rhs.m_numitems;
00262 return (0);
00263 }
00264
00266 void AppendExc (
00267 const _CT& item
00268 ) {
00269 if (m_numitems >= m_numalloc) {
00270 ReserveExc(MAX(16,2*m_numitems));
00271 }
00272 m_items[m_numitems++] = item;
00273 return;
00274 }
00275
00277 void AppendExc (
00278 const _CT *items,
00279 unsigned numitems
00280 ) {
00281 ReserveExc(m_numitems+numitems);
00282 memcpy(m_items+m_numitems,items,numitems*sizeof(_CT));
00283 m_numitems += numitems;
00284 return;
00285 }
00286
00288 void AppendExc (
00289 const SIMPLE_ARRAY<_CT>& rhs
00290 ) {
00291 ReserveExc(m_numitems+rhs.m_numitems);
00292 memcpy(m_items+m_numitems,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00293 m_numitems += rhs.m_numitems;
00294 return;
00295 }
00296
00298 ERRVALUE AppendUnique (
00299 const _CT& item
00300 ) {
00301 unsigned j;
00302 for (j = 0; (j < m_numitems); ++j) {
00303 if (m_items[j] == item) break;
00304 }
00305 return ((j == m_numitems) ? Append(item) : 0);
00306 }
00307
00309 void AppendUniqueExc (
00310 const _CT& item
00311 ) {
00312 unsigned j;
00313 for (j = 0; (j < m_numitems); ++j) {
00314 if (m_items[j] == item) break;
00315 }
00316 if (j == m_numitems) AppendExc(item);
00317 return;
00318 }
00319
00321 ERRVALUE Assign (
00322 const _CT *items,
00323 unsigned numitems
00324 ) {
00325 ERRVALUE err;
00326 if ((err = Reserve(numitems)) < 0) return (err);
00327 memcpy(m_items,items,numitems*sizeof(_CT));
00328 m_numitems = numitems;
00329 return (0);
00330 }
00331
00340 void Attach (
00341 _CT *& items,
00342 unsigned numitems
00343 ) {
00344 Free();
00345 m_items = items;
00346 m_numitems = m_numalloc = numitems;
00347 items = 0;
00348 return;
00349 }
00350
00352 ERRVALUE Extend (
00353 ) {
00354 if (m_numitems >= m_numalloc) {
00355 ERRVALUE err;
00356 if ((err = Reserve(MAX(16,2*m_numitems))) < 0) return (err);
00357 }
00358 ++m_numitems;
00359 return (0);
00360 }
00361
00363 void Clear (
00364 ) { m_numitems = 0; }
00365
00367 void ClearItems (
00368 ) { memset(m_items, 0, m_numitems * sizeof(_CT)); }
00369
00371 void ClearItems (
00372 unsigned start,
00373 unsigned end = -1
00374 ) {
00375 if (end >= m_numitems) end = m_numitems - 1;
00376 if (end >= start) {
00377 memset(m_items + start, 0, (end - start + 1) * sizeof(_CT));
00378 }
00379 return;
00380 }
00381
00384 ERRVALUE Copy (
00385 const SIMPLE_ARRAY<_CT>& rhs
00386 ) {
00387 if (this != &rhs) {
00388 if (m_numalloc < rhs.m_numitems) {
00389 Free();
00390 ERRVALUE err = MmAlloc((void**)&m_items,rhs.m_numitems*sizeof(_CT));
00391 if (err < 0) return (err);
00392 m_numalloc = rhs.m_numitems;
00393 }
00394 memcpy(m_items,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00395 m_numitems = rhs.m_numitems;
00396 }
00397 return (0);
00398 }
00399
00409 _CT* Detach (
00410 ) {
00411 _CT* ret = m_items;
00412 m_numalloc = m_numitems = 0;
00413 m_items = 0;
00414 return (ret);
00415 }
00416
00418 void ExchangeItems (
00419 unsigned index1,
00420 unsigned index2
00421 ) {
00422 _CT temp = m_items[index1];
00423 m_items[index1] = m_items[index2];
00424 m_items[index2] = temp;
00425 return;
00426 }
00427
00429 void Free (
00430 ) {
00431 m_numalloc = m_numitems = 0;
00432 MmFree(m_items);
00433 return;
00434 }
00435
00437 const _CT& GetItem (
00438 unsigned index
00439 ) const { return (m_items[index]); }
00440
00442 const _CT* GetItems (
00443 ) const { return (m_items); }
00444
00446 _CT* GetItems (
00447 ) { return (m_items); }
00448
00451 const _CT& GetLast (
00452 ) const { return (m_items[m_numitems-1]); }
00453
00455 unsigned GetMaxItems (
00456 ) const { return (m_numalloc); }
00457
00459 unsigned GetNumItems (
00460 ) const { return (m_numitems); }
00461
00463 UINT32 GetRefCount (
00464 ) const { return (m_RefCount); }
00465
00467 unsigned GetSizeInBytes (
00468 ) const { return (m_numitems*sizeof(_CT)); }
00469
00473 bool HasItem (
00474 const _CT& item
00475 ) const {
00476 for (unsigned i = 0; (i < m_numitems); ++i) {
00477 if (m_items[i] == item) return (true);
00478 }
00479 return (false);
00480 }
00481
00483 ERRVALUE Insert (
00484 unsigned pos,
00485 const _CT& item
00486 ) {
00487 if (pos < 0 || pos > m_numitems) return (EBadFuncParm);
00488 if (m_numitems >= m_numalloc) {
00489 ERRVALUE err;
00490 if ((err = Reserve(MAX(16,2*m_numitems))) < 0) return (err);
00491 }
00492 if (pos < m_numitems) {
00493 memmove(&m_items[pos+1], &m_items[pos], (m_numitems - pos) * sizeof(_CT));
00494 }
00495 ++m_numitems;
00496 m_items[pos] = item;
00497 return (0);
00498 }
00499
00501 void InsertItems (
00502 unsigned start,
00503 unsigned num = 1
00504 ) {
00505 ReserveExc(m_numitems+num);
00506 memmove(&m_items[start + num], &m_items[start], (m_numitems - start) * sizeof(_CT));
00507 m_numitems += num;
00508 return;
00509 }
00510
00512 bool IsEmpty (
00513 ) const { return (GetNumItems() == 0); }
00514
00519 template<typename _Pr1> unsigned Locate (
00520 const _CT& item,
00521 _Pr1 _Pr,
00522 bool& bFound
00523 ) const {
00524 bFound = false;
00525 unsigned l = 1, r = m_numitems;
00526 while (l <= r) {
00527 unsigned q = (l+r) / 2 - 1;
00528 int test = _Pr(item, m_items[q]);
00529 if (test == 0) { bFound = true; return (q); }
00530 if (test < 0) {
00531 r = q;
00532 }
00533 else {
00534 l = q + 2;
00535 }
00536 }
00537 return (m_numitems);
00538 }
00539
00541 void Release (
00542 ) { if (--m_RefCount == 0) delete this; }
00543
00545 void RemoveDuplicates (
00546 ) {
00547 for (unsigned i = 0; (i < m_numitems); ++i) {
00548 for (unsigned k = i+1; (k < m_numitems); ++k) {
00549 if (m_items[i] == m_items[k]) {
00550 m_items[k] = m_items[m_numitems-1];
00551 --m_numitems;
00552 --k;
00553 }
00554 }
00555 }
00556 return;
00557 }
00558
00560 void RemoveFast (
00561 unsigned item
00562 ) {
00563 if (item >= 0 && item < m_numitems) {
00564 --m_numitems;
00565 m_items[item] = m_items[m_numitems];
00566 }
00567 return;
00568 }
00569
00572 void RemoveItem (
00573 unsigned item
00574 ) {
00575 if (item < m_numitems && item >= 0) {
00576 --m_numitems;
00577 if (item < m_numitems) { memmove(&m_items[item], &m_items[item+1], (m_numitems - item) * sizeof(_CT)); }
00578 }
00579 return;
00580 }
00581
00584 void RemoveItems (
00585 unsigned item,
00586 unsigned count
00587 ) {
00588 if (item < m_numitems) {
00589 if (count < 0 || item + count > m_numitems) count = m_numitems - item;
00590 m_numitems -= count;
00591 if (item < m_numitems) { memmove(&m_items[item], &m_items[item+count], (m_numitems - item) * sizeof(_CT)); }
00592 }
00593 return;
00594 }
00595
00597 void RemoveLast (
00598 unsigned count = 1
00599 ) {
00600 if (count > m_numitems)
00601 m_numitems = 0;
00602 else
00603 m_numitems -= count;
00604 return;
00605 }
00606
00610 bool RemoveMatchingItems (
00611 const _CT& item
00612 ) {
00613 unsigned i, num;
00614 for (num = i = 0; (i < m_numitems); ++i) {
00615 if (m_items[i] != item) {
00616 if (num < i) m_items[num] = m_items[i];
00617 ++num;
00618 }
00619 }
00620 bool retval = (m_numitems != num);
00621 m_numitems = num;
00622 return (retval);
00623 }
00624
00626 ERRVALUE Reserve (
00627 unsigned newmaxitems,
00628 bool clear = false
00629 ) {
00630 if (clear) m_numitems = 0;
00631 if (newmaxitems > m_numalloc) {
00632 ERRVALUE err;
00633 if (m_numitems == 0) {
00635 MmFree(m_items);
00636 }
00637 if ((err = MmRealloc((void**)&m_items,newmaxitems*sizeof(_CT))) < 0) return (err);
00638 m_numalloc = newmaxitems;
00639 }
00640 return (0);
00641 }
00642
00645 void ReserveExc (
00646 unsigned newmaxitems,
00647 bool clear = false
00648 ) {
00649 if (clear) m_numitems = 0;
00650 if (newmaxitems > m_numalloc) {
00651 if (m_numitems == 0) {
00653 MmFree(m_items);
00654 }
00655 MmReallocExc((void**)&m_items,newmaxitems*sizeof(_CT));
00656 m_numalloc = newmaxitems;
00657 }
00658 return;
00659 }
00660
00664 ERRVALUE Resize (
00665 unsigned numitems,
00666 bool keepold = true,
00667 bool clear = false
00668 ) {
00669 ERRVALUE err;
00670 if ((err = Reserve(numitems,!keepold)) < 0) return (err);
00671 if (clear && numitems > m_numitems) memset(static_cast<void*>(m_items+m_numitems),0,(numitems-m_numitems)*sizeof(_CT));
00672 m_numitems = numitems;
00673 return (0);
00674 }
00675
00677 void Reverse (
00678 ) {
00679 for (unsigned i = 0; (i < m_numitems/2); ++i) {
00680 _CT temp(m_items[i]);
00681 m_items[i] = m_items[m_numitems-i-1];
00682 m_items[m_numitems-i-1] = temp;
00683 }
00684 }
00685
00687 void SetAll (
00688 const _CT& value
00689 ) {
00690 for (unsigned i = 0; (i < m_numitems); ++i) {
00691 m_items[i] = value;
00692 }
00693 }
00694
00696 void SetItem (
00697 unsigned index,
00698 const _CT& item
00699 ) {
00700 m_items[index] = item;
00701 }
00702
00705 ERRVALUE SetItems (
00706 unsigned firstitem,
00707 const _CT *items,
00708 unsigned numitems
00709 ) {
00710 ERRVALUE err;
00711 if ((err = Reserve(firstitem+numitems)) < 0) return (err);
00712 memcpy(m_items+firstitem,items,numitems*sizeof(_CT));
00713 if (m_numitems < firstitem + numitems) m_numitems = firstitem + numitems;
00714 return (0);
00715 }
00716
00720 void Sort (
00721 int (*CompFunc)(_CT*, _CT*, void*),
00722 void *data = 0
00723 ) {
00724
00725 heapsort(m_items, m_numitems, sizeof(_CT), reinterpret_cast<int (*)(void*, void*, void*)>(CompFunc), data);
00726 }
00727
00731 void SortRange (
00732 int (*CompFunc)(_CT*, _CT*, void*),
00733 unsigned firstidx,
00734 unsigned numitems,
00735 void *data = 0
00736 ) {
00737 if (numitems <= 0 || firstidx < 0 || firstidx + numitems > m_numitems) return;
00738 heapsort(m_items + firstidx, numitems, sizeof(_CT), reinterpret_cast<int (*)(void*, void*, void*)>(CompFunc), data);
00739 }
00740
00743 void Swap (
00744 SIMPLE_ARRAY<_CT>& rhs
00745 ) {
00746 _CT *t_items = m_items;
00747 m_items = rhs.m_items;
00748 rhs.m_items = t_items;
00749 unsigned t_numitems = m_numitems;
00750 m_numitems = rhs.m_numitems;
00751 rhs.m_numitems = t_numitems;
00752 unsigned t_numalloc = m_numalloc;
00753 m_numalloc = rhs.m_numalloc;
00754 rhs.m_numalloc = t_numalloc;
00755 }
00756
00758 void SwapBytes (
00759 ) {
00760 for (unsigned i = 0; (i < m_numitems); ++i) ::SwapBytes(m_items[i]);
00761 }
00762
00763 private:
00764 #ifndef GENERATING_DOXYGEN_OUTPUT
00765 _CT *m_items;
00766 unsigned m_numitems;
00767 unsigned m_numalloc;
00768 UINT32 m_RefCount;
00769 #endif // GENERATING_DOXYGEN_OUTPUT
00770
00771 };
00772
00773 #endif // INC_MI32_SIMPLEAR_H