tList.h
Engine/source/core/util/tList.h
Classes:
class
A list template class.
class
class
class
Used instead of a (void *) for type-safety of persistent iterators.
Namespaces:
namespace
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#ifndef _TORQUE_LIST_ 25#define _TORQUE_LIST_ 26 27#ifndef _TORQUE_TYPES_H_ 28#include "platform/types.h" 29#endif 30 31namespace Torque 32{ 33 34/// A list template class. 35/// A classic list class similar to the STL list class. The list 36/// class supports fast insert and erase operations, but slow dynamic 37/// access. The list is circular and the iterator supports iterating 38/// past the end() or rend() in order to loop around. 39/// @ingroup UtilContainers 40template<typename Type> 41class List 42{ 43 struct Link; 44 struct PrivatePersist {}; ///< Used instead of a (void *) for type-safety of persistent iterators 45 46public: 47 /// A PersistentIter is used for the special cases where you need to store an iterator for 48 /// efficiency reasons. The _Iterator class handles the conversion to/from PersistentIter. 49 /// @note The data in the node this points to could go away, so only use these in cases where 50 /// you control the allocation/deallocation of the nodes in the list. 51 typedef PrivatePersist *PersistentIter; 52 53 // Iterator support 54 template<typename U,typename E> 55 class _Iterator 56 { 57 public: 58 typedef U ValueType; 59 typedef U* Pointer; 60 typedef U& Reference; 61 62 _Iterator(); 63 _Iterator(PersistentIter &iter) { _link = (Link *)iter; } 64 65 operator PersistentIter() const { return (PrivatePersist *)_link; } 66 67 _Iterator& operator++(); 68 _Iterator operator++(int); 69 _Iterator& operator--(); 70 _Iterator operator--(int); 71 bool operator==(const _Iterator&) const; 72 bool operator!=(const _Iterator&) const; 73 U* operator->() const; 74 U& operator*() const; 75 76 private: 77 friend class List; 78 79 E* _link; 80 _Iterator(E*); 81 }; 82 83 // types 84 typedef Type ValueType; 85 typedef Type& Reference; 86 typedef const Type& ConstReference; 87 88 typedef _Iterator<Type,Link> Iterator; 89 typedef _Iterator<const Type,const Link> ConstIterator; 90 91 typedef S32 DifferenceType; 92 typedef U32 SizeType; 93 94 // initialization 95 List(); 96 ~List(); 97 List(const List& p); 98 99 // management 100 U32 getSize() const; ///< Return the number of elements 101 void resize(U32); ///< Set the list size 102 void clear(); ///< Empty the List 103 bool isEmpty() const; ///< Node count == 0? 104 105 // insert elements 106 Iterator insert(U32 index, const Type& = Type()); ///< Insert new element at the given index 107 Iterator insert(Iterator, const Type& = Type()); ///< Insert at the given iter 108 Iterator pushFront(const Type& = Type()); ///< Insert at first element 109 Iterator pushBack(const Type& = Type()); ///< Insert after the last element 110 111 // erase elements 112 void erase(U32); ///< Preserves element order 113 void erase(Iterator); ///< Preserves element order 114 void popFront(); ///< Remove the first element 115 void popBack(); ///< Remove the last element 116 117 // forward Iterator access 118 Iterator begin(); ///< _Iterator to first element 119 ConstIterator begin() const; ///< _Iterator to first element 120 Iterator end(); ///< _Iterator to last element + 1 121 ConstIterator end() const; ///< _Iterator to last element + 1 122 123 // reverse Iterator access 124 Iterator rbegin(); ///< _Iterator to first element - 1 125 ConstIterator rbegin() const; ///< _Iterator to first element - 1 126 Iterator rend(); ///< _Iterator to last element 127 ConstIterator rend() const; ///< _Iterator to last element 128 129 // type access 130 Type& first(); ///< First element 131 const Type& first() const; ///< First element 132 Type& last(); ///< Last element 133 const Type& last() const; ///< Last element 134 135 // operators 136 void operator=(const List& p); 137 Type& operator[](U32); 138 const Type& operator[](U32) const; 139 140private: 141 struct Link 142 { 143 Link* next; 144 Link* prev; 145 Link(): next(NULL), prev(NULL) {} 146 Link(Link* p,Link* n): next(n),prev(p) {} 147 }; 148 149 struct Node: Link 150 { 151 Type value; 152 Node() {} 153 Node(Link* p,Link* n,const Type& x): Link(p,n),value(x) {} 154 }; 155 156 Link _head; 157 U32 _size; 158 159 Link* _node(U32 index) const; 160 void _destroy(); 161}; 162 163template<class Type> List<Type>::List() 164{ 165 _size = 0; 166 _head.next = &_head; 167 _head.prev = &_head; 168} 169 170template<class Type> List<Type>::List(const List& p) 171{ 172 _size = 0; 173 _head.next = &_head; 174 _head.prev = &_head; 175 *this = p; 176} 177 178template<class Type> List<Type>::~List() 179{ 180 _destroy(); 181} 182 183 184//----------------------------------------------------------------------------- 185 186template<class Type> typename List<Type>::Link* List<Type>::_node(U32 index) const 187{ 188 Iterator itr(_head.next); 189 while (index--) 190 itr++; 191 return itr._link; 192} 193 194template<class Type> void List<Type>::_destroy() 195{ 196 for (Iterator itr(begin()); itr != end(); ) 197 { 198 Node* n = static_cast<Node*>((itr++)._link); 199 delete n; 200 } 201} 202 203 204//----------------------------------------------------------------------------- 205// management 206 207template<class Type> inline U32 List<Type>::getSize() const 208{ 209 return _size; 210} 211 212template<class Type> void List<Type>::resize(U32 size) 213{ 214 if (size > _size) 215 { 216 while (_size != size) 217 pushBack(Type()); 218 } 219 else 220 { 221 while (_size != size) 222 popBack(); 223 } 224} 225 226template<class Type> void List<Type>::clear() 227{ 228 _destroy(); 229 _head.next = &_head; 230 _head.prev = &_head; 231 _size = 0; 232} 233 234template<class Type> inline bool List<Type>::isEmpty() const 235{ 236 return _size == 0; 237} 238 239 240//----------------------------------------------------------------------------- 241// add Nodes 242 243template<class Type> typename List<Type>::Iterator List<Type>::insert(Iterator itr, const Type& x) 244{ 245 Link* node = itr._link; 246 Node* n = new Node(node->prev,node,x); 247 node->prev->next = n; 248 node->prev = n; 249 _size++; 250 return n; 251} 252 253template<class Type> inline typename List<Type>::Iterator List<Type>::insert(U32 index, const Type& x) 254{ 255 return insert(_node(index),x); 256} 257 258template<class Type> inline typename List<Type>::Iterator List<Type>::pushFront(const Type& x) 259{ 260 return insert(_head.next,x); 261} 262 263template<class Type> inline typename List<Type>::Iterator List<Type>::pushBack(const Type& x) 264{ 265 return insert(&_head,x); 266} 267 268 269//----------------------------------------------------------------------------- 270// remove elements 271 272template<class Type> void List<Type>::erase(Iterator itr) 273{ 274 Node* node = static_cast<Node*>(itr._link); 275 node->prev->next = node->next; 276 node->next->prev = node->prev; 277 delete node; 278 _size--; 279} 280 281template<class Type> inline void List<Type>::erase(U32 index) 282{ 283 erase(_node(index)); 284} 285 286template<class Type> inline void List<Type>::popFront() 287{ 288 erase(_head.next); 289} 290 291template<class Type> inline void List<Type>::popBack() 292{ 293 erase(_head.prev); 294} 295 296 297//----------------------------------------------------------------------------- 298// Iterator access 299 300template<class Type> inline typename List<Type>::Iterator List<Type>::begin() 301{ 302 return _head.next; 303} 304 305template<class Type> inline typename List<Type>::ConstIterator List<Type>::begin() const 306{ 307 return _head.next; 308} 309 310template<class Type> inline typename List<Type>::Iterator List<Type>::end() 311{ 312 return &_head; 313} 314 315template<class Type> inline typename List<Type>::ConstIterator List<Type>::end() const 316{ 317 return &_head; 318} 319 320template<class Type> inline typename List<Type>::Iterator List<Type>::rbegin() 321{ 322 return _head.prev; 323} 324 325template<class Type> inline typename List<Type>::ConstIterator List<Type>::rbegin() const 326{ 327 return _head.prev; 328} 329 330template<class Type> inline typename List<Type>::Iterator List<Type>::rend() 331{ 332 return &_head; 333} 334 335template<class Type> inline typename List<Type>::ConstIterator List<Type>::rend() const 336{ 337 return &_head; 338} 339 340 341//----------------------------------------------------------------------------- 342// type access 343 344template<class Type> inline Type& List<Type>::first() 345{ 346 return static_cast<Node*>(_head.next)->value; 347} 348 349template<class Type> inline const Type& List<Type>::first() const 350{ 351 return static_cast<Node*>(_head.next)->value; 352} 353 354template<class Type> inline Type& List<Type>::last() 355{ 356 return static_cast<Node*>(_head.prev)->value; 357} 358 359template<class Type> inline const Type& List<Type>::last() const 360{ 361 return static_cast<Node*>(_head.prev)->value; 362} 363 364 365//----------------------------------------------------------------------------- 366// operators 367 368template<class Type> void List<Type>::operator=(const List& p) 369{ 370 if (_size >= p._size) 371 { 372 // Destroy the elements we're not going to use and copy the rest 373 while (_size != p._size) 374 popBack(); 375 } 376 377 U32 count = _size; 378 ConstIterator src = p.begin(); 379 Iterator dst = begin(); 380 while (count--) 381 *dst++ = *src++; 382 while (src != p.end()) 383 pushBack(*src++); 384} 385 386template<class Type> inline Type& List<Type>::operator[](U32 index) 387{ 388 return static_cast<Node*>(_node(index))->value; 389} 390 391template<class Type> inline const Type& List<Type>::operator[](U32 index) const 392{ 393 return static_cast<Node*>(_node(index))->value; 394} 395 396//----------------------------------------------------------------------------- 397// _Iterator class 398 399template<class Type> template<class U,typename E> 400inline List<Type>::_Iterator<U,E>::_Iterator() 401{ 402 _link = 0; 403} 404 405template<class Type> template<class U,typename E> 406inline List<Type>::_Iterator<U,E>::_Iterator(E* ptr) 407{ 408 _link = ptr; 409} 410 411// The checking for _MSC_VER on the ++/-- operators is due to a bug with the VS2008 compiler 412// recheck this and remove if fixed with VS2008 SP1 413 414template<class Type> template<class U,typename E> 415#ifdef _MSC_VER 416inline typename List<Type>:: _Iterator<U,E>& List<Type>::_Iterator<U,E>::operator++() 417#else 418inline typename List<Type>::template _Iterator<U,E>& List<Type>::_Iterator<U,E>::operator++() 419#endif 420{ 421 _link = _link->next; 422 return *this; 423} 424 425template<class Type> template<class U,typename E> 426#ifdef _MSC_VER 427inline typename List<Type>::_Iterator<U,E> List<Type>::_Iterator<U,E>::operator++(int) 428#else 429inline typename List<Type>::template _Iterator<U,E> List<Type>::_Iterator<U,E>::operator++(int) 430#endif 431{ 432 _Iterator itr(*this); 433 _link = _link->next; 434 return itr; 435} 436 437template<class Type> template<class U,typename E> 438#ifdef _MSC_VER 439inline typename List<Type>::_Iterator<U,E>& List<Type>::_Iterator<U,E>::operator--() 440#else 441inline typename List<Type>::template _Iterator<U,E>& List<Type>::_Iterator<U,E>::operator--() 442#endif 443{ 444 _link = _link->prev; 445 return *this; 446} 447 448template<class Type> template<class U,typename E> 449#ifdef _MSC_VER 450inline typename List<Type>::_Iterator<U,E> List<Type>::_Iterator<U,E>::operator--(int) 451#else 452inline typename List<Type>::template _Iterator<U,E> List<Type>::_Iterator<U,E>::operator--(int) 453#endif 454{ 455 _Iterator itr(*this); 456 _link = _link->prev; 457 return itr; 458} 459 460template<class Type> template<class U,typename E> 461inline bool List<Type>::_Iterator<U,E>::operator==(const _Iterator& b) const 462{ 463 return _link == b._link; 464} 465 466template<class Type> template<class U,typename E> 467inline bool List<Type>::_Iterator<U,E>::operator!=(const _Iterator& b) const 468{ 469 return !(_link == b._link); 470} 471 472template<class Type> template<class U,typename E> 473inline U* List<Type>::_Iterator<U,E>::operator->() const 474{ 475 // Can't use static_cast because of const / non-const versions of Iterator. 476 // Could use reflection functions, but C-style cast is easier in this case. 477 return &((Node*)_link)->value; 478} 479 480template<class Type> template<class U,typename E> 481inline U& List<Type>::_Iterator<U,E>::operator*() const 482{ 483 // Can't use static_cast because of const / non-const versions of Iterator. 484 // Could use reflection functions, but C-style cast is easier in this case. 485 return ((Node*)_link)->value; 486} 487 488} // Namespace 489 490#endif // _TORQUE_LIST_ 491 492