summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qvariant.cpp64
-rw-r--r--src/corelib/kernel/qvariant.h21
-rw-r--r--src/corelib/kernel/qvariant_p.h2
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;
}