summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-06-14 15:05:34 +0200
committerLars Knoll <lars.knoll@qt.io>2019-12-08 10:29:42 +0100
commitadd048bc4eee8e4422fe2b434b4b817f56693d33 (patch)
treec83275a8046a64b38ce474a1f9a6f2297526aab5 /src/corelib
parentf2569c0ff75eb9a8418bb065c33c318f0a44c8ed (diff)
Start moving QArrayData's size and data pointer to the main class
This requires that the allocation functions return two pointers: the d pointer and the pointer to the actual data. Ported QArrayDataPointer & SimpleVector to the inlined size & data. For now, the size and offset members are not yet removed from QArrayData, to let QVector, QByteArray and QString compile unmodified. Change-Id: I8489300976723d75b8fd5831427b1e2bba486196 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/text/qbytearray.cpp29
-rw-r--r--src/corelib/text/qstring.cpp28
-rw-r--r--src/corelib/tools/qarraydata.cpp29
-rw-r--r--src/corelib/tools/qarraydata.h81
-rw-r--r--src/corelib/tools/qarraydataops.h6
-rw-r--r--src/corelib/tools/qarraydatapointer.h118
-rw-r--r--src/corelib/tools/qvector.h20
7 files changed, 194 insertions, 117 deletions
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 78395a47e3..7562227d7d 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -731,7 +731,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
return invalidCompressedData();
}
- QScopedPointer<QByteArray::Data, QByteArrayDataDeleter> d(QByteArray::Data::allocate(expectedSize + 1));
+ QScopedPointer<QByteArray::Data, QByteArrayDataDeleter> d(QByteArray::Data::allocate(expectedSize + 1).first);
if (Q_UNLIKELY(d.data() == nullptr))
return invalidCompressedData();
@@ -764,7 +764,8 @@ QByteArray qUncompress(const uchar* data, int nbytes)
return invalidCompressedData();
} else {
// grow the block
- QByteArray::Data *p = QByteArray::Data::reallocateUnaligned(d.data(), len + 1);
+ char *dataPointer = d->data();
+ QByteArray::Data *p = QByteArray::Data::reallocateUnaligned(d.data(), dataPointer, len + 1).first;
if (Q_UNLIKELY(p == nullptr))
return invalidCompressedData();
d.take(); // don't free
@@ -1204,7 +1205,7 @@ QByteArray &QByteArray::operator=(const char *str)
if (!str) {
x = Data::sharedNull();
} else if (!*str) {
- x = Data::allocate(0);
+ x = Data::allocate(0).first;
} else {
const int len = int(strlen(str));
const int fullLen = len + 1;
@@ -1693,9 +1694,9 @@ QByteArray::QByteArray(const char *data, int size)
if (size < 0)
size = int(strlen(data));
if (!size) {
- d = Data::allocate(0);
+ d = Data::allocate(0).first;
} else {
- d = Data::allocate(uint(size) + 1u);
+ d = Data::allocate(uint(size) + 1u).first;
Q_CHECK_PTR(d);
d->size = size;
memcpy(d->data(), data, size);
@@ -1714,9 +1715,9 @@ QByteArray::QByteArray(const char *data, int size)
QByteArray::QByteArray(int size, char ch)
{
if (size <= 0) {
- d = Data::allocate(0);
+ d = Data::allocate(0).first;
} else {
- d = Data::allocate(uint(size) + 1u);
+ d = Data::allocate(uint(size) + 1u).first;
Q_CHECK_PTR(d);
d->size = size;
memset(d->data(), ch, size);
@@ -1732,7 +1733,7 @@ QByteArray::QByteArray(int size, char ch)
QByteArray::QByteArray(int size, Qt::Initialization)
{
- d = Data::allocate(uint(size) + 1u);
+ d = Data::allocate(uint(size) + 1u).first;
Q_CHECK_PTR(d);
d->size = size;
d->data()[size] = '\0';
@@ -1769,7 +1770,7 @@ void QByteArray::resize(int size)
// which is used in place of the Qt 3 idiom:
// QByteArray a(sz);
//
- Data *x = Data::allocate(uint(size) + 1u);
+ Data *x = Data::allocate(uint(size) + 1u).first;
Q_CHECK_PTR(x);
x->size = size;
x->data()[size] = '\0';
@@ -1806,7 +1807,7 @@ QByteArray &QByteArray::fill(char ch, int size)
void QByteArray::reallocData(uint alloc, Data::ArrayOptions options)
{
if (d->needsDetach()) {
- Data *x = Data::allocate(alloc, options);
+ Data *x = Data::allocate(alloc, options).first;
Q_CHECK_PTR(x);
x->size = qMin(int(alloc) - 1, d->size);
::memcpy(x->data(), d->data(), x->size);
@@ -1815,7 +1816,7 @@ void QByteArray::reallocData(uint alloc, Data::ArrayOptions options)
Data::deallocate(d);
d = x;
} else {
- Data *x = Data::reallocateUnaligned(d, alloc, options);
+ Data *x = Data::reallocateUnaligned(d, d->data(), alloc, options).first;
Q_CHECK_PTR(x);
d = x;
}
@@ -3130,7 +3131,7 @@ QByteArray QByteArray::mid(int pos, int len) const
return QByteArray();
case QContainerImplHelper::Empty:
{
- QByteArrayDataPtr empty = { Data::allocate(0) };
+ QByteArrayDataPtr empty = { Data::allocate(0).first };
return QByteArray(empty);
}
case QContainerImplHelper::Full:
@@ -4444,9 +4445,9 @@ QByteArray QByteArray::fromRawData(const char *data, int size)
if (!data) {
x = Data::sharedNull();
} else if (!size) {
- x = Data::allocate(0);
+ x = Data::allocate(0).first;
} else {
- x = Data::fromRawData(data, size);
+ x = Data::fromRawData(data, size).ptr;
Q_CHECK_PTR(x);
}
QByteArrayDataPtr dataPtr = { x };
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 4d3f2016ac..8ae365338d 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -2109,9 +2109,9 @@ QString::QString(const QChar *unicode, int size)
++size;
}
if (!size) {
- d = Data::allocate(0);
+ d = Data::allocate(0).first;
} else {
- d = Data::allocate(size + 1);
+ d = Data::allocate(size + 1).first;
Q_CHECK_PTR(d);
d->size = size;
memcpy(d->data(), unicode, size * sizeof(QChar));
@@ -2129,9 +2129,9 @@ QString::QString(const QChar *unicode, int size)
QString::QString(int size, QChar ch)
{
if (size <= 0) {
- d = Data::allocate(0);
+ d = Data::allocate(0).first;
} else {
- d = Data::allocate(size + 1);
+ d = Data::allocate(size + 1).first;
Q_CHECK_PTR(d);
d->size = size;
d->data()[size] = '\0';
@@ -2151,7 +2151,7 @@ QString::QString(int size, QChar ch)
*/
QString::QString(int size, Qt::Initialization)
{
- d = Data::allocate(size + 1);
+ d = Data::allocate(size + 1).first;
Q_CHECK_PTR(d);
d->size = size;
d->data()[size] = '\0';
@@ -2169,7 +2169,7 @@ QString::QString(int size, Qt::Initialization)
*/
QString::QString(QChar ch)
{
- d = Data::allocate(2);
+ d = Data::allocate(2).first;
Q_CHECK_PTR(d);
d->size = 1;
d->data()[0] = ch.unicode();
@@ -2354,7 +2354,7 @@ void QString::reallocData(uint alloc, bool grow)
allocOptions |= QArrayData::GrowsForward;
if (d->needsDetach()) {
- Data *x = Data::allocate(alloc, allocOptions);
+ Data *x = Data::allocate(alloc, allocOptions).first;
Q_CHECK_PTR(x);
x->size = qMin(int(alloc) - 1, d->size);
::memcpy(x->data(), d->data(), x->size * sizeof(QChar));
@@ -2363,7 +2363,7 @@ void QString::reallocData(uint alloc, bool grow)
Data::deallocate(d);
d = x;
} else {
- Data *p = Data::reallocateUnaligned(d, alloc, allocOptions);
+ Data *p = Data::reallocateUnaligned(d, d->data(), alloc, allocOptions).first;
Q_CHECK_PTR(p);
d = p;
}
@@ -4898,7 +4898,7 @@ QString QString::mid(int position, int n) const
return QString();
case QContainerImplHelper::Empty:
{
- QStringDataPtr empty = { Data::allocate(0) };
+ QStringDataPtr empty = { Data::allocate(0).first };
return QString(empty);
}
case QContainerImplHelper::Full:
@@ -5354,11 +5354,11 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
if (!str) {
d = Data::sharedNull();
} else if (size == 0 || (!*str && size < 0)) {
- d = Data::allocate(0);
+ d = Data::allocate(0).first;
} else {
if (size < 0)
size = qstrlen(str);
- d = Data::allocate(size + 1);
+ d = Data::allocate(size + 1).first;
Q_CHECK_PTR(d);
d->size = size;
d->data()[size] = '\0';
@@ -5418,7 +5418,7 @@ QString QString::fromLocal8Bit_helper(const char *str, int size)
if (!str)
return QString();
if (size == 0 || (!*str && size < 0)) {
- QStringDataPtr empty = { Data::allocate(0) };
+ QStringDataPtr empty = { Data::allocate(0).first };
return QString(empty);
}
#if QT_CONFIG(textcodec)
@@ -9124,9 +9124,9 @@ QString QString::fromRawData(const QChar *unicode, int size)
if (!unicode) {
x = Data::sharedNull();
} else if (!size) {
- x = Data::allocate(0);
+ x = Data::allocate(0).first;
} else {
- x = Data::fromRawData(reinterpret_cast<const ushort *>(unicode), size);
+ x = Data::fromRawData(reinterpret_cast<const ushort *>(unicode), size).ptr;
Q_CHECK_PTR(x);
}
QStringDataPtr dataPtr = { x };
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index aa7fac15ef..8052c2ca69 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -198,16 +198,19 @@ static QArrayData *reallocateData(QArrayData *header, size_t allocSize, uint opt
return header;
}
-QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
+void *QArrayData::allocate(QArrayData **dptr, size_t objectSize, size_t alignment,
size_t capacity, ArrayOptions options) noexcept
{
+ Q_ASSERT(dptr);
// Alignment is a power of two
Q_ASSERT(alignment >= alignof(QArrayData)
&& !(alignment & (alignment - 1)));
- if (capacity == 0)
+ if (capacity == 0) {
// optimization for empty headers
- return const_cast<QArrayData *>(&qt_array_empty);
+ *dptr = const_cast<QArrayData *>(&qt_array_empty);
+ return sharedNullData();
+ }
size_t headerSize = sizeof(QArrayData);
@@ -225,14 +228,17 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
options |= AllocatedDataType | MutableData;
options &= ~ImmutableHeader;
QArrayData *header = allocateData(allocSize, options);
+ quintptr data = 0;
if (header) {
- quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
+ // find where offset should point to so that data() is aligned to alignment bytes
+ data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
& ~(alignment - 1);
header->offset = data - quintptr(header);
header->alloc = capacity;
}
- return header;
+ *dptr = header;
+ return reinterpret_cast<void *>(data);
}
QArrayData *QArrayData::prepareRawData(ArrayOptions options) Q_DECL_NOTHROW
@@ -243,8 +249,9 @@ QArrayData *QArrayData::prepareRawData(ArrayOptions options) Q_DECL_NOTHROW
return header;
}
-QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, size_t capacity,
- ArrayOptions options) noexcept
+QPair<QArrayData *, void *>
+QArrayData::reallocateUnaligned(QArrayData *data, void *dataPointer,
+ size_t objectSize, size_t capacity, ArrayOptions options) noexcept
{
Q_ASSERT(data);
Q_ASSERT(data->isMutable());
@@ -252,12 +259,14 @@ QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize,
size_t headerSize = sizeof(QArrayData);
size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
+ qptrdiff offset = reinterpret_cast<char *>(dataPointer) - reinterpret_cast<char *>(data);
options |= AllocatedDataType | MutableData;
- options &= ~ImmutableHeader;
QArrayData *header = reallocateData(data, allocSize, options);
- if (header)
+ if (header) {
header->alloc = capacity;
- return header;
+ dataPointer = reinterpret_cast<char *>(header) + offset;
+ }
+ return qMakePair(static_cast<QArrayData *>(header), dataPointer);
}
void QArrayData::deallocate(QArrayData *data, size_t objectSize,
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 56d61340f0..6cf0ea1cb6 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -41,11 +41,14 @@
#ifndef QARRAYDATA_H
#define QARRAYDATA_H
-#include <QtCore/qrefcount.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qatomic.h>
#include <string.h>
QT_BEGIN_NAMESPACE
+template <class T> struct QTypedArrayData;
+
struct Q_CORE_EXPORT QArrayData
{
enum ArrayOption {
@@ -169,10 +172,12 @@ struct Q_CORE_EXPORT QArrayData
#if defined(Q_CC_GNU)
__attribute__((__malloc__))
#endif
- static QArrayData *allocate(size_t objectSize, size_t alignment,
+ static void *allocate(QArrayData **pdata, size_t objectSize, size_t alignment,
size_t capacity, ArrayOptions options = DefaultAllocationFlags) noexcept;
Q_REQUIRED_RESULT static QArrayData *reallocateUnaligned(QArrayData *data, size_t objectSize,
size_t newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) noexcept;
+ Q_REQUIRED_RESULT static QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer,
+ size_t objectSize, size_t newCapacity, ArrayOptions newOptions = DefaultAllocationFlags) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT static QArrayData *prepareRawData(ArrayOptions options = ArrayOptions(RawDataType))
Q_DECL_NOTHROW;
static void deallocate(QArrayData *data, size_t objectSize,
@@ -190,6 +195,23 @@ struct Q_CORE_EXPORT QArrayData
Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions)
+template <class T, size_t N>
+struct QStaticArrayData
+{
+ // static arrays are of type RawDataType
+ QArrayData header;
+ T data[N];
+};
+
+// Support for returning QArrayDataPointer<T> from functions
+template <class T>
+struct QArrayDataPointerRef
+{
+ QTypedArrayData<T> *ptr;
+ T *data;
+ uint size;
+};
+
template <class T>
struct QTypedArrayData
: QArrayData
@@ -282,27 +304,26 @@ struct QTypedArrayData
class AlignmentDummy { QArrayData header; T data; };
- Q_REQUIRED_RESULT static QTypedArrayData *allocate(size_t capacity,
+ Q_REQUIRED_RESULT static QPair<QTypedArrayData *, T *> allocate(size_t capacity,
ArrayOptions options = DefaultAllocationFlags)
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
- void *result = QArrayData::allocate(sizeof(T),
- alignof(AlignmentDummy), capacity, options);
+ QArrayData *d;
+ void *result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, options);
#if (defined(Q_CC_GNU) && Q_CC_GNU >= 407) || QT_HAS_BUILTIN(__builtin_assume_aligned)
result = __builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy));
#endif
- return static_cast<QTypedArrayData *>(result);
+ return qMakePair(static_cast<QTypedArrayData *>(d), static_cast<T *>(result));
}
- static QTypedArrayData *reallocateUnaligned(QTypedArrayData *data, size_t capacity,
+ static QPair<QTypedArrayData *, T *>
+ reallocateUnaligned(QTypedArrayData *data, T *dataPointer, size_t capacity,
ArrayOptions options = DefaultAllocationFlags)
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
- void *result = QArrayData::reallocateUnaligned(data, sizeof(T), capacity, options);
-#if (defined(Q_CC_GNU) && Q_CC_GNU >= 407) || QT_HAS_BUILTIN(__builtin_assume_aligned)
- result =__builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy));
-#endif
- return static_cast<QTypedArrayData *>(result);
+ QPair<QArrayData *, void *> pair =
+ QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, options);
+ return qMakePair(static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second));
}
static void deallocate(QArrayData *data)
@@ -311,17 +332,18 @@ struct QTypedArrayData
QArrayData::deallocate(data, sizeof(T), alignof(AlignmentDummy));
}
- static QTypedArrayData *fromRawData(const T *data, size_t n,
+ static QArrayDataPointerRef<T> fromRawData(const T *data, size_t n,
ArrayOptions options = DefaultRawFlags)
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
- QTypedArrayData *result = static_cast<QTypedArrayData *>(prepareRawData(options));
- if (result) {
- Q_ASSERT(!result->isShared()); // No shared empty, please!
-
- result->offset = reinterpret_cast<const char *>(data)
- - reinterpret_cast<const char *>(result);
- result->size = int(n);
+ QArrayDataPointerRef<T> result = {
+ static_cast<QTypedArrayData *>(prepareRawData(options)), const_cast<T *>(data), uint(n)
+ };
+ if (result.ptr) {
+ Q_ASSERT(!result.ptr->isShared()); // No shared empty, please!
+ result.ptr->offset = reinterpret_cast<const char *>(data)
+ - reinterpret_cast<const char *>(result.ptr);
+ result.ptr->size = int(n);
}
return result;
}
@@ -345,21 +367,6 @@ struct QTypedArrayData
}
};
-template <class T, size_t N>
-struct QStaticArrayData
-{
- // static arrays are of type RawDataType
- QArrayData header;
- T data[N];
-};
-
-// Support for returning QArrayDataPointer<T> from functions
-template <class T>
-struct QArrayDataPointerRef
-{
- QTypedArrayData<T> *ptr;
-};
-
#define Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
{ Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, size, 0, offset } \
/**/
@@ -412,7 +419,9 @@ struct QArrayDataPointerRef
\
QArrayDataPointerRef<Type> ref = \
{ static_cast<QTypedArrayData<Type> *>( \
- const_cast<QArrayData *>(&literal.header)) }; \
+ const_cast<QArrayData *>(&literal.header)), \
+ const_cast<Type *>(literal.data), \
+ Size }; \
/**/
namespace QtPrivate {
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index ac7fc7bc4e..8fe35952bf 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -47,6 +47,8 @@
QT_BEGIN_NAMESPACE
+template <class T> struct QArrayDataPointer;
+
namespace QtPrivate {
QT_WARNING_PUSH
@@ -56,7 +58,7 @@ QT_WARNING_DISABLE_GCC("-Wstringop-overflow")
template <class T>
struct QPodArrayOps
- : QTypedArrayData<T>
+ : public QArrayDataPointer<T>
{
typedef T parameter_type;
@@ -148,7 +150,7 @@ QT_WARNING_POP
template <class T>
struct QGenericArrayOps
- : QTypedArrayData<T>
+ : public QArrayDataPointer<T>
{
typedef const T &parameter_type;
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index 86997985d1..c52b84f4ce 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -52,26 +52,38 @@ private:
typedef QArrayDataOps<T> DataOps;
public:
+ typedef typename Data::iterator iterator;
+ typedef typename Data::const_iterator const_iterator;
+
QArrayDataPointer() noexcept
- : d(Data::sharedNull())
+ : d(Data::sharedNull()), b(Data::sharedNullData()), size(0)
{
}
QArrayDataPointer(const QArrayDataPointer &other)
- : d(other.d->ref()
- ? other.d
- : other.clone(other.d->cloneFlags()))
+ : d(other.d), b(other.b), size(other.size)
+ {
+ if (!other.d->ref()) {
+ // must clone
+ QPair<Data *, T *> pair = other.clone(other.d->cloneFlags());
+ d = pair.first;
+ b = pair.second;
+ }
+ }
+
+ QArrayDataPointer(Data *header, T *data, size_t n = 0)
+ : d(header), b(data), size(n)
{
}
- explicit QArrayDataPointer(QTypedArrayData<T> *ptr)
- : d(ptr)
+ explicit QArrayDataPointer(QPair<QTypedArrayData<T> *, T *> data, size_t n = 0)
+ : d(data.first), b(data.second), size(n)
{
- Q_CHECK_PTR(ptr);
+ Q_CHECK_PTR(d);
}
QArrayDataPointer(QArrayDataPointerRef<T> ref)
- : d(ref.ptr)
+ : d(ref.ptr), b(ref.data), size(ref.size)
{
}
@@ -83,7 +95,7 @@ public:
}
QArrayDataPointer(QArrayDataPointer &&other) noexcept
- : d(other.d)
+ : d(other.d), b(other.b), size(other.size)
{
other.d = Data::sharedNull();
}
@@ -95,16 +107,28 @@ public:
return *this;
}
- DataOps &operator*() const
+ DataOps &operator*()
+ {
+ Q_ASSERT(d);
+ return *static_cast<DataOps *>(this);
+ }
+
+ DataOps *operator->()
+ {
+ Q_ASSERT(d);
+ return static_cast<DataOps *>(this);
+ }
+
+ const DataOps &operator*() const
{
Q_ASSERT(d);
- return *static_cast<DataOps *>(d);
+ return *static_cast<const DataOps *>(this);
}
- DataOps *operator->() const
+ const DataOps *operator->() const
{
Q_ASSERT(d);
- return static_cast<DataOps *>(d);
+ return static_cast<const DataOps *>(this);
}
~QArrayDataPointer()
@@ -121,62 +145,92 @@ public:
return d == Data::sharedNull();
}
- Data *data() const
- {
- return d;
- }
+ T *data() { return b; }
+ const T *data() const { return b; }
+
+ iterator begin() { return data(); }
+ iterator end() { return data() + size; }
+ const_iterator begin() const { return data(); }
+ const_iterator end() const { return data() + size; }
+ const_iterator constBegin() const { return data(); }
+ const_iterator constEnd() const { return data() + size; }
void swap(QArrayDataPointer &other) noexcept
{
qSwap(d, other.d);
+ qSwap(b, other.b);
+ qSwap(size, other.size);
}
void clear()
{
- QArrayDataPointer tmp(d);
+ QArrayDataPointer tmp(d, b, size);
d = Data::sharedNull();
+ b = reinterpret_cast<T *>(d);
+ size = 0;
}
bool detach()
{
if (d->needsDetach()) {
- Data *copy = clone(d->detachFlags());
- QArrayDataPointer old(d);
- d = copy;
+ QPair<Data *, T *> copy = clone(d->detachFlags());
+ QArrayDataPointer old(d, b, size);
+ d = copy.first;
+ b = copy.second;
return true;
}
return false;
}
+ // forwards from QArrayData
+ int allocatedCapacity() { return d->allocatedCapacity(); }
+ int constAllocatedCapacity() const { return d->constAllocatedCapacity(); }
+ int refCounterValue() const { return d->refCounterValue(); }
+ bool ref() { return d->ref(); }
+ bool deref() { return d->deref(); }
+ bool isMutable() const { return d->isMutable(); }
+ bool isStatic() const { return d->isStatic(); }
+ bool isShared() const { return d->isShared(); }
+ bool needsDetach() const { return d->needsDetach(); }
+ size_t detachCapacity(size_t newSize) const { return d->detachCapacity(newSize); }
+ typename Data::ArrayOptions &flags() { return reinterpret_cast<typename Data::ArrayOptions &>(d->flags); }
+ typename Data::ArrayOptions flags() const { return typename Data::ArrayOption(d->flags); }
+ typename Data::ArrayOptions detachFlags() const { return d->detachFlags(); }
+ typename Data::ArrayOptions cloneFlags() const { return d->cloneFlags(); }
+
private:
- Q_REQUIRED_RESULT Data *clone(QArrayData::ArrayOptions options) const
+ Q_REQUIRED_RESULT QPair<Data *, T *> clone(QArrayData::ArrayOptions options) const
{
- Data *x = Data::allocate(d->detachCapacity(d->size), options);
- Q_CHECK_PTR(x);
- QArrayDataPointer copy(x);
-
- if (d->size)
- copy->copyAppend(d->begin(), d->end());
+ QPair<Data *, T *> pair = Data::allocate(d->detachCapacity(size),
+ options);
+ Q_CHECK_PTR(pair.first);
+ QArrayDataPointer copy(pair.first, pair.second, 0);
+ if (size)
+ copy->copyAppend(begin(), end());
- Data *result = copy.d;
+ pair.first = copy.d;
copy.d = Data::sharedNull();
- return result;
+ return pair;
}
Data *d;
+ T *b;
+
+public:
+ uint size;
};
template <class T>
inline bool operator==(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
{
- return lhs.data() == rhs.data();
+ return lhs.data() == rhs.data() && lhs.size == rhs.size;
}
template <class T>
inline bool operator!=(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
{
- return lhs.data() != rhs.data();
+ return lhs.data() != rhs.data() || lhs.size != rhs.size;
}
template <class T>
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index bf422e72d4..330bf8bb98 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -369,11 +369,11 @@ inline QVector<T>::QVector(const QVector<T> &v)
d = v.d;
} else {
if (v.d->flags & Data::CapacityReserved) {
- d = Data::allocate(v.d->allocatedCapacity());
+ d = Data::allocate(v.d->allocatedCapacity()).first;
Q_CHECK_PTR(d);
d->flags |= Data::CapacityReserved;
} else {
- d = Data::allocate(v.d->size);
+ d = Data::allocate(v.d->size).first;
Q_CHECK_PTR(d);
}
if (v.d->size) {
@@ -394,9 +394,10 @@ void QVector<T>::detach()
if (d->isStatic())
return;
- if (d->needsDetach())
+ if (d->needsDetach()) {
realloc(d->allocatedCapacity(), d->detachFlags());
- Q_ASSERT(isDetached());
+ Q_ASSERT(isDetached());
+ }
}
template <typename T>
@@ -497,7 +498,7 @@ QVector<T>::QVector(int asize)
{
Q_ASSERT_X(asize >= 0, "QVector::QVector", "Size must be greater than or equal to 0.");
if (Q_LIKELY(asize > 0)) {
- d = Data::allocate(asize);
+ d = Data::allocate(asize).first;
Q_CHECK_PTR(d);
d->size = asize;
defaultConstruct(d->begin(), d->end());
@@ -511,7 +512,7 @@ QVector<T>::QVector(int asize, const T &t)
{
Q_ASSERT_X(asize >= 0, "QVector::QVector", "Size must be greater than or equal to 0.");
if (asize > 0) {
- d = Data::allocate(asize);
+ d = Data::allocate(asize).first;
Q_CHECK_PTR(d);
d->size = asize;
T* i = d->end();
@@ -531,7 +532,7 @@ template <typename T>
QVector<T>::QVector(std::initializer_list<T> args)
{
if (args.size() > 0) {
- d = Data::allocate(args.size());
+ d = Data::allocate(args.size()).first;
Q_CHECK_PTR(d);
// std::initializer_list<T>::iterator is guaranteed to be
// const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct
@@ -585,7 +586,8 @@ void QVector<T>::realloc(int aalloc, QArrayData::ArrayOptions options)
QT_TRY {
// allocate memory
- x = Data::allocate(aalloc, options);
+ auto pair = Data::allocate(aalloc, options);
+ x = pair.first;
Q_CHECK_PTR(x);
// aalloc is bigger then 0 so it is not [un]sharedEmpty
Q_ASSERT(!x->isStatic());
@@ -749,7 +751,7 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, T &&t)
Q_ASSERT_X(isValidIterator(before), "QVector::insert", "The specified iterator argument 'before' is invalid");
const auto offset = std::distance(d->begin(), before);
- if (!isDetached() || d->size + 1 > int(d->alloc))
+ if (!isDetached() || d->size + 1 > int(d->allocatedCapacity()))
realloc(d->size + 1, QArrayData::GrowsForward);
if (!QTypeInfoQuery<T>::isRelocatable) {
T *i = d->end();