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 QLIST_H
00043 #define QLIST_H
00044
00045 #include <QtCore/qiterator.h>
00046 #include <QtCore/qatomic.h>
00047 #include <QtCore/qalgorithms.h>
00048
00049 #ifndef QT_NO_STL
00050 #include <iterator>
00051 #include <list>
00052 #endif
00053
00054 #include <new>
00055 #include <limits.h>
00056 #include <string.h>
00057
00058 QT_BEGIN_HEADER
00059
00060 QT_BEGIN_NAMESPACE
00061
00062 QT_MODULE(Core)
00063
00064 template <typename T> class QVector;
00065 template <typename T> class QSet;
00066
00067 struct Q_CORE_EXPORT QListData {
00068 struct Data {
00069 QBasicAtomicInt ref;
00070 int alloc, begin, end;
00071 uint sharable : 1;
00072 void *array[1];
00073 };
00074 enum { DataHeaderSize = sizeof(Data) - sizeof(void *) };
00075
00076 Data *detach(int alloc);
00077 Data *detach_grow(int *i, int n);
00078 Data *detach();
00079 Data *detach2();
00080 Data *detach3();
00081 void realloc(int alloc);
00082 static Data shared_null;
00083 Data *d;
00084 void **erase(void **xi);
00085 void **append(int n);
00086 void **append();
00087 void **append(const QListData &l);
00088 void **append2(const QListData &l);
00089 void **prepend();
00090 void **insert(int i);
00091 void remove(int i);
00092 void remove(int i, int n);
00093 void move(int from, int to);
00094 inline int size() const { return d->end - d->begin; }
00095 inline bool isEmpty() const { return d->end == d->begin; }
00096 inline void **at(int i) const { return d->array + d->begin + i; }
00097 inline void **begin() const { return d->array + d->begin; }
00098 inline void **end() const { return d->array + d->end; }
00099 };
00100
00101 template <typename T>
00102 class QList
00103 {
00104 struct Node { void *v;
00105 #if defined(Q_CC_BOR)
00106 Q_INLINE_TEMPLATE T &t();
00107 #else
00108 Q_INLINE_TEMPLATE T &t()
00109 { return *reinterpret_cast<T*>(QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
00110 ? v : this); }
00111 #endif
00112 };
00113
00114 union { QListData p; QListData::Data *d; };
00115
00116 public:
00117 inline QList() : d(&QListData::shared_null) { d->ref.ref(); }
00118 inline QList(const QList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
00119 ~QList();
00120 QList<T> &operator=(const QList<T> &l);
00121 bool operator==(const QList<T> &l) const;
00122 inline bool operator!=(const QList<T> &l) const { return !(*this == l); }
00123
00124 inline int size() const { return p.size(); }
00125
00126 inline void detach() { if (d->ref != 1) detach_helper(); }
00127
00128 inline void detachShared()
00129 {
00130
00131 if (d->ref != 1 && this->d != &QListData::shared_null)
00132 detach_helper();
00133 }
00134
00135 inline bool isDetached() const { return d->ref == 1; }
00136 inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
00137 inline bool isSharedWith(const QList<T> &other) const { return d == other.d; }
00138
00139 inline bool isEmpty() const { return p.isEmpty(); }
00140
00141 void clear();
00142
00143 const T &at(int i) const;
00144 const T &operator[](int i) const;
00145 T &operator[](int i);
00146
00147 void reserve(int size);
00148 void append(const T &t);
00149 void append(const QList<T> &t);
00150 void prepend(const T &t);
00151 void insert(int i, const T &t);
00152 void replace(int i, const T &t);
00153 void removeAt(int i);
00154 int removeAll(const T &t);
00155 bool removeOne(const T &t);
00156 T takeAt(int i);
00157 T takeFirst();
00158 T takeLast();
00159 void move(int from, int to);
00160 void swap(int i, int j);
00161 int indexOf(const T &t, int from = 0) const;
00162 int lastIndexOf(const T &t, int from = -1) const;
00163 QBool contains(const T &t) const;
00164 int count(const T &t) const;
00165
00166 class const_iterator;
00167
00168 class iterator {
00169 public:
00170 Node *i;
00171 typedef std::random_access_iterator_tag iterator_category;
00172 typedef qptrdiff difference_type;
00173 typedef T value_type;
00174 typedef T *pointer;
00175 typedef T &reference;
00176
00177 inline iterator() : i(0) {}
00178 inline iterator(Node *n) : i(n) {}
00179 inline iterator(const iterator &o): i(o.i){}
00180 inline T &operator*() const { return i->t(); }
00181 inline T *operator->() const { return &i->t(); }
00182 inline T &operator[](int j) const { return i[j].t(); }
00183 inline bool operator==(const iterator &o) const { return i == o.i; }
00184 inline bool operator!=(const iterator &o) const { return i != o.i; }
00185 inline bool operator<(const iterator& other) const { return i < other.i; }
00186 inline bool operator<=(const iterator& other) const { return i <= other.i; }
00187 inline bool operator>(const iterator& other) const { return i > other.i; }
00188 inline bool operator>=(const iterator& other) const { return i >= other.i; }
00189 #ifndef QT_STRICT_ITERATORS
00190 inline bool operator==(const const_iterator &o) const
00191 { return i == o.i; }
00192 inline bool operator!=(const const_iterator &o) const
00193 { return i != o.i; }
00194 inline bool operator<(const const_iterator& other) const
00195 { return i < other.i; }
00196 inline bool operator<=(const const_iterator& other) const
00197 { return i <= other.i; }
00198 inline bool operator>(const const_iterator& other) const
00199 { return i > other.i; }
00200 inline bool operator>=(const const_iterator& other) const
00201 { return i >= other.i; }
00202 #endif
00203 inline iterator &operator++() { ++i; return *this; }
00204 inline iterator operator++(int) { Node *n = i; ++i; return n; }
00205 inline iterator &operator--() { i--; return *this; }
00206 inline iterator operator--(int) { Node *n = i; i--; return n; }
00207 inline iterator &operator+=(int j) { i+=j; return *this; }
00208 inline iterator &operator-=(int j) { i-=j; return *this; }
00209 inline iterator operator+(int j) const { return iterator(i+j); }
00210 inline iterator operator-(int j) const { return iterator(i-j); }
00211 inline int operator-(iterator j) const { return int(i - j.i); }
00212 };
00213 friend class iterator;
00214
00215 class const_iterator {
00216 public:
00217 Node *i;
00218 typedef std::random_access_iterator_tag iterator_category;
00219 typedef qptrdiff difference_type;
00220 typedef T value_type;
00221 typedef const T *pointer;
00222 typedef const T &reference;
00223
00224 inline const_iterator() : i(0) {}
00225 inline const_iterator(Node *n) : i(n) {}
00226 inline const_iterator(const const_iterator &o): i(o.i) {}
00227 #ifdef QT_STRICT_ITERATORS
00228 inline explicit const_iterator(const iterator &o): i(o.i) {}
00229 #else
00230 inline const_iterator(const iterator &o): i(o.i) {}
00231 #endif
00232 inline const T &operator*() const { return i->t(); }
00233 inline const T *operator->() const { return &i->t(); }
00234 inline const T &operator[](int j) const { return i[j].t(); }
00235 inline bool operator==(const const_iterator &o) const { return i == o.i; }
00236 inline bool operator!=(const const_iterator &o) const { return i != o.i; }
00237 inline bool operator<(const const_iterator& other) const { return i < other.i; }
00238 inline bool operator<=(const const_iterator& other) const { return i <= other.i; }
00239 inline bool operator>(const const_iterator& other) const { return i > other.i; }
00240 inline bool operator>=(const const_iterator& other) const { return i >= other.i; }
00241 inline const_iterator &operator++() { ++i; return *this; }
00242 inline const_iterator operator++(int) { Node *n = i; ++i; return n; }
00243 inline const_iterator &operator--() { i--; return *this; }
00244 inline const_iterator operator--(int) { Node *n = i; i--; return n; }
00245 inline const_iterator &operator+=(int j) { i+=j; return *this; }
00246 inline const_iterator &operator-=(int j) { i-=j; return *this; }
00247 inline const_iterator operator+(int j) const { return const_iterator(i+j); }
00248 inline const_iterator operator-(int j) const { return const_iterator(i-j); }
00249 inline int operator-(const_iterator j) const { return i - j.i; }
00250 };
00251 friend class const_iterator;
00252
00253
00254 inline iterator begin() { detach(); return reinterpret_cast<Node *>(p.begin()); }
00255 inline const_iterator begin() const { return reinterpret_cast<Node *>(p.begin()); }
00256 inline const_iterator constBegin() const { return reinterpret_cast<Node *>(p.begin()); }
00257 inline iterator end() { detach(); return reinterpret_cast<Node *>(p.end()); }
00258 inline const_iterator end() const { return reinterpret_cast<Node *>(p.end()); }
00259 inline const_iterator constEnd() const { return reinterpret_cast<Node *>(p.end()); }
00260 iterator insert(iterator before, const T &t);
00261 iterator erase(iterator pos);
00262 iterator erase(iterator first, iterator last);
00263
00264
00265 typedef iterator Iterator;
00266 typedef const_iterator ConstIterator;
00267 inline int count() const { return p.size(); }
00268 inline int length() const { return p.size(); }
00269 inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
00270 inline const T& first() const { Q_ASSERT(!isEmpty()); return at(0); }
00271 T& last() { Q_ASSERT(!isEmpty()); return *(--end()); }
00272 const T& last() const { Q_ASSERT(!isEmpty()); return at(count() - 1); }
00273 inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); }
00274 inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); }
00275 inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
00276 inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
00277 QList<T> mid(int pos, int length = -1) const;
00278
00279 T value(int i) const;
00280 T value(int i, const T &defaultValue) const;
00281
00282
00283 inline void push_back(const T &t) { append(t); }
00284 inline void push_front(const T &t) { prepend(t); }
00285 inline T& front() { return first(); }
00286 inline const T& front() const { return first(); }
00287 inline T& back() { return last(); }
00288 inline const T& back() const { return last(); }
00289 inline void pop_front() { removeFirst(); }
00290 inline void pop_back() { removeLast(); }
00291 inline bool empty() const { return isEmpty(); }
00292 typedef int size_type;
00293 typedef T value_type;
00294 typedef value_type *pointer;
00295 typedef const value_type *const_pointer;
00296 typedef value_type &reference;
00297 typedef const value_type &const_reference;
00298 typedef qptrdiff difference_type;
00299
00300 #ifdef QT3_SUPPORT
00301 inline QT3_SUPPORT iterator remove(iterator pos) { return erase(pos); }
00302 inline QT3_SUPPORT int remove(const T &t) { return removeAll(t); }
00303 inline QT3_SUPPORT int findIndex(const T& t) const { return indexOf(t); }
00304 inline QT3_SUPPORT iterator find(const T& t)
00305 { int i = indexOf(t); return (i == -1 ? end() : (begin()+i)); }
00306 inline QT3_SUPPORT const_iterator find (const T& t) const
00307 { int i = indexOf(t); return (i == -1 ? end() : (begin()+i)); }
00308 inline QT3_SUPPORT iterator find(iterator from, const T& t)
00309 { int i = indexOf(t, from - begin()); return i == -1 ? end() : begin()+i; }
00310 inline QT3_SUPPORT const_iterator find(const_iterator from, const T& t) const
00311 { int i = indexOf(t, from - begin()); return i == -1 ? end() : begin()+i; }
00312 #endif
00313
00314
00315 QList<T> &operator+=(const QList<T> &l);
00316 inline QList<T> operator+(const QList<T> &l) const
00317 { QList n = *this; n += l; return n; }
00318 inline QList<T> &operator+=(const T &t)
00319 { append(t); return *this; }
00320 inline QList<T> &operator<< (const T &t)
00321 { append(t); return *this; }
00322 inline QList<T> &operator<<(const QList<T> &l)
00323 { *this += l; return *this; }
00324
00325 QVector<T> toVector() const;
00326 QSet<T> toSet() const;
00327
00328 static QList<T> fromVector(const QVector<T> &vector);
00329 static QList<T> fromSet(const QSet<T> &set);
00330
00331 #ifndef QT_NO_STL
00332 static inline QList<T> fromStdList(const std::list<T> &list)
00333 { QList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
00334 inline std::list<T> toStdList() const
00335 { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
00336 #endif
00337
00338 private:
00339 Node *detach_helper_grow(int i, int n);
00340 void detach_helper(int alloc);
00341 void detach_helper();
00342 void free(QListData::Data *d);
00343
00344 void node_construct(Node *n, const T &t);
00345 void node_destruct(Node *n);
00346 void node_copy(Node *from, Node *to, Node *src);
00347 void node_destruct(Node *from, Node *to);
00348 };
00349
00350 #if defined(Q_CC_BOR)
00351 template <typename T>
00352 Q_INLINE_TEMPLATE T &QList<T>::Node::t()
00353 { return QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic ? *(T*)v:*(T*)this; }
00354 #endif
00355
00356 template <typename T>
00357 Q_INLINE_TEMPLATE void QList<T>::node_construct(Node *n, const T &t)
00358 {
00359 if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t);
00360 else if (QTypeInfo<T>::isComplex) new (n) T(t);
00361 #if (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__IBMCPP__)) && !defined(__OPTIMIZE__)
00362
00363
00364
00365 else *reinterpret_cast<T*>(n) = t;
00366 #else
00367
00368 else ::memcpy(n, &t, sizeof(T));
00369 #endif
00370 }
00371
00372 template <typename T>
00373 Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *n)
00374 {
00375 if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) delete reinterpret_cast<T*>(n->v);
00376 else if (QTypeInfo<T>::isComplex) reinterpret_cast<T*>(n)->~T();
00377 }
00378
00379 template <typename T>
00380 Q_INLINE_TEMPLATE void QList<T>::node_copy(Node *from, Node *to, Node *src)
00381 {
00382 Node *current = from;
00383 if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
00384 QT_TRY {
00385 while(current != to) {
00386 current->v = new T(*reinterpret_cast<T*>(src->v));
00387 ++current;
00388 ++src;
00389 }
00390 } QT_CATCH(...) {
00391 while (current-- != from)
00392 delete reinterpret_cast<T*>(current->v);
00393 QT_RETHROW;
00394 }
00395
00396 } else if (QTypeInfo<T>::isComplex) {
00397 QT_TRY {
00398 while(current != to) {
00399 new (current) T(*reinterpret_cast<T*>(src));
00400 ++current;
00401 ++src;
00402 }
00403 } QT_CATCH(...) {
00404 while (current-- != from)
00405 (reinterpret_cast<T*>(current))->~T();
00406 QT_RETHROW;
00407 }
00408 } else {
00409 if (src != from && to - from > 0)
00410 memcpy(from, src, (to - from) * sizeof(Node *));
00411 }
00412 }
00413
00414 template <typename T>
00415 Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *from, Node *to)
00416 {
00417 if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic)
00418 while(from != to) --to, delete reinterpret_cast<T*>(to->v);
00419 else if (QTypeInfo<T>::isComplex)
00420 while (from != to) --to, reinterpret_cast<T*>(to)->~T();
00421 }
00422
00423 template <typename T>
00424 Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l)
00425 {
00426 if (d != l.d) {
00427 QListData::Data *o = l.d;
00428 o->ref.ref();
00429 if (!d->ref.deref())
00430 free(d);
00431 d = o;
00432 if (!d->sharable)
00433 detach_helper();
00434 }
00435 return *this;
00436 }
00437 template <typename T>
00438 inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t)
00439 {
00440 int iBefore = int(before.i - reinterpret_cast<Node *>(p.begin()));
00441 Node *n = reinterpret_cast<Node *>(p.insert(iBefore));
00442 QT_TRY {
00443 node_construct(n, t);
00444 } QT_CATCH(...) {
00445 p.remove(iBefore);
00446 QT_RETHROW;
00447 }
00448 return n;
00449 }
00450 template <typename T>
00451 inline typename QList<T>::iterator QList<T>::erase(iterator it)
00452 { node_destruct(it.i);
00453 return reinterpret_cast<Node *>(p.erase(reinterpret_cast<void**>(it.i))); }
00454 template <typename T>
00455 inline const T &QList<T>::at(int i) const
00456 { Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::at", "index out of range");
00457 return reinterpret_cast<Node *>(p.at(i))->t(); }
00458 template <typename T>
00459 inline const T &QList<T>::operator[](int i) const
00460 { Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::operator[]", "index out of range");
00461 return reinterpret_cast<Node *>(p.at(i))->t(); }
00462 template <typename T>
00463 inline T &QList<T>::operator[](int i)
00464 { Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::operator[]", "index out of range");
00465 detach(); return reinterpret_cast<Node *>(p.at(i))->t(); }
00466 template <typename T>
00467 inline void QList<T>::removeAt(int i)
00468 { if(i >= 0 && i < p.size()) { detach();
00469 node_destruct(reinterpret_cast<Node *>(p.at(i))); p.remove(i); } }
00470 template <typename T>
00471 inline T QList<T>::takeAt(int i)
00472 { Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::take", "index out of range");
00473 detach(); Node *n = reinterpret_cast<Node *>(p.at(i)); T t = n->t(); node_destruct(n);
00474 p.remove(i); return t; }
00475 template <typename T>
00476 inline T QList<T>::takeFirst()
00477 { T t = first(); removeFirst(); return t; }
00478 template <typename T>
00479 inline T QList<T>::takeLast()
00480 { T t = last(); removeLast(); return t; }
00481
00482 template <typename T>
00483 Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc)
00484 {
00485 if (d->alloc < alloc) {
00486 if (d->ref != 1)
00487 detach_helper(alloc);
00488 else
00489 p.realloc(alloc);
00490 }
00491 }
00492
00493 template <typename T>
00494 Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
00495 {
00496 if (d->ref != 1) {
00497 Node *n = detach_helper_grow(INT_MAX, 1);
00498 QT_TRY {
00499 node_construct(n, t);
00500 } QT_CATCH(...) {
00501 --d->end;
00502 QT_RETHROW;
00503 }
00504 } else {
00505 if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
00506 Node *n = reinterpret_cast<Node *>(p.append());
00507 QT_TRY {
00508 node_construct(n, t);
00509 } QT_CATCH(...) {
00510 --d->end;
00511 QT_RETHROW;
00512 }
00513 } else {
00514 Node *n, copy;
00515 node_construct(©, t);
00516 QT_TRY {
00517 n = reinterpret_cast<Node *>(p.append());;
00518 } QT_CATCH(...) {
00519 node_destruct(©);
00520 QT_RETHROW;
00521 }
00522 *n = copy;
00523 }
00524 }
00525 }
00526
00527 template <typename T>
00528 inline void QList<T>::prepend(const T &t)
00529 {
00530 if (d->ref != 1) {
00531 Node *n = detach_helper_grow(0, 1);
00532 QT_TRY {
00533 node_construct(n, t);
00534 } QT_CATCH(...) {
00535 ++d->begin;
00536 QT_RETHROW;
00537 }
00538 } else {
00539 if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
00540 Node *n = reinterpret_cast<Node *>(p.prepend());
00541 QT_TRY {
00542 node_construct(n, t);
00543 } QT_CATCH(...) {
00544 ++d->begin;
00545 QT_RETHROW;
00546 }
00547 } else {
00548 Node *n, copy;
00549 node_construct(©, t);
00550 QT_TRY {
00551 n = reinterpret_cast<Node *>(p.prepend());;
00552 } QT_CATCH(...) {
00553 node_destruct(©);
00554 QT_RETHROW;
00555 }
00556 *n = copy;
00557 }
00558 }
00559 }
00560
00561 template <typename T>
00562 inline void QList<T>::insert(int i, const T &t)
00563 {
00564 if (d->ref != 1) {
00565 Node *n = detach_helper_grow(i, 1);
00566 QT_TRY {
00567 node_construct(n, t);
00568 } QT_CATCH(...) {
00569 p.remove(i);
00570 QT_RETHROW;
00571 }
00572 } else {
00573 if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
00574 Node *n = reinterpret_cast<Node *>(p.insert(i));
00575 QT_TRY {
00576 node_construct(n, t);
00577 } QT_CATCH(...) {
00578 p.remove(i);
00579 QT_RETHROW;
00580 }
00581 } else {
00582 Node *n, copy;
00583 node_construct(©, t);
00584 QT_TRY {
00585 n = reinterpret_cast<Node *>(p.insert(i));;
00586 } QT_CATCH(...) {
00587 node_destruct(©);
00588 QT_RETHROW;
00589 }
00590 *n = copy;
00591 }
00592 }
00593 }
00594
00595 template <typename T>
00596 inline void QList<T>::replace(int i, const T &t)
00597 {
00598 Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::replace", "index out of range");
00599 detach();
00600 reinterpret_cast<Node *>(p.at(i))->t() = t;
00601 }
00602
00603 template <typename T>
00604 inline void QList<T>::swap(int i, int j)
00605 {
00606 Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(),
00607 "QList<T>::swap", "index out of range");
00608 detach();
00609 void *t = d->array[d->begin + i];
00610 d->array[d->begin + i] = d->array[d->begin + j];
00611 d->array[d->begin + j] = t;
00612 }
00613
00614 template <typename T>
00615 inline void QList<T>::move(int from, int to)
00616 {
00617 Q_ASSERT_X(from >= 0 && from < p.size() && to >= 0 && to < p.size(),
00618 "QList<T>::move", "index out of range");
00619 detach();
00620 p.move(from, to);
00621 }
00622
00623 template<typename T>
00624 Q_OUTOFLINE_TEMPLATE QList<T> QList<T>::mid(int pos, int alength) const
00625 {
00626 if (alength < 0 || pos + alength > size())
00627 alength = size() - pos;
00628 if (pos == 0 && alength == size())
00629 return *this;
00630 QList<T> cpy;
00631 cpy.reserve(alength);
00632 cpy.d->end = alength;
00633 QT_TRY {
00634 cpy.node_copy(reinterpret_cast<Node *>(cpy.p.begin()),
00635 reinterpret_cast<Node *>(cpy.p.end()),
00636 reinterpret_cast<Node *>(p.begin() + pos));
00637 } QT_CATCH(...) {
00638
00639 cpy.d->end = 0;
00640 QT_RETHROW;
00641 }
00642 return cpy;
00643 }
00644
00645 template<typename T>
00646 Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i) const
00647 {
00648 if (i < 0 || i >= p.size()) {
00649 return T();
00650 }
00651 return reinterpret_cast<Node *>(p.at(i))->t();
00652 }
00653
00654 template<typename T>
00655 Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i, const T& defaultValue) const
00656 {
00657 return ((i < 0 || i >= p.size()) ? defaultValue : reinterpret_cast<Node *>(p.at(i))->t());
00658 }
00659
00660 template <typename T>
00661 Q_OUTOFLINE_TEMPLATE typename QList<T>::Node *QList<T>::detach_helper_grow(int i, int c)
00662 {
00663 Node *n = reinterpret_cast<Node *>(p.begin());
00664 QListData::Data *x = p.detach_grow(&i, c);
00665 QT_TRY {
00666 node_copy(reinterpret_cast<Node *>(p.begin()),
00667 reinterpret_cast<Node *>(p.begin() + i), n);
00668 } QT_CATCH(...) {
00669 qFree(d);
00670 d = x;
00671 QT_RETHROW;
00672 }
00673 QT_TRY {
00674 node_copy(reinterpret_cast<Node *>(p.begin() + i + c),
00675 reinterpret_cast<Node *>(p.end()), n + i);
00676 } QT_CATCH(...) {
00677 node_destruct(reinterpret_cast<Node *>(p.begin()),
00678 reinterpret_cast<Node *>(p.begin() + i));
00679 qFree(d);
00680 d = x;
00681 QT_RETHROW;
00682 }
00683
00684 if (!x->ref.deref())
00685 free(x);
00686
00687 return reinterpret_cast<Node *>(p.begin() + i);
00688 }
00689
00690 template <typename T>
00691 Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper(int alloc)
00692 {
00693 Node *n = reinterpret_cast<Node *>(p.begin());
00694 QListData::Data *x = p.detach(alloc);
00695 QT_TRY {
00696 node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n);
00697 } QT_CATCH(...) {
00698 qFree(d);
00699 d = x;
00700 QT_RETHROW;
00701 }
00702
00703 if (!x->ref.deref())
00704 free(x);
00705 }
00706
00707 template <typename T>
00708 Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper()
00709 {
00710 detach_helper(d->alloc);
00711 }
00712
00713 template <typename T>
00714 Q_OUTOFLINE_TEMPLATE QList<T>::~QList()
00715 {
00716 if (d && !d->ref.deref())
00717 free(d);
00718 }
00719
00720 template <typename T>
00721 Q_OUTOFLINE_TEMPLATE bool QList<T>::operator==(const QList<T> &l) const
00722 {
00723 if (p.size() != l.p.size())
00724 return false;
00725 if (d == l.d)
00726 return true;
00727 Node *i = reinterpret_cast<Node *>(p.end());
00728 Node *b = reinterpret_cast<Node *>(p.begin());
00729 Node *li = reinterpret_cast<Node *>(l.p.end());
00730 while (i != b) {
00731 --i; --li;
00732 if (!(i->t() == li->t()))
00733 return false;
00734 }
00735 return true;
00736 }
00737
00738
00739 template <typename T>
00740 Q_OUTOFLINE_TEMPLATE void QList<T>::free(QListData::Data *data)
00741 {
00742 node_destruct(reinterpret_cast<Node *>(data->array + data->begin),
00743 reinterpret_cast<Node *>(data->array + data->end));
00744 if (data->ref == 0)
00745 qFree(data);
00746 }
00747
00748
00749 template <typename T>
00750 Q_OUTOFLINE_TEMPLATE void QList<T>::clear()
00751 {
00752 *this = QList<T>();
00753 }
00754
00755 template <typename T>
00756 Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t)
00757 {
00758 detachShared();
00759 const T t = _t;
00760 int removedCount=0, i=0;
00761 Node *n;
00762 while (i < p.size())
00763 if ((n = reinterpret_cast<Node *>(p.at(i)))->t() == t) {
00764 node_destruct(n);
00765 p.remove(i);
00766 ++removedCount;
00767 } else {
00768 ++i;
00769 }
00770 return removedCount;
00771 }
00772
00773 template <typename T>
00774 Q_OUTOFLINE_TEMPLATE bool QList<T>::removeOne(const T &_t)
00775 {
00776 detachShared();
00777 int index = indexOf(_t);
00778 if (index != -1) {
00779 removeAt(index);
00780 return true;
00781 }
00782 return false;
00783 }
00784
00785 template <typename T>
00786 Q_OUTOFLINE_TEMPLATE typename QList<T>::iterator QList<T>::erase(typename QList<T>::iterator afirst,
00787 typename QList<T>::iterator alast)
00788 {
00789 for (Node *n = afirst.i; n < alast.i; ++n)
00790 node_destruct(n);
00791 int idx = afirst - begin();
00792 p.remove(idx, alast - afirst);
00793 return begin() + idx;
00794 }
00795
00796 template <typename T>
00797 Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l)
00798 {
00799 if (!l.isEmpty()) {
00800 if (isEmpty()) {
00801 *this = l;
00802 } else {
00803 Node *n = (d->ref != 1)
00804 ? detach_helper_grow(INT_MAX, l.size())
00805 : reinterpret_cast<Node *>(p.append2(l.p));
00806 QT_TRY {
00807 node_copy(n, reinterpret_cast<Node *>(p.end()),
00808 reinterpret_cast<Node *>(l.p.begin()));
00809 } QT_CATCH(...) {
00810
00811 d->end -= int(reinterpret_cast<Node *>(p.end()) - n);
00812 QT_RETHROW;
00813 }
00814 }
00815 }
00816 return *this;
00817 }
00818
00819 template <typename T>
00820 inline void QList<T>::append(const QList<T> &t)
00821 {
00822 *this += t;
00823 }
00824
00825 template <typename T>
00826 Q_OUTOFLINE_TEMPLATE int QList<T>::indexOf(const T &t, int from) const
00827 {
00828 if (from < 0)
00829 from = qMax(from + p.size(), 0);
00830 if (from < p.size()) {
00831 Node *n = reinterpret_cast<Node *>(p.at(from -1));
00832 Node *e = reinterpret_cast<Node *>(p.end());
00833 while (++n != e)
00834 if (n->t() == t)
00835 return int(n - reinterpret_cast<Node *>(p.begin()));
00836 }
00837 return -1;
00838 }
00839
00840 template <typename T>
00841 Q_OUTOFLINE_TEMPLATE int QList<T>::lastIndexOf(const T &t, int from) const
00842 {
00843 if (from < 0)
00844 from += p.size();
00845 else if (from >= p.size())
00846 from = p.size()-1;
00847 if (from >= 0) {
00848 Node *b = reinterpret_cast<Node *>(p.begin());
00849 Node *n = reinterpret_cast<Node *>(p.at(from + 1));
00850 while (n-- != b) {
00851 if (n->t() == t)
00852 return n - b;
00853 }
00854 }
00855 return -1;
00856 }
00857
00858 template <typename T>
00859 Q_OUTOFLINE_TEMPLATE QBool QList<T>::contains(const T &t) const
00860 {
00861 Node *b = reinterpret_cast<Node *>(p.begin());
00862 Node *i = reinterpret_cast<Node *>(p.end());
00863 while (i-- != b)
00864 if (i->t() == t)
00865 return QBool(true);
00866 return QBool(false);
00867 }
00868
00869 template <typename T>
00870 Q_OUTOFLINE_TEMPLATE int QList<T>::count(const T &t) const
00871 {
00872 int c = 0;
00873 Node *b = reinterpret_cast<Node *>(p.begin());
00874 Node *i = reinterpret_cast<Node *>(p.end());
00875 while (i-- != b)
00876 if (i->t() == t)
00877 ++c;
00878 return c;
00879 }
00880
00881 Q_DECLARE_SEQUENTIAL_ITERATOR(List)
00882 Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List)
00883
00884 QT_END_NAMESPACE
00885
00886 QT_END_HEADER
00887
00888 #endif // QLIST_H