"L. Spiro Engine"

F:/My Projects/LSEngine/Modules/LSTL/Src/LinkedList/LSTLLinkedList.h

00001 
00016 #ifndef __LSTL_LINKEDLIST_H__
00017 #define __LSTL_LINKEDLIST_H__
00018 
00019 #include "../LSTLib.h"
00020 #include "LSTLLinkedListBase.h"
00021 #include <new>
00022 
00023 namespace lstl {
00024 
00031         template <typename _tType>
00032         class CLinkedList : protected CLinkedListBase {
00033         public :
00034                 // == Various constructors.
00035                 LSE_CALL                                                                CLinkedList() :
00036                         m_lpllnHead( NULL ),
00037                         m_lpllnTail( NULL ),
00038                         m_paOurAllocator( &Parent::m_aAllocator ) {
00039                 }
00040                 LSE_CALL                                                                ~CLinkedList() {
00041                         Reset();
00042                 }
00043 
00044 
00045                 // == Types.
00049                 typedef struct LSTL_LINKED_LIST_NODE {
00053                         _tType                                                          tLinkedListObject;
00054 
00058                         LSTL_LINKED_LIST_NODE *                         pllnLinkedListNext;
00059 
00063                         LSTL_LINKED_LIST_NODE *                         pllnLinkedListPrev;
00064                 } * LPLSTL_LINKED_LIST_NODE, * const LPCLSTL_LINKED_LIST_NODE;
00065 
00066 
00067                 // == Functions.
00074                 LSVOID LSE_CALL                                                 SetAllocator( CAllocator * _paAllocator ) {
00075                         Reset();
00076                         m_paOurAllocator = _paAllocator;
00077                         if ( !m_paOurAllocator ) {
00078                                 m_paOurAllocator = &Parent::m_aAllocator;
00079                         }
00080                 }
00081 
00087                 CAllocator * LSE_CALL                                   GetAllocator() {
00088                         return m_paOurAllocator;
00089                 }
00090 
00094                 LSVOID LSE_CALL                                                 Reset() {
00095                         LPLSTL_LINKED_LIST_NODE lpllnNext = NULL;
00096                         for ( LPLSTL_LINKED_LIST_NODE lpllnThis = m_lpllnHead;
00097                                 lpllnThis; lpllnThis = lpllnNext ) {
00098                                 lpllnNext = lpllnThis->pllnLinkedListNext;
00099                                 Destroy( (*lpllnThis) );
00100                                 m_paOurAllocator->Free( lpllnThis );
00101                         }
00102 
00103                         m_lpllnHead = m_lpllnTail = NULL;
00104                 }
00105 
00114                 LPLSTL_LINKED_LIST_NODE LSE_CALL                InsertAfter( const _tType &_tNew, LPLSTL_LINKED_LIST_NODE _lpllnNode ) {
00115                         LPLSTL_LINKED_LIST_NODE lpllnNew = NewNode();
00116                         if ( !lpllnNew ) { return NULL; }
00117                         Construct( (*lpllnNew) );
00118                         lpllnNew->tLinkedListObject = _tNew;
00119 
00120                         if ( !_lpllnNode ) {
00121                                 // Insert at the head.
00122                                 if ( m_lpllnHead ) {
00123                                         lpllnNew->pllnLinkedListNext = m_lpllnHead;
00124                                 }
00125                         }
00126                         else {
00127                                 // Otherwise it goes after some item or another.
00128                                 lpllnNew->pllnLinkedListNext = _lpllnNode->pllnLinkedListNext;
00129                                 lpllnNew->pllnLinkedListPrev = _lpllnNode;
00130                         }
00131 
00132                         // Fix the links in the objects surrounding this one.
00133                         if ( lpllnNew->pllnLinkedListNext ) {
00134                                 lpllnNew->pllnLinkedListNext->pllnLinkedListPrev = lpllnNew;
00135                         }
00136                         else {
00137                                 // At the tail.
00138                                 m_lpllnTail = lpllnNew;
00139                         }
00140 
00141                         if ( lpllnNew->pllnLinkedListPrev ) {
00142                                 lpllnNew->pllnLinkedListPrev->pllnLinkedListNext = lpllnNew;
00143                         }
00144                         else {
00145                                 // At the head.
00146                                 m_lpllnHead = lpllnNew;
00147                         }
00148 
00149                         return lpllnNew;
00150                 }
00151 
00158                 LSVOID LSE_CALL                                                 RemoveItem( LPLSTL_LINKED_LIST_NODE _lpllnNode ) {
00159                         if ( !_lpllnNode ) { return; }
00160                         // Unlink the object.
00161                         if ( _lpllnNode->pllnLinkedListPrev ) {
00162                                 _lpllnNode->pllnLinkedListPrev->pllnLinkedListNext = _lpllnNode->pllnLinkedListNext;
00163                         }
00164                         else {
00165                                 // At the head.
00166                                 m_lpllnHead = _lpllnNode->pllnLinkedListNext;
00167                         }
00168 
00169                         if ( _lpllnNode->pllnLinkedListNext ) {
00170                                 _lpllnNode->pllnLinkedListNext->pllnLinkedListPrev = _lpllnNode->pllnLinkedListPrev;
00171                         }
00172                         else {
00173                                 // At the tail.
00174                                 m_lpllnTail = _lpllnNode->pllnLinkedListPrev;
00175                         }
00176 
00177                         Destroy( (*_lpllnNode) );
00178                         m_paOurAllocator->Free( _lpllnNode );
00179                 }
00180 
00186                 LPLSTL_LINKED_LIST_NODE LSE_CALL                Head() {
00187                         return m_lpllnHead;
00188                 }
00189 
00195                 LPLSTL_LINKED_LIST_NODE LSE_CALL                Tail() {
00196                         return m_lpllnTail;
00197                 }
00198 
00205                 LPLSTL_LINKED_LIST_NODE LSE_CALL                PushFront( const _tType &_tNew ) {
00206                         return InsertAfter( _tNew, NULL );
00207                 }
00208 
00215                 LPLSTL_LINKED_LIST_NODE LSE_CALL                PushBack( const _tType &_tNew ) {
00216                         return InsertAfter( _tNew, m_lpllnTail );
00217                 }
00218 
00224                 LSUINT32 LSE_CALL                                               Length() {
00225                         LSUINT32 ui32Len = 0UL;
00226                         for ( LPLSTL_LINKED_LIST_NODE lpllnThis = m_lpllnHead;
00227                                 lpllnThis; lpllnThis = lpllnThis->pllnLinkedListNext ) {
00228                                 ++ui32Len;
00229                         }
00230                         return ui32Len;
00231                 }
00232 
00239                 LPLSTL_LINKED_LIST_NODE LSE_CALL                Find( const _tType &_tValue ) {
00240                         for ( LPLSTL_LINKED_LIST_NODE lpllnThis = m_lpllnHead;
00241                                 lpllnThis; lpllnThis = lpllnThis->pllnLinkedListNext ) {
00242                                 if ( lpllnThis->tLinkedListObject == _tValue ) {
00243                                         return lpllnThis;
00244                                 }
00245                         }
00246                         return NULL;
00247                 }
00248 
00249 
00250         protected :
00251                 // == Members.
00255                 LPLSTL_LINKED_LIST_NODE                                 m_lpllnHead;
00256 
00260                 LPLSTL_LINKED_LIST_NODE                                 m_lpllnTail;
00261 
00265                 CAllocator *                                                    m_paOurAllocator;
00266 
00267                 
00268                 // == Functions.
00274                 LSVOID LSE_CALL                                                 Construct( LSTL_LINKED_LIST_NODE &_llnNode ) {
00275                         _llnNode.pllnLinkedListNext = _llnNode.pllnLinkedListPrev = NULL;
00276                         new( &_llnNode.tLinkedListObject ) _tType;
00277                 }
00283                 LSVOID LSE_CALL                                                 Destroy( const LSTL_LINKED_LIST_NODE &_llnNode ) {
00284                         // This gives warning C4100 when this class is created with types that have no destructor,
00285                         //      claiming _llnNode is unreferenced.
00286                         // Erase this warning with some do-nothing code.
00287                         static_cast<LSTL_LINKED_LIST_NODE>(_llnNode);
00288                         _llnNode.tLinkedListObject.~_tType();
00289                 }
00290 
00296                 LPLSTL_LINKED_LIST_NODE LSE_CALL                NewNode() {
00297                         return static_cast<LPLSTL_LINKED_LIST_NODE>(m_paOurAllocator->Alloc( sizeof( LSTL_LINKED_LIST_NODE ) ));
00298                 }
00299 
00300         private :
00301                 typedef CLinkedListBase                                 Parent;
00302         };
00303 
00304 }       // namespace lstl
00305 
00306 #endif  // __LSTL_LINKEDLIST_H__
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator