Guiliani  Version 2.5 revision 7293 (documentation build 13)
eC_TList_doubleLinked.h
1/*
2* Copyright (C) TES Electronic Solutions GmbH,
3* All Rights Reserved.
4* Contact: info@guiliani.de
5*
6* This file is part of the Guiliani HMI framework
7* for the development of graphical user interfaces on embedded systems.
8*/
9
10#ifndef EC_TL__H_
11#define EC_TL__H_
12
13//Iterator implementation
14#include "eC_TList_Iterators.h"
15#include <cassert>
16
17// memory-mapping
18#include "eC_CustomMemoryMapping.h"
19
25template <class T>
27{
28public:
29 ListNode() : m_tValue()
30 {
31 m_pkNext = NULL;
32 m_pkPrevious = NULL;
33 }
34
35 //-------------------------------------
36 ~ListNode() {}
37
38 //-------------------------------------
39
42
45
48};
49
50
51//----------------------------------------------------------------------------
52
54
65template <class T>
67{
68 typedef ListNode<T> Node;
69
70 friend class eC_TSafeIterator<T>;
71
72public:
75
78
80 typedef bool(*compare)(T lhs, T rhs);
81
84
90
93
98 eC_UInt GetQuantity() const;
99
104 eC_Bool IsEmpty() const;
105
110 void Add(const T &tValue);
111
116 void AddAtEnd(const T &tValue);
117
123 void AddBefore(const T &tValue2Add, Iterator & kIter);
124
130 void AddAfter(const T &tValue2Add, Iterator & kIter);
131
138 eC_Bool AddUnique(const T &tValue);
139
146 eC_Bool AddUniqueAtEnd(const T &tValue);
147
154 void AddSorted(const T &tValue);
155
163 eC_Bool AddUniqueSorted(const T &tValue);
164
173 eC_Bool Remove(SafeIterator & kIter);
174
182 eC_Bool Remove(const T &tValue);
183
189 eC_Bool RemoveFront(T& rtValue);
190
196 eC_Bool RemoveEnd(T& rtValue);
197
201 void RemoveAll();
202
207 void RemoveAll(const T &tValue);
208
214 eC_Bool MoveBefore(Iterator & kIter1, Iterator & kIter2);
215
223 eC_Bool MoveBefore(Iterator &kStartIter, Iterator &kEndIter, Iterator &kIter);
224
230 eC_Bool MoveAfter(Iterator & kIter1, Iterator & kIter2);
231
239 eC_Bool MoveAfter(Iterator &kStartIter, Iterator &kEndIter, Iterator &kIter);
240
246 eC_Bool Swap(Iterator & kIter1, Iterator & kIter2);
247
252
260 eC_Bool Contains(const T &tValue) const;
261
266 eC_Bool Empty() const;
267
279 void Sort(eC_Bool bIsQuicksort = true, compare comp = NULL);
280
287 eC_Bool GetFirst(T& rtValue) const;
288
295 eC_Bool GetNext(T& rtValue) const;
296
306 {
307 eC_TIterator<T> kIter(m_pkFront);
308 return kIter;
309 }
310
316 {
318 kIter.m_pNode = m_pkFront;
319 if (m_pkFront != NULL)
320 {
321 kIter.m_pSaveNextNode = m_pkFront->m_pkNext;
322 kIter.m_pSavePrevNode = m_pkFront->m_pkPrevious;
323 }
324 kIter.SetList(this);
325 return kIter;
326 }
327
337 {
338 eC_TIterator<T> kIter(m_pkLast);
339 return kIter;
340 }
341
347 {
349 kIter.m_pNode = m_pkLast;
350 if (m_pkLast != NULL)
351 {
352 kIter.m_pSaveNextNode = m_pkLast->m_pkNext;
353 kIter.m_pSavePrevNode = m_pkLast->m_pkPrevious;
354 }
355 kIter.SetList(this);
356 return kIter;
357 }
358
372 eC_TIterator<T> GetFind(const T &tValue) const
373 {
374 eC_TIterator<T> kIter;
375 Node* pkSearch = m_pkFront;
376
377 while (pkSearch)
378 {
379 if (pkSearch->m_tValue == tValue)
380 {
381 kIter.m_pNode = pkSearch;
382 return kIter;
383 }
384
385 pkSearch = pkSearch->m_pkNext;
386 }
387
388 kIter.m_pNode = NULL;
389 return kIter;
390 }
391
403 {
405 Node* pkSearch = m_pkFront;
406
407 while (pkSearch)
408 {
409 if (pkSearch->m_tValue == tValue)
410 {
411 kIter.m_pNode = pkSearch;
412 kIter.m_pSaveNextNode = pkSearch->m_pkNext;
413 kIter.m_pSavePrevNode = pkSearch->m_pkPrevious;
414 kIter.SetList(this);
415 return kIter;
416 }
417
418 pkSearch = pkSearch->m_pkNext;
419 }
420
421 kIter.m_pNode = NULL;
422 kIter.SetList(this);
423 return kIter;
424 }
425
432 eC_TIterator<T> GetAt(eC_UInt uiPos) const
433 {
434 Node* pkRet = m_pkFront;
435
436 while (pkRet != NULL && uiPos > 0)
437 {
438 pkRet = pkRet->m_pkNext;
439 --uiPos;
440 }
441
442 return eC_TIterator<T>(pkRet);
443 }
444
453 {
455 if ((m_pkFront != NULL) && (uiPos < GetQuantity()))
456 {
457 Node* pkRet = m_pkFront;
458
459 while (pkRet != NULL && uiPos > 0)
460 {
461 pkRet = pkRet->m_pkNext;
462 --uiPos;
463 }
464
465 kIter.m_pNode = pkRet;
466 if (pkRet != NULL)
467 {
468 kIter.m_pSaveNextNode = pkRet->m_pkNext;
469 kIter.m_pSavePrevNode = pkRet->m_pkPrevious;
470 }
471 }
472 kIter.SetList(this);
473 return kIter;
474 }
475
483 {
484 // Avoid copying ourselves
485 if (&copy == this) return *this;
486
487 //Delete old stuff;
488 RemoveAll();
489
490 Iterator iter = copy.GetBegin();
491
492 while (iter.IsInsideList())
493 {
494 AddAtEnd(*iter);
495 ++iter;
496 }
497
498 return *this;
499 }
500
501 //-------------------------------------
502
503private:
504 Node * m_pkFront;
505 Node* m_pkLast;
506
507 mutable Node* m_pkIterator;
508
509 eC_UInt m_uiQuantity;
510
511 eC_TSafeIterator<T>** m_ppIterRegister; //pointer to array where safe iterators are registerd
512 eC_UInt m_uiIterRegisterCnt;
513 eC_UInt m_uiIterRegisterSize;
514
515 eC_Bool Remove(Node* tNode);
516
517 void SortArraysUsingQuickSort(Node** ppkArray, eC_Int iFirst, eC_Int iLast, compare comp = NULL);
518
519 void SortArraysUsingMergeSort(Node** ppkMerged, eC_UInt uiQuantity, compare comp = NULL);
520
521 void RegisterIterator(eC_TSafeIterator<T>*);
522 void UnregisterIterator(eC_TSafeIterator<T>*);
523 void UpdateIterators(Node*, Update_t) const;
524};
525
526//----------------------------------------------------------------------------
527
528// "(List)" in backets is required when passing a dereferenced pointer to
529// the list to the macro, e.g.:
530// CDevice::eC_TListDoubleLinked<CSomething*>* pSomethingList;
531// FOR_ALL_FORWARD(SomethingIter, *pSomethingList)
532#define FOR_ALL_FORWARD(Iterator,List) for ((Iterator) = (List).GetBegin(); \
533 (Iterator).IsInsideList(); ++(Iterator))
534
535#define FOR_ALL_BACKWARD(Iterator,List) for ((Iterator) = (List).GetEnd(); \
536 (Iterator).IsInsideList(); --(Iterator))
537
538#define FOR_ALL_FORWARD_SAFE(Iterator,List) for ((Iterator) = (List).GetBeginSafe(); \
539 (Iterator).IsValid() || (Iterator).IsNextValid(); ++(Iterator))
540
541#define FOR_ALL_BACKWARD_SAFE(Iterator,List) for ((Iterator) = (List).GetEndSafe(); \
542 (Iterator).IsValid() || (Iterator).IsPreviousValid(); --(Iterator))
543
544//----------------------------------------------------------------------------
545
546template <class T>
548 m_pkFront(NULL),
549 m_pkLast(NULL),
550 m_pkIterator(NULL),
551 m_uiQuantity(0),
552 m_ppIterRegister(NULL),
553 m_uiIterRegisterCnt(0),
554 m_uiIterRegisterSize(0)
555{
556}
557
558template<class T>
560 m_pkFront(NULL),
561 m_pkLast(NULL),
562 m_pkIterator(NULL),
563 m_uiQuantity(0),
564 m_ppIterRegister(NULL),
565 m_uiIterRegisterCnt(0),
566 m_uiIterRegisterSize(0)
567{
568 operator=(copy);
569}
570
571//----------------------------------------------------------------------------
572template <class T>
574{
575 RemoveAll();
576 // Unregister all safe iterators.
577 for (eC_UInt i = 0; i < m_uiIterRegisterCnt; i++)
578 {
579 (m_ppIterRegister[i])->SetList(NULL);
580 }
581
582 delete[] m_ppIterRegister;
583}
584
585//----------------------------------------------------------------------------
586template <class T>
588{
589 return m_uiQuantity;
590}
591
592//----------------------------------------------------------------------------
593template <class T>
595{
596 return m_uiQuantity == 0;
597}
598
599//----------------------------------------------------------------------------
600template <class T>
601eC_Bool eC_TListDoubleLinked<T>::GetFirst(T& rtValue) const
602{
603 if (m_pkFront)
604 {
605 rtValue = m_pkFront->m_tValue;
606 m_pkIterator = m_pkFront->m_pkNext;
607 return true;
608 }
609 else
610 {
611 m_pkIterator = 0;
612 return false;
613 }
614}
615
616//----------------------------------------------------------------------------
617template <class T>
618eC_Bool eC_TListDoubleLinked<T>::GetNext(T& rtValue) const
619{
620 if (m_pkIterator)
621 {
622 rtValue = m_pkIterator->m_tValue;
623 m_pkIterator = m_pkIterator->m_pkNext;
624 return true;
625 }
626 else
627 {
628 return false;
629 }
630}
631
632//----------------------------------------------------------------------------
633//adds an element tValue at front of list
634template <class T>
635void eC_TListDoubleLinked<T>::Add(const T &tValue)
636{
637 Node * pkNewNode = new Node();
638 pkNewNode->m_tValue = tValue;
639
640 // next of new element is formerly front element
641 // (front element could be NULL)
642 pkNewNode->m_pkNext = m_pkFront;
643
644
645 if (m_pkFront) //list is not empty
646 {
647 // previous of formerly front is new node
648 // last element will remain the same
649 m_pkFront->m_pkPrevious = pkNewNode;
650 }
651 else
652 {
653 // list was empty, so new element is first element and last element
654 m_pkLast = pkNewNode;
655 }
656
657 // new first element already has no previous when it was constructed
658 // new front is new node
659 m_pkFront = pkNewNode;
660
661 m_uiQuantity++;
662
663 // Update SafeIterators which are registered, which are pointing at formerly
664 // first element (they need to know new element)
665 UpdateIterators(pkNewNode, ADDED);
666}
667
668//----------------------------------------------------------------------------
669template <class T>
671{
672 Node * pkNode = new Node();
673 pkNode->m_tValue = tValue;
674 pkNode->m_pkPrevious = m_pkLast;
675
676 //list is not empty
677 if (m_pkLast)
678 {
679 //next of last node is new node
680 m_pkLast->m_pkNext = pkNode;
681 }
682 else
683 {
684 //list was empty, so new node is First and Last
685 m_pkFront = pkNode;
686 }
687
688 //last element has no next
689 pkNode->m_pkNext = 0;
690
691 m_pkLast = pkNode;
692 m_uiQuantity++;
693
694 // Update SafeIterators, if pointing at last Element (needs to know new Element)
695 UpdateIterators(pkNode, ADDED);
696}
697
698//----------------------------------------------------------------------------
699template <class T>
700void eC_TListDoubleLinked<T>::AddBefore(const T &tValue2Add, Iterator & kIter)
701{
702 Node * pNodeInList = kIter.GetNode();
703
704 // If kIter is illegal call Add()
705 if (NULL == pNodeInList)
706 return Add(tValue2Add);
707
708 Node* pkNode = new Node();
709 pkNode->m_tValue = tValue2Add;
710
711 Node* pkNodePre = pNodeInList->m_pkPrevious;
712 pkNode->m_pkNext = pNodeInList;
713
714 if (pkNodePre)
715 {
716 pkNode->m_pkPrevious = pkNodePre;
717 pkNodePre->m_pkNext = pkNode;
718 }
719 else
720 {
721 m_pkFront = pkNode;
722 pkNode->m_pkPrevious = 0;
723 }
724
725 pNodeInList->m_pkPrevious = pkNode;
726 m_uiQuantity++;
727
728 // Update SafeIterators, if pointing at last Element (needs to know new element)
729 UpdateIterators(pkNode, ADDED);
730}
731
732//----------------------------------------------------------------------------
733template <class T>
734void eC_TListDoubleLinked<T>::AddAfter(const T &tValue2Add, Iterator & kIter)
735{
736 Node * pNodeInList = kIter.GetNode();
737
738 // If kIter is illegal call call AddAtEnd()
739 if (NULL == pNodeInList)
740 return AddAtEnd(tValue2Add);
741
742 Node* pkNode = new Node();
743 pkNode->m_tValue = tValue2Add;
744
745 Node* pkNodeNext = pNodeInList->m_pkNext;
746 pkNode->m_pkPrevious = pNodeInList;
747
748 if (pkNodeNext)
749 {
750 pkNodeNext->m_pkPrevious = pkNode;
751 pkNode->m_pkNext = pkNodeNext;
752 }
753 else
754 {
755 m_pkLast = pkNode;
756 pkNode->m_pkNext = 0;
757 }
758
759 pNodeInList->m_pkNext = pkNode;
760 m_uiQuantity++;
761 // Update SafeIterators, if pointing at last Element (needs to know new element)
762 UpdateIterators(pkNode, ADDED);
763}
764
765//----------------------------------------------------------------------------
766template <class T>
768{
769 if (Contains(tValue))
770 {
771 return false;
772 }
773
774 Add(tValue);
775 return true;
776}
777
778//----------------------------------------------------------------------------
779template <class T>
781{
782 if (Contains(tValue))
783 {
784 return false;
785 }
786
787 AddAtEnd(tValue);
788 return true;
789}
790
791//----------------------------------------------------------------------------
792template <class T>
794{
795 if (Contains(tValue))
796 {
797 return false;
798 }
799
800 AddSorted(tValue);
801 return true;
802}
803
804//----------------------------------------------------------------------------
805template <class T>
807{
808 Node * pkSortIter = 0;
809
810 //not Empty, set Iterater at the end
811 if ((pkSortIter = m_pkLast) != 0)
812 {
813 //if tValue > Value of last element
814 if (tValue > pkSortIter->m_tValue)
815 {
816 AddAtEnd(tValue);
817 return;
818 }
819
820 //if not added at end
821 pkSortIter = m_pkFront;
822
823 //if tValue <= Value of first element
824 if (!(tValue > pkSortIter->m_tValue))
825 {
826 Add(tValue);
827 return;
828 }
829
830 //not added at front and not added at end
831 //search for right position
832 while (tValue > pkSortIter->m_tValue)
833 {
834 //Iterate trough list
835 pkSortIter = pkSortIter->m_pkNext;
836 }
837
838 //node behind new Node
839 Node* pkNextNode = pkSortIter;
840 //node in front of new Node
841 Node* pkPrevNode = pkNextNode->m_pkPrevious;
842
843 Node* pkNewNode = new Node();
844 pkNewNode->m_pkNext = pkNextNode;
845 pkNewNode->m_tValue = tValue;
846
847 if (pkPrevNode)
848 {
849 pkPrevNode->m_pkNext = pkNewNode;
850 }
851
852 pkNextNode->m_pkPrevious = pkNewNode;
853 pkNewNode->m_pkPrevious = pkPrevNode;
854 m_uiQuantity++;
855
856 // Update SafeIterators, if pointing at Previous or next Element (needs to know new Element)
857 UpdateIterators(pkNewNode, ADDED);
858 }
859 else
860 {
861 // list is empty -> add at front
862 Add(tValue);
863 }
864}
865
866//----------------------------------------------------------------------------
867template <class T>
869{
870 eC_Bool bResult = Remove(kIter.GetNode());
871
872 //after removing iterator it is invalid
873 kIter.m_pNode = NULL;
874 return bResult;
875}
876
877//----------------------------------------------------------------------------
878template <class T>
879eC_Bool eC_TListDoubleLinked<T>::Remove(const T &tValue)
880{
881 //finds node with specified value and passes it to Remove()
882 return Remove((GetFind(tValue)).m_pNode);
883}
884
885//----------------------------------------------------------------------------
886template <class T>
888{
889 // list is not empty and node is not 0
890 if (ptNode && m_pkFront)
891 {
892 Node * pkSave = NULL;
893
894 // special case: remove first element
895 if (m_pkFront == ptNode)
896 {
897 // save the node that we want to delete
898 pkSave = m_pkFront;
899 // update front
900 m_pkFront = m_pkFront->m_pkNext;
901
902 // there is another element in list
903 if (m_pkFront != NULL)
904 {
905 // new front has no previous element
906 m_pkFront->m_pkPrevious = NULL;
907 }
908 else
909 {
910 // last remaining element of the list is getting deleted
911 m_pkLast = NULL;
912 }
913
914 }
915 else if (m_pkLast == ptNode)
916
917 {
918 // special case: removing last element in list
919 // the list can still have several elements afterwards
920
921 // save formerly last element
922 pkSave = m_pkLast;
923 // new last element is the element before the formerly last
924 m_pkLast = m_pkLast->m_pkPrevious;
925
926 // there is another element in list
927 if (m_pkLast != NULL)
928 {
929 // next of new last element is NULL
930 m_pkLast->m_pkNext = NULL;
931 }
932 else
933 {
934 // last remaining element of the list is getting deleted
935 m_pkFront = NULL;
936 }
937
938 }
939 else
940 {
941 // case: not first and not last element
942 pkSave = ptNode;
943
944 ptNode->m_pkPrevious->m_pkNext = ptNode->m_pkNext;
945 ptNode->m_pkNext->m_pkPrevious = ptNode->m_pkPrevious;
946 }
947
948 m_uiQuantity--;
949 UpdateIterators(pkSave, REMOVED);
950
951 // deleting node after removing it from data structure of list
952 delete pkSave;
953 pkSave = NULL;
954
955 return true;
956 }
957
958 return false; // nothing removed
959}
960
961//----------------------------------------------------------------------------
962template <class T>
964{
965 if (m_pkFront)
966 {
967 // output parameter, only valid if function returns true
968 rtValue = m_pkFront->m_tValue;
969
970 Node* pkSave = m_pkFront;
971 m_pkFront = m_pkFront->m_pkNext;
972
973 if (m_pkFront)
974 {
975 m_pkFront->m_pkPrevious = NULL;
976 }
977 else
978 {
979 // front was last element
980 m_pkLast = NULL;
981 }
982
983 m_uiQuantity--;
984 UpdateIterators(pkSave, REMOVED);
985
986 delete pkSave;
987 pkSave = NULL;
988
989 return true;
990 }
991
992 return false;
993}
994
995//----------------------------------------------------------------------------
996template <class T>
998{
999 if (m_pkLast)
1000 {
1001 // output parameter, only valid if function returns true
1002 rtValue = m_pkLast->m_tValue;
1003
1004 Node* pkSave = m_pkLast;
1005
1006 // First and only element
1007 if (m_pkLast == m_pkFront)
1008 {
1009 m_pkLast = NULL;
1010 m_pkFront = NULL;
1011 }
1012 else
1013 {
1014 // Last element is not first element
1015 m_pkLast = m_pkLast->m_pkPrevious;
1016 m_pkLast->m_pkNext = NULL;
1017 }
1018
1019 m_uiQuantity--;
1020 UpdateIterators(pkSave, REMOVED);
1021
1022 delete pkSave;
1023 pkSave = NULL;
1024
1025 return true;
1026 }
1027
1028 return false;
1029}
1030
1031//----------------------------------------------------------------------------
1032template <class T>
1034{
1035 Node * pkIterator = m_pkFront;
1036
1037 // while not at end of list
1038 while (pkIterator)
1039 {
1040 // save pointer to next
1041 Node * pkNode = pkIterator->m_pkNext;
1042 // delete current
1043 delete pkIterator;
1044 // next iteration working on current next
1045 pkIterator = pkNode;
1046 }
1047
1048 m_pkFront = NULL;
1049 m_pkLast = NULL;
1050 m_uiQuantity = 0;
1051 UpdateIterators(pkIterator, KILL);
1052}
1053
1054//---------------------------------------------------------------------------
1055template <class T>
1057{
1058 Node * pkIteratorNode = m_pkFront;
1059
1060 while (pkIteratorNode)
1061 {
1062 Node * pkNextNode = pkIteratorNode->m_pkNext;
1063
1064 if (tValue == pkIteratorNode->m_tValue)
1065 {
1066 Remove(pkIteratorNode);
1067 }
1068
1069 pkIteratorNode = pkNextNode;
1070 }
1071}
1072
1073//----------------------------------------------------------------------------
1074template <class T>
1076{
1077 Node * pkReverse = NULL;
1078
1079 m_pkLast = m_pkFront;
1080
1081 while (m_pkFront)
1082 {
1083 Node * pkNode = m_pkFront;
1084 m_pkFront = m_pkFront->m_pkNext;
1085 pkNode->m_pkNext = pkReverse;
1086
1087 if (pkReverse)
1088 {
1089 pkReverse->m_pkPrevious = pkNode;
1090 }
1091
1092 pkReverse = pkNode;
1093 }
1094
1095 m_pkFront = pkReverse;
1096
1097 if (m_pkFront)
1098 {
1099 m_pkFront->m_pkPrevious = NULL;
1100 }
1101
1102 UpdateIterators(0, REVERSE_ORDER);
1103}
1104
1105//----------------------------------------------------------------------------
1106template <class T>
1107eC_Bool eC_TListDoubleLinked<T>::Contains(const T &tValue) const
1108{
1109 Node * pkSearch = m_pkFront;
1110
1111 while (pkSearch)
1112 {
1113 if (pkSearch->m_tValue == tValue)
1114 {
1115 return true;
1116 }
1117
1118 pkSearch = pkSearch->m_pkNext;
1119 }
1120
1121 return false;
1122}
1123
1124//----------------------------------------------------------------------------
1125template <class T>
1127{
1128 return !m_pkFront;
1129}
1130
1131//----------------------------------------------------------------------------
1132template <class T>
1134{
1135 if (!(kIter1.GetNode() && kIter2.GetNode()))
1136 {
1137 return false;
1138 }
1139
1140 if (kIter1.GetNode()->m_pkNext == kIter2.GetNode())
1141 {
1142 return false;
1143 }
1144
1145 // adjust former previous of iter1
1146 ListNode<T>* oldPrevious1 = kIter1.GetNode()->m_pkPrevious;
1147 if (oldPrevious1 != NULL)
1148 oldPrevious1->m_pkNext = kIter1.GetNode()->m_pkNext;
1149 else
1150 m_pkFront = kIter1.GetNode()->m_pkNext;
1151
1152 // adjust former next of iter1
1153 ListNode<T>* oldNext1 = kIter1.GetNode()->m_pkNext;
1154 if (oldNext1 != NULL)
1155 oldNext1->m_pkPrevious = kIter1.GetNode()->m_pkPrevious;
1156 else
1157 m_pkLast = kIter1.GetNode()->m_pkPrevious;
1158
1159 // adjust former previous of iter2
1160 ListNode<T>* oldPrevious2 = kIter2.GetNode()->m_pkPrevious;
1161 if (oldPrevious2 != NULL)
1162 oldPrevious2->m_pkNext = kIter1.GetNode();
1163 else
1164 m_pkFront = kIter1.GetNode();
1165
1166 // new previous
1167 kIter1.GetNode()->m_pkPrevious = oldPrevious2;
1168
1169 // new next
1170 kIter1.GetNode()->m_pkNext = kIter2.GetNode();
1171 kIter2.GetNode()->m_pkPrevious = kIter1.GetNode();
1172
1173 return true;
1174}
1175
1176//----------------------------------------------------------------------------
1177template <class T>
1178eC_Bool eC_TListDoubleLinked<T>::MoveBefore(Iterator &kStartIter, Iterator &kEndIter, Iterator &kIter)
1179{
1180 if (!(kStartIter.GetNode() && kEndIter.GetNode() && kIter.GetNode()))
1181 {
1182 return false;
1183 }
1184
1185 if (kEndIter.GetNode()->m_pkNext == kIter.GetNode())
1186 {
1187 return false;
1188 }
1189
1190 // adjust former previous of start
1191 ListNode<T>* oldPreviousStart = kStartIter.GetNode()->m_pkPrevious;
1192 if (oldPreviousStart != NULL)
1193 oldPreviousStart->m_pkNext = kEndIter.GetNode()->m_pkNext;
1194 else
1195 m_pkFront = kEndIter.GetNode()->m_pkNext;
1196
1197 // adjust former next of end
1198 ListNode<T>* oldNextEnd = kEndIter.GetNode()->m_pkNext;
1199 if (oldNextEnd != NULL)
1200 oldNextEnd->m_pkPrevious = kStartIter.GetNode()->m_pkPrevious;
1201 else
1202 m_pkLast = kStartIter.GetNode()->m_pkPrevious;
1203
1204 // adjust former previous of iter
1205 ListNode<T>* oldPrevious = kIter.GetNode()->m_pkPrevious;
1206 if (oldPrevious != NULL)
1207 oldPrevious->m_pkNext = kStartIter.GetNode();
1208 else
1209 m_pkFront = kStartIter.GetNode();
1210
1211 // new previous
1212 kStartIter.GetNode()->m_pkPrevious = oldPrevious;
1213
1214 // new next
1215 kEndIter.GetNode()->m_pkNext = kIter.GetNode();
1216 kIter.GetNode()->m_pkPrevious = kEndIter.GetNode();
1217
1218 return true;
1219}
1220
1221//----------------------------------------------------------------------------
1222template <class T>
1224{
1225 if (!(kIter1.GetNode() && kIter2.GetNode()))
1226 {
1227 return false;
1228 }
1229
1230 if (kIter1.GetNode()->m_pkPrevious == kIter2.GetNode())
1231 {
1232 return false;
1233 }
1234
1235 // adjust former previous of iter1
1236 ListNode<T>* oldPrevious1 = kIter1.GetNode()->m_pkPrevious;
1237 if (oldPrevious1 != NULL)
1238 oldPrevious1->m_pkNext = kIter1.GetNode()->m_pkNext;
1239 else
1240 m_pkFront = kIter1.GetNode()->m_pkNext;
1241
1242 // adjust former next of iter1
1243 ListNode<T>* oldNext1 = kIter1.GetNode()->m_pkNext;
1244 if (oldNext1 != NULL)
1245 oldNext1->m_pkPrevious = kIter1.GetNode()->m_pkPrevious;
1246 else
1247 m_pkLast = kIter1.GetNode()->m_pkPrevious;
1248
1249 // adjust former next of iter2
1250 ListNode<T>* oldNext2 = kIter2.GetNode()->m_pkNext;
1251 if (oldNext2 != NULL)
1252 oldNext2->m_pkPrevious = kIter1.GetNode();
1253 else
1254 m_pkLast = kIter1.GetNode();
1255
1256 // new previous
1257 kIter1.GetNode()->m_pkPrevious = kIter2.GetNode();
1258
1259 // new next
1260 kIter1.GetNode()->m_pkNext = oldNext2;
1261 kIter2.GetNode()->m_pkNext = kIter1.GetNode();
1262
1263 return true;
1264}
1265
1266//----------------------------------------------------------------------------
1267template <class T>
1268eC_Bool eC_TListDoubleLinked<T>::MoveAfter(Iterator &kStartIter, Iterator &kEndIter, Iterator &kIter)
1269{
1270 if (!(kStartIter.GetNode() && kEndIter.GetNode() && kIter.GetNode()))
1271 {
1272 return false;
1273 }
1274
1275 if (kStartIter.GetNode()->m_pkPrevious == kIter.GetNode())
1276 {
1277 return false;
1278 }
1279
1280 // adjust former previous of start
1281 ListNode<T>* oldPreviousStart = kStartIter.GetNode()->m_pkPrevious;
1282 if (oldPreviousStart != NULL)
1283 oldPreviousStart->m_pkNext = kEndIter.GetNode()->m_pkNext;
1284 else
1285 m_pkFront = kStartIter.GetNode()->m_pkNext;
1286
1287 // adjust former next of end
1288 ListNode<T>* oldNextEnd = kEndIter.GetNode()->m_pkNext;
1289 if (oldNextEnd != NULL)
1290 oldNextEnd->m_pkPrevious = kStartIter.GetNode()->m_pkPrevious;
1291 else
1292 m_pkLast = kEndIter.GetNode()->m_pkPrevious;
1293
1294 // adjust former next of iter
1295 ListNode<T>* oldNext = kIter.GetNode()->m_pkNext;
1296 if (oldNext != NULL)
1297 oldNext->m_pkPrevious = kEndIter.GetNode();
1298 else
1299 m_pkLast = kEndIter.GetNode();
1300
1301 // new previous
1302 kStartIter.GetNode()->m_pkPrevious = kIter.GetNode();
1303
1304 // new next
1305 kEndIter.GetNode()->m_pkNext = oldNext;
1306 kIter.GetNode()->m_pkNext = kStartIter.GetNode();
1307
1308 return true;
1309}
1310
1311//----------------------------------------------------------------------------
1312template <class T>
1314{
1315 if (!(kIter1.GetNode() && kIter2.GetNode()))
1316 {
1317 return false;
1318 }
1319
1320 T tTempValue = kIter1.GetNode()->m_tValue;
1321 kIter1.GetNode()->m_tValue = kIter2.GetNode()->m_tValue;
1322 kIter2.GetNode()->m_tValue = tTempValue;
1323
1324 return true;
1325}
1326
1327//----------------------------------------------------------------------------
1328template <class T>
1329void eC_TListDoubleLinked<T>::SortArraysUsingQuickSort(Node** ppSortPointers, eC_Int iFirst, eC_Int iLast, compare comp)
1330{
1331 //quicksort implementation
1332 eC_Int iIter1 = iFirst, iIter2 = iLast;
1333 T tPivo = ppSortPointers[(iFirst + iLast) / 2]->m_tValue;
1334
1335 while (iIter1 <= iIter2)
1336 {
1337 if (NULL != comp)
1338 {
1339 // m_tValue< tPivo
1340 while (comp(ppSortPointers[iIter1]->m_tValue, tPivo))
1341 {
1342 iIter1++;
1343 }
1344
1345 while (comp(tPivo, ppSortPointers[iIter2]->m_tValue))
1346 {
1347 iIter2--;
1348 }
1349 }
1350 else
1351 {
1352 // m_tValue< tPivo
1353 while (
1354 !((ppSortPointers[iIter1]->m_tValue) > tPivo) &&
1355 !((ppSortPointers[iIter1]->m_tValue) == tPivo)
1356 )
1357 {
1358 iIter1++;
1359 }
1360
1361 while ((ppSortPointers[iIter2]->m_tValue) > tPivo)
1362 {
1363 iIter2--;
1364 }
1365 }
1366
1367 //swap elements
1368 if (iIter1 <= iIter2)
1369 {
1370 Node * pkTempNode = ppSortPointers[iIter1];
1371 ppSortPointers[iIter1] = ppSortPointers[iIter2];
1372 ppSortPointers[iIter2] = pkTempNode;
1373
1374 iIter1++;
1375 iIter2--;
1376 }
1377 }
1378
1379 //more than 1 element in "upper" part of Array
1380 if (iFirst < iIter2)
1381 {
1382 SortArraysUsingQuickSort(ppSortPointers, iFirst, iIter2, comp);
1383 }
1384
1385 //more than 1 element in "lower" part of Array
1386 if (iIter1 < iLast)
1387 {
1388 SortArraysUsingQuickSort(ppSortPointers, iIter1, iLast, comp);
1389 }
1390}
1391
1392//----------------------------------------------------------------------------
1393
1394template <class T>
1395void eC_TListDoubleLinked<T>::SortArraysUsingMergeSort(Node** ppkMerged, eC_UInt uiQuantity, compare comp)
1396{
1397 // If there's only one element, there's nothing to sort
1398 if (uiQuantity > 1)
1399 {
1400 // Mergesort implementation
1401 eC_UInt uiMiddle = uiQuantity / 2;
1402 eC_UInt uiRightQuantity = uiQuantity - uiMiddle;
1403 eC_UInt uiLeftQuantity = uiMiddle;
1404
1405 Node** ppkLeft = new Node*[uiLeftQuantity];
1406 for (eC_UInt i = 0; i < uiLeftQuantity; ++i)
1407 ppkLeft[i] = NULL;
1408
1409 Node** ppkRight = new Node*[uiRightQuantity];
1410 for (eC_UInt i = 0; i < uiRightQuantity; ++i)
1411 ppkRight[i] = NULL;
1412
1413 eC_UInt uiRight, uiLeft;
1414 for (uiLeft = 0; uiLeft < uiMiddle; ++uiLeft)
1415 ppkLeft[uiLeft] = ppkMerged[uiLeft];
1416
1417 uiRight = 0;
1418 for (eC_UInt ui = uiMiddle; ui < uiQuantity; ++ui)
1419 {
1420 ppkRight[uiRight] = ppkMerged[ui];
1421 uiRight++;
1422 }
1423
1424 // Recursive call with first half of the list and number of elements of it
1425 SortArraysUsingMergeSort(ppkLeft, uiLeft, comp);
1426
1427 // Recursive call with second half of the list and number of elements of it
1428 SortArraysUsingMergeSort(ppkRight, uiRight, comp);
1429
1430 // Merging part
1431 eC_UInt ui = 0, uj = 0, uk = 0;
1432 while (ui < uiQuantity)
1433 {
1434 if ((uiLeftQuantity != uj) && (uiRightQuantity != uk))
1435 {
1436 if (NULL != comp)
1437 {
1438 if (comp(ppkRight[uk]->m_tValue, ppkLeft[uj]->m_tValue))
1439 {
1440 ppkMerged[ui] = ppkRight[uk];
1441 uk++;
1442 }
1443 else
1444 {
1445 ppkMerged[ui] = ppkLeft[uj];
1446 uj++;
1447 }
1448 }
1449 else
1450 {
1451 // if right < left (inverted logic is needed since not all operators may be defined)
1452 if (
1453 !(ppkRight[uk]->m_tValue > ppkLeft[uj]->m_tValue) &&
1454 !(ppkRight[uk]->m_tValue == ppkLeft[uj]->m_tValue)
1455 )
1456 {
1457 ppkMerged[ui] = ppkRight[uk];
1458 uk++;
1459 }
1460 else
1461 {
1462 ppkMerged[ui] = ppkLeft[uj];
1463 uj++;
1464 }
1465 }
1466 }
1467 else if (uiLeftQuantity != uj)
1468 {
1469 ppkMerged[ui] = ppkLeft[uj];
1470 uj++;
1471 }
1472 else if (uiRightQuantity != uk)
1473 {
1474 ppkMerged[ui] = ppkRight[uk];
1475 uk++;
1476 }
1477 ui++;
1478 }
1479 delete[] ppkLeft;
1480 delete[] ppkRight;
1481 }
1482}
1483
1484//----------------------------------------------------------------------------
1485
1486template <class T>
1487void eC_TListDoubleLinked<T>::Sort(eC_Bool bIsQuicksort, compare comp)
1488{
1489 if (m_uiQuantity > 1)
1490 {
1491 eC_UInt ui;
1492 Node** ppSortPointers;
1493 ppSortPointers = new Node *[m_uiQuantity];
1494
1495 Iterator pkIter;
1496 pkIter = GetBegin();
1497
1498 //Get pointers to List Nodes into Array;
1499 for (ui = 0; ui < m_uiQuantity; ui++)
1500 {
1501 ppSortPointers[ui] = pkIter.GetNode();
1502 if (pkIter.IsValid())
1503 {
1504 ++pkIter;
1505 }
1506 else
1507 {
1508 delete[] ppSortPointers;
1509 return;
1510 }
1511 }
1512
1513 //sort Node pointers in Array
1514 if (bIsQuicksort)
1515 SortArraysUsingQuickSort(ppSortPointers, 0, m_uiQuantity - 1, comp);
1516 else
1517 SortArraysUsingMergeSort(ppSortPointers, m_uiQuantity, comp);
1518
1519 //set List pointers
1520
1521 //firstElement
1522 m_pkFront = ppSortPointers[0];
1523
1524 ppSortPointers[0]->m_pkPrevious = NULL;
1525 ppSortPointers[0]->m_pkNext = ppSortPointers[1];
1526
1527 for (ui = 1; ui < m_uiQuantity - 1; ui++)
1528 {
1529 ppSortPointers[ui]->m_pkPrevious = ppSortPointers[ui - 1];
1530 ppSortPointers[ui]->m_pkNext = ppSortPointers[ui + 1];
1531 }
1532
1533 //lastElement
1534 ppSortPointers[m_uiQuantity - 1]->m_pkPrevious = ppSortPointers[m_uiQuantity - 2];
1535 ppSortPointers[m_uiQuantity - 1]->m_pkNext = NULL;
1536
1537 m_pkLast = ppSortPointers[m_uiQuantity - 1];
1538
1539 delete[] ppSortPointers;
1540
1541 UpdateIterators(pkIter.GetNode(), KILL);
1542 }
1543}
1544
1545//----------------------------------------------------------------------------
1546
1547template <class T>
1548void eC_TListDoubleLinked<T>::UpdateIterators(Node* pkNode, Update_t eUpdate) const
1549{
1550 for (eC_UInt i = 0; i < m_uiIterRegisterCnt; i++)
1551 {
1552 //Update Safe Iterators, if element is removed or added
1553 assert(m_ppIterRegister[i] != NULL);
1554 (m_ppIterRegister[i])->Validate(pkNode, eUpdate);
1555 }
1556}
1557
1558//----------------------------------------------------------------------------
1559template <class T>
1561{
1562 if (pkNewIter)
1563 {
1564 if (m_uiIterRegisterSize == m_uiIterRegisterCnt)
1565 {
1566 //resize Array (+5)
1567 eC_TSafeIterator<T>** ppTempRegister = new eC_TSafeIterator<T>*[m_uiIterRegisterSize + 5];
1568
1569 //Copy elements from old array to new one
1570 for (eC_UInt i = 0; i < m_uiIterRegisterCnt; i++)
1571 {
1572 ppTempRegister[i] = m_ppIterRegister[i];
1573 }
1574
1575 if (m_uiIterRegisterSize != 0)
1576 {
1577 //delete old array
1578 delete[] m_ppIterRegister;
1579 }
1580
1581 m_ppIterRegister = ppTempRegister;
1582 m_uiIterRegisterSize = m_uiIterRegisterSize + 5;
1583 }
1584
1585 //add new Iterator pointer
1586 m_ppIterRegister[m_uiIterRegisterCnt] = pkNewIter;
1587 m_uiIterRegisterCnt++;
1588 pkNewIter->SetList(this);
1589 }
1590}
1591
1592//----------------------------------------------------------------------------
1593template <class T>
1595{
1596 if (pkRemoveIter)
1597 {
1598 for (eC_UInt i = 0; i < m_uiIterRegisterCnt; i++)
1599 {
1600 //delete and shrink
1601 if (m_ppIterRegister[i] == pkRemoveIter)
1602 {
1603 m_ppIterRegister[i] = NULL;
1604 pkRemoveIter->SetList(NULL);
1605 for (eC_UInt j = i; j < m_uiIterRegisterCnt - 1; j++)
1606 {
1607 m_ppIterRegister[j] = m_ppIterRegister[j + 1];
1608 }
1609
1610 m_uiIterRegisterCnt--;
1611 break;
1612 }
1613 }
1614 }
1615}
1616
1617//----------------------------------------------------------------------------
1618
1622template<typename T>
1623bool operator==(const eC_TListDoubleLinked<T>& list1,
1624 const eC_TListDoubleLinked<T>& list2)
1625{
1626 if (list1.GetQuantity() != list2.GetQuantity())
1627 {
1628 return false;
1629 }
1630
1631 typename eC_TListDoubleLinked<T>::Iterator it1, it2;
1632 it2 = list2.GetBegin();
1633
1634 for (it1 = list1.GetBegin(); it1.IsInsideList(); ++it1, ++it2)
1635 {
1636 if (!((*it1) == (*it2)))
1637 {
1638 return false;
1639 }
1640 }
1641
1642 return true;
1643}
1644
1648template<typename T>
1649bool operator!=(const eC_TListDoubleLinked<T>& list1,
1650 const eC_TListDoubleLinked<T>& list2)
1651{
1652 return !(list1 == list2);
1653}
1654
1655// prevent compiler errors if memory-mapping is active
1656#include "eC_CustomMemoryMappingUndef.h"
1657
1658#endif
ListNode template class.
Definition: eC_TList_doubleLinked.h:27
ListNode * m_pkPrevious
pointer to previous node
Definition: eC_TList_doubleLinked.h:44
ListNode * m_pkNext
pointer to next node
Definition: eC_TList_doubleLinked.h:41
T m_tValue
value of this node
Definition: eC_TList_doubleLinked.h:47
Classic iterator implementation with operator++, operator–, operator*.
Definition: eC_TList_Iterators.h:36
virtual eC_Bool IsInsideList() const
Definition: eC_TList_Iterators.h:139
ListNode< T > Node
typedef for node
Definition: eC_TList_Iterators.h:41
Node * m_pNode
this node
Definition: eC_TList_Iterators.h:44
Node * GetNode() const
Definition: eC_TList_Iterators.h:242
eC_Bool IsValid() const
Definition: eC_TList_Iterators.h:128
Represents a double linked list template with header and tail node.
Definition: eC_TList_doubleLinked.h:67
void RemoveAll(const T &tValue)
Definition: eC_TList_doubleLinked.h:1056
eC_TSafeIterator< T > GetAtSafe(eC_UInt uiPos)
Definition: eC_TList_doubleLinked.h:452
void Sort(eC_Bool bIsQuicksort=true, compare comp=NULL)
Definition: eC_TList_doubleLinked.h:1487
eC_Bool MoveBefore(Iterator &kIter1, Iterator &kIter2)
Definition: eC_TList_doubleLinked.h:1133
eC_Bool RemoveEnd(T &rtValue)
Definition: eC_TList_doubleLinked.h:997
eC_Bool Remove(SafeIterator &kIter)
Definition: eC_TList_doubleLinked.h:868
eC_Bool Empty() const
Definition: eC_TList_doubleLinked.h:1126
eC_TListDoubleLinked(const eC_TListDoubleLinked< T > &copy)
Definition: eC_TList_doubleLinked.h:559
eC_Bool Contains(const T &tValue) const
Definition: eC_TList_doubleLinked.h:1107
void AddAfter(const T &tValue2Add, Iterator &kIter)
Definition: eC_TList_doubleLinked.h:734
eC_TIterator< T > GetEnd() const
Definition: eC_TList_doubleLinked.h:336
eC_TIterator< T > Iterator
Iterator is typedef'd as eC_TIterator ot type T.
Definition: eC_TList_doubleLinked.h:74
eC_TListDoubleLinked< T > & operator=(const eC_TListDoubleLinked< T > &copy)
Definition: eC_TList_doubleLinked.h:482
eC_TSafeIterator< T > GetEndSafe()
Definition: eC_TList_doubleLinked.h:346
eC_Bool AddUniqueAtEnd(const T &tValue)
Definition: eC_TList_doubleLinked.h:780
eC_Bool AddUnique(const T &tValue)
Definition: eC_TList_doubleLinked.h:767
void AddSorted(const T &tValue)
Definition: eC_TList_doubleLinked.h:806
void RemoveAll()
Definition: eC_TList_doubleLinked.h:1033
eC_Bool Remove(const T &tValue)
Definition: eC_TList_doubleLinked.h:879
eC_UInt GetQuantity() const
Definition: eC_TList_doubleLinked.h:587
eC_Bool MoveAfter(Iterator &kStartIter, Iterator &kEndIter, Iterator &kIter)
Definition: eC_TList_doubleLinked.h:1268
eC_Bool GetFirst(T &rtValue) const
Definition: eC_TList_doubleLinked.h:601
void ReverseOrder()
Definition: eC_TList_doubleLinked.h:1075
eC_TIterator< T > GetAt(eC_UInt uiPos) const
Definition: eC_TList_doubleLinked.h:432
eC_Bool MoveAfter(Iterator &kIter1, Iterator &kIter2)
Definition: eC_TList_doubleLinked.h:1223
eC_TIterator< T > GetBegin() const
Definition: eC_TList_doubleLinked.h:305
eC_TSafeIterator< T > SafeIterator
SafeIterator is typedef'd as eC_TSafeIterator ot type T.
Definition: eC_TList_doubleLinked.h:77
eC_TSafeIterator< T > GetFindSafe(const T &tValue)
Definition: eC_TList_doubleLinked.h:402
~eC_TListDoubleLinked()
Definition: eC_TList_doubleLinked.h:573
eC_Bool MoveBefore(Iterator &kStartIter, Iterator &kEndIter, Iterator &kIter)
Definition: eC_TList_doubleLinked.h:1178
eC_TSafeIterator< T > GetBeginSafe()
Definition: eC_TList_doubleLinked.h:315
eC_Bool GetNext(T &rtValue) const
Definition: eC_TList_doubleLinked.h:618
void AddBefore(const T &tValue2Add, Iterator &kIter)
Definition: eC_TList_doubleLinked.h:700
eC_Bool RemoveFront(T &rtValue)
Definition: eC_TList_doubleLinked.h:963
eC_Bool AddUniqueSorted(const T &tValue)
Definition: eC_TList_doubleLinked.h:793
eC_Bool IsEmpty() const
Definition: eC_TList_doubleLinked.h:594
eC_TIterator< T > GetFind(const T &tValue) const
Definition: eC_TList_doubleLinked.h:372
bool(* compare)(T lhs, T rhs)
compare-function
Definition: eC_TList_doubleLinked.h:80
eC_TListDoubleLinked()
Definition: eC_TList_doubleLinked.h:547
void AddAtEnd(const T &tValue)
Definition: eC_TList_doubleLinked.h:670
eC_Bool Swap(Iterator &kIter1, Iterator &kIter2)
Definition: eC_TList_doubleLinked.h:1313
void Add(const T &tValue)
Definition: eC_TList_doubleLinked.h:635
An iterator that stays valid even if elements are deleted from the list.
Definition: eC_TList_Iterators.h:313
bool operator==(const NSmartPtr::SharedPtr< C1 > &a, const NSmartPtr::SharedPtr< C2 > &b)
Definition: SharedPtr.h:240
bool operator!=(const NSmartPtr::SharedPtr< C1 > &a, const NSmartPtr::SharedPtr< C2 > &b)
Definition: SharedPtr.h:226