simplify QList<T>::append(), QList<T>::prepend() and QList<T>::insert() [ci reset]

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-07-14 02:03:24 +03:00
parent 588d12877d
commit 156eff71fb
6 changed files with 44 additions and 149 deletions

View file

@ -19,10 +19,7 @@
** **
****************************************************************************/ ****************************************************************************/
#include <new>
#include "qlist.h" #include "qlist.h"
#include "qtools_p.h"
#include <string.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -39,52 +36,6 @@ QT_BEGIN_NAMESPACE
QListData::Data QListData::shared_null = { QAtomicInt(1), 0, 0, 0, { 0 } }; QListData::Data QListData::shared_null = { QAtomicInt(1), 0, 0, 0, { 0 } };
/*!
* Detaches the QListData by allocating new memory for a list which will be bigger
* than the copied one and is expected to grow further.
* *idx is the desired insertion point and is clamped to the actual size of the list.
* num is the number of new elements to insert at the insertion point.
* Returns the old (shared) data, it is up to the caller to deref() and free().
* For the new data node_copy needs to be called.
*
* \internal
*/
QListData::Data *QListData::detach_grow(int *idx, int num)
{
Data *x = d;
int l = x->end - x->begin;
int nl = l + num;
int alloc = qAllocMore(nl * QT_POINTER_SIZE, QListData::DataHeaderSize) / QT_POINTER_SIZE;
Data* t = static_cast<Data *>(::malloc(DataHeaderSize + alloc * QT_POINTER_SIZE));
Q_CHECK_PTR(t);
t->ref = 1;
t->alloc = alloc;
// The space reservation algorithm's optimization is biased towards appending:
// Something which looks like an append will put the data at the beginning,
// while something which looks like a prepend will put it in the middle
// instead of at the end. That's based on the assumption that prepending
// is uncommon and even an initial prepend will eventually be followed by
// at least some appends.
int bg;
if (*idx < 0) {
*idx = 0;
bg = (alloc - nl) >> 1;
} else if (*idx > l) {
*idx = l;
bg = 0;
} else if (*idx < (l >> 1)) {
bg = (alloc - nl) >> 1;
} else {
bg = 0;
}
t->begin = bg;
t->end = bg + nl;
d = t;
return x;
}
/*! /*!
* Detaches the QListData by allocating new memory for a list which possibly * Detaches the QListData by allocating new memory for a list which possibly
* has a different size than the copied one. * has a different size than the copied one.

View file

@ -33,7 +33,6 @@
#endif #endif
#include <new> #include <new>
#include <limits.h>
#include <string.h> #include <string.h>
@ -52,7 +51,6 @@ struct Q_CORE_EXPORT QListData {
enum { DataHeaderSize = sizeof(Data) - QT_POINTER_SIZE }; enum { DataHeaderSize = sizeof(Data) - QT_POINTER_SIZE };
Data *detach(int alloc); Data *detach(int alloc);
Data *detach_grow(int *i, int n);
static void freeData(Data *); static void freeData(Data *);
void reallocData(int alloc); void reallocData(int alloc);
static Data shared_null; static Data shared_null;
@ -291,7 +289,6 @@ public:
{ std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
private: private:
Node *detach_helper_grow(int i, int n);
void detach_helper(int alloc); void detach_helper(int alloc);
void detach_helper(); void detach_helper();
@ -432,8 +429,9 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc)
template <typename T> template <typename T>
Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t) Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
{ {
if (d->ref != 1) { detach();
Node *n = detach_helper_grow(INT_MAX, 1); if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
Node *n = reinterpret_cast<Node *>(p.append());
QT_TRY { QT_TRY {
node_construct(n, t); node_construct(n, t);
} QT_CATCH(...) { } QT_CATCH(...) {
@ -441,33 +439,24 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
QT_RETHROW; QT_RETHROW;
} }
} else { } else {
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { Node *n, copy;
Node *n = reinterpret_cast<Node *>(p.append()); node_construct(&copy, t); // t might be a reference to an object in the array
QT_TRY { QT_TRY {
node_construct(n, t); n = reinterpret_cast<Node *>(p.append());;
} QT_CATCH(...) { } QT_CATCH(...) {
--d->end; node_destruct(&copy);
QT_RETHROW; QT_RETHROW;
}
} else {
Node *n, copy;
node_construct(&copy, t); // t might be a reference to an object in the array
QT_TRY {
n = reinterpret_cast<Node *>(p.append());;
} QT_CATCH(...) {
node_destruct(&copy);
QT_RETHROW;
}
*n = copy;
} }
*n = copy;
} }
} }
template <typename T> template <typename T>
inline void QList<T>::prepend(const T &t) inline void QList<T>::prepend(const T &t)
{ {
if (d->ref != 1) { detach();
Node *n = detach_helper_grow(0, 1); if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
Node *n = reinterpret_cast<Node *>(p.prepend());
QT_TRY { QT_TRY {
node_construct(n, t); node_construct(n, t);
} QT_CATCH(...) { } QT_CATCH(...) {
@ -475,33 +464,24 @@ inline void QList<T>::prepend(const T &t)
QT_RETHROW; QT_RETHROW;
} }
} else { } else {
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { Node *n, copy;
Node *n = reinterpret_cast<Node *>(p.prepend()); node_construct(&copy, t); // t might be a reference to an object in the array
QT_TRY { QT_TRY {
node_construct(n, t); n = reinterpret_cast<Node *>(p.prepend());;
} QT_CATCH(...) { } QT_CATCH(...) {
++d->begin; node_destruct(&copy);
QT_RETHROW; QT_RETHROW;
}
} else {
Node *n, copy;
node_construct(&copy, t); // t might be a reference to an object in the array
QT_TRY {
n = reinterpret_cast<Node *>(p.prepend());;
} QT_CATCH(...) {
node_destruct(&copy);
QT_RETHROW;
}
*n = copy;
} }
*n = copy;
} }
} }
template <typename T> template <typename T>
inline void QList<T>::insert(int i, const T &t) inline void QList<T>::insert(int i, const T &t)
{ {
if (d->ref != 1) { detach();
Node *n = detach_helper_grow(i, 1); if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) {
Node *n = reinterpret_cast<Node *>(p.insert(i));
QT_TRY { QT_TRY {
node_construct(n, t); node_construct(n, t);
} QT_CATCH(...) { } QT_CATCH(...) {
@ -509,25 +489,15 @@ inline void QList<T>::insert(int i, const T &t)
QT_RETHROW; QT_RETHROW;
} }
} else { } else {
if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { Node *n, copy;
Node *n = reinterpret_cast<Node *>(p.insert(i)); node_construct(&copy, t); // t might be a reference to an object in the array
QT_TRY { QT_TRY {
node_construct(n, t); n = reinterpret_cast<Node *>(p.insert(i));;
} QT_CATCH(...) { } QT_CATCH(...) {
p.remove(i); node_destruct(&copy);
QT_RETHROW; QT_RETHROW;
}
} else {
Node *n, copy;
node_construct(&copy, t); // t might be a reference to an object in the array
QT_TRY {
n = reinterpret_cast<Node *>(p.insert(i));;
} QT_CATCH(...) {
node_destruct(&copy);
QT_RETHROW;
}
*n = copy;
} }
*n = copy;
} }
} }
@ -598,36 +568,6 @@ Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i, const T& defaultValue) const
return ((i < 0 || i >= p.size()) ? defaultValue : reinterpret_cast<Node *>(p.at(i))->t()); return ((i < 0 || i >= p.size()) ? defaultValue : reinterpret_cast<Node *>(p.at(i))->t());
} }
template <typename T>
Q_OUTOFLINE_TEMPLATE typename QList<T>::Node *QList<T>::detach_helper_grow(int i, int c)
{
Node *n = reinterpret_cast<Node *>(p.begin());
QListData::Data *x = p.detach_grow(&i, c);
QT_TRY {
node_copy(reinterpret_cast<Node *>(p.begin()),
reinterpret_cast<Node *>(p.begin() + i), n);
} QT_CATCH(...) {
QListData::freeData(d);
d = x;
QT_RETHROW;
}
QT_TRY {
node_copy(reinterpret_cast<Node *>(p.begin() + i + c),
reinterpret_cast<Node *>(p.end()), n + i);
} QT_CATCH(...) {
node_destruct(reinterpret_cast<Node *>(p.begin()),
reinterpret_cast<Node *>(p.begin() + i));
QListData::freeData(d);
d = x;
QT_RETHROW;
}
if (!x->ref.deref())
QListData::freeData(x);
return reinterpret_cast<Node *>(p.begin() + i);
}
template <typename T> template <typename T>
Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper(int alloc) Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper(int alloc)
{ {
@ -740,9 +680,8 @@ Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l)
if (isEmpty()) { if (isEmpty()) {
*this = l; *this = l;
} else { } else {
Node *n = (d->ref != 1) detach();
? detach_helper_grow(INT_MAX, l.size()) Node *n = reinterpret_cast<Node *>(p.append(l.p));
: reinterpret_cast<Node *>(p.append(l.p));
QT_TRY { QT_TRY {
node_copy(n, reinterpret_cast<Node *>(p.end()), node_copy(n, reinterpret_cast<Node *>(p.end()),
reinterpret_cast<Node *>(l.p.begin())); reinterpret_cast<Node *>(l.p.begin()));

View file

@ -39,6 +39,8 @@
#include "qstylehelper_p.h" #include "qstylehelper_p.h"
#include <limits.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance) Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)

View file

@ -20,13 +20,13 @@
****************************************************************************/ ****************************************************************************/
#include "qrasterizer_p.h" #include "qrasterizer_p.h"
#include "qpoint.h"
#include <QPoint> #include "qrect.h"
#include <QRect>
#include "qdatabuffer_p.h" #include "qdatabuffer_p.h"
#include "qdrawhelper_p.h" #include "qdrawhelper_p.h"
#include <limits.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
typedef int Q16Dot16; typedef int Q16Dot16;

View file

@ -135,6 +135,8 @@
#include "QtGui/qdesktopwidget.h" #include "QtGui/qdesktopwidget.h"
#include "QtGui/qlineedit.h" #include "QtGui/qlineedit.h"
#include <limits.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QCompletionModel::QCompletionModel(QCompleterPrivate *c, QObject *parent) QCompletionModel::QCompletionModel(QCompleterPrivate *c, QObject *parent)

View file

@ -26,6 +26,7 @@
#include <qvariant.h> #include <qvariant.h>
#include <qsqlfield.h> #include <qsqlfield.h>
#include <limits.h>
//TESTED_CLASS= //TESTED_CLASS=
//TESTED_FILES= //TESTED_FILES=