00001
00058 #ifndef INC_MI32_MILIST_H
00059 #define INC_MI32_MILIST_H
00060
00061 #ifndef INC_MI32_MEMALLOC_H
00062 #include <mi32/memalloc.h>
00063 #endif
00064
00065 #include <functional>
00066
00067 template <typename _LIT> class MILIST {
00068
00069 protected:
00070
00071 struct LISTITEM {
00072 _LIT m_Item;
00073 LISTITEM *m_Next, *m_Prev;
00074
00075 LISTITEM (
00076 const _LIT& item
00077 ) : m_Item(item), m_Prev(0), m_Next(0) {}
00078
00079 private:
00080 #ifndef GENERATING_DOXYGEN_OUTPUT
00081
00082 LISTITEM (const LISTITEM&);
00083 LISTITEM& operator= (const LISTITEM&);
00084 #endif // GENERATING_DOXYGEN_OUTPUT
00085 };
00086
00087 public:
00088
00089
00090
00091 class ITERATOR;
00092 class CONST_ITERATOR;
00093 friend class CONST_ITERATOR;
00094
00096 class CONST_ITERATOR {
00097 public:
00098
00099 CONST_ITERATOR (
00100 ) {}
00101
00102 CONST_ITERATOR (
00103 LISTITEM *item
00104 ) : m_Ptr(item) {}
00105
00106 CONST_ITERATOR (
00107 const ITERATOR& item
00108 ) : m_Ptr(item.m_Ptr) {}
00109
00110 const _LIT& operator* (
00111 ) const { return (CONST_ITERATOR::m_Ptr->m_Item); }
00112
00113 const _LIT* operator-> (
00114 ) const { return (&**this); }
00115
00117 CONST_ITERATOR& operator++ (
00118 ) {
00119 CONST_ITERATOR::m_Ptr = CONST_ITERATOR::m_Ptr->m_Next;
00120 return (*this);
00121 }
00122
00124 CONST_ITERATOR operator++(int
00125 ) {
00126 CONST_ITERATOR temp = *this;
00127 ++*this;
00128 return (temp);
00129 }
00130
00132 CONST_ITERATOR& operator-- (
00133 ) {
00134 CONST_ITERATOR::m_Ptr = CONST_ITERATOR::m_Ptr->m_Prev;
00135 return (*this);
00136 }
00137
00139 CONST_ITERATOR operator--(int
00140 ) {
00141 CONST_ITERATOR temp = *this;
00142 --*this;
00143 return (temp);
00144 }
00145
00146 bool operator== (
00147 const CONST_ITERATOR& rhs
00148 ) const { return (CONST_ITERATOR::m_Ptr == rhs.m_Ptr); }
00149
00150 bool operator!= (
00151 const CONST_ITERATOR& rhs
00152 ) const { return (!(*this == rhs)); }
00153
00154 LISTITEM *GetNode (
00155 ) const { return (m_Ptr); }
00156
00157 protected:
00158 LISTITEM *m_Ptr;
00159 };
00160
00161 friend class ITERATOR;
00162
00163 class ITERATOR : public CONST_ITERATOR {
00164 public:
00165
00166 ITERATOR (
00167 ) {}
00168
00169 ITERATOR (
00170 LISTITEM *item
00171 ) : CONST_ITERATOR(item) {}
00172
00174 _LIT& operator* (
00175 ) const { return (CONST_ITERATOR::m_Ptr->m_Item); }
00176
00178 _LIT* operator-> (
00179 ) const { return (&**this); }
00180
00182 ITERATOR& operator++ (
00183 ) {
00184 CONST_ITERATOR::m_Ptr = CONST_ITERATOR::m_Ptr->m_Next;
00185 return (*this);
00186 }
00187
00189 ITERATOR operator++(int
00190 ) {
00191 ITERATOR temp = *this;
00192 ++*this;
00193 return (temp);
00194 }
00195
00197 ITERATOR& operator-- (
00198 ) {
00199 CONST_ITERATOR::m_Ptr = CONST_ITERATOR::m_Ptr->m_Prev;
00200 return (*this);
00201 }
00202
00204 ITERATOR operator--(int
00205 ) {
00206 ITERATOR temp = *this;
00207 --*this;
00208 return (temp);
00209 }
00210
00212 bool operator== (
00213 const ITERATOR& rhs
00214 ) const { return (CONST_ITERATOR::m_Ptr == rhs.m_Ptr); }
00215
00217 bool operator!= (
00218 const ITERATOR& rhs
00219 ) const { return (!(*this == rhs)); }
00220
00221 };
00222
00224 MILIST (
00225 ) : m_Head(0), m_NumItems(0) {
00226 MmAllocCExc((void **)&m_Head, sizeof(LISTITEM));
00227 m_Head->m_Next = m_Head->m_Prev = m_Head;
00228 }
00229
00231 MILIST (
00232 const MILIST<_LIT>& rhs
00233 ) : m_Head(0), m_NumItems(0) {
00234 MmAllocCExc((void **)&m_Head, sizeof(LISTITEM));
00235 m_Head->m_Next = m_Head->m_Prev = m_Head;
00236 for (CONST_ITERATOR it = rhs.Begin(); (it != rhs.End()); ++it) {
00237 Insert(End(), *it);
00238 }
00239 }
00240
00242 ~MILIST (
00243 ) {
00244 Clear();
00245 MmFree(m_Head);
00246 }
00247
00249 MILIST<_LIT>& operator= (
00250 const MILIST<_LIT>& rhs
00251 ) {
00252 if (this != &rhs) {
00253 Clear();
00254 for (CONST_ITERATOR it = rhs.Begin(); (it != rhs.End()); ++it) {
00255 Insert(End(), *it);
00256 }
00257 }
00258 return (*this);
00259 }
00260
00262 ITERATOR Begin (
00263 ) { return (ITERATOR(m_Head->m_Next)); }
00264
00266 CONST_ITERATOR Begin (
00267 ) const { return (CONST_ITERATOR(m_Head->m_Next)); }
00268
00270 void Clear (
00271 ) { Remove(Begin(), End()); }
00272
00276 bool Contains (
00277 const _LIT& item
00278 ) const {
00279 for (CONST_ITERATOR it = Begin(); (it != End()); ++it) {
00280 if (*it == item) return (true);
00281 }
00282 return (false);
00283 }
00284
00287 ITERATOR CopyIterator (
00288 CONST_ITERATOR it
00289 ) { return (ITERATOR(it.GetNode())); }
00290
00293 CONST_ITERATOR Find (
00294 const _LIT& item
00295 ) const {
00296 CONST_ITERATOR it = Begin();
00297 for (; (it != End()); ++it) {
00298 if (*it == item) break;
00299 }
00300 return (it);
00301 }
00302
00305 ITERATOR Find (
00306 const _LIT& item
00307 ) {
00308 ITERATOR it = Begin();
00309 for (; (it != End()); ++it) {
00310 if (*it == item) break;
00311 }
00312 return (it);
00313 }
00314
00316 ITERATOR End (
00317 ) { return (ITERATOR(m_Head)); }
00318
00320 CONST_ITERATOR End (
00321 ) const { return (CONST_ITERATOR(m_Head)); }
00322
00324 void Exchange (
00325 MILIST<_LIT>& other
00326 ) {
00327 LISTITEM *TempHead = m_Head;
00328 m_Head = other.m_Head;
00329 other.m_Head = TempHead;
00330 INT32 TempNumItems = m_NumItems;
00331 m_NumItems = other.m_NumItems;
00332 other.m_NumItems = TempNumItems;
00333 return;
00334 }
00335
00337 void Extract (
00338 MILIST<_LIT>& other,
00339 ITERATOR& it
00340 ) {
00341 other.RemoveItem(it);
00342 InsertItem(it,End());
00343 }
00344
00346 const _LIT& GetBack (
00347 ) const { return (m_Head->m_Prev->m_Item); }
00348
00350 _LIT& GetBack (
00351 ) { return (m_Head->m_Prev->m_Item); }
00352
00354 const _LIT& GetFront (
00355 ) const { return (m_Head->m_Next->m_Item); }
00356
00358 _LIT& GetFront (
00359 ) { return (m_Head->m_Next->m_Item); }
00360
00364 const _LIT& GetIndexed (
00365 int index
00366 ) const {
00367 CONST_ITERATOR it = Begin();
00368 while (index > 0 && it != End()) {++it;--index;}
00369 return (*it);
00370 }
00371
00375 _LIT& GetIndexed (
00376 int index
00377 ) {
00378 ITERATOR it = Begin();
00379 while (index > 0 && it != End()) {++it;--index;}
00380 return (*it);
00381 }
00382
00384 INT32 GetNumItems (
00385 ) const { return (m_NumItems); }
00386
00388 bool HasSameValues (
00389 const MILIST<_LIT>& rhs
00390 ) const {
00391 if (m_NumItems != rhs.m_NumItems) return (false);
00392 for (CONST_ITERATOR lit = Begin();(lit != End()); ++lit) {
00393 if (!rhs.Contains(*lit)) return (false);
00394 }
00395 return (true);
00396 }
00397
00400 _LIT& Insert (
00401 ITERATOR it,
00402 const _LIT& item
00403 ) { return (InsertBefore(it,item)); }
00404
00407 _LIT& InsertAfter (
00408 ITERATOR it,
00409 const _LIT& item
00410 ) {
00411 LISTITEM *pPrev = it.GetNode();
00412 LISTITEM *pNew = new LISTITEM(item);
00413 pNew->m_Prev = pPrev;
00414 pNew->m_Next = pPrev->m_Next;
00415 pPrev->m_Next->m_Prev = pNew;
00416 pPrev->m_Next = pNew;
00417 ++m_NumItems;
00418 return (pNew->m_Item);
00419 }
00420
00423 _LIT& InsertBefore (
00424 ITERATOR it,
00425 const _LIT& item
00426 ) {
00427 LISTITEM *pNext = it.GetNode();
00428 LISTITEM *pNew = new LISTITEM(item);
00429 pNew->m_Next = pNext;
00430 pNew->m_Prev = pNext->m_Prev;
00431 pNext->m_Prev->m_Next = pNew;
00432 pNext->m_Prev = pNew;
00433 ++m_NumItems;
00434 return (pNew->m_Item);
00435 }
00436
00438 bool IsEmpty (
00439 ) const { return (m_NumItems == 0); }
00440
00442 bool IsEqual (
00443 const MILIST<_LIT>& rhs
00444 ) const {
00445 if (m_NumItems != rhs.m_NumItems) return (false);
00446 for (CONST_ITERATOR lit = Begin(), rit = rhs.Begin(); (lit != End()); ++lit, ++rit) {
00447 if (*lit != *rit) return (false);
00448 }
00449 return (true);
00450 }
00451
00453 void Lower (
00454 ITERATOR it
00455 ) {
00456 if (it == Begin()) return;
00457 ITERATOR lower = it;
00458 --lower;
00459 RemoveItem(it);
00460 InsertItem(it, lower);
00461 }
00462
00464 void Lower (
00465 int pos
00466 ) {
00467 ITERATOR it;
00468 for (it = Begin(); (it != End() && pos > 0); --pos, ++it)
00469 ;
00470 if (it != End()) Lower(it);
00471 }
00472
00474 void Merge (
00475 MILIST<_LIT>& other
00476 ) {
00477 if (other.IsEmpty()) return;
00478 if (IsEmpty()) {
00479 LISTITEM *temp = m_Head;
00480 m_Head = other.m_Head;
00481 other.m_Head = temp;
00482 m_NumItems = other.m_NumItems;
00483 other.m_NumItems = 0;
00484 }
00485 else {
00486 other.m_Head->m_Prev->m_Next = m_Head;
00487 other.m_Head->m_Next->m_Prev = m_Head->m_Prev;
00488 m_Head->m_Prev->m_Next = other.m_Head->m_Next;
00489 m_Head->m_Prev = other.m_Head->m_Prev;
00490 m_NumItems += other.m_NumItems;
00491 other.m_Head->m_Prev = other.m_Head->m_Next = other.m_Head;
00492 other.m_NumItems = 0;
00493 }
00494 return;
00495 }
00496
00498 void MoveToBack (
00499 ITERATOR it
00500 ) {
00501 if (it == --End()) return;
00502 RemoveItem(it);
00503 InsertItem(it, End());
00504 }
00505
00507 void MoveToFront (
00508 ITERATOR it
00509 ) {
00510 if (it == Begin()) return;
00511 RemoveItem(it);
00512 InsertItem(it, Begin());
00513 }
00514
00517 _LIT& PushFront (
00518 const _LIT& item
00519 ) { return (Insert(Begin(), item)); }
00520
00522 void PopFront (
00523 ) { Remove(Begin()); }
00524
00527 _LIT& PushBack (
00528 const _LIT& item
00529 ) { return (Insert(End(), item)); }
00530
00532 void PopBack (
00533 ) { Remove(--End()); }
00534
00536 void Raise (
00537 ITERATOR it
00538 ) {
00539 if (it == --End()) return;
00540 ITERATOR upper = it;
00541 ++upper;
00542 RemoveItem(it);
00543 InsertItem(it, ++upper);
00544 }
00545
00547 void Raise (
00548 int pos
00549 ) {
00550 ITERATOR it;
00551 for (it = Begin(); (it != End() && pos > 0); --pos, ++it)
00552 ;
00553 if (it != End()) Raise(it);
00554 }
00555
00558 void Remove (
00559 ITERATOR it
00560 ) {
00561 RemoveItem(it);
00562 delete it.GetNode();
00563 }
00564
00566 void Remove (
00567 ITERATOR start,
00568 ITERATOR end
00569 ) {
00570 for (ITERATOR it = start; (it != end); ) {
00571 Remove(it++);
00572 }
00573 }
00574
00576 void RemoveDuplicates (
00577 ) {
00578 if (m_NumItems < 2) return;
00579 for (ITERATOR check = Begin(); (check != End()); ++check) {
00580 ITERATOR it = check;
00581 for (++it; (it != End()); ++it) {
00582 if (*check == *it) {
00583 ITERATOR prev = it;
00584 --prev;
00585 Remove(it);
00586 it = prev;
00587 }
00588 }
00589 }
00590 return;
00591 }
00592
00594 void RemoveMatching (
00595 const _LIT& item
00596 ) {
00597 for (ITERATOR it = Begin(); (it != End()); ) {
00598 if (*it == item) {
00599 Remove(it++);
00600 }
00601 else {
00602 ++it;
00603 }
00604 }
00605 return;
00606 }
00607
00609 void RemovePos (
00610 int pos
00611 ) {
00612 ITERATOR it;
00613 for (it = Begin(); (it != End() && pos > 0); --pos, ++it)
00614 ;
00615 if (it != End()) Remove(it);
00616 }
00617
00619 void Reverse (
00620 ) {
00621 LISTITEM *pItem = m_Head;
00622 do {
00623 LISTITEM *pNext = pItem->m_Next;
00624 pItem->m_Next = pItem->m_Prev;
00625 pItem->m_Prev = pNext;
00626 pItem = pNext;
00627 } while (pItem != m_Head);
00628 return;
00629 }
00630
00632 ITERATOR ReverseBegin (
00633 ) { return (ITERATOR(m_Head->m_Prev)); }
00634
00636 CONST_ITERATOR ReverseBegin (
00637 ) const { return (CONST_ITERATOR(m_Head->m_Prev)); }
00638
00640 ITERATOR ReverseEnd (
00641 ) { return (ITERATOR(m_Head)); }
00642
00644 CONST_ITERATOR ReverseEnd (
00645 ) const { return (CONST_ITERATOR(m_Head)); }
00646
00648 void Sort (
00649 ) { SortItems(); }
00650
00652 template<class _Pr1>
00653 void Sort (
00654 _Pr1 _Pr
00655 ) {
00656 if (m_NumItems < 2) return;
00657 MILIST<_LIT> NewList;
00658 ITERATOR *ItArray = new ITERATOR[m_NumItems+1];
00659 ItArray[0] = NewList.End();
00660
00661 while (m_NumItems > 0) {
00662 ITERATOR item = Begin();
00663 RemoveItem(item);
00664
00665 INT32 index = 0;
00666 if (NewList.m_NumItems) {
00667 INT32 Left = 0, Right = NewList.m_NumItems-1;
00668 do {
00669 index = (Left+Right) / 2;
00670 if (_Pr(*item, *ItArray[index])) {
00671 Right = index - 1;
00672 }
00673 else {
00674 Left = ++index;
00675 }
00676 } while (Left <= Right);
00677 }
00678
00679 ITERATOR place = ItArray[index];
00680 for (int i = NewList.m_NumItems+1; (i > index); --i) ItArray[i] = ItArray[i-1];
00681 ItArray[index] = item;
00682 NewList.InsertItem(item, place);
00683 }
00684
00685 delete [] ItArray;
00686 LISTITEM *temp = m_Head;
00687 m_Head = NewList.m_Head;
00688 NewList.m_Head = temp;
00689 m_NumItems = NewList.m_NumItems;
00690 return;
00691 }
00692
00694 void Sort (
00695 bool (*PredFunc)(const _LIT& lhs, const _LIT& rhs)
00696 ) { SortItems(PredFunc); }
00697
00698 private:
00699 #ifndef GENERATING_DOXYGEN_OUTPUT
00700
00701 void InsertItem (
00702 ITERATOR it,
00703 ITERATOR place
00704 ) {
00705 LISTITEM *q = it.GetNode();
00706 LISTITEM *after = place.GetNode();
00707
00708 q->m_Next = after;
00709 q->m_Prev = after->m_Prev;
00710 after->m_Prev->m_Next = q;
00711 after->m_Prev = q;
00712 m_NumItems ++;
00713 return;
00714 }
00715
00716 void RemoveItem (
00717 ITERATOR it
00718 ) {
00719 LISTITEM *q = it.GetNode();
00720 q->m_Next->m_Prev = q->m_Prev;
00721 q->m_Prev->m_Next = q->m_Next;
00722 m_NumItems --;
00723 return;
00724 }
00725
00726 void SortItems (
00727 ) {
00728 if (m_NumItems < 2) return;
00729 MILIST<_LIT> NewList;
00730 ITERATOR *ItArray = new ITERATOR[m_NumItems+1];
00731 ItArray[0] = NewList.End();
00732
00733 while (m_NumItems > 0) {
00734 ITERATOR item = Begin();
00735 RemoveItem(item);
00736
00737 INT32 index = 0;
00738 if (NewList.m_NumItems) {
00739 INT32 Left = 0, Right = NewList.m_NumItems-1;
00740 do {
00741 index = (Left+Right) / 2;
00742 if (*item < *ItArray[index]) {
00743 Right = index - 1;
00744 }
00745 else {
00746 Left = ++index;
00747 }
00748 } while (Left <= Right);
00749 }
00750
00751 ITERATOR place = ItArray[index];
00752 for (int i = NewList.m_NumItems+1; (i > index); --i) ItArray[i] = ItArray[i-1];
00753 ItArray[index] = item;
00754 NewList.InsertItem(item, place);
00755 }
00756
00757 delete [] ItArray;
00758 LISTITEM *temp = m_Head;
00759 m_Head = NewList.m_Head;
00760 NewList.m_Head = temp;
00761 m_NumItems = NewList.m_NumItems;
00762 return;
00763 }
00764
00765 void SortItems (
00766 bool (*PredFunc)(const _LIT& lhs, const _LIT& rhs)
00767 ) {
00768 if (m_NumItems < 2) return;
00769 MILIST<_LIT> NewList;
00770 ITERATOR *ItArray = new ITERATOR[m_NumItems+1];
00771 ItArray[0] = NewList.End();
00772
00773 while (m_NumItems > 0) {
00774 ITERATOR item = Begin();
00775 RemoveItem(item);
00776
00777 INT32 index = 0;
00778 if (NewList.m_NumItems) {
00779 INT32 Left = 0, Right = NewList.m_NumItems-1;
00780 do {
00781 index = (Left+Right) / 2;
00782 if (PredFunc(*item, *ItArray[index])) {
00783 Right = index - 1;
00784 }
00785 else {
00786 Left = ++index;
00787 }
00788 } while (Left <= Right);
00789 }
00790
00791 ITERATOR place = ItArray[index];
00792 for (int i = NewList.m_NumItems + 1; (i > index); --i) ItArray[i] = ItArray[i-1];
00793 ItArray[index] = item;
00794 NewList.InsertItem(item, place);
00795 }
00796
00797 delete [] ItArray;
00798 LISTITEM *temp = m_Head;
00799 m_Head = NewList.m_Head;
00800 NewList.m_Head = temp;
00801 m_NumItems = NewList.m_NumItems;
00802 return;
00803 }
00804
00805 LISTITEM *m_Head;
00806 INT32 m_NumItems;
00807 #endif // GENERATING_DOXYGEN_OUTPUT
00808 };
00809
00810 #endif // INC_MI32_MILIST_H