Go to the
documentation of this file.
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifndef QLINKEDLIST_H
00043 #define QLINKEDLIST_H
00044
00045 #include <QtCore/qiterator.h>
00046 #include <QtCore/qatomic.h>
00047
00048 #ifndef QT_NO_STL
00049 #include <iterator>
00050 #include <list>
00051 #endif
00052
00053 QT_BEGIN_HEADER
00054
00055 QT_BEGIN_NAMESPACE
00056
00057 QT_MODULE(Core)
00058
00059 struct Q_CORE_EXPORT QLinkedListData
00060 {
00061 QLinkedListData *n, *p;
00062 QBasicAtomicInt ref;
00063 int size;
00064 uint sharable : 1;
00065
00066 static QLinkedListData shared_null;
00067 };
00068
00069 template <typename T>
00070 struct QLinkedListNode
00071 {
00072 inline QLinkedListNode(const T &arg): t(arg) { }
00073 QLinkedListNode *n, *p;
00074 T t;
00075 };
00076
00077 template <class T>
00078 class QLinkedList
00079 {
00080 typedef QLinkedListNode<T> Node;
00081 union { QLinkedListData *d; QLinkedListNode<T> *e; };
00082
00083 public:
00084 inline QLinkedList() : d(&QLinkedListData::shared_null) { d->ref.ref(); }
00085 inline QLinkedList(const QLinkedList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); }
00086 ~QLinkedList();
00087 QLinkedList<T> &operator=(const QLinkedList<T> &);
00088 bool operator==(const QLinkedList<T> &l) const;
00089 inline bool operator!=(const QLinkedList<T> &l) const { return !(*this == l); }
00090
00091 inline int size() const { return d->size; }
00092 inline void detach()
00093 { if (d->ref != 1) detach_helper(); }
00094 inline bool isDetached() const { return d->ref == 1; }
00095 inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
00096 inline bool isSharedWith(const QLinkedList<T> &other) const { return d == other.d; }
00097
00098 inline bool isEmpty() const { return d->size == 0; }
00099
00100 void clear();
00101
00102 void append(const T &);
00103 void prepend(const T &);
00104 T takeFirst();
00105 T takeLast();
00106 int removeAll(const T &t);
00107 bool removeOne(const T &t);
00108 bool contains(const T &t) const;
00109 int count(const T &t) const;
00110
00111 class const_iterator;
00112
00113 class iterator
00114 {
00115 public:
00116 typedef std::bidirectional_iterator_tag iterator_category;
00117 typedef qptrdiff difference_type;
00118 typedef T value_type;
00119 typedef T *pointer;
00120 typedef T &reference;
00121 Node *i;
00122 inline iterator() : i(0) {}
00123 inline iterator(Node *n) : i(n) {}
00124 inline iterator(const iterator &o) : i(o.i) {}
00125 inline iterator &operator=(const iterator &o) { i = o.i; return *this; }
00126 inline T &operator*() const { return i->t; }
00127 inline T *operator->() const { return &i->t; }
00128 inline bool operator==(const iterator &o) const { return i == o.i; }
00129 inline bool operator!=(const iterator &o) const { return i != o.i; }
00130 inline bool operator==(const const_iterator &o) const
00131 { return i == o.i; }
00132 inline bool operator!=(const const_iterator &o) const
00133 { return i != o.i; }
00134 inline iterator &operator++() { i = i->n; return *this; }
00135 inline iterator operator++(int) { Node *n = i; i = i->n; return n; }
00136 inline iterator &operator--() { i = i->p; return *this; }
00137 inline iterator operator--(int) { Node *n = i; i = i->p; return n; }
00138 inline iterator operator+(int j) const
00139 { Node *n = i; if (j > 0) while (j--) n = n->n; else while (j++) n = n->p; return n; }
00140 inline iterator operator-(int j) const { return operator+(-j); }
00141 inline iterator &operator+=(int j) { return *this = *this + j; }
00142 inline iterator &operator-=(int j) { return *this = *this - j; }
00143 };
00144 friend class iterator;
00145
00146 class const_iterator
00147 {
00148 public:
00149 typedef std::bidirectional_iterator_tag iterator_category;
00150 typedef qptrdiff difference_type;
00151 typedef T value_type;
00152 typedef const T *pointer;
00153 typedef const T &reference;
00154 Node *i;
00155 inline const_iterator() : i(0) {}
00156 inline const_iterator(Node *n) : i(n) {}
00157 inline const_iterator(const const_iterator &o) : i(o.i){}
00158 inline const_iterator(iterator ci) : i(ci.i){}
00159 inline const_iterator &operator=(const const_iterator &o) { i = o.i; return *this; }
00160 inline const T &operator*() const { return i->t; }
00161 inline const T *operator->() const { return &i->t; }
00162 inline bool operator==(const const_iterator &o) const { return i == o.i; }
00163 inline bool operator!=(const const_iterator &o) const { return i != o.i; }
00164 inline const_iterator &operator++() { i = i->n; return *this; }
00165 inline const_iterator operator++(int) { Node *n = i; i = i->n; return n; }
00166 inline const_iterator &operator--() { i = i->p; return *this; }
00167 inline const_iterator operator--(int) { Node *n = i; i = i->p; return n; }
00168 inline const_iterator operator+(int j) const
00169 { Node *n = i; if (j > 0) while (j--) n = n->n; else while (j++) n = n->p; return n; }
00170 inline const_iterator operator-(int j) const { return operator+(-j); }
00171 inline const_iterator &operator+=(int j) { return *this = *this + j; }
00172 inline const_iterator &operator-=(int j) { return *this = *this - j; }
00173 };
00174 friend class const_iterator;
00175
00176
00177 inline iterator begin() { detach(); return e->n; }
00178 inline const_iterator begin() const { return e->n; }
00179 inline const_iterator constBegin() const { return e->n; }
00180 inline iterator end() { detach(); return e; }
00181 inline const_iterator end() const { return e; }
00182 inline const_iterator constEnd() const { return e; }
00183 iterator insert(iterator before, const T &t);
00184 iterator erase(iterator pos);
00185 iterator erase(iterator first, iterator last);
00186
00187
00188 typedef iterator Iterator;
00189 typedef const_iterator ConstIterator;
00190 inline int count() const { return d->size; }
00191 inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
00192 inline const T& first() const { Q_ASSERT(!isEmpty()); return *begin(); }
00193 T& last() { Q_ASSERT(!isEmpty()); return *(--end()); }
00194 const T& last() const { Q_ASSERT(!isEmpty()); return *(--end()); }
00195 inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); }
00196 inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); }
00197 inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
00198 inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
00199
00200
00201 inline void push_back(const T &t) { append(t); }
00202 inline void push_front(const T &t) { prepend(t); }
00203 inline T& front() { return first(); }
00204 inline const T& front() const { return first(); }
00205 inline T& back() { return last(); }
00206 inline const T& back() const { return last(); }
00207 inline void pop_front() { removeFirst(); }
00208 inline void pop_back() { removeLast(); }
00209 inline bool empty() const { return isEmpty(); }
00210 typedef int size_type;
00211 typedef T value_type;
00212 typedef value_type *pointer;
00213 typedef const value_type *const_pointer;
00214 typedef value_type &reference;
00215 typedef const value_type &const_reference;
00216 typedef qptrdiff difference_type;
00217
00218 #ifndef QT_NO_STL
00219 static inline QLinkedList<T> fromStdList(const std::list<T> &list)
00220 { QLinkedList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
00221 inline std::list<T> toStdList() const
00222 { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
00223 #endif
00224
00225 #ifdef QT3_SUPPORT
00226
00227 inline QT3_SUPPORT iterator remove(iterator pos) { return erase(pos); }
00228 inline QT3_SUPPORT int findIndex(const T& t) const
00229 { int i=0; for (const_iterator it = begin(); it != end(); ++it, ++i) if(*it == t) return i; return -1;}
00230 inline QT3_SUPPORT iterator find(iterator from, const T& t)
00231 { while (from != end() && !(*from == t)) ++from; return from; }
00232 inline QT3_SUPPORT iterator find(const T& t)
00233 { return find(begin(), t); }
00234 inline QT3_SUPPORT const_iterator find(const_iterator from, const T& t) const
00235 { while (from != end() && !(*from == t)) ++from; return from; }
00236 inline QT3_SUPPORT const_iterator find(const T& t) const
00237 { return find(begin(), t); }
00238 #endif
00239
00240
00241 QLinkedList<T> &operator+=(const QLinkedList<T> &l);
00242 QLinkedList<T> operator+(const QLinkedList<T> &l) const;
00243 inline QLinkedList<T> &operator+=(const T &t) { append(t); return *this; }
00244 inline QLinkedList<T> &operator<< (const T &t) { append(t); return *this; }
00245 inline QLinkedList<T> &operator<<(const QLinkedList<T> &l) { *this += l; return *this; }
00246
00247 private:
00248 void detach_helper();
00249 void free(QLinkedListData*);
00250 };
00251
00252 template <typename T>
00253 inline QLinkedList<T>::~QLinkedList()
00254 {
00255 if (!d)
00256 return;
00257 if (!d->ref.deref())
00258 free(d);
00259 }
00260
00261 template <typename T>
00262 void QLinkedList<T>::detach_helper()
00263 {
00264 union { QLinkedListData *d; Node *e; } x;
00265 x.d = new QLinkedListData;
00266 x.d->ref = 1;
00267 x.d->size = d->size;
00268 x.d->sharable = true;
00269 Node *original = e->n;
00270 Node *copy = x.e;
00271 while (original != e) {
00272 QT_TRY {
00273 copy->n = new Node(original->t);
00274 copy->n->p = copy;
00275 original = original->n;
00276 copy = copy->n;
00277 } QT_CATCH(...) {
00278 copy->n = x.e;
00279 free(x.d);
00280 QT_RETHROW;
00281 }
00282 }
00283 copy->n = x.e;
00284 x.e->p = copy;
00285 if (!d->ref.deref())
00286 free(d);
00287 d = x.d;
00288 }
00289
00290 template <typename T>
00291 void QLinkedList<T>::free(QLinkedListData *x)
00292 {
00293 Node *y = reinterpret_cast<Node*>(x);
00294 Node *i = y->n;
00295 if (x->ref == 0) {
00296 while(i != y) {
00297 Node *n = i;
00298 i = i->n;
00299 delete n;
00300 }
00301 delete x;
00302 }
00303 }
00304
00305 template <typename T>
00306 void QLinkedList<T>::clear()
00307 {
00308 *this = QLinkedList<T>();
00309 }
00310
00311 template <typename T>
00312 QLinkedList<T> &QLinkedList<T>::operator=(const QLinkedList<T> &l)
00313 {
00314 if (d != l.d) {
00315 QLinkedListData *o = l.d;
00316 o->ref.ref();
00317 if (!d->ref.deref())
00318 free(d);
00319 d = o;
00320 if (!d->sharable)
00321 detach_helper();
00322 }
00323 return *this;
00324 }
00325
00326 template <typename T>
00327 bool QLinkedList<T>::operator== (const QLinkedList<T> &l) const
00328 {
00329 if (d->size != l.d->size)
00330 return false;
00331 if (e == l.e)
00332 return true;
00333 Node *i = e->n;
00334 Node *il = l.e->n;
00335 while (i != e) {
00336 if (! (i->t == il->t))
00337 return false;
00338 i = i->n;
00339 il = il->n;
00340 }
00341 return true;
00342 }
00343
00344 template <typename T>
00345 void QLinkedList<T>::append(const T &t)
00346 {
00347 detach();
00348 Node *i = new Node(t);
00349 i->n = e;
00350 i->p = e->p;
00351 i->p->n = i;
00352 e->p = i;
00353 d->size++;
00354 }
00355
00356 template <typename T>
00357 void QLinkedList<T>::prepend(const T &t)
00358 {
00359 detach();
00360 Node *i = new Node(t);
00361 i->n = e->n;
00362 i->p = e;
00363 i->n->p = i;
00364 e->n = i;
00365 d->size++;
00366 }
00367
00368 template <typename T>
00369 int QLinkedList<T>::removeAll(const T &_t)
00370 {
00371 detach();
00372 const T t = _t;
00373 Node *i = e->n;
00374 int c = 0;
00375 while (i != e) {
00376 if (i->t == t) {
00377 Node *n = i;
00378 i->n->p = i->p;
00379 i->p->n = i->n;
00380 i = i->n;
00381 delete n;
00382 c++;
00383 } else {
00384 i = i->n;
00385 }
00386 }
00387 d->size-=c;
00388 return c;
00389 }
00390
00391 template <typename T>
00392 bool QLinkedList<T>::removeOne(const T &_t)
00393 {
00394 detach();
00395 iterator it = qFind(begin(), end(), _t);
00396 if (it != end()) {
00397 erase(it);
00398 return true;
00399 }
00400 return false;
00401 }
00402
00403 template <typename T>
00404 inline T QLinkedList<T>::takeFirst()
00405 {
00406 T t = first();
00407 removeFirst();
00408 return t;
00409 }
00410
00411 template <typename T>
00412 inline T QLinkedList<T>::takeLast()
00413 {
00414 T t = last();
00415 removeLast();
00416 return t;
00417 }
00418
00419 template <typename T>
00420 bool QLinkedList<T>::contains(const T &t) const
00421 {
00422 Node *i = e;
00423 while ((i = i->n) != e)
00424 if (i->t == t)
00425 return true;
00426 return false;
00427 }
00428
00429 template <typename T>
00430 int QLinkedList<T>::count(const T &t) const
00431 {
00432 Node *i = e;
00433 int c = 0;
00434 while ((i = i->n) != e)
00435 if (i->t == t)
00436 c++;
00437 return c;
00438 }
00439
00440
00441 template <typename T>
00442 typename QLinkedList<T>::iterator QLinkedList<T>::insert(iterator before, const T &t)
00443 {
00444 Node *i = before.i;
00445 Node *m = new Node(t);
00446 m->n = i;
00447 m->p = i->p;
00448 m->p->n = m;
00449 i->p = m;
00450 d->size++;
00451 return m;
00452 }
00453
00454 template <typename T>
00455 typename QLinkedList<T>::iterator QLinkedList<T>::erase(typename QLinkedList<T>::iterator afirst,
00456 typename QLinkedList<T>::iterator alast)
00457 {
00458 while (afirst != alast)
00459 erase(afirst++);
00460 return alast;
00461 }
00462
00463
00464 template <typename T>
00465 typename QLinkedList<T>::iterator QLinkedList<T>::erase(iterator pos)
00466 {
00467 detach();
00468 Node *i = pos.i;
00469 if (i != e) {
00470 Node *n = i;
00471 i->n->p = i->p;
00472 i->p->n = i->n;
00473 i = i->n;
00474 delete n;
00475 d->size--;
00476 }
00477 return i;
00478 }
00479
00480 template <typename T>
00481 QLinkedList<T> &QLinkedList<T>::operator+=(const QLinkedList<T> &l)
00482 {
00483 detach();
00484 int n = l.d->size;
00485 d->size += n;
00486 Node *original = l.e->n;
00487 while (n--) {
00488 QT_TRY {
00489 Node *copy = new Node(original->t);
00490 original = original->n;
00491 copy->n = e;
00492 copy->p = e->p;
00493 copy->p->n = copy;
00494 e->p = copy;
00495 } QT_CATCH(...) {
00496
00497 while (n++<d->size)
00498 removeLast();
00499 QT_RETHROW;
00500 }
00501 }
00502 return *this;
00503 }
00504
00505 template <typename T>
00506 QLinkedList<T> QLinkedList<T>::operator+(const QLinkedList<T> &l) const
00507 {
00508 QLinkedList<T> n = *this;
00509 n += l;
00510 return n;
00511 }
00512
00513 Q_DECLARE_SEQUENTIAL_ITERATOR(LinkedList)
00514 Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(LinkedList)
00515
00516 QT_END_NAMESPACE
00517
00518 QT_END_HEADER
00519
00520 #endif // QLINKEDLIST_H