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