diff options
Diffstat (limited to 'src/corelib/tools/qlist.h')
-rw-r--r-- | src/corelib/tools/qlist.h | 101 |
1 files changed, 84 insertions, 17 deletions
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 3c21ec1..89e082b 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -117,6 +117,7 @@ public: inline int size() const { return p.size(); } inline void detach() { if (d->ref != 1) detach_helper(); } + inline void detachShared() { if (d->ref != 1 && d != &QListData::shared_null) detach_helper(); } inline bool isDetached() const { return d->ref == 1; } inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } @@ -352,12 +353,27 @@ Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *n) template <typename T> Q_INLINE_TEMPLATE void QList<T>::node_copy(Node *from, Node *to, Node *src) { - if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) - while(from != to) - (from++)->v = new T(*reinterpret_cast<T*>((src++)->v)); - else if (QTypeInfo<T>::isComplex) - while(from != to) - new (from++) T(*reinterpret_cast<T*>(src++)); + Node *current = from; + if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { + QT_TRY { + while(current != to) + (current++)->v = new T(*reinterpret_cast<T*>((src++)->v)); + } QT_CATCH(...) { + while (current != from) + delete reinterpret_cast<T*>(current--); + QT_RETHROW; + } + } + else if (QTypeInfo<T>::isComplex) { + QT_TRY { + while(current != to) + new (current++) T(*reinterpret_cast<T*>(src++)); + } QT_CATCH(...) { + while (current != from) + (reinterpret_cast<T*>(current--))->~T(); + QT_RETHROW; + } + } } template <typename T> @@ -384,8 +400,16 @@ Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l) } template <typename T> inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t) -{ Node *n = reinterpret_cast<Node *>(p.insert(before.i-reinterpret_cast<Node *>(p.begin()))); - node_construct(n,t); return n; } +{ + Node *n = reinterpret_cast<Node *>(p.insert(before.i - reinterpret_cast<Node *>(p.begin()))); + QT_TRY { + node_construct(n, t); + } QT_CATCH(...) { + p.remove(before.i - reinterpret_cast<Node *>(p.begin())); + QT_RETHROW; + } + return n; +} template <typename T> inline typename QList<T>::iterator QList<T>::erase(iterator it) { node_destruct(it.i); @@ -423,10 +447,22 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t) { detach(); if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { - node_construct(reinterpret_cast<Node *>(p.append()), t); + Node *n = reinterpret_cast<Node *>(p.append()); + QT_TRY { + node_construct(n, t); + } QT_CATCH(...) { + --d->end; + QT_RETHROW; + } } else { const T cpy(t); - node_construct(reinterpret_cast<Node *>(p.append()), cpy); + Node *n = reinterpret_cast<Node *>(p.append()); + QT_TRY { + node_construct(n, cpy); + } QT_CATCH(...) { + --d->end; + QT_RETHROW; + } } } @@ -435,10 +471,22 @@ inline void QList<T>::prepend(const T &t) { detach(); if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { - node_construct(reinterpret_cast<Node *>(p.prepend()), t); + Node *n = reinterpret_cast<Node *>(p.prepend()); + QT_TRY { + node_construct(n, t); + } QT_CATCH(...) { + ++d->begin; + QT_RETHROW; + } } else { const T cpy(t); - node_construct(reinterpret_cast<Node *>(p.prepend()), cpy); + Node *n = reinterpret_cast<Node *>(p.prepend()); + QT_TRY { + node_construct(n, cpy); + } QT_CATCH(...) { + ++d->begin; + QT_RETHROW; + } } } @@ -447,10 +495,22 @@ inline void QList<T>::insert(int i, const T &t) { detach(); if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { - node_construct(reinterpret_cast<Node *>(p.insert(i)), t); + Node *n = reinterpret_cast<Node *>(p.insert(i)); + QT_TRY { + node_construct(n, t); + } QT_CATCH(...) { + p.remove(i); + QT_RETHROW; + } } else { const T cpy(t); - node_construct(reinterpret_cast<Node *>(p.insert(i)), cpy); + Node *n = reinterpret_cast<Node *>(p.insert(i)); + QT_TRY { + node_construct(n, cpy); + } QT_CATCH(...) { + p.remove(i); + QT_RETHROW; + } } } @@ -522,7 +582,14 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() { Node *n = reinterpret_cast<Node *>(p.begin()); QListData::Data *x = p.detach2(); - node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n); + QT_TRY { + node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n); + } QT_CATCH(...) { + qFree(d); + d = x; + QT_RETHROW; + } + if (!x->ref.deref()) free(x); } @@ -572,7 +639,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::clear() template <typename T> Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t) { - detach(); + detachShared(); const T t = _t; int removedCount=0, i=0; Node *n; @@ -590,7 +657,7 @@ Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t) template <typename T> Q_OUTOFLINE_TEMPLATE bool QList<T>::removeOne(const T &_t) { - detach(); + detachShared(); int index = indexOf(_t); if (index != -1) { removeAt(index); |