qlinkedlist.h
上传用户:detong
上传日期:2022-06-22
资源大小:20675k
文件大小:14k
源码类别:

系统编程

开发平台:

Unix_Linux

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
  4. ** Contact: Qt Software Information (qt-info@nokia.com)
  5. **
  6. ** This file is part of the QtCore module of the Qt Toolkit.
  7. **
  8. ** Commercial Usage
  9. ** Licensees holding valid Qt Commercial licenses may use this file in
  10. ** accordance with the Qt Commercial License Agreement provided with the
  11. ** Software or, alternatively, in accordance with the terms contained in
  12. ** a written agreement between you and Nokia.
  13. **
  14. **
  15. ** GNU General Public License Usage
  16. ** Alternatively, this file may be used under the terms of the GNU
  17. ** General Public License versions 2.0 or 3.0 as published by the Free
  18. ** Software Foundation and appearing in the file LICENSE.GPL included in
  19. ** the packaging of this file.  Please review the following information
  20. ** to ensure GNU General Public Licensing requirements will be met:
  21. ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
  22. ** http://www.gnu.org/copyleft/gpl.html.  In addition, as a special
  23. ** exception, Nokia gives you certain additional rights. These rights
  24. ** are described in the Nokia Qt GPL Exception version 1.3, included in
  25. ** the file GPL_EXCEPTION.txt in this package.
  26. **
  27. ** Qt for Windows(R) Licensees
  28. ** As a special exception, Nokia, as the sole copyright holder for Qt
  29. ** Designer, grants users of the Qt/Eclipse Integration plug-in the
  30. ** right for the Qt/Eclipse Integration to link to functionality
  31. ** provided by Qt Designer and its related libraries.
  32. **
  33. ** If you are unsure which license is appropriate for your use, please
  34. ** contact the sales department at qt-sales@nokia.com.
  35. **
  36. ****************************************************************************/
  37. #ifndef QLINKEDLIST_H
  38. #define QLINKEDLIST_H
  39. #include <QtCore/qiterator.h>
  40. #include <QtCore/qatomic.h>
  41. #ifndef QT_NO_STL
  42. #include <iterator>
  43. #include <list>
  44. #endif
  45. QT_BEGIN_HEADER
  46. QT_BEGIN_NAMESPACE
  47. QT_MODULE(Core)
  48. struct Q_CORE_EXPORT QLinkedListData
  49. {
  50.     QLinkedListData *n, *p;
  51.     QBasicAtomicInt ref;
  52.     int size;
  53.     uint sharable : 1;
  54.     static QLinkedListData shared_null;
  55. };
  56. template <typename T>
  57. struct QLinkedListNode
  58. {
  59.     inline QLinkedListNode(const T &arg): t(arg) { }
  60.     QLinkedListNode *n, *p;
  61.     T t;
  62. };
  63. template <class T>
  64. class QLinkedList
  65. {
  66.     typedef QLinkedListNode<T> Node;
  67.     union { QLinkedListData *d; QLinkedListNode<T> *e; };
  68. public:
  69.     inline QLinkedList() : d(&QLinkedListData::shared_null) { d->ref.ref(); }
  70.     inline QLinkedList(const QLinkedList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); }
  71.     ~QLinkedList();
  72.     QLinkedList<T> &operator=(const QLinkedList<T> &);
  73.     bool operator==(const QLinkedList<T> &l) const;
  74.     inline bool operator!=(const QLinkedList<T> &l) const { return !(*this == l); }
  75.     inline int size() const { return d->size; }
  76.     inline void detach()
  77.     { if (d->ref != 1) detach_helper(); }
  78.     inline bool isDetached() const { return d->ref == 1; }
  79.     inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
  80.     inline bool isEmpty() const { return d->size == 0; }
  81.     void clear();
  82.     void append(const T &);
  83.     void prepend(const T &);
  84.     T takeFirst();
  85.     T takeLast();
  86.     int removeAll(const T &t);
  87.     bool removeOne(const T &t);
  88.     bool contains(const T &t) const;
  89.     int count(const T &t) const;
  90.     class const_iterator;
  91.     class iterator
  92.     {
  93.     public:
  94.         typedef std::bidirectional_iterator_tag  iterator_category;
  95.         typedef ptrdiff_t  difference_type;
  96.         typedef T value_type;
  97.         typedef T *pointer;
  98.         typedef T &reference;
  99.         Node *i;
  100.         inline iterator() : i(0) {}
  101.         inline iterator(Node *n) : i(n) {}
  102.         inline iterator(const iterator &o) : i(o.i) {}
  103.         inline iterator &operator=(const iterator &o) { i = o.i; return *this; }
  104.         inline T &operator*() const { return i->t; }
  105.         inline T *operator->() const { return &i->t; }
  106.         inline bool operator==(const iterator &o) const { return i == o.i; }
  107.         inline bool operator!=(const iterator &o) const { return i != o.i; }
  108.         inline bool operator==(const const_iterator &o) const
  109.             { return i == o.i; }
  110.         inline bool operator!=(const const_iterator &o) const
  111.             { return i != o.i; }
  112.         inline iterator &operator++() { i = i->n; return *this; }
  113.         inline iterator operator++(int) { Node *n = i; i = i->n; return n; }
  114.         inline iterator &operator--() { i = i->p; return *this; }
  115.         inline iterator operator--(int) { Node *n = i; i = i->p; return n; }
  116.         inline iterator operator+(int j) const
  117.         { Node *n = i; if (j > 0) while (j--) n = n->n; else while (j++) n = n->p; return n; }
  118.         inline iterator operator-(int j) const { return operator+(-j); }
  119.         inline iterator &operator+=(int j) { return *this = *this + j; }
  120.         inline iterator &operator-=(int j) { return *this = *this - j; }
  121.     };
  122.     friend class iterator;
  123.     class const_iterator
  124.     {
  125.     public:
  126.         typedef std::bidirectional_iterator_tag  iterator_category;
  127.         typedef ptrdiff_t  difference_type;
  128.         typedef T value_type;
  129.         typedef const T *pointer;
  130.         typedef const T &reference;
  131.         Node *i;
  132.         inline const_iterator() : i(0) {}
  133.         inline const_iterator(Node *n) : i(n) {}
  134.         inline const_iterator(const const_iterator &o) : i(o.i){}
  135.         inline const_iterator(iterator ci) : i(ci.i){}
  136. inline const_iterator &operator=(const const_iterator &o) { i = o.i; return *this; }
  137.         inline const T &operator*() const { return i->t; }
  138.         inline const T *operator->() const { return &i->t; }
  139.         inline bool operator==(const const_iterator &o) const { return i == o.i; }
  140.         inline bool operator!=(const const_iterator &o) const { return i != o.i; }
  141.         inline const_iterator &operator++() { i = i->n; return *this; }
  142.         inline const_iterator operator++(int) { Node *n = i; i = i->n; return n; }
  143.         inline const_iterator &operator--() { i = i->p; return *this; }
  144.         inline const_iterator operator--(int) { Node *n = i; i = i->p; return n; }
  145.         inline const_iterator operator+(int j) const
  146.         { Node *n = i; if (j > 0) while (j--) n = n->n; else while (j++) n = n->p; return n; }
  147.         inline const_iterator operator-(int j) const { return operator+(-j); }
  148.         inline const_iterator &operator+=(int j) { return *this = *this + j; }
  149.         inline const_iterator &operator-=(int j) { return *this = *this - j; }
  150.     };
  151.     friend class const_iterator;
  152.     // stl style
  153.     inline iterator begin() { detach(); return e->n; }
  154.     inline const_iterator begin() const { return e->n; }
  155.     inline const_iterator constBegin() const { return e->n; }
  156.     inline iterator end() { detach(); return e; }
  157.     inline const_iterator end() const { return e; }
  158.     inline const_iterator constEnd() const { return e; }
  159.     iterator insert(iterator before, const T &t);
  160.     iterator erase(iterator pos);
  161.     iterator erase(iterator first, iterator last);
  162.     // more Qt
  163.     typedef iterator Iterator;
  164.     typedef const_iterator ConstIterator;
  165.     inline int count() const { return d->size; }
  166.     inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
  167.     inline const T& first() const { Q_ASSERT(!isEmpty()); return *begin(); }
  168.     T& last() { Q_ASSERT(!isEmpty()); return *(--end()); }
  169.     const T& last() const { Q_ASSERT(!isEmpty()); return *(--end()); }
  170.     inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); }
  171.     inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); }
  172.     // stl compatibility
  173.     inline void push_back(const T &t) { append(t); }
  174.     inline void push_front(const T &t) { prepend(t); }
  175.     inline T& front() { return first(); }
  176.     inline const T& front() const { return first(); }
  177.     inline T& back() { return last(); }
  178.     inline const T& back() const { return last(); }
  179.     inline void pop_front() { removeFirst(); }
  180.     inline void pop_back() { removeLast(); }
  181.     inline bool empty() const { return isEmpty(); }
  182.     typedef int size_type;
  183.     typedef T value_type;
  184.     typedef value_type *pointer;
  185.     typedef const value_type *const_pointer;
  186.     typedef value_type &reference;
  187.     typedef const value_type &const_reference;
  188.     typedef ptrdiff_t difference_type;
  189. #ifndef QT_NO_STL
  190.     static inline QLinkedList<T> fromStdList(const std::list<T> &list)
  191.     { QLinkedList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
  192.     inline std::list<T> toStdList() const
  193.     { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
  194. #endif
  195. #ifdef QT3_SUPPORT
  196.     // compatibility
  197.     inline QT3_SUPPORT iterator remove(iterator pos) { return erase(pos); }
  198.     inline QT3_SUPPORT int findIndex(const T& t) const
  199.     { int i=0; for (const_iterator it = begin(); it != end(); ++it, ++i) if(*it == t) return i; return -1;}
  200.     inline QT3_SUPPORT iterator find(iterator from, const T& t)
  201.     { while (from != end() && !(*from == t)) ++from; return from; }
  202.     inline QT3_SUPPORT iterator find(const T& t)
  203.     { return find(begin(), t); }
  204.     inline QT3_SUPPORT const_iterator find(const_iterator from, const T& t) const
  205.     { while (from != end() && !(*from == t)) ++from; return from; }
  206.     inline QT3_SUPPORT const_iterator find(const T& t) const
  207.     { return find(begin(), t); }
  208. #endif
  209.     // comfort
  210.     QLinkedList<T> &operator+=(const QLinkedList<T> &l);
  211.     QLinkedList<T> operator+(const QLinkedList<T> &l) const;
  212.     inline QLinkedList<T> &operator+=(const T &t) { append(t); return *this; }
  213.     inline QLinkedList<T> &operator<< (const T &t) { append(t); return *this; }
  214.     inline QLinkedList<T> &operator<<(const QLinkedList<T> &l) { *this += l; return *this; }
  215. private:
  216.     void detach_helper();
  217.     void free(QLinkedListData*);
  218. };
  219. template <typename T>
  220. inline QLinkedList<T>::~QLinkedList()
  221. {
  222.     if (!d)
  223.         return;
  224.     if (!d->ref.deref())
  225.         free(d);
  226. }
  227. template <typename T>
  228. void QLinkedList<T>::detach_helper()
  229. {
  230.     union { QLinkedListData *d; Node *e; } x;
  231.     x.d = new QLinkedListData;
  232.     x.d->ref = 1;
  233.     x.d->size = d->size;
  234.     x.d->sharable = true;
  235.     Node *i = e->n, *j = x.e;
  236.     while (i != e) {
  237.         j->n = new Node(i->t);
  238.         j->n->p = j;
  239.         i = i->n;
  240.         j = j->n;
  241.     }
  242.     j->n = x.e;
  243.     x.e->p = j;
  244.     if (!d->ref.deref())
  245.         free(d);
  246.     d = x.d;
  247. }
  248. template <typename T>
  249. void QLinkedList<T>::free(QLinkedListData *x)
  250. {
  251.     Node *y = reinterpret_cast<Node*>(x);
  252.     Node *i = y->n;
  253.     if (x->ref == 0) {
  254.         while(i != y) {
  255.             Node *n = i;
  256.             i = i->n;
  257.             delete n;
  258.         }
  259.         delete x;
  260.     }
  261. }
  262. template <typename T>
  263. void QLinkedList<T>::clear()
  264. {
  265.     *this = QLinkedList<T>();
  266. }
  267. template <typename T>
  268. QLinkedList<T> &QLinkedList<T>::operator=(const QLinkedList<T> &l)
  269. {
  270.     if (d != l.d) {
  271.         l.d->ref.ref();
  272.         if (!d->ref.deref())
  273.             free(d);
  274.         d = l.d;
  275.         if (!d->sharable)
  276.             detach_helper();
  277.     }
  278.     return *this;
  279. }
  280. template <typename T>
  281. bool QLinkedList<T>::operator== (const QLinkedList<T> &l) const
  282. {
  283.     if (d->size != l.d->size)
  284.         return false;
  285.     if (e == l.e)
  286.         return true;
  287.     Node *i = e->n;
  288.     Node *il = l.e->n;
  289.     while (i != e) {
  290.         if (! (i->t == il->t))
  291.             return false;
  292.         i = i->n;
  293.         il = il->n;
  294.     }
  295.     return true;
  296. }
  297. template <typename T>
  298. void QLinkedList<T>::append(const T &t)
  299. {
  300.     detach();
  301.     Node *i = new Node(t);
  302.     i->n = e;
  303.     i->p = e->p;
  304.     i->p->n = i;
  305.     e->p = i;
  306.     d->size++;
  307. }
  308. template <typename T>
  309. void QLinkedList<T>::prepend(const T &t)
  310. {
  311.     detach();
  312.     Node *i = new Node(t);
  313.     i->n = e->n;
  314.     i->p = e;
  315.     i->n->p = i;
  316.     e->n = i;
  317.     d->size++;
  318. }
  319. template <typename T>
  320. int QLinkedList<T>::removeAll(const T &_t)
  321. {
  322.     detach();
  323.     const T t = _t;
  324.     Node *i = e->n;
  325.     int c = 0;
  326.     while (i != e) {
  327.         if (i->t == t) {
  328.             Node *n = i;
  329.             i->n->p = i->p;
  330.             i->p->n = i->n;
  331.             i = i->n;
  332.             delete n;
  333.             c++;
  334.         } else {
  335.             i = i->n;
  336.         }
  337.     }
  338.     d->size-=c;
  339.     return c;
  340. }
  341. template <typename T>
  342. bool QLinkedList<T>::removeOne(const T &_t)
  343. {
  344.     detach();
  345.     iterator it = qFind(begin(), end(), _t);
  346.     if (it != end()) {
  347.         erase(it);
  348.         return true;
  349.     }
  350.     return false;
  351. }
  352. template <typename T>
  353. inline T QLinkedList<T>::takeFirst()
  354. {
  355.     T t = first();
  356.     removeFirst();
  357.     return t;
  358. }
  359. template <typename T>
  360. inline T QLinkedList<T>::takeLast()
  361. {
  362.     T t = last();
  363.     removeLast();
  364.     return t;
  365. }
  366. template <typename T>
  367. bool QLinkedList<T>::contains(const T &t) const
  368. {
  369.     Node *i = e;
  370.     while ((i = i->n) != e)
  371.         if (i->t == t)
  372.             return true;
  373.     return false;
  374. }
  375. template <typename T>
  376. int QLinkedList<T>::count(const T &t) const
  377. {
  378.     Node *i = e;
  379.     int c = 0;
  380.     while ((i = i->n) != e)
  381.         if (i->t == t)
  382.             c++;
  383.     return c;
  384. }
  385. template <typename T>
  386. typename QLinkedList<T>::iterator QLinkedList<T>::insert(iterator before, const T &t)
  387. {
  388.     Node *i = before.i;
  389.     Node *m = new Node(t);
  390.     m->n = i;
  391.     m->p = i->p;
  392.     m->p->n = m;
  393.     i->p = m;
  394.     d->size++;
  395.     return m;
  396. }
  397. template <typename T>
  398. typename QLinkedList<T>::iterator QLinkedList<T>::erase(typename QLinkedList<T>::iterator afirst,
  399.                                                          typename QLinkedList<T>::iterator alast)
  400. {
  401.     while (afirst != alast)
  402.         erase(afirst++);
  403.     return alast;
  404. }
  405. template <typename T>
  406. typename QLinkedList<T>::iterator QLinkedList<T>::erase(iterator pos)
  407. {
  408.     detach();
  409.     Node *i = pos.i;
  410.     if (i != e) {
  411.         Node *n = i;
  412.         i->n->p = i->p;
  413.         i->p->n = i->n;
  414.         i = i->n;
  415.         delete n;
  416.         d->size--;
  417.     }
  418.     return i;
  419. }
  420. template <typename T>
  421. QLinkedList<T> &QLinkedList<T>::operator+=(const QLinkedList<T> &l)
  422. {
  423.     detach();
  424.     int n = l.d->size;
  425.     d->size += n;
  426.     Node *o = l.e->n;
  427.     while (n--) {
  428.         Node *i = new Node(o->t);
  429.         o = o->n;
  430.         i->n = e;
  431.         i->p = e->p;
  432.         i->p->n = i;
  433.         e->p = i;
  434.     }
  435.     return *this;
  436. }
  437. template <typename T>
  438. QLinkedList<T> QLinkedList<T>::operator+(const QLinkedList<T> &l) const
  439. {
  440.     QLinkedList<T> n = *this;
  441.     n += l;
  442.     return n;
  443. }
  444. Q_DECLARE_SEQUENTIAL_ITERATOR(LinkedList)
  445. Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(LinkedList)
  446. QT_END_NAMESPACE
  447. QT_END_HEADER
  448. #endif // QLINKEDLIST_H