diff options
Diffstat (limited to 'src/corelib/tools')
-rw-r--r-- | src/corelib/tools/qarraydata.cpp | 9 | ||||
-rw-r--r-- | src/corelib/tools/qarraydata.h | 23 | ||||
-rw-r--r-- | src/corelib/tools/qarraydatapointer.h | 4 |
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; |