summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qlist.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qlist.h')
-rw-r--r--src/corelib/tools/qlist.h101
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);