"L. Spiro Engine"
|
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__