summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools')
-rw-r--r--src/corelib/tools/qarraydata.cpp9
-rw-r--r--src/corelib/tools/qarraydata.h23
-rw-r--r--src/corelib/tools/qarraydatapointer.h4
3 files changed, 32 insertions, 4 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index efed984aef..8f0a95c82c 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -56,16 +56,19 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
&& !(alignment & (alignment - 1)));
// Don't allocate empty headers
- if (!capacity)
+ if (!(options & RawData) && !capacity)
return !(options & Unsharable)
? const_cast<QArrayData *>(&qt_array_empty)
: const_cast<QArrayData *>(&qt_array_unsharable_empty);
+ size_t allocSize = sizeof(QArrayData) + objectSize * capacity;
+
// Allocate extra (alignment - Q_ALIGNOF(QArrayData)) padding bytes so we
// can properly align the data array. This assumes malloc is able to
// provide appropriate alignment for the header -- as it should!
- size_t allocSize = sizeof(QArrayData) + objectSize * capacity
- + (alignment - Q_ALIGNOF(QArrayData));
+ // Padding is skipped when allocating a header for RawData.
+ if (!(options & RawData))
+ allocSize += (alignment - Q_ALIGNOF(QArrayData));
QArrayData *header = static_cast<QArrayData *>(qMalloc(allocSize));
Q_CHECK_PTR(header);
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 8eb543ee51..5a17d718c9 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -73,9 +73,18 @@ struct Q_CORE_EXPORT QArrayData
return reinterpret_cast<const char *>(this) + offset;
}
+ // This refers to array data mutability, not "header data" represented by
+ // data members in QArrayData. Shared data (array and header) must still
+ // follow COW principles.
+ bool isMutable() const
+ {
+ return alloc != 0;
+ }
+
enum AllocateOption {
CapacityReserved = 0x1,
Unsharable = 0x2,
+ RawData = 0x4,
Default = 0
};
@@ -139,6 +148,20 @@ struct QTypedArrayData
QArrayData::deallocate(data, sizeof(T), Q_ALIGNOF(AlignmentDummy));
}
+ static QTypedArrayData *fromRawData(const T *data, size_t n,
+ AllocateOptions options = Default)
+ {
+ QTypedArrayData *result = allocate(0, options | RawData);
+ if (result) {
+ Q_ASSERT(!result->ref.isShared()); // No shared empty, please!
+
+ result->offset = reinterpret_cast<const char *>(data)
+ - reinterpret_cast<const char *>(result);
+ result->size = n;
+ }
+ return result;
+ }
+
static QTypedArrayData *sharedNull()
{
return static_cast<QTypedArrayData *>(
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index 1dc02daa63..8b1d2a805c 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -114,6 +114,8 @@ public:
void setSharable(bool sharable)
{
+ // Can't call setSharable on static read-only data, like shared_null
+ // and the internal shared-empties.
if (d->alloc == 0 && d->size == 0) {
d = Data::allocate(0, sharable
? QArrayData::Default
@@ -138,7 +140,7 @@ public:
bool detach()
{
- if (d->ref.isShared()) {
+ if (!d->isMutable() || d->ref.isShared()) {
Data *copy = clone(d->detachFlags());
QArrayDataPointer old(d);
d = copy;