diff options
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 64 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.h | 21 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant_p.h | 2 |
3 files changed, 63 insertions, 24 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 036ee42e05..97623727a8 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -248,24 +248,32 @@ static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok) // the type of d has already been set, but other field are not set static void customConstruct(QVariant::Private *d, const void *copy) { - const QMetaType type = d->type(); - const uint size = type.sizeOf(); - if (!size) { + QtPrivate::QMetaTypeInterface *iface = d->typeInterface(); + if (!(iface && iface->size)) { *d = QVariant::Private(); return; } - if (QVariant::Private::canUseInternalSpace(type)) { - type.construct(&d->data, copy); + if (QVariant::Private::canUseInternalSpace(iface)) { + // QVariant requires type to be copy and default constructible + Q_ASSERT(iface->copyCtr); + Q_ASSERT(iface->defaultCtr); + if (copy) + iface->copyCtr(iface, &d->data, copy); + else + iface->defaultCtr(iface, &d->data); d->is_shared = false; } else { - d->data.shared = QVariant::PrivateShared::create(type); - type.construct(d->data.shared->data(), copy); + d->data.shared = QVariant::PrivateShared::create(iface); + if (copy) + iface->copyCtr(iface, d->data.shared->data(), copy); + else + iface->defaultCtr(iface, d->data.shared->data()); d->is_shared = true; } // need to check for nullptr_t here, as this can get called by fromValue(nullptr). fromValue() uses // std::addressof(value) which in this case returns the address of the nullptr object. - d->is_null = !copy || type == QMetaType::fromType<std::nullptr_t>(); + d->is_null = !copy || QMetaType(iface) == QMetaType::fromType<std::nullptr_t>(); } static void customClear(QVariant::Private *d) @@ -471,11 +479,23 @@ static void customClear(QVariant::Private *d) Constructs a variant private of type \a type, and initializes with \a copy if \a copy is not \nullptr. -*/ +*/ +//### Qt 7: Remove in favor of QMetaType overload void QVariant::create(int type, const void *copy) { - d = Private(QMetaType(type)); + create(QMetaType(type), copy); +} + +/*! + \fn QVariant::create(int type, const void *copy) + + \internal + \overload +*/ +void QVariant::create(QMetaType type, const void *copy) +{ + d = Private(type); customConstruct(&d, copy); } @@ -510,9 +530,14 @@ QVariant::QVariant(const QVariant &p) d.data.shared->ref.ref(); return; } - QMetaType t = d.type(); - if (t.isValid()) - t.construct(&d, p.constData()); + QtPrivate::QMetaTypeInterface *iface = d.typeInterface(); + auto other = p.constData(); + if (iface) { + if (other) + iface->copyCtr(iface, &d, other); + else + iface->defaultCtr(iface, &d); + } } /*! @@ -995,9 +1020,14 @@ QVariant &QVariant::operator=(const QVariant &variant) d = variant.d; } else { d = variant.d; - QMetaType t = d.type(); - if (t.isValid()) - t.construct(&d, variant.constData()); + QtPrivate::QMetaTypeInterface *iface = d.typeInterface(); + const void *other = variant.constData(); + if (iface) { + if (other) + iface->copyCtr(iface, &d, other); + else + iface->defaultCtr(iface, &d); + } } return *this; @@ -2021,7 +2051,7 @@ bool QVariant::convert(QMetaType targetType) QVariant oldValue = *this; clear(); - create(targetType.id(), nullptr); + create(targetType, nullptr); if (!oldValue.canConvert(targetType)) return false; diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index b7d347a61e..d95d3cd0fb 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -426,10 +426,11 @@ public: private: inline PrivateShared() : ref(1) { } public: - static PrivateShared *create(QMetaType type) + static PrivateShared *create(const QtPrivate::QMetaTypeInterface *type) { - size_t size = type.sizeOf(); - size_t align = type.alignOf(); + Q_ASSERT(type); + size_t size = type->size; + size_t align = type->alignment; size += sizeof(PrivateShared); if (align > sizeof(PrivateShared)) { @@ -463,10 +464,11 @@ public: static constexpr size_t MaxInternalSize = 3*sizeof(void *); template<typename T> static constexpr bool CanUseInternalSpace = (QTypeInfo<T>::isRelocatable && sizeof(T) <= MaxInternalSize && alignof(T) <= alignof(double)); - static constexpr bool canUseInternalSpace(QMetaType type) + static constexpr bool canUseInternalSpace(QtPrivate::QMetaTypeInterface *type) { - return type.flags() & QMetaType::RelocatableType && - size_t(type.sizeOf()) <= MaxInternalSize && size_t(type.alignOf()) <= alignof(double); + Q_ASSERT(type); + return QMetaType::TypeFlags(type->flags) & QMetaType::RelocatableType && + size_t(type->size) <= MaxInternalSize && size_t(type->alignment) <= alignof(double); } union @@ -506,6 +508,12 @@ public: { return QMetaType(reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2)); } + + inline QtPrivate::QMetaTypeInterface * typeInterface() const + { + return reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2); + } + inline int typeId() const { return type().id(); @@ -531,6 +539,7 @@ private: protected: Private d; void create(int type, const void *copy); + void create(QMetaType type, const void *copy); bool equals(const QVariant &other) const; bool convert(int type, void *ptr) const; bool view(int type, void *ptr); diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index f0b15012ec..ef6042d745 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -65,7 +65,7 @@ inline void v_construct(QVariant::Private *x, const T &t) new (&x->data) T(t); x->is_shared = false; } else { - x->data.shared = QVariant::PrivateShared::create(QMetaType::fromType<T>()); + x->data.shared = QVariant::PrivateShared::create(QtPrivate::qMetaTypeInterfaceForType<T>()); new (x->data.shared->data()) T(t); x->is_shared = true; } |