00001
00048 #ifndef INC_MI32_OBSLIST_H
00049 #define INC_MI32_OBSLIST_H
00050
00051 #ifndef INC_MI32_OBSERVER_H
00052 #include <mi32/observer.h>
00053 #endif
00054
00055
00056
00065 template <typename _LIT> class OBSERVABLE_LIST {
00066
00067 private:
00068 #ifndef GENERATING_DOXYGEN_OUTPUT
00069
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 void Swap (
00080 LISTITEM& other
00081 ) {
00082 UINT8 buffer[sizeof(LISTITEM)];
00083 memcpy(buffer, this, sizeof(LISTITEM));
00084 memcpy(this, &other, sizeof(LISTITEM));
00085 memcpy(&other, buffer, sizeof(LISTITEM));
00086 return;
00087 }
00088 };
00089
00090 #endif
00091
00092 public:
00093
00094 class OBSERVER;
00095 friend class OBSERVER;
00096
00098 class OBSERVER : public OBSERVER_BASE {
00099 public:
00100
00102 OBSERVER (
00103 OBSERVABLE_LIST<_LIT>& list
00104 ): OBSERVER_BASE(list.m_ObserverMgr) { }
00105
00107 virtual void OnChanged (
00108 const _LIT&
00109 ) { }
00110
00112 virtual void OnChangeOrderBegin (
00113 const _LIT&
00114 ) { }
00115
00117 virtual void OnChangeOrderEnd (
00118 const _LIT&
00119 ) { }
00120
00122 virtual void OnClear (
00123 ) { }
00124
00126 virtual void OnInsert (
00127 const _LIT&
00128 ) { }
00129
00131 virtual void OnRemove (
00132 const _LIT&
00133 ) { }
00134
00136 virtual void OnSort (
00137 ) { }
00138
00139 };
00140
00141 class ITERATOR;
00142 class CONST_ITERATOR;
00143 friend class ITERATOR;
00144 friend class CONST_ITERATOR;
00145
00147 class CONST_ITERATOR {
00148 public:
00149
00150 CONST_ITERATOR (
00151 ) {}
00152
00153 CONST_ITERATOR (
00154 LISTITEM *item
00155 ) : m_Ptr(item) {}
00156
00157 CONST_ITERATOR (
00158 const ITERATOR& item
00159 ) : m_Ptr(item.m_Ptr) {}
00160
00161 const _LIT& operator* (
00162 ) const {
00163 return (m_Ptr->m_Item);
00164 }
00165
00166 const _LIT* operator-> (
00167 ) const {
00168 return (&**this);
00169 }
00170
00172 CONST_ITERATOR& operator++ (
00173 ) {
00174 m_Ptr = m_Ptr->m_Next;
00175 return (*this);
00176 }
00177
00179 CONST_ITERATOR operator++(int
00180 ) {
00181 CONST_ITERATOR temp = *this;
00182 ++*this;
00183 return (temp);
00184 }
00185
00187 CONST_ITERATOR& operator-- (
00188 ) {
00189 m_Ptr = m_Ptr->m_Prev;
00190 return (*this);
00191 }
00192
00194 CONST_ITERATOR operator--(int
00195 ) {
00196 CONST_ITERATOR temp = *this;
00197 --*this;
00198 return (temp);
00199 }
00200
00201 bool operator== (
00202 const CONST_ITERATOR& rhs
00203 ) const {
00204 return (m_Ptr == rhs.m_Ptr);
00205 }
00206
00207 bool operator!= (
00208 const CONST_ITERATOR& rhs
00209 ) const {
00210 return (!(*this == rhs));
00211 }
00212
00213 LISTITEM *GetNode (
00214 ) const {
00215 return (m_Ptr);
00216 }
00217
00218 protected:
00219
00220 LISTITEM *m_Ptr;
00221 };
00222
00224 class ITERATOR : public CONST_ITERATOR {
00225 public:
00226
00227 ITERATOR (
00228 ) {}
00229
00230 ITERATOR (
00231 LISTITEM *item
00232 ) : CONST_ITERATOR(item) {}
00233
00234 _LIT& operator* (
00235 ) const {
00236 return (CONST_ITERATOR::m_Ptr->m_Item);
00237 }
00238
00239 _LIT* operator-> (
00240 ) const {
00241 return (&**this);
00242 }
00243
00245 ITERATOR& operator++ (
00246 ) {
00247 CONST_ITERATOR::m_Ptr = CONST_ITERATOR::m_Ptr->m_Next;
00248 return (*this);
00249 }
00250
00252 ITERATOR operator++(int
00253 ) {
00254 ITERATOR temp = *this;
00255 ++*this;
00256 return (temp);
00257 }
00258
00260 ITERATOR& operator-- (
00261 ) {
00262 CONST_ITERATOR::m_Ptr = CONST_ITERATOR::m_Ptr->m_Prev;
00263 return (*this);
00264 }
00265
00267 ITERATOR operator--(int
00268 ) {
00269 ITERATOR temp = *this;
00270 --*this;
00271 return (temp);
00272 }
00273
00275 bool operator== (
00276 const ITERATOR& rhs
00277 ) const {
00278 return (CONST_ITERATOR::m_Ptr == rhs.m_Ptr);
00279 }
00280
00282 bool operator!= (
00283 const ITERATOR& rhs
00284 ) const {
00285 return (!(*this == rhs));
00286 }
00287
00288 };
00289
00290
00292 OBSERVABLE_LIST (
00293 ) : m_Head(0), m_NumItems(0) {
00294 MmAllocCExc((void **)&m_Head, sizeof(LISTITEM));
00295 m_Head->m_Next = m_Head->m_Prev = m_Head;
00296 }
00297
00299 OBSERVABLE_LIST (
00300 const OBSERVABLE_LIST<_LIT>& rhs
00301 ) : m_Head(0), m_NumItems(0) {
00302 MmAllocCExc((void **)&m_Head, sizeof(LISTITEM));
00303 m_Head->m_Next = m_Head->m_Prev = m_Head;
00304 for (CONST_ITERATOR it = rhs.Begin(); (it != rhs.End()); ++it) {
00305 Insert(End(), *it);
00306 }
00307 }
00308
00310 ~OBSERVABLE_LIST (
00311 ) {
00312 Clear();
00313 MmFree(m_Head);
00314 }
00315
00317 OBSERVABLE_LIST<_LIT>& operator= (
00318 const OBSERVABLE_LIST<_LIT>& rhs
00319 ) {
00320 if (this != &rhs) {
00321 Clear();
00322 for (CONST_ITERATOR it = rhs.Begin(); (it != rhs.End()); ++it) {
00323 Insert(End(), *it);
00324 }
00325 }
00326 return (*this);
00327 }
00328
00330 ITERATOR Begin (
00331 ) { return (ITERATOR(m_Head->m_Next)); }
00332
00334 CONST_ITERATOR Begin (
00335 ) const { return (CONST_ITERATOR(m_Head->m_Next)); }
00336
00338 void Clear (
00339 ) {
00340 for (ITERATOR it = Begin(); (it != End()); ) {
00341 Remove(it++,false);
00342 }
00343 m_ObserverMgr.NotifyClear();
00344 return;
00345 }
00346
00348 ITERATOR End (
00349 ) { return (ITERATOR(m_Head)); }
00350
00352 CONST_ITERATOR End (
00353 ) const { return (CONST_ITERATOR(m_Head)); }
00354
00356 const _LIT& GetBack (
00357 ) const { return (*(--End())); }
00358
00360 _LIT& GetBack (
00361 ) { return (*(--End())); }
00362
00364 const _LIT& GetFront (
00365 ) const { return (*Begin()); }
00366
00368 _LIT& GetFront (
00369 ) { return (*Begin()); }
00370
00372 INT32 GetNumItems (
00373 ) const { return (m_NumItems); }
00374
00377 _LIT& Insert (
00378 ITERATOR p,
00379 const _LIT& item
00380 ) {
00381 LISTITEM *obj = p.GetNode();
00382 LISTITEM *newitem = new LISTITEM(item);
00383 newitem->m_Next = obj;
00384 newitem->m_Prev = obj->m_Prev;
00385 obj->m_Prev->m_Next = newitem;
00386 obj->m_Prev = newitem;
00387 m_NumItems ++;
00388 m_ObserverMgr.NotifyInsert(newitem->m_Item);
00389 return (newitem->m_Item);
00390 }
00391
00393 bool IsEmpty (
00394 ) const { return (m_NumItems == 0); }
00395
00397 void Lower (
00398 ITERATOR it
00399 ) {
00400 if (it == Begin()) return;
00401 m_ObserverMgr.NotifyChangeOrderBegin(*it);
00402 ITERATOR lower = it;
00403 --lower;
00404 RemoveItem(it);
00405 InsertItem(it, lower);
00406 m_ObserverMgr.NotifyChangeOrderEnd(*it);
00407 return;
00408 }
00409
00411 void MoveToBack (
00412 ITERATOR it
00413 ) {
00414 if (it == --End()) return;
00415 m_ObserverMgr.NotifyChangeOrderBegin(*it);
00416 RemoveItem(it);
00417 InsertItem(it, End());
00418 m_ObserverMgr.NotifyChangeOrderEnd(*it);
00419 return;
00420 }
00421
00423 void MoveToFront (
00424 ITERATOR it
00425 ) {
00426 if (it == Begin()) return;
00427 m_ObserverMgr.NotifyChangeOrderBegin(*it);
00428 RemoveItem(it);
00429 InsertItem(it, Begin());
00430 m_ObserverMgr.NotifyChangeOrderEnd(*it);
00431 return;
00432 }
00433
00436 void NotifyChanged (
00437 const _LIT& item
00438 ) { m_ObserverMgr.NotifyChanged(item); }
00439
00442 _LIT& PushFront (
00443 const _LIT& item
00444 ) { return (Insert(Begin(), item)); }
00445
00447 void PopFront (
00448 ) { Remove(Begin()); }
00449
00452 _LIT& PushBack (
00453 const _LIT& item
00454 ) { return (Insert(End(), item)); }
00455
00457 void PopBack (
00458 ) { Remove(--End()); }
00459
00461 void Raise (
00462 ITERATOR it
00463 ) {
00464 if (it == --End()) return;
00465 m_ObserverMgr.NotifyChangeOrderBegin(*it);
00466 ITERATOR upper = it;
00467 ++upper;
00468 RemoveItem(it);
00469 InsertItem(it, ++upper);
00470 m_ObserverMgr.NotifyChangeOrderEnd(*it);
00471 return;
00472 }
00473
00475 void Remove (
00476 const _LIT& item
00477 ) {
00478 for (ITERATOR it = Begin(); (it != End()); ) {
00479 if ((&*it) == &item) {
00480 Remove(it++);
00481 }
00482 else {
00483 ++it;
00484 }
00485 }
00486 return;
00487 }
00488
00491 void Remove (
00492 ITERATOR it,
00493 bool notify = true
00494 ) {
00495 RemoveItem(it);
00496 if (notify) m_ObserverMgr.NotifyRemove(*it);
00497 delete it.GetNode();
00498 return;
00499 }
00500
00502 void Remove (
00503 ITERATOR start,
00504 ITERATOR end
00505 ) {
00506 for (ITERATOR it = start; (it != end); ) {
00507 Remove(it++);
00508 }
00509 return;
00510 }
00511
00513 void RemovePos (
00514 int pos
00515 ) {
00516 ITERATOR it;
00517 for (it = Begin(); (it != End() && pos > 0); --pos)
00518 ;
00519 if (it != End()) Remove(it);
00520 return;
00521 }
00522
00524 void Sort (
00525 ) {
00526 SortItems();
00527 m_ObserverMgr.NotifySort();
00528 return;
00529 }
00530
00532 void Sort (
00533 bool (*PredFunc)(const _LIT& lhs, const _LIT& rhs)
00534 ) {
00535 SortItems(PredFunc);
00536 m_ObserverMgr.NotifySort();
00537 return;
00538 }
00539
00541 void RemoveDuplicates (
00542 ) {
00543 if (m_NumItems < 2) return;
00544 for (ITERATOR check = Begin(); (check != End()); ++check) {
00545 for (ITERATOR it = ++check; (it != End()); ++it) {
00546 if (*check == *it) {
00547 ITERATOR prev = --it;
00548 Remove(it);
00549 it = prev;
00550 }
00551 }
00552 }
00553 return;
00554 }
00555
00556
00557 private:
00558 #ifndef GENERATING_DOXYGEN_OUTPUT
00559
00560 class OBSERVERMGR : public SUBJECT<OBSERVER> {
00561 public:
00562 typedef SUBJECT<OBSERVER> BASECLASS;
00563 typedef typename BASECLASS::ITERATOR ITERATOR;
00564
00565 void NotifyChanged (
00566 const _LIT& item
00567 ) {
00568 for (ITERATOR it = BASECLASS::ObserverBegin(); (it != BASECLASS::ObserverEnd()); ++it) {
00569 (*it)->OnChanged(item);
00570 }
00571 }
00572
00573 void NotifyChangeOrderBegin (
00574 const _LIT& item
00575 ) {
00576 for (ITERATOR it = BASECLASS::ObserverBegin(); (it != BASECLASS::ObserverEnd()); ++it) {
00577 (*it)->OnChangeOrderBegin(item);
00578 }
00579 }
00580
00581 void NotifyChangeOrderEnd (
00582 const _LIT& item
00583 ) {
00584 for (ITERATOR it = BASECLASS::ObserverBegin(); (it != BASECLASS::ObserverEnd()); ++it) {
00585 (*it)->OnChangeOrderEnd(item);
00586 }
00587 }
00588
00589 void NotifyClear (
00590 ) {
00591 for (ITERATOR it = BASECLASS::ObserverBegin(); (it != BASECLASS::ObserverEnd()); ++it) {
00592 (*it)->OnClear();
00593 }
00594 }
00595
00596 void NotifyInsert (
00597 const _LIT& item
00598 ) {
00599 for (ITERATOR it = BASECLASS::ObserverBegin(); (it != BASECLASS::ObserverEnd()); ++it) {
00600 (*it)->OnInsert(item);
00601 }
00602 }
00603
00604 void NotifyRemove (
00605 const _LIT& item
00606 ) {
00607 for (ITERATOR it = BASECLASS::ObserverBegin(); (it != BASECLASS::ObserverEnd()); ++it) {
00608 (*it)->OnRemove(item);
00609 }
00610 }
00611
00612 void NotifySort (
00613 ) {
00614 for (ITERATOR it = BASECLASS::ObserverBegin(); (it != BASECLASS::ObserverEnd()); ++it) {
00615 (*it)->OnSort();
00616 }
00617 }
00618 };
00619
00620 void InsertItem (
00621 ITERATOR it,
00622 ITERATOR place
00623 ) {
00624 LISTITEM *q = it.GetNode();
00625 LISTITEM *after = place.GetNode();
00626
00627 q->m_Next = after;
00628 q->m_Prev = after->m_Prev;
00629 after->m_Prev->m_Next = q;
00630 after->m_Prev = q;
00631 m_NumItems ++;
00632 return;
00633 }
00634
00635 void RemoveItem (
00636 ITERATOR it
00637 ) {
00638 LISTITEM *q = it.GetNode();
00639 q->m_Next->m_Prev = q->m_Prev;
00640 q->m_Prev->m_Next = q->m_Next;
00641 m_NumItems --;
00642 return;
00643 }
00644
00645 void SortItems (
00646 ) {
00647 if (m_NumItems < 2) return;
00648 OBSERVABLE_LIST<_LIT> NewList;
00649 ITERATOR *ItArray = new ITERATOR[m_NumItems+1];
00650 ItArray[0] = NewList.End();
00651
00652 while (m_NumItems > 0) {
00653 ITERATOR item = Begin();
00654 RemoveItem(item);
00655
00656 INT32 index = 0;
00657 if (NewList.m_NumItems) {
00658 INT32 Left = 0, Right = NewList.m_NumItems-1;
00659 do {
00660 index = (Left+Right) / 2;
00661 if (*item < *ItArray[index]) {
00662 Right = index - 1;
00663 }
00664 else {
00665 Left = ++index;
00666 }
00667 } while (Left <= Right);
00668 }
00669
00670 ITERATOR place = ItArray[index];
00671 for (int i = NewList.m_NumItems+1; (i > index); --i) ItArray[i] = ItArray[i-1];
00672 ItArray[index] = item;
00673 NewList.InsertItem(item, place);
00674 }
00675
00676 delete [] ItArray;
00677 LISTITEM *temp = m_Head;
00678 m_Head = NewList.m_Head;
00679 NewList.m_Head = temp;
00680 m_NumItems = NewList.m_NumItems;
00681 return;
00682 }
00683
00684 void SortItems (
00685 bool (*PredFunc)(const _LIT& lhs, const _LIT& rhs)
00686 ) {
00687 if (m_NumItems < 2) return;
00688 OBSERVABLE_LIST<_LIT> NewList;
00689 ITERATOR *ItArray = new ITERATOR[m_NumItems+1];
00690 ItArray[0] = NewList.End();
00691
00692 while (m_NumItems > 0) {
00693 ITERATOR item = Begin();
00694 RemoveItem(item);
00695
00696 INT32 index = 0;
00697 if (NewList.m_NumItems) {
00698 INT32 Left = 0, Right = NewList.m_NumItems-1;
00699 do {
00700 index = (Left+Right) / 2;
00701 if (PredFunc(*item, *ItArray[index])) {
00702 Right = index - 1;
00703 }
00704 else {
00705 Left = ++index;
00706 }
00707 } while (Left <= Right);
00708 }
00709
00710 ITERATOR place = ItArray[index];
00711 for (int i = NewList.m_NumItems + 1; (i > index); --i) ItArray[i] = ItArray[i-1];
00712 ItArray[index] = item;
00713 NewList.InsertItem(item, place);
00714 }
00715
00716 delete [] ItArray;
00717 LISTITEM *temp = m_Head;
00718 m_Head = NewList.m_Head;
00719 NewList.m_Head = temp;
00720 m_NumItems = NewList.m_NumItems;
00721 return;
00722 }
00723
00724 LISTITEM *m_Head;
00725 INT32 m_NumItems;
00726 OBSERVERMGR m_ObserverMgr;
00727 #endif // GENERATING_DOXYGEN_OUTPUT
00728
00729 };
00730
00731 #endif // INC_MI32_OBSLIST_H