| 264 | /** |
| 265 | * Simple double linked list, modeled after the list template of the standard |
| 266 | * C++ library. |
| 267 | */ |
| 268 | template<class t_T> |
| 269 | class List<t_T*> { |
| 270 | protected: |
| 271 | #if defined (_WIN32_WCE) || defined (_MSC_VER) |
| 272 | //FIXME evc4 and msvc7 doesn't like it as protected member |
| 273 | public: |
| 274 | #endif |
| 275 | struct NodeBase { |
| 276 | NodeBase *_prev; |
| 277 | NodeBase *_next; |
| 278 | }; |
| 279 | |
| 280 | template <class t_T2> |
| 281 | struct Node : public NodeBase { |
| 282 | t_T2 _data; |
| 283 | |
| 284 | Node(const t_T2 &x) : _data(x) {} |
| 285 | }; |
| 286 | |
| 287 | template <class t_T2> |
| 288 | class Iterator { |
| 289 | friend class List<t_T*>; |
| 290 | NodeBase *_node; |
| 291 | |
| 292 | #if !defined (__WINSCW__) |
| 293 | explicit Iterator(NodeBase *node) : _node(node) {} |
| 294 | #else |
| 295 | Iterator(NodeBase *node) : _node(node) {} |
| 296 | #endif |
| 297 | |
| 298 | public: |
| 299 | Iterator() : _node(0) {} |
| 300 | |
| 301 | // Prefix inc |
| 302 | Iterator<t_T2> &operator++() { |
| 303 | if (_node) |
| 304 | _node = _node->_next; |
| 305 | return *this; |
| 306 | } |
| 307 | // Postfix inc |
| 308 | Iterator<t_T2> operator++(int) { |
| 309 | Iterator tmp(_node); |
| 310 | ++(*this); |
| 311 | return tmp; |
| 312 | } |
| 313 | // Prefix dec |
| 314 | Iterator<t_T2> &operator--() { |
| 315 | if (_node) |
| 316 | _node = _node->_prev; |
| 317 | return *this; |
| 318 | } |
| 319 | // Postfix dec |
| 320 | Iterator<t_T2> operator--(int) { |
| 321 | Iterator tmp(_node); |
| 322 | --(*this); |
| 323 | return tmp; |
| 324 | } |
| 325 | t_T2& operator*() const { |
| 326 | assert(_node); |
| 327 | #if (__GNUC__ == 2) && (__GNUC_MINOR__ >= 95) |
| 328 | return static_cast<List<t_T*>::Node<t_T2> *>(_node)->_data; |
| 329 | #else |
| 330 | return static_cast<Node<t_T2>*>(_node)->_data; |
| 331 | #endif |
| 332 | } |
| 333 | t_T2* operator->() const { |
| 334 | return &(operator*()); |
| 335 | } |
| 336 | |
| 337 | bool operator==(const Iterator<t_T2>& x) const { |
| 338 | return _node == x._node; |
| 339 | } |
| 340 | |
| 341 | bool operator!=(const Iterator<t_T2>& x) const { |
| 342 | return _node != x._node; |
| 343 | } |
| 344 | }; |
| 345 | |
| 346 | NodeBase *_anchor; |
| 347 | bool _autoFree; |
| 348 | |
| 349 | public: |
| 350 | typedef Iterator<t_T*> iterator; |
| 351 | typedef Iterator<t_T* const> const_iterator; |
| 352 | |
| 353 | typedef t_T* value_type; |
| 354 | |
| 355 | public: |
| 356 | List(bool autoFree = false) : _autoFree(autoFree) { |
| 357 | _anchor = new NodeBase; |
| 358 | _anchor->_prev = _anchor; |
| 359 | _anchor->_next = _anchor; |
| 360 | } |
| 361 | List(const List<t_T*>& list) { |
| 362 | // FIXME: really set _autoFree to false here? |
| 363 | _autoFree = false; |
| 364 | _anchor = new NodeBase; |
| 365 | _anchor->_prev = _anchor; |
| 366 | _anchor->_next = _anchor; |
| 367 | |
| 368 | insert(begin(), list.begin(), list.end()); |
| 369 | } |
| 370 | |
| 371 | ~List() { |
| 372 | clear(); |
| 373 | delete _anchor; |
| 374 | } |
| 375 | |
| 376 | void push_front(t_T *const &element) { |
| 377 | insert(begin(), element); |
| 378 | } |
| 379 | |
| 380 | void push_back(t_T *const &element) { |
| 381 | insert(end(), element); |
| 382 | } |
| 383 | |
| 384 | void insert(iterator pos, t_T *const &element) { |
| 385 | NodeBase *newNode = new Node<t_T*>(element); |
| 386 | |
| 387 | newNode->_next = pos._node; |
| 388 | newNode->_prev = pos._node->_prev; |
| 389 | newNode->_prev->_next = newNode; |
| 390 | newNode->_next->_prev = newNode; |
| 391 | } |
| 392 | |
| 393 | template <typename iterator2> |
| 394 | void insert(iterator pos, iterator2 first, iterator2 last) { |
| 395 | for (; first != last; ++first) |
| 396 | insert(pos, *first); |
| 397 | } |
| 398 | |
| 399 | iterator erase(iterator pos) { |
| 400 | assert(pos != end()); |
| 401 | |
| 402 | NodeBase *next = pos._node->_next; |
| 403 | NodeBase *prev = pos._node->_prev; |
| 404 | if (_autoFree) |
| 405 | delete *pos; |
| 406 | Node<t_T*> *node = static_cast<Node<t_T*> *>(pos._node); |
| 407 | prev->_next = next; |
| 408 | next->_prev = prev; |
| 409 | delete node; |
| 410 | return iterator(next); |
| 411 | } |
| 412 | |
| 413 | iterator reverse_erase(iterator pos) { |
| 414 | assert(pos != end()); |
| 415 | |
| 416 | NodeBase *next = pos._node->_next; |
| 417 | NodeBase *prev = pos._node->_prev; |
| 418 | if (_autoFree) |
| 419 | delete *pos; |
| 420 | Node<t_T*> *node = static_cast<Node<t_T*> *>(pos._node); |
| 421 | prev->_next = next; |
| 422 | next->_prev = prev; |
| 423 | delete node; |
| 424 | return iterator(prev); |
| 425 | } |
| 426 | |
| 427 | iterator erase(iterator first, iterator last) { |
| 428 | while (first != last) |
| 429 | erase(first++); |
| 430 | |
| 431 | return last; |
| 432 | } |
| 433 | |
| 434 | void remove(t_T *const &val) { |
| 435 | iterator i = begin(); |
| 436 | while (i != end()) |
| 437 | if (val == i.operator*()) |
| 438 | i = erase(i); |
| 439 | else |
| 440 | ++i; |
| 441 | } |
| 442 | |
| 443 | |
| 444 | List<t_T*>& operator =(const List<t_T*>& list) { |
| 445 | if (this != &list) { |
| 446 | iterator i; |
| 447 | const_iterator j; |
| 448 | |
| 449 | for (i = begin(), j = list.begin(); (i != end()) && (j != list.end()) ; ++i, ++j) { |
| 450 | if (_autoFree) |
| 451 | delete *i; |
| 452 | static_cast<Node<t_T*> *>(i._node)->_data = static_cast<Node<t_T*> *>(j._node)->_data; |
| 453 | } |
| 454 | |
| 455 | if (i == end()) |
| 456 | insert(i, j, list.end()); |
| 457 | else |
| 458 | erase(i, end()); |
| 459 | // FIXME: really set _autoFree to false here? |
| 460 | _autoFree = false; |
| 461 | } |
| 462 | |
| 463 | return *this; |
| 464 | } |
| 465 | |
| 466 | uint size() const { |
| 467 | int n = 0; |
| 468 | for (const_iterator i = begin(); i != end(); ++i) |
| 469 | ++n; |
| 470 | return n; |
| 471 | } |
| 472 | |
| 473 | void clear() { |
| 474 | erase(begin(), end()); |
| 475 | } |
| 476 | |
| 477 | bool empty() const { |
| 478 | return (_anchor == _anchor->_next); |
| 479 | } |
| 480 | |
| 481 | |
| 482 | iterator begin() { |
| 483 | return iterator(_anchor->_next); |
| 484 | } |
| 485 | |
| 486 | iterator reverse_begin() { |
| 487 | return iterator(_anchor->_prev); |
| 488 | } |
| 489 | |
| 490 | iterator end() { |
| 491 | return iterator(_anchor); |
| 492 | } |
| 493 | |
| 494 | const_iterator begin() const { |
| 495 | return const_iterator(_anchor->_next); |
| 496 | } |
| 497 | |
| 498 | const_iterator reverse_begin() const { |
| 499 | return const_iterator(_anchor->_prev); |
| 500 | } |
| 501 | |
| 502 | const_iterator end() const { |
| 503 | return const_iterator(_anchor); |
| 504 | } |
| 505 | }; |