summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qmetatype.cpp1319
-rw-r--r--src/corelib/kernel/qmetatype.h472
-rw-r--r--src/corelib/kernel/qmetatype_p.h98
-rw-r--r--src/dbus/qdbusmetaobject.cpp40
-rw-r--r--src/gui/kernel/qguivariant.cpp32
-rw-r--r--src/widgets/kernel/qwidgetsvariant.cpp33
6 files changed, 603 insertions, 1391 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 4fcf39f321..52f36aa7ce 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -37,8 +37,6 @@
**
****************************************************************************/
-#include <bitset>
-
#include "qmetatype.h"
#include "qmetatype_p.h"
#include "qobjectdefs.h"
@@ -87,6 +85,9 @@
# include "qline.h"
#endif
+#include <bitset>
+#include <new>
+
QT_BEGIN_NAMESPACE
#define NS(x) QT_PREPEND_NAMESPACE(x)
@@ -99,6 +100,88 @@ struct DefinedTypesFilter {
static const bool IsAccepted = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && QModulesPrivate::QTypeModuleInfo<T>::IsCore;
};
};
+
+struct QMetaTypeCustomRegistery
+{
+ QReadWriteLock lock;
+ QVector<QtPrivate::QMetaTypeInterface *> registry;
+ QHash<QByteArray, QtPrivate::QMetaTypeInterface *> aliases;
+#ifndef QT_NO_DATASTREAM
+ struct DataStreamOps
+ {
+ QMetaType::SaveOperator saveOp;
+ QMetaType::LoadOperator loadOp;
+ };
+ QHash<int, DataStreamOps> dataStreamOp;
+#endif
+ // index of first empty (unregistered) type in registry, if any.
+ int firstEmpty = 0;
+
+ int registerCustomType(QtPrivate::QMetaTypeInterface *ti)
+ {
+ {
+ QWriteLocker l(&lock);
+ if (ti->typeId)
+ return ti->typeId;
+ QByteArray name =
+#ifndef QT_NO_QOBJECT
+ QMetaObject::normalizedType
+#endif
+ (ti->name);
+ if (auto ti2 = aliases.value(name)) {
+ ti->typeId.storeRelaxed(ti2->typeId.loadRelaxed());
+ return ti2->typeId;
+ }
+ aliases[name] = ti;
+ int size = registry.size();
+ while (firstEmpty < size && registry[firstEmpty])
+ ++firstEmpty;
+ if (firstEmpty < size) {
+ registry[firstEmpty] = ti;
+ ++firstEmpty;
+ } else {
+ registry.append(ti);
+ firstEmpty = registry.size();
+ }
+ ti->typeId = firstEmpty + QMetaType::User;
+ }
+ if (ti->legacyRegisterOp)
+ ti->legacyRegisterOp();
+ return ti->typeId;
+ };
+
+ void unregisterDynamicType(int id)
+ {
+ if (!id)
+ return;
+ Q_ASSERT(id > QMetaType::User);
+ QWriteLocker l(&lock);
+ int idx = id - QMetaType::User - 1;
+ auto &ti = registry[idx];
+
+ // We must unregister all names.
+ auto it = aliases.begin();
+ while (it != aliases.end()) {
+ if (it.value() == ti)
+ it = aliases.erase(it);
+ else
+ ++it;
+ }
+
+ ti = nullptr;
+
+ firstEmpty = std::min(firstEmpty, idx);
+ }
+
+ QtPrivate::QMetaTypeInterface *getCustomType(int id)
+ {
+ QReadLocker l(&lock);
+ return registry.value(id - QMetaType::User - 1);
+ }
+};
+
+Q_GLOBAL_STATIC(QMetaTypeCustomRegistery, customTypeRegistery)
+
} // namespace
/*!
@@ -373,6 +456,10 @@ struct DefinedTypesFilter {
Returns \c true if this QMetaType object contains valid
information about a type, false otherwise.
*/
+bool QMetaType::isValid() const
+{
+ return d_ptr;
+}
/*!
\fn bool QMetaType::isRegistered() const
@@ -381,6 +468,10 @@ struct DefinedTypesFilter {
Returns \c true if this QMetaType object contains valid
information about a type, false otherwise.
*/
+bool QMetaType::isRegistered() const
+{
+ return d_ptr;
+}
/*!
\fn int QMetaType::id() const
@@ -388,6 +479,18 @@ struct DefinedTypesFilter {
Returns id type hold by this QMetatype instance.
*/
+int QMetaType::id() const
+{
+ if (d_ptr) {
+ if (d_ptr->typeId)
+ return d_ptr->typeId;
+ auto reg = customTypeRegistery();
+ if (reg) {
+ return reg->registerCustomType(d_ptr);
+ }
+ }
+ return 0;
+}
/*!
\fn bool QMetaType::sizeOf() const
@@ -402,6 +505,12 @@ struct DefinedTypesFilter {
\sa QMetaType::construct(), QMetaType::sizeOf()
*/
+int QMetaType::sizeOf() const
+{
+ if (d_ptr)
+ return d_ptr->size;
+ return 0;
+}
/*!
\fn TypeFlags QMetaType::flags() const
@@ -411,6 +520,12 @@ struct DefinedTypesFilter {
\sa QMetaType::TypeFlags, QMetaType::typeFlags()
*/
+QMetaType::TypeFlags QMetaType::flags() const
+{
+ if (d_ptr)
+ return TypeFlags(d_ptr->flags);
+ return {};
+}
/*!
\fn const QMetaObject *QMetaType::metaObject() const
@@ -432,6 +547,10 @@ struct DefinedTypesFilter {
\sa QMetaType::metaObjectForType(), QMetaType::flags()
*/
+const QMetaObject *QMetaType::metaObject() const
+{
+ return d_ptr ? d_ptr->metaObject : nullptr;
+}
/*!
\fn void *QMetaType::create(const void *copy = 0) const
@@ -443,6 +562,19 @@ struct DefinedTypesFilter {
\sa QMetaType::destroy()
*/
+void *QMetaType::create(const void *copy) const
+{
+ if (d_ptr) {
+ void *where =
+#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
+ d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__ ?
+ operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)) :
+#endif
+ operator new(d_ptr->size);
+ return construct(where, copy);
+ }
+ return nullptr;
+}
/*!
\fn void QMetaType::destroy(void *data) const
@@ -453,18 +585,19 @@ struct DefinedTypesFilter {
\sa QMetaType::create()
*/
+void QMetaType::destroy(void *data) const
+{
+ if (d_ptr && d_ptr->dtor) {
+ d_ptr->dtor(d_ptr, data);
+ if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+ operator delete(data, std::align_val_t(d_ptr->alignment));
+ } else {
+ operator delete(data);
+ }
+ }
+}
/*!
- \fn void *QMetaType::construct(int type, const void *copy)
- \deprecated
-
- Constructs a value of the given type which is a copy of \a copy.
- The default value for \a copy is \nullptr.
-
- Deprecated, use the static function QMetaType::create(int type,
- const void *copy) instead.
-*/
-/*!
\fn void *QMetaType::construct(void *where, const void *copy = 0) const
\since 5.0
@@ -490,6 +623,21 @@ struct DefinedTypesFilter {
special hardware instructions (e.g., aligned SSE loads and stores
on x86).
*/
+void *QMetaType::construct(void *where, const void *copy) const
+{
+ if (!where)
+ return nullptr;
+ if (d_ptr) {
+ if (copy && d_ptr->copyCtr) {
+ d_ptr->copyCtr(d_ptr, where, copy);
+ return where;
+ } else if (!copy && d_ptr->defaultCtr) {
+ d_ptr->defaultCtr(d_ptr, where);
+ return where;
+ }
+ }
+ return nullptr;
+}
/*!
\fn void QMetaType::destruct(void *data) const
@@ -502,12 +650,48 @@ struct DefinedTypesFilter {
destructor, it doesn't invoke the delete operator.
\sa QMetaType::construct()
*/
+void QMetaType::destruct(void *data) const
+{
+ if (!data)
+ return;
+ if (d_ptr && d_ptr->dtor) {
+ d_ptr->dtor(d_ptr, data);
+ return;
+ }
+}
/*!
\fn QMetaType::~QMetaType()
Destructs this object.
*/
+QMetaType::~QMetaType()
+{
+ if (d_ptr && !d_ptr->ref.deref()) {
+ if (auto reg = customTypeRegistery())
+ reg->unregisterDynamicType(d_ptr->typeId.loadRelaxed());
+ Q_ASSERT(d_ptr->deleteSelf);
+ d_ptr->deleteSelf(d_ptr);
+ }
+}
+
+QMetaType::QMetaType(QtPrivate::QMetaTypeInterface *d) : d_ptr(d)
+{
+ if (d_ptr)
+ d_ptr->ref.ref();
+}
+
+QMetaType::QMetaType() : d_ptr(nullptr) {}
+
+QMetaType::QMetaType(const QMetaType &other) : QMetaType(other.d_ptr) {}
+QMetaType &QMetaType::operator=(const QMetaType &other)
+{
+ if (d_ptr != other.d_ptr) {
+ this->~QMetaType();
+ new (this) QMetaType(other.d_ptr);
+ }
+ return *this;
+}
/*!
\fn template<typename T> QMetaType QMetaType::fromType()
@@ -549,22 +733,17 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ
{nullptr, 0, QMetaType::UnknownType}
};
-Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = nullptr;
-Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper = nullptr;
-Q_CORE_EXPORT const QMetaObject *qMetaObjectWidgetsHelper = nullptr;
+Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr;
+Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr;
-class QCustomTypeInfo : public QMetaTypeInterface
+static const QMetaTypeModuleHelper *qModuleHelperForType(int type)
{
-public:
- QCustomTypeInfo()
- : alias(-1)
- {
- QMetaTypeInterface empty = QT_METATYPE_INTERFACE_INIT(void);
- *static_cast<QMetaTypeInterface*>(this) = empty;
- }
- QByteArray typeName;
- int alias;
-};
+ if (type >= QMetaType::FirstGuiType && type <= QMetaType::LastGuiType)
+ return qMetaTypeGuiHelper;
+ else if (type >= QMetaType::FirstWidgetsType && type <= QMetaType::LastWidgetsType)
+ return qMetaTypeWidgetsHelper;
+ return nullptr;
+}
template<typename T, typename Key>
class QMetaTypeFunctionRegistry
@@ -616,11 +795,6 @@ QMetaTypeComparatorRegistry;
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
QMetaTypeDebugStreamRegistry;
-Q_STATIC_ASSERT(std::is_pod<QMetaTypeInterface>::value);
-
-Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
-Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
-Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
Q_GLOBAL_STATIC(QMetaTypeComparatorRegistry, customTypesComparatorRegistry)
Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry)
@@ -863,13 +1037,11 @@ void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp,
{
if (idx < User)
return; //builtin types should not be registered;
- QVector<QCustomTypeInfo> *ct = customTypes();
- if (!ct)
- return;
- QWriteLocker locker(customTypesLock());
- QCustomTypeInfo &inf = (*ct)[idx - User];
- inf.saveOp = saveOp;
- inf.loadOp = loadOp;
+
+ if (auto reg = customTypeRegistery()) {
+ QWriteLocker locker(&reg->lock);
+ reg->dataStreamOp[idx] = { saveOp, loadOp };
+ }
}
#endif // QT_NO_DATASTREAM
@@ -968,13 +1140,11 @@ const char *QMetaType::typeName(int typeId)
return nullptr; // It can happen when someone cast int to QVariant::Type, we should not crash...
}
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- QReadLocker locker(customTypesLock());
- return ct && uint(ct->count()) > type - QMetaType::User && !ct->at(type - QMetaType::User).typeName.isEmpty()
- ? ct->at(type - QMetaType::User).typeName.constData()
- : nullptr;
-
-#undef QT_METATYPE_TYPEID_TYPENAME_CONVERTER
+ if (auto reg = customTypeRegistery()) {
+ if (auto ti = reg->getCustomType(typeId))
+ return ti->name;
+ }
+ return nullptr;
}
/*!
@@ -988,7 +1158,7 @@ const char *QMetaType::typeName(int typeId)
*/
QByteArray QMetaType::name() const
{
- return QMetaType::typeName(m_typeId);
+ return d_ptr ? d_ptr->name : nullptr;
}
/*
@@ -1007,338 +1177,40 @@ static inline int qMetaTypeStaticType(const char *typeName, int length)
/*
Similar to QMetaType::type(), but only looks in the custom set of
types, and doesn't lock the mutex.
- The extra \a firstInvalidIndex parameter is an easy way to avoid
- iterating over customTypes() a second time in registerNormalizedType().
-*/
-static int qMetaTypeCustomType_unlocked(const char *typeName, int length, int *firstInvalidIndex = nullptr)
-{
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- if (!ct)
- return QMetaType::UnknownType;
-
- if (firstInvalidIndex)
- *firstInvalidIndex = -1;
- for (int v = 0; v < ct->count(); ++v) {
- const QCustomTypeInfo &customInfo = ct->at(v);
- if ((length == customInfo.typeName.size())
- && !memcmp(typeName, customInfo.typeName.constData(), length)) {
- if (customInfo.alias >= 0)
- return customInfo.alias;
- return v + QMetaType::User;
- }
- if (firstInvalidIndex && (*firstInvalidIndex < 0) && customInfo.typeName.isEmpty())
- *firstInvalidIndex = v;
- }
- return QMetaType::UnknownType;
-}
-
-/*!
- \internal
- This function is needed until existing code outside of qtbase
- has been changed to call the new version of registerType().
- */
-int QMetaType::registerType(const char *typeName, Deleter deleter,
- Creator creator)
-{
- return registerType(typeName, deleter, creator,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Destruct,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Construct, 0, TypeFlags(), nullptr);
-}
-
-/*!
- \internal
- \since 5.5
-
- Unregisters the user type with the given \a typeId and all its aliases.
- Returns \c true if the type was unregistered or \c false otherwise.
-
- This function was added for QML to be able to deregister types after
- they are unloaded to prevent an infinite increase in custom types for
- applications that are unloading/reloading components often.
- */
-bool QMetaType::unregisterType(int type)
-{
- QWriteLocker locker(customTypesLock());
- QVector<QCustomTypeInfo> *ct = customTypes();
-
- // check if user type
- if ((type < User) || ((type - User) >= ct->size()))
- return false;
-
- // only types without Q_DECLARE_METATYPE can be unregistered
- if (ct->data()[type - User].flags & WasDeclaredAsMetaType)
- return false;
-
- // invalidate type and all its alias entries
- for (int v = 0; v < ct->count(); ++v) {
- if (((v + User) == type) || (ct->at(v).alias == type))
- ct->data()[v].typeName.clear();
- }
- return true;
-}
-
-
-/*!
- \internal
- \since 5.0
-
- Registers a user type for marshalling, with \a typeName, a \a
- deleter, a \a creator, a \a destructor, a \a constructor, and
- a \a size. Returns the type's handle, or -1 if the type could
- not be registered.
- */
-int QMetaType::registerType(const char *typeName, Deleter deleter,
- Creator creator,
- Destructor destructor,
- Constructor constructor,
- int size, TypeFlags flags, const QMetaObject *metaObject)
-{
-#ifdef QT_NO_QOBJECT
- NS(QByteArray) normalizedTypeName = typeName;
-#else
- NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
-#endif
-
- return registerNormalizedType(normalizedTypeName, deleter, creator, destructor, constructor, size, flags, metaObject);
-}
-
-/*!
- \internal
- \since 5.12
-
- Registers a user type for marshalling, with \a typeName, a
- \a destructor, a \a constructor, and a \a size. Returns the
- type's handle, or -1 if the type could not be registered.
- */
-int QMetaType::registerType(const char *typeName,
- TypedDestructor destructor,
- TypedConstructor constructor,
- int size,
- TypeFlags flags,
- const QMetaObject *metaObject)
+*/
+static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
{
-#ifdef QT_NO_QOBJECT
- NS(QByteArray) normalizedTypeName = typeName;
-#else
- NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+ if (auto reg = customTypeRegistery()) {
+#if QT_CONFIG(thread)
+ Q_ASSERT(!reg->lock.tryLockForWrite());
#endif
-
- return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
-}
-
-
-static int registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
- QMetaType::Destructor destructor,
- QMetaType::Constructor constructor,
- QMetaType::TypedDestructor typedDestructor,
- QMetaType::TypedConstructor typedConstructor,
- int size, QMetaType::TypeFlags flags, const QMetaObject *metaObject)
-{
- QVector<QCustomTypeInfo> *ct = customTypes();
- if (!ct || normalizedTypeName.isEmpty() || (!destructor && !typedDestructor) || (!constructor && !typedConstructor))
- return -1;
-
- int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
- normalizedTypeName.size());
-
- int previousSize = 0;
- QMetaType::TypeFlags::Int previousFlags = 0;
- if (idx == QMetaType::UnknownType) {
- QWriteLocker locker(customTypesLock());
- int posInVector = -1;
- idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
- normalizedTypeName.size(),
- &posInVector);
- if (idx == QMetaType::UnknownType) {
- QCustomTypeInfo inf;
- inf.typeName = normalizedTypeName;
-#ifndef QT_NO_DATASTREAM
- inf.loadOp = nullptr;
- inf.saveOp = nullptr;
-#endif
- inf.alias = -1;
- inf.typedConstructor = typedConstructor;
- inf.typedDestructor = typedDestructor;
- inf.constructor = constructor;
- inf.destructor = destructor;
- inf.size = size;
- inf.flags = flags;
- inf.metaObject = metaObject;
- if (posInVector == -1) {
- idx = ct->size() + QMetaType::User;
- ct->append(inf);
- } else {
- idx = posInVector + QMetaType::User;
- ct->data()[posInVector] = inf;
- }
- return idx;
+ if (auto ti = reg->aliases.value(QByteArray(typeName, length), nullptr)) {
+ return ti->typeId;
}
-
- if (idx >= QMetaType::User) {
- previousSize = ct->at(idx - QMetaType::User).size;
- previousFlags = ct->at(idx - QMetaType::User).flags;
-
- // Set new/additional flags in case of old library/app.
- // Ensures that older code works in conjunction with new Qt releases
- // requiring the new flags.
- if (flags != previousFlags) {
- QCustomTypeInfo &inf = ct->data()[idx - QMetaType::User];
- inf.flags |= flags;
- if (metaObject)
- inf.metaObject = metaObject;
- }
- }
- }
-
- if (idx < QMetaType::User) {
- previousSize = QMetaType::sizeOf(idx);
- previousFlags = QMetaType::typeFlags(idx);
- }
-
- if (Q_UNLIKELY(previousSize != size)) {
- qFatal("QMetaType::registerType: Binary compatibility break "
- "-- Size mismatch for type '%s' [%i]. Previously registered "
- "size %i, now registering size %i.",
- normalizedTypeName.constData(), idx, previousSize, size);
- }
-
- // these flags cannot change in a binary compatible way:
- const int binaryCompatibilityFlag = QMetaType::PointerToQObject | QMetaType::IsEnumeration | QMetaType::SharedPointerToQObject
- | QMetaType::WeakPointerToQObject | QMetaType::TrackingPointerToQObject;
- if (Q_UNLIKELY((previousFlags ^ flags) & binaryCompatibilityFlag)) {
-
- const char *msg = "QMetaType::registerType: Binary compatibility break. "
- "\nType flags for type '%s' [%i] don't match. Previously "
- "registered TypeFlags(0x%x), now registering TypeFlags(0x%x). ";
-
- qFatal(msg, normalizedTypeName.constData(), idx, previousFlags, int(flags));
}
-
- return idx;
-}
-
-/*!
- \internal
- \since 5.0
- \overload
- Don't use, kept for binary compatibility
-
- ### TODO Qt6: remove me
-*/
-int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter,
- Creator creator,
- Destructor destructor,
- Constructor constructor,
- int size, TypeFlags flags, const QMetaObject *metaObject)
-{
- Q_UNUSED(deleter);
- Q_UNUSED(creator);
- return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
-}
-
-
-/*!
- \internal
- \since 5.5
-
- Registers a user type for marshalling, with \a normalizedTypeName,
- a \a destructor, a \a constructor, and a \a size. Returns the type's
- handle, or -1 if the type could not be registered.
-
- \note normalizedTypeName is not checked for conformance with
- Qt's normalized format, so it must already conform.
-
- ### TODO Qt6: remove me
- */
-int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
- Destructor destructor,
- Constructor constructor,
- int size, TypeFlags flags, const QMetaObject *metaObject)
-{
- return NS(registerNormalizedType)(normalizedTypeName, destructor, constructor, nullptr, nullptr, size, flags, metaObject);
-}
-
-/*!
- \internal
- \since 5.12
-
- Registers a user type for marshalling, with \a normalizedTypeName,
- a \a destructor, a \a constructor, and a \a size. Returns the type's
- handle, or -1 if the type could not be registered.
-
- \note normalizedTypeName is not checked for conformance with
- Qt's normalized format, so it must already conform.
- */
-int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
- TypedDestructor destructor,
- TypedConstructor constructor,
- int size, TypeFlags flags, const QMetaObject *metaObject)
-{
- return NS(registerNormalizedType)(normalizedTypeName, nullptr, nullptr, destructor, constructor, size, flags, metaObject);
-}
-
-/*!
- \internal
- \since 4.7
-
- Registers a user type for marshalling, as an alias of another type (typedef)
-*/
-int QMetaType::registerTypedef(const char* typeName, int aliasId)
-{
-#ifdef QT_NO_QOBJECT
- NS(QByteArray) normalizedTypeName = typeName;
-#else
- NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
-#endif
-
- return registerNormalizedTypedef(normalizedTypeName, aliasId);
+ return QMetaType::UnknownType;
}
/*!
\internal
- \since 5.0
Registers a user type for marshalling, as an alias of another type (typedef).
Note that normalizedTypeName is not checked for conformance with Qt's normalized format,
so it must already conform.
*/
-int QMetaType::registerNormalizedTypedef(const NS(QByteArray) &normalizedTypeName, int aliasId)
+void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeName,
+ QMetaType metaType)
{
- QVector<QCustomTypeInfo> *ct = customTypes();
- if (!ct || normalizedTypeName.isEmpty())
- return -1;
-
- int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
- normalizedTypeName.size());
-
- if (idx == UnknownType) {
- QWriteLocker locker(customTypesLock());
- int posInVector = -1;
- idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
- normalizedTypeName.size(),
- &posInVector);
-
- if (idx == UnknownType) {
- QCustomTypeInfo inf;
- inf.typeName = normalizedTypeName;
- inf.alias = aliasId;
- if (posInVector == -1)
- ct->append(inf);
- else
- ct->data()[posInVector] = inf;
- return aliasId;
- }
- }
-
- if (idx != aliasId) {
- qWarning("QMetaType::registerTypedef: "
- "-- Type name '%s' previously registered as typedef of '%s' [%i], "
- "now registering as typedef of '%s' [%i].",
- normalizedTypeName.constData(), QMetaType::typeName(idx), idx,
- QMetaType::typeName(aliasId), aliasId);
+ if (!metaType.isValid())
+ return;
+ if (auto reg = customTypeRegistery()) {
+ QWriteLocker lock(&reg->lock);
+ auto &al = reg->aliases[normalizedTypeName];
+ if (al)
+ return;
+ al = metaType.d_ptr;
}
- return idx;
}
/*!
@@ -1349,16 +1221,7 @@ int QMetaType::registerNormalizedTypedef(const NS(QByteArray) &normalizedTypeNam
*/
bool QMetaType::isRegistered(int type)
{
- // predefined type
- if ((type >= FirstCoreType && type <= LastCoreType)
- || (type >= FirstGuiType && type <= LastGuiType)
- || (type >= FirstWidgetsType && type <= LastWidgetsType)) {
- return true;
- }
-
- QReadLocker locker(customTypesLock());
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- return ((type >= User) && (ct && ct->count() > type - User) && !ct->at(type - User).typeName.isEmpty());
+ return QMetaType(type).isRegistered();
}
template <bool tryNormalizedType>
@@ -1368,7 +1231,7 @@ static inline int qMetaTypeTypeImpl(const char *typeName, int length)
return QMetaType::UnknownType;
int type = qMetaTypeStaticType(typeName, length);
if (type == QMetaType::UnknownType) {
- QReadLocker locker(customTypesLock());
+ QReadLocker locker(&customTypeRegistery()->lock);
type = qMetaTypeCustomType_unlocked(typeName, length);
#ifndef QT_NO_QOBJECT
if ((type == QMetaType::UnknownType) && tryNormalizedType) {
@@ -1423,7 +1286,6 @@ int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
}
#ifndef QT_NO_DATASTREAM
-
namespace
{
@@ -1467,30 +1329,29 @@ struct FilteredOperatorSwitch
return true;
}
};
+
template<typename T>
struct FilteredOperatorSwitch<T, /* IsAcceptedType = */ false>
{
- static const QMetaTypeInterface* getMetaTypeInterface(int type)
+ static const QMetaTypeModuleHelper *getMetaTypeInterface()
{
- if (QModulesPrivate::QTypeModuleInfo<T>::IsGui && qMetaTypeGuiHelper)
- return &qMetaTypeGuiHelper[type - QMetaType::FirstGuiType];
- else if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget && qMetaTypeWidgetsHelper)
- return &qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType];
+ if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
+ return qMetaTypeGuiHelper;
+ else if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
+ return qMetaTypeWidgetsHelper;
return nullptr;
}
static bool save(QDataStream &stream, const T *data, int type)
{
- if (auto interface = getMetaTypeInterface(type)) {
- interface->saveOp(stream, data);
- return true;
+ if (auto interface = getMetaTypeInterface()) {
+ return interface->save(stream, type, data);
}
return false;
}
static bool load(QDataStream &stream, T *data, int type)
{
- if (auto interface = getMetaTypeInterface(type)) {
- interface->loadOp(stream, data);
- return true;
+ if (auto interface = getMetaTypeInterface()) {
+ return interface->load(stream, type, data);
}
return false;
}
@@ -1525,17 +1386,17 @@ public:
}
bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data)
{
- const QVector<QCustomTypeInfo> * const ct = customTypes();
+ auto ct = customTypeRegistery();
if (!ct)
return false;
- QMetaType::SaveOperator saveOp = nullptr;
+ QMetaType::SaveOperator op = nullptr;
{
- QReadLocker locker(customTypesLock());
- saveOp = ct->at(m_type - QMetaType::User).saveOp;
+ QReadLocker lock(&ct->lock);
+ op = ct->dataStreamOp.value(m_type).saveOp;
}
- if (!saveOp)
+ if (!op)
return false;
- saveOp(stream, data);
+ op(stream, data);
return true;
}
bool delegate(const void*) { return false; }
@@ -1576,17 +1437,17 @@ public:
}
bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data)
{
- const QVector<QCustomTypeInfo> * const ct = customTypes();
+ auto ct = customTypeRegistery();
if (!ct)
return false;
- QMetaType::LoadOperator loadOp = nullptr;
+ QMetaType::LoadOperator op = nullptr;
{
- QReadLocker locker(customTypesLock());
- loadOp = ct->at(m_type - QMetaType::User).loadOp;
+ QReadLocker lock(&ct->lock);
+ op = ct->dataStreamOp.value(m_type).loadOp;
}
- if (!loadOp)
+ if (!op)
return false;
- loadOp(stream, const_cast<QMetaTypeSwitcher::NotBuiltinType*>(data));
+ op(stream, const_cast<QMetaTypeSwitcher::NotBuiltinType *>(data));
return true;
}
bool delegate(const void*) { return false; }
@@ -1647,10 +1508,7 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
*/
void *QMetaType::create(int type, const void *copy)
{
- QMetaType info(type);
- if (int size = info.sizeOf())
- return info.construct(operator new(size), copy);
- return nullptr;
+ return QMetaType(type).create(copy);
}
/*!
@@ -1660,73 +1518,9 @@ void *QMetaType::create(int type, const void *copy)
*/
void QMetaType::destroy(int type, void *data)
{
- QMetaType info(type);
- info.destruct(data);
- operator delete(data);
+ QMetaType(type).destroy(data);
}
-namespace {
-class TypeConstructor {
- template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
- struct ConstructorImpl {
- static void *Construct(const int /*type*/, void *where, const void *copy) { return QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct(where, copy); }
- };
- template<typename T>
- struct ConstructorImpl<T, /* IsAcceptedType = */ false> {
- static void *Construct(const int type, void *where, const void *copy)
- {
- if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
- return Q_LIKELY(qMetaTypeGuiHelper)
- ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].constructor(where, copy)
- : nullptr;
-
- if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
- return Q_LIKELY(qMetaTypeWidgetsHelper)
- ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].constructor(where, copy)
- : nullptr;
-
- // This point can be reached only for known types that definition is not available, for example
- // in bootstrap mode. We have no other choice then ignore it.
- return nullptr;
- }
- };
-public:
- TypeConstructor(const int type, void *where)
- : m_type(type)
- , m_where(where)
- {}
-
- template<typename T>
- void *delegate(const T *copy) { return ConstructorImpl<T>::Construct(m_type, m_where, copy); }
- void *delegate(const void *) { return m_where; }
- void *delegate(const QMetaTypeSwitcher::UnknownType*) { return m_where; }
- void *delegate(const QMetaTypeSwitcher::NotBuiltinType *copy) { return customTypeConstructor(m_type, m_where, copy); }
-
-private:
- static void *customTypeConstructor(const int type, void *where, const void *copy)
- {
- QMetaType::Constructor ctor;
- QMetaType::TypedConstructor tctor;
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- {
- QReadLocker locker(customTypesLock());
- if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
- return nullptr;
- const auto &typeInfo = ct->at(type - QMetaType::User);
- ctor = typeInfo.constructor;
- tctor = typeInfo.typedConstructor;
- }
- Q_ASSERT_X((ctor || tctor) , "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered");
- if (Q_UNLIKELY(tctor))
- return tctor(type, where, copy);
- return ctor(where, copy);
- }
-
- const int m_type;
- void *m_where;
-};
-} // namespace
-
/*!
\since 5.0
@@ -1755,75 +1549,10 @@ private:
*/
void *QMetaType::construct(int type, void *where, const void *copy)
{
- if (!where)
- return nullptr;
- TypeConstructor constructor(type, where);
- return QMetaTypeSwitcher::switcher<void*>(constructor, type, copy);
+ return QMetaType(type).construct(where, copy);
}
-namespace {
-class TypeDestructor {
- template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
- struct DestructorImpl {
- static void Destruct(const int /* type */, void *where) { QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct(where); }
- };
- template<typename T>
- struct DestructorImpl<T, /* IsAcceptedType = */ false> {
- static void Destruct(const int type, void *where)
- {
- if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) {
- if (Q_LIKELY(qMetaTypeGuiHelper))
- qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].destructor(where);
- return;
- }
- if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) {
- if (Q_LIKELY(qMetaTypeWidgetsHelper))
- qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].destructor(where);
- return;
- }
- // This point can be reached only for known types that definition is not available, for example
- // in bootstrap mode. We have no other choice then ignore it.
- }
- };
-public:
- TypeDestructor(const int type)
- : m_type(type)
- {}
-
- template<typename T>
- void delegate(const T *where) { DestructorImpl<T>::Destruct(m_type, const_cast<T*>(where)); }
- // MSVC2013 and earlier can not const_cast a std::nullptr_t pointer.
- void delegate(const std::nullptr_t *) {}
- void delegate(const void *) {}
- void delegate(const QMetaTypeSwitcher::UnknownType*) {}
- void delegate(const QMetaTypeSwitcher::NotBuiltinType *where)
- { customTypeDestructor(m_type, const_cast<void *>(static_cast<const void *>(where))); }
-
-private:
- static void customTypeDestructor(const int type, void *where)
- {
- QMetaType::Destructor dtor;
- QMetaType::TypedDestructor tdtor;
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- {
- QReadLocker locker(customTypesLock());
- if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
- return;
- const auto &typeInfo = ct->at(type - QMetaType::User);
- dtor = typeInfo.destructor;
- tdtor = typeInfo.typedDestructor;
- }
- Q_ASSERT_X((dtor || tdtor), "void QMetaType::destruct(int type, void *where)", "The type was not properly registered");
- if (Q_UNLIKELY(tdtor))
- return tdtor(type, where);
- dtor(where);
- }
-
- const int m_type;
-};
-} // namespace
-
/*!
\since 5.0
@@ -1836,58 +1565,9 @@ private:
*/
void QMetaType::destruct(int type, void *where)
{
- if (!where)
- return;
- TypeDestructor destructor(type);
- QMetaTypeSwitcher::switcher<void>(destructor, type, where);
+ return QMetaType(type).destruct(where);
}
-
-namespace {
-class SizeOf {
- template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
- struct SizeOfImpl {
- static int Size(const int) { return QTypeInfo<T>::sizeOf; }
- };
- template<typename T>
- struct SizeOfImpl<T, /* IsAcceptedType = */ false> {
- static int Size(const int type)
- {
- if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
- return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].size : 0;
-
- if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
- return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].size : 0;
-
- // This point can be reached only for known types that definition is not available, for example
- // in bootstrap mode. We have no other choice then ignore it.
- return 0;
- }
- };
-
-public:
- SizeOf(int type)
- : m_type(type)
- {}
-
- template<typename T>
- int delegate(const T*) { return SizeOfImpl<T>::Size(m_type); }
- int delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
- int delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeSizeOf(m_type); }
-private:
- static int customTypeSizeOf(const int type)
- {
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- QReadLocker locker(customTypesLock());
- if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
- return 0;
- return ct->at(type - QMetaType::User).size;
- }
-
- const int m_type;
-};
-} // namespace
-
/*!
\since 5.0
@@ -1901,61 +1581,9 @@ private:
*/
int QMetaType::sizeOf(int type)
{
- SizeOf sizeOf(type);
- return QMetaTypeSwitcher::switcher<int>(sizeOf, type);
+ return QMetaType(type).sizeOf();
}
-namespace {
-class Flags
-{
- template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
- struct FlagsImpl
- {
- static quint32 Flags(const int /* type */)
- {
- return QtPrivate::QMetaTypeTypeFlags<T>::Flags;
- }
- };
- template<typename T>
- struct FlagsImpl<T, /* IsAcceptedType = */ false>
- {
- static quint32 Flags(const int type)
- {
- if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
- return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].flags : 0;
-
- if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
- return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].flags : 0;
-
- // This point can be reached only for known types that definition is not available, for example
- // in bootstrap mode. We have no other choice then ignore it.
- return 0;
- }
- };
-public:
- Flags(const int type)
- : m_type(type)
- {}
- template<typename T>
- quint32 delegate(const T*) { return FlagsImpl<T>::Flags(m_type); }
- quint32 delegate(const void*) { return 0; }
- quint32 delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
- quint32 delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeFlags(m_type); }
-private:
- const int m_type;
- static quint32 customTypeFlags(const int type)
- {
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- if (Q_UNLIKELY(!ct || type < QMetaType::User))
- return 0;
- QReadLocker locker(customTypesLock());
- if (Q_UNLIKELY(ct->count() <= type - QMetaType::User))
- return 0;
- return ct->at(type - QMetaType::User).flags;
- }
-};
-} // namespace
-
/*!
\since 5.0
@@ -1965,61 +1593,9 @@ private:
*/
QMetaType::TypeFlags QMetaType::typeFlags(int type)
{
- Flags flags(type);
- return static_cast<QMetaType::TypeFlags>(QMetaTypeSwitcher::switcher<quint32>(flags, type));
+ return QMetaType(type).flags();
}
-#ifndef QT_BOOTSTRAPPED
-namespace {
-class MetaObject
-{
-public:
- MetaObject(const int type)
- : m_type(type)
- {}
-
- template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
- struct MetaObjectImpl
- {
- static const QMetaObject *MetaObject(int /*type*/)
- { return QtPrivate::MetaObjectForType<T>::value(); }
- };
- template<typename T>
- struct MetaObjectImpl<T, /* IsAcceptedType = */ false>
- {
- static const QMetaObject *MetaObject(int type) {
- if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
- return Q_LIKELY(qMetaTypeGuiHelper)
- ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].metaObject
- : nullptr;
- if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
- return Q_LIKELY(qMetaTypeWidgetsHelper)
- ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].metaObject
- : nullptr;
- return nullptr;
- }
- };
-
- template <typename T>
- const QMetaObject *delegate(const T *) { return MetaObjectImpl<T>::MetaObject(m_type); }
- const QMetaObject *delegate(const void*) { return nullptr; }
- const QMetaObject *delegate(const QMetaTypeSwitcher::UnknownType*) { return nullptr; }
- const QMetaObject *delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customMetaObject(m_type); }
-private:
- const int m_type;
- static const QMetaObject *customMetaObject(const int type)
- {
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- if (Q_UNLIKELY(!ct || type < QMetaType::User))
- return nullptr;
- QReadLocker locker(customTypesLock());
- if (Q_UNLIKELY(ct->count() <= type - QMetaType::User))
- return nullptr;
- return ct->at(type - QMetaType::User).metaObject;
- }
-};
-} // namespace
-#endif
/*!
\since 5.0
@@ -2030,13 +1606,7 @@ private:
*/
const QMetaObject *QMetaType::metaObjectForType(int type)
{
-#ifndef QT_BOOTSTRAPPED
- MetaObject mo(type);
- return QMetaTypeSwitcher::switcher<const QMetaObject*>(mo, type);
-#else
- Q_UNUSED(type);
- return nullptr;
-#endif
+ return QMetaType(type).metaObject();
}
/*!
@@ -2094,25 +1664,6 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
\sa qRegisterMetaType(), QMetaType::isRegistered(), Q_DECLARE_METATYPE()
*/
-/*! \typedef QMetaType::Deleter
- \internal
-*/
-/*! \typedef QMetaType::Creator
- \internal
-*/
-/*! \typedef QMetaType::SaveOperator
- \internal
-*/
-/*! \typedef QMetaType::LoadOperator
- \internal
-*/
-/*! \typedef QMetaType::Destructor
- \internal
-*/
-/*! \typedef QMetaType::Constructor
- \internal
-*/
-
/*!
\fn int qRegisterMetaType()
\relates QMetaType
@@ -2169,85 +1720,24 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
\sa Q_DECLARE_METATYPE(), QMetaType::type()
*/
-namespace {
-class TypeInfo {
- template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
- struct TypeInfoImpl
- {
- TypeInfoImpl(const uint /* type */, QMetaTypeInterface &info)
- {
- QMetaTypeInterface tmp = QT_METATYPE_INTERFACE_INIT_NO_DATASTREAM(T);
- info = tmp;
- }
- };
-
- template<typename T>
- struct TypeInfoImpl<T, /* IsAcceptedType = */ false>
- {
- TypeInfoImpl(const uint type, QMetaTypeInterface &info)
- {
- if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) {
- if (Q_LIKELY(qMetaTypeGuiHelper))
- info = qMetaTypeGuiHelper[type - QMetaType::FirstGuiType];
- return;
- }
- if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) {
- if (Q_LIKELY(qMetaTypeWidgetsHelper))
- info = qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType];
- return;
- }
- }
- };
-public:
- QMetaTypeInterface info;
- TypeInfo(const uint type)
- : m_type(type)
- {
- QMetaTypeInterface tmp = QT_METATYPE_INTERFACE_INIT_EMPTY();
- info = tmp;
+static QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
+{
+ if (typeId >= QMetaType::User) {
+ if (auto reg = customTypeRegistery())
+ return reg->getCustomType(typeId);
}
- template<typename T>
- void delegate(const T*) { TypeInfoImpl<T>(m_type, info); }
- void delegate(const QMetaTypeSwitcher::UnknownType*) {}
- void delegate(const QMetaTypeSwitcher::NotBuiltinType*) { customTypeInfo(m_type); }
-private:
- void customTypeInfo(const uint type)
- {
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- if (Q_UNLIKELY(!ct))
- return;
- QReadLocker locker(customTypesLock());
- if (Q_LIKELY(uint(ct->count()) > type - QMetaType::User))
- info = ct->at(type - QMetaType::User);
+ if (auto moduleHelper = qModuleHelperForType(typeId))
+ return moduleHelper->interfaceForType(typeId);
+
+ switch (typeId) {
+ QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ default:
+ return nullptr;
}
-
- const uint m_type;
-};
-} // namespace
-
-/*!
- \fn QMetaType QMetaType::typeInfo(const int type)
- \internal
-*/
-QMetaType QMetaType::typeInfo(const int type)
-{
- TypeInfo typeInfo(type);
- QMetaTypeSwitcher::switcher<void>(typeInfo, type);
- return (typeInfo.info.constructor || typeInfo.info.typedConstructor)
- ? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx |
- (typeInfo.info.typedConstructor ? QMetaType::ConstructEx | QMetaType::DestructEx : 0))
- , static_cast<const QMetaTypeInterface *>(nullptr) // typeInfo::info is a temporary variable, we can't return address of it.
- , typeInfo.info.typedConstructor
- , typeInfo.info.typedDestructor
- , typeInfo.info.saveOp
- , typeInfo.info.loadOp
- , typeInfo.info.constructor
- , typeInfo.info.destructor
- , typeInfo.info.size
- , typeInfo.info.flags
- , type
- , typeInfo.info.metaObject)
- : QMetaType(UnknownType);
}
/*!
@@ -2258,252 +1748,7 @@ QMetaType QMetaType::typeInfo(const int type)
\note: The default parameter was added in Qt 5.15
*/
-QMetaType::QMetaType(const int typeId)
- : m_typeId(typeId)
-{
- if (Q_UNLIKELY(typeId == UnknownType)) {
- // Constructs invalid QMetaType instance.
- m_extensionFlags = 0xffffffff;
- Q_ASSERT(!isValid());
- } else {
- // TODO it can be better.
- *this = QMetaType::typeInfo(typeId);
- if (m_typeId == UnknownType)
- m_extensionFlags = 0xffffffff;
- else if (m_typeId == QMetaType::Void)
- m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
- }
-}
-
-/*!
- \fn QMetaType::QMetaType(const QMetaType &other)
- \since 5.0
-
- Copy constructs a QMetaType object.
-*/
-QMetaType::QMetaType(const QMetaType &other)
- : m_typedConstructor(other.m_typedConstructor)
- , m_typedDestructor(other.m_typedDestructor)
- , m_saveOp(other.m_saveOp)
- , m_loadOp(other.m_loadOp)
- , m_constructor(other.m_constructor)
- , m_destructor(other.m_destructor)
- , m_extension(other.m_extension) // space reserved for future use
- , m_size(other.m_size)
- , m_typeFlags(other.m_typeFlags)
- , m_extensionFlags(other.m_extensionFlags)
- , m_typeId(other.m_typeId)
- , m_metaObject(other.m_metaObject)
-{}
-
-QMetaType &QMetaType::operator =(const QMetaType &other)
-{
- m_typedConstructor = other.m_typedConstructor;
- m_typedDestructor = other.m_typedDestructor;
- m_saveOp = other.m_saveOp;
- m_loadOp = other.m_loadOp;
- m_constructor = other.m_constructor;
- m_destructor = other.m_destructor;
- m_size = other.m_size;
- m_typeFlags = other.m_typeFlags;
- m_extensionFlags = other.m_extensionFlags;
- m_extension = other.m_extension; // space reserved for future use
- m_typeId = other.m_typeId;
- m_metaObject = other.m_metaObject;
- return *this;
-}
-
-/*!
- \fn void QMetaType::ctor(const QMetaTypeInterface *info)
- \internal
-
- Method used for future binary compatible extensions. The function may be
- called from within QMetaType's constructor to force a library call from
- inlined code.
-*/
-void QMetaType::ctor(const QMetaTypeInterface *info)
-{
- // Special case for Void type, the type is valid but not constructible.
- // In future we may consider to remove this assert and extend this function to initialize
- // differently m_extensionFlags for different types. Currently it is not needed.
- Q_ASSERT(m_typeId == QMetaType::Void);
- Q_UNUSED(info);
- m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
-}
-
-/*!
- \fn void QMetaType::dtor()
- \internal
-
- Method used for future binary compatible extensions. The function may be
- called from within QMetaType's destructor to force a library call from
- inlined code.
-*/
-void QMetaType::dtor()
-{}
-
-/*!
- \fn void *QMetaType::createExtended(const void *copy) const
- \internal
-
- Method used for future binary compatible extensions. The function may be called
- during QMetaType::create to force library call from inlined code.
-
- ### TODO Qt6 remove the extension
-*/
-void *QMetaType::createExtended(const void *copy) const
-{
- if (m_typeId == QMetaType::UnknownType)
- return nullptr;
- if (Q_UNLIKELY(m_typedConstructor && !m_constructor))
- return m_typedConstructor(m_typeId, operator new(m_size), copy);
- return m_constructor(operator new(m_size), copy);
-}
-
-/*!
- \fn void QMetaType::destroyExtended(void *data) const
- \internal
-
- Method used for future binary compatible extensions. The function may be called
- during QMetaType::destroy to force library call from inlined code.
-
- ### TODO Qt6 remove the extension
-*/
-void QMetaType::destroyExtended(void *data) const
-{
- if (m_typeId == QMetaType::UnknownType)
- return;
- if (Q_UNLIKELY(m_typedDestructor && !m_destructor))
- m_typedDestructor(m_typeId, data);
- else
- m_destructor(data);
- operator delete(data);
-}
-
-/*!
- \fn void *QMetaType::constructExtended(void *where, const void *copy) const
- \internal
-
- Method used for future binary compatible extensions. The function may be called
- during QMetaType::construct to force library call from inlined code.
-*/
-void *QMetaType::constructExtended(void *where, const void *copy) const
-{
- if (m_typeId == QMetaType::UnknownType)
- return nullptr;
- if (m_typedConstructor && !m_constructor)
- return m_typedConstructor(m_typeId, where, copy);
- return nullptr;
-}
-
-/*!
- \fn void QMetaType::destructExtended(void *data) const
- \internal
-
- Method used for future binary compatible extensions. The function may be called
- during QMetaType::destruct to force library call from inlined code.
-*/
-void QMetaType::destructExtended(void *data) const
-{
- if (m_typeId == QMetaType::UnknownType)
- return;
- if (m_typedDestructor && !m_destructor)
- m_typedDestructor(m_typeId, data);
-}
-
-/*!
- \fn uint QMetaType::sizeExtended() const
- \internal
-
- Method used for future binary compatible extensions. The function may be
- called from within QMetaType::size to force a library call from
- inlined code.
-*/
-uint QMetaType::sizeExtended() const
-{
- return 0;
-}
-
-/*!
- \fn QMetaType::TypeFlags QMetaType::flagsExtended() const
- \internal
-
- Method used for future binary compatible extensions. The function may be
- called from within QMetaType::flags to force a library call from
- inlined code.
-*/
-QMetaType::TypeFlags QMetaType::flagsExtended() const
-{
- return { };
-}
-
-/*!
- \brief QMetaType::metaObjectExtended
- \internal
-
- Method used for future binary compatible extensions. The function may be
- called from within QMetaType::metaObject to force a library call from
- inlined code.
-*/
-const QMetaObject *QMetaType::metaObjectExtended() const
-{
- return nullptr;
-}
-
-
-namespace QtPrivate
-{
-const QMetaObject *metaObjectForQWidget()
-{
- if (!qMetaTypeWidgetsHelper)
- return nullptr;
- return qMetaObjectWidgetsHelper;
-}
-
-void qt5CompatibilityHookPostRegister(int id, const QByteArray &normalizedTypeName)
-{
- // In Qt6 QList got typedef'ed to QVector. To keep runtime behavior compatibility
- // with Qt5 we install corresponding aliases. For example if one register
- // QVector<QVector<int>>
- // we need to register the type plus all possible aliases:
- // QVector<QList<int>>
- // QList<QVector<int>>
- // QList<QList<int>>
- // ### Qt6 TODO This is slow, as it allocates couple of strings we would need to
- // if def this call with something like QT_NO_QLIST
- const char *vectorName = "QVector<";
- const char *listName = "QList<";
-
- auto isSubstringOfAType = [](char c) { return c != ' ' && c != ',' && c != '<'; };
- QVarLengthArray<int> indexes;
-
- for (auto containerName: {vectorName, listName}) {
- for (int i = normalizedTypeName.indexOf(containerName, 0); i != -1; i = normalizedTypeName.indexOf(containerName, i + 1)) {
- if (!i || (i > 0 && !isSubstringOfAType(normalizedTypeName[i - 1])))
- indexes.append(i);
- }
- }
- // To avoid problems with the constantly changing size we start replacements
- // from the end of normalizedTypeName
- std::sort(indexes.rbegin(), indexes.rend());
-
- for (quint64 combination = 1; ; ++combination) {
- std::bitset<64> bits(combination);
- QByteArray name = normalizedTypeName;
- for (auto j = 0; j < indexes.size(); ++j) {
- if (bits.test(j)) {
- auto i = indexes[j];
- auto replaceFrom = normalizedTypeName[i + 1] == 'V' ? vectorName : listName;
- auto replaceTo = normalizedTypeName[i + 1] == 'V' ? listName : vectorName;
- name.replace(i, sizeof(replaceFrom), replaceTo);
- }
- }
- QMetaType::registerNormalizedTypedef(name, id);
- if (bits.count() >= size_t(indexes.size()))
- break;
- }
-}
-}
+QMetaType::QMetaType(int typeId) : QMetaType(interfaceForType(typeId)) {}
namespace QtMetaTypePrivate {
const bool VectorBoolElements::true_element = true;
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index b5a62d1aa0..b89f5cff00 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -46,6 +46,7 @@
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qrefcount.h>
#ifndef QT_NO_QOBJECT
#include <QtCore/qobjectdefs.h>
#endif
@@ -245,6 +246,9 @@ struct QMetaObject;
namespace QtPrivate
{
+
+class QMetaTypeInterface;
+
/*!
This template is used for implicit conversion from type From to type To.
\internal
@@ -424,13 +428,6 @@ struct ConverterFunctor : public AbstractConverterFunction
}
class Q_CORE_EXPORT QMetaType {
- enum ExtensionFlag { NoExtensionFlags,
- CreateEx = 0x1, DestroyEx = 0x2,
- ConstructEx = 0x4, DestructEx = 0x8,
- NameEx = 0x10, SizeEx = 0x20,
- CtorEx = 0x40, DtorEx = 0x80,
- FlagsEx = 0x100, MetaObjectEx = 0x200
- };
public:
#ifndef Q_CLANG_QDOC
// The code that actually gets compiled.
@@ -501,16 +498,6 @@ public:
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
- typedef void (*Deleter)(void *);
- typedef void *(*Creator)(const void *);
-
-#if 1 || QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt6: fix this
- typedef void (*Destructor)(void *);
- typedef void *(*Constructor)(void *, const void *); // TODO Qt6: remove me
-#endif
- typedef void (*TypedDestructor)(int, void *);
- typedef void *(*TypedConstructor)(int, void *, const void *);
-
typedef void (*SaveOperator)(QDataStream &, const void *);
typedef void (*LoadOperator)(QDataStream &, void *);
#ifndef QT_NO_DATASTREAM
@@ -519,41 +506,8 @@ public:
static void registerStreamOperators(int type, SaveOperator saveOp,
LoadOperator loadOp);
#endif
- static int registerType(const char *typeName, Deleter deleter,
- Creator creator);
- static int registerType(const char *typeName, Deleter deleter,
- Creator creator,
- Destructor destructor,
- Constructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static int registerType(const char *typeName,
- TypedDestructor destructor,
- TypedConstructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static bool unregisterType(int type);
- static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Deleter deleter,
- Creator creator,
- Destructor destructor,
- Constructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Destructor destructor,
- Constructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, TypedDestructor destructor,
- TypedConstructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static int registerTypedef(const char *typeName, int aliasId);
- static int registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, int aliasId);
+ static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type);
+
static int type(const char *typeName);
static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName);
@@ -563,10 +517,6 @@ public:
static const QMetaObject *metaObjectForType(int type);
static bool isRegistered(int type);
static void *create(int type, const void *copy = nullptr);
-#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED static void *construct(int type, const void *copy = nullptr)
- { return create(type, copy); }
-#endif
static void destroy(int type, void *data);
static void *construct(int type, void *where, const void *copy);
static void destruct(int type, void *where);
@@ -576,32 +526,37 @@ public:
static bool load(QDataStream &stream, int type, void *data);
#endif
- explicit QMetaType(const int type = QMetaType::UnknownType); // ### Qt6: drop const
- inline ~QMetaType();
+ explicit QMetaType(int type);
+ explicit QMetaType(QtPrivate::QMetaTypeInterface *d);
+ QMetaType();
+ ~QMetaType();
+ QMetaType(const QMetaType &other);
+ QMetaType &operator=(const QMetaType &);
+ QMetaType(QMetaType &&other) : d_ptr(other.d_ptr) { other.d_ptr = nullptr; }
+ QMetaType &operator=(QMetaType &&other)
+ {
+ qSwap(d_ptr, other.d_ptr);
+ return *this;
+ }
- inline bool isValid() const;
- inline bool isRegistered() const;
- inline int id() const;
- inline int sizeOf() const;
- inline TypeFlags flags() const;
- inline const QMetaObject *metaObject() const;
+ bool isValid() const;
+ bool isRegistered() const;
+ int id() const;
+ int sizeOf() const;
+ TypeFlags flags() const;
+ const QMetaObject *metaObject() const;
QT_PREPEND_NAMESPACE(QByteArray) name() const;
- inline void *create(const void *copy = nullptr) const;
- inline void destroy(void *data) const;
- inline void *construct(void *where, const void *copy = nullptr) const;
- inline void destruct(void *data) const;
+ void *create(const void *copy = nullptr) const;
+ void destroy(void *data) const;
+ void *construct(void *where, const void *copy = nullptr) const;
+ void destruct(void *data) const;
template<typename T>
- static QMetaType fromType()
- { return QMetaType(qMetaTypeId<T>()); }
-
- friend bool operator==(const QMetaType &a, const QMetaType &b)
- { return a.m_typeId == b.m_typeId; }
-
- friend bool operator!=(const QMetaType &a, const QMetaType &b)
- { return a.m_typeId != b.m_typeId; }
+ static QMetaType fromType();
+ friend bool operator==(const QMetaType &a, const QMetaType &b) { return a.id() == b.id(); }
+ friend bool operator!=(const QMetaType &a, const QMetaType &b) { return !(a == b); }
public:
template<typename T>
@@ -719,34 +674,6 @@ public:
static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
-private:
- static QMetaType typeInfo(const int type);
- inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
- TypedConstructor creator,
- TypedDestructor deleter,
- SaveOperator saveOp,
- LoadOperator loadOp,
- Constructor constructor,
- Destructor destructor,
- uint sizeOf,
- uint theTypeFlags,
- int typeId,
- const QMetaObject *metaObject);
- QMetaType(const QMetaType &other);
- QMetaType &operator =(const QMetaType &);
- inline bool isExtended(const ExtensionFlag flag) const { return m_extensionFlags & flag; }
-
- // Methods used for future binary compatible extensions
- void ctor(const QMetaTypeInterface *info);
- void dtor();
- uint sizeExtended() const;
- QMetaType::TypeFlags flagsExtended() const;
- const QMetaObject *metaObjectExtended() const;
- void *createExtended(const void *copy = nullptr) const;
- void destroyExtended(void *data) const;
- void *constructExtended(void *where, const void *copy = nullptr) const;
- void destructExtended(void *data) const;
-
static bool registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type);
#ifndef QT_NO_DEBUG_STREAM
static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
@@ -764,19 +691,7 @@ private:
static bool registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to);
static void unregisterConverterFunction(int from, int to);
private:
-
- TypedConstructor m_typedConstructor;
- TypedDestructor m_typedDestructor;
- SaveOperator m_saveOp;
- LoadOperator m_loadOp;
- Constructor m_constructor;
- Destructor m_destructor;
- void *m_extension; // space reserved for future use
- uint m_size;
- uint m_typeFlags;
- uint m_extensionFlags;
- int m_typeId;
- const QMetaObject *m_metaObject;
+ QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
};
#undef QT_DEFINE_METATYPE_ID
@@ -1553,33 +1468,38 @@ namespace QtPrivate
template<typename T, typename Enable = void>
struct MetaObjectForType
{
- static inline const QMetaObject *value() { return nullptr; }
+ static constexpr inline const QMetaObject *value() { return nullptr; }
};
+#ifndef QT_NO_QOBJECT
template<>
struct MetaObjectForType<void>
{
- static inline const QMetaObject *value() { return nullptr; }
+ static constexpr inline const QMetaObject *value() { return nullptr; }
};
template<typename T>
struct MetaObjectForType<T*, typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type>
{
- static inline const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
{
- static inline const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
{
- static inline const QMetaObject *value() { return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject; }
+ static constexpr inline const QMetaObject *value()
+ {
+ return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject;
+ }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
{
- static inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
+ static constexpr inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
};
+#endif
template<typename T>
struct IsSharedPointerToTypeDerivedFromQObject
@@ -1726,22 +1646,6 @@ namespace QtPrivate
};
template<class T>
- struct Qt5CompatibilityHook
- {
- static inline void postRegister(int, const QByteArray &) {};
- };
-
- Q_CORE_EXPORT void qt5CompatibilityHookPostRegister(int id, const QByteArray &normalizedTypeName);
-
- template<class T>
- struct Qt5CompatibilityHook<QVector<T>>
- {
- static inline void postRegister(int id, const QByteArray &normalizedTypeName)
- {
- qt5CompatibilityHookPostRegister(id, normalizedTypeName);
- }
- };
-
Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
} // namespace QtPrivate
@@ -1837,38 +1741,29 @@ namespace QtPrivate {
}
template <typename T>
-int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName
+int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &_normalizedTypeName
#ifndef Q_CLANG_QDOC
- , T * dummy = 0
- , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
+ , T * = 0
+ , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
#endif
)
{
+ auto normalizedTypeName = _normalizedTypeName;
#ifndef QT_NO_QOBJECT
+ // FIXME currently not normalized because we don't do compile time normalization
+ normalizedTypeName = QMetaObject::normalizedType(_normalizedTypeName.constData());
Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()), "qRegisterNormalizedMetaType", "qRegisterNormalizedMetaType was called with a not normalized type name, please call qRegisterMetaType instead.");
#endif
- const int typedefOf = dummy ? -1 : QtPrivate::QMetaTypeIdHelper<T>::qt_metatype_id();
- if (typedefOf != -1)
- return QMetaType::registerNormalizedTypedef(normalizedTypeName, typedefOf);
-
- QMetaType::TypeFlags flags(QtPrivate::QMetaTypeTypeFlags<T>::Flags);
-
- if (defined)
- flags |= QMetaType::WasDeclaredAsMetaType;
- const int id = QMetaType::registerNormalizedType(normalizedTypeName,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct,
- int(sizeof(T)),
- flags,
- QtPrivate::MetaObjectForType<T>::value());
+ const QMetaType metaType = QMetaType::fromType<T>();
+ const int id = metaType.id();
if (id > 0) {
+ QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
- QtPrivate::Qt5CompatibilityHook<T>::postRegister(id, normalizedTypeName);
}
return id;
@@ -1907,8 +1802,11 @@ void qRegisterMetaTypeStreamOperators(const char *typeName
template <typename T>
inline Q_DECL_CONSTEXPR int qMetaTypeId()
{
- Q_STATIC_ASSERT_X(QMetaTypeId2<T>::Defined, "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system");
- return QMetaTypeId2<T>::qt_metatype_id();
+ if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
+ return QMetaTypeId2<T>::MetaType;
+ } else {
+ return QMetaType::fromType<T>().id();
+ }
}
template <typename T>
@@ -2074,6 +1972,7 @@ inline int qRegisterMetaTypeStreamOperators()
{ \
enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID }; \
static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return METATYPEID; } \
+ static constexpr const char * const name = #NAME; \
}; \
QT_END_NAMESPACE
@@ -2292,104 +2191,6 @@ QT_BEGIN_NAMESPACE
#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
-inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
- TypedConstructor creator,
- TypedDestructor deleter,
- SaveOperator saveOp,
- LoadOperator loadOp,
- Constructor constructor,
- Destructor destructor,
- uint size,
- uint theTypeFlags,
- int typeId,
- const QMetaObject *_metaObject)
- : m_typedConstructor(creator)
- , m_typedDestructor(deleter)
- , m_saveOp(saveOp)
- , m_loadOp(loadOp)
- , m_constructor(constructor)
- , m_destructor(destructor)
- , m_extension(nullptr)
- , m_size(size)
- , m_typeFlags(theTypeFlags)
- , m_extensionFlags(extensionFlags)
- , m_typeId(typeId)
- , m_metaObject(_metaObject)
-{
- if (Q_UNLIKELY(isExtended(CtorEx) || typeId == QMetaType::Void))
- ctor(info);
-}
-
-inline QMetaType::~QMetaType()
-{
- if (Q_UNLIKELY(isExtended(DtorEx)))
- dtor();
-}
-
-inline bool QMetaType::isValid() const
-{
- return m_typeId != UnknownType;
-}
-
-inline bool QMetaType::isRegistered() const
-{
- return isValid();
-}
-
-inline int QMetaType::id() const
-{
- return m_typeId;
-}
-
-inline void *QMetaType::create(const void *copy) const
-{
- // ### TODO Qt6 remove the extension
- return createExtended(copy);
-}
-
-inline void QMetaType::destroy(void *data) const
-{
- // ### TODO Qt6 remove the extension
- destroyExtended(data);
-}
-
-inline void *QMetaType::construct(void *where, const void *copy) const
-{
- if (Q_UNLIKELY(isExtended(ConstructEx)))
- return constructExtended(where, copy);
- return m_constructor(where, copy);
-}
-
-inline void QMetaType::destruct(void *data) const
-{
- if (Q_UNLIKELY(isExtended(DestructEx)))
- return destructExtended(data);
- if (Q_UNLIKELY(!data))
- return;
- m_destructor(data);
-}
-
-inline int QMetaType::sizeOf() const
-{
- if (Q_UNLIKELY(isExtended(SizeEx)))
- return sizeExtended();
- return m_size;
-}
-
-inline QMetaType::TypeFlags QMetaType::flags() const
-{
- if (Q_UNLIKELY(isExtended(FlagsEx)))
- return flagsExtended();
- return QMetaType::TypeFlags(m_typeFlags);
-}
-
-inline const QMetaObject *QMetaType::metaObject() const
-{
- if (Q_UNLIKELY(isExtended(MetaObjectEx)))
- return metaObjectExtended();
- return m_metaObject;
-}
-
QT_END_NAMESPACE
@@ -2451,6 +2252,163 @@ namespace QtPrivate {
};
}
+namespace QtPrivate {
+
+class QMetaTypeInterface
+{
+public:
+ uint revision; // 0 in Qt 6.0. Can increase if new field are added
+ uint size;
+ uint alignment;
+ uint flags;
+ const QMetaObject *metaObject;
+ const char *name;
+
+ QBasicAtomicInt typeId;
+ QtPrivate::RefCount ref;
+
+ // Called when the type is unregistered, to delete this
+ using DeleteSelf = void (*)(QMetaTypeInterface *);
+ DeleteSelf deleteSelf;
+
+ using DefaultCtrFn = void (*)(const QMetaTypeInterface *, void *);
+ DefaultCtrFn defaultCtr;
+ using CopyCtrFn = void (*)(const QMetaTypeInterface *, void *, const void *);
+ CopyCtrFn copyCtr;
+ using MoveCtrFn = void (*)(const QMetaTypeInterface *, void *, void *);
+ MoveCtrFn moveCtr;
+ using DtorFn = void (*)(const QMetaTypeInterface *, void *);
+ DtorFn dtor;
+
+ using LegacyRegisterOp = void (*)();
+ LegacyRegisterOp legacyRegisterOp;
+};
+
+template<typename T>
+constexpr auto typenameHelper()
+{
+ constexpr auto prefix = sizeof(
+#ifdef Q_CC_CLANG
+ "auto QtPrivate::typenameHelper() [T = ") - 1;
+#else
+ "constexpr auto QtPrivate::typenameHelper() [with T = ") - 1;
+#endif
+ constexpr int suffix = sizeof("]");
+ constexpr int len = sizeof(__PRETTY_FUNCTION__) - prefix - suffix;
+ std::array<char, len + 1> result {};
+ for (int i = 0; i < len; ++i)
+ result[i] = __PRETTY_FUNCTION__[prefix + i];
+ return result;
+}
+
+template<typename T, typename = void>
+struct BuiltinMetaType : std::integral_constant<int, 0>
+{
+};
+template<typename T>
+struct BuiltinMetaType<T, std::enable_if_t<QMetaTypeId2<T>::IsBuiltIn>>
+ : std::integral_constant<int, QMetaTypeId2<T>::MetaType>
+{
+};
+
+template<typename T>
+class QMetaTypeForType
+{
+ static const decltype(typenameHelper<T>()) name;
+
+public:
+ static QMetaTypeInterface metaType;
+};
+
+#ifdef Q_CC_CLANG
+// Workaround for https://bugs.llvm.org/show_bug.cgi?id=44554 : Every lambda used for initializing
+// static members need a different signature for explicit instentiation
+#define QT_METATYPE_CONSTEXPRLAMDA(...) [](std::integral_constant<int, __COUNTER__> = {}) constexpr __VA_ARGS__ ()
+#elif defined(Q_CC_MSVC) && Q_CC_MSVC < 1920
+// Workaround a bug with 'if constexpr' not working in lambda that are not generic in MSVC 2017
+#define QT_METATYPE_CONSTEXPRLAMDA(...) [](auto) constexpr __VA_ARGS__ (0)
+#else
+#define QT_METATYPE_CONSTEXPRLAMDA(...) []() constexpr __VA_ARGS__ ()
+#endif
+
+template<typename T>
+QMetaTypeInterface QMetaTypeForType<T>::metaType = {
+ /*.revision=*/ 0,
+ /*.size=*/ sizeof(T),
+ /*.alignment=*/ alignof(T),
+ /*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
+ /*.metaObject=*/ MetaObjectForType<T>::value(),
+ /*.name=*/ QT_METATYPE_CONSTEXPRLAMDA( -> const char * {
+ if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
+ return QMetaTypeId2<T>::name;
+ } else {
+ return name.data();
+ }
+ }),
+ /*.typeId=*/ BuiltinMetaType<T>::value,
+ /*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC,
+ /*.deleteSelf=*/ nullptr,
+ /*.defaultCtr=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::DefaultCtrFn {
+ if constexpr (std::is_default_constructible_v<T>) {
+ return [](const QMetaTypeInterface *, void *addr) { new (addr) T(); };
+ } else {
+ return nullptr;
+ }
+ }),
+ /*.copyCtr=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::CopyCtrFn {
+ if (std::is_copy_constructible_v<T>) {
+ return [](const QMetaTypeInterface *, void *addr, const void *other) {
+ new (addr) T(*reinterpret_cast<const T *>(other));
+ };
+ } else {
+ return nullptr;
+ }
+ }),
+ /*.moveCtr=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::MoveCtrFn {
+ if constexpr (std::is_move_constructible_v<T>) {
+ return [](const QMetaTypeInterface *, void *addr, void *other) {
+ new (addr) T(std::move(*reinterpret_cast<T *>(other)));
+ };
+ } else {
+ return nullptr;
+ }
+ }),
+ /*.dtor=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::DtorFn {
+ return [](const QMetaTypeInterface *, void *addr) { reinterpret_cast<T *>(addr)->~T(); };
+ }),
+ /*.legacyRegisterOp=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::LegacyRegisterOp {
+ if constexpr (QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn) {
+ return []() { QMetaTypeId2<T>::qt_metatype_id(); };
+ } else {
+ return nullptr;
+ }
+ })
+};
+#undef QT_METATYPE_CONSTEXPRLAMDA
+
+template<typename T>
+constexpr const decltype(typenameHelper<T>()) QMetaTypeForType<T>::name = typenameHelper<T>();
+
+
+template<typename T>
+constexpr QMetaTypeInterface *qMetaTypeIntefaceForType()
+{
+ using Ty = std::remove_cv_t<std::remove_reference_t<T>>;
+ if constexpr (std::is_same_v<Ty, void>) {
+ return nullptr;
+ } else {
+ return &QMetaTypeForType<Ty>::metaType;
+ }
+}
+
+} // namespace QtPrivate
+
+template<typename T>
+QMetaType QMetaType::fromType()
+{
+ return QMetaType(QtPrivate::qMetaTypeIntefaceForType<T>());
+}
+
QT_END_NAMESPACE
#endif // QMETATYPE_H
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index f2057e25b4..b07792dfca 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -121,77 +121,15 @@ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_DECLARE_WIDGETS_MODULE_TYPES_ITER)
#undef QT_DECLARE_GUI_MODULE_TYPES_ITER
#undef QT_DECLARE_WIDGETS_MODULE_TYPES_ITER
-class QMetaTypeInterface
+class QMetaTypeModuleHelper
{
public:
- QMetaType::SaveOperator saveOp;
- QMetaType::LoadOperator loadOp;
- QMetaType::Constructor constructor; // TODO Qt6: remove me
- QMetaType::Destructor destructor;
- int size;
- QMetaType::TypeFlags::Int flags;
- const QMetaObject *metaObject;
- QMetaType::TypedConstructor typedConstructor;
- QMetaType::TypedDestructor typedDestructor;
-};
-
+ virtual QtPrivate::QMetaTypeInterface *interfaceForType(int) const = 0;
#ifndef QT_NO_DATASTREAM
-# define QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL(Type) \
- /*saveOp*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Save), \
- /*loadOp*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Load),
-# define QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type) \
- /*saveOp*/ nullptr, \
- /*loadOp*/ nullptr,
-#else
-# define QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type) \
- /*saveOp*/ nullptr, \
- /*loadOp*/ nullptr,
-# define QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL(Type) \
- QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type)
-#endif
-
-#ifndef QT_BOOTSTRAPPED
-#define METAOBJECT_DELEGATE(Type) (QtPrivate::MetaObjectForType<Type>::value())
-#else
-#define METAOBJECT_DELEGATE(Type) nullptr
+ virtual bool save(QDataStream &stream, int type, const void *data) const = 0;
+ virtual bool load(QDataStream &stream, int type, void *data) const = 0;
#endif
-
-#define QT_METATYPE_INTERFACE_INIT_IMPL(Type, DATASTREAM_DELEGATE) \
-{ \
- DATASTREAM_DELEGATE(Type) \
- /*constructor*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Construct), \
- /*destructor*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Destruct), \
- /*size*/(QTypeInfo<Type>::sizeOf), \
- /*flags*/QtPrivate::QMetaTypeTypeFlags<Type>::Flags, \
- /*metaObject*/METAOBJECT_DELEGATE(Type), \
- /*typedConstructor*/ nullptr, \
- /*typedDestructor*/ nullptr \
-}
-
-
-/* These QT_METATYPE_INTERFACE_INIT* macros are used to initialize QMetaTypeInterface instance.
-
- - QT_METATYPE_INTERFACE_INIT(Type) -> It takes Type argument and creates all necessary wrapper functions for the Type,
- it detects if QT_NO_DATASTREAM was defined. Probably it is the macro that you want to use.
-
- - QT_METATYPE_INTERFACE_INIT_EMPTY() -> It initializes an empty QMetaTypeInterface instance.
-
- - QT_METATYPE_INTERFACE_INIT_NO_DATASTREAM(Type) -> Temporary workaround for missing auto-detection of data stream
- operators. It creates same instance as QT_METATYPE_INTERFACE_INIT(Type) but with null stream operators callbacks.
- */
-#define QT_METATYPE_INTERFACE_INIT(Type) QT_METATYPE_INTERFACE_INIT_IMPL(Type, QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL)
-#define QT_METATYPE_INTERFACE_INIT_NO_DATASTREAM(Type) QT_METATYPE_INTERFACE_INIT_IMPL(Type, QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL)
-#define QT_METATYPE_INTERFACE_INIT_EMPTY() \
-{ \
- QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(void) \
- /*constructor*/ nullptr, \
- /*destructor*/ nullptr, \
- /*size*/ 0, \
- /*flags*/ 0, \
- /*metaObject*/ nullptr , \
- /*typedConstructor*/ nullptr, \
- /*typedDestructor*/ nullptr \
-}
+};
namespace QtMetaTypePrivate {
template<typename T>
@@ -253,6 +191,32 @@ template<> struct TypeDefinition<QQuaternion> { static const bool IsAvailable =
#ifdef QT_NO_ICON
template<> struct TypeDefinition<QIcon> { static const bool IsAvailable = false; };
#endif
+
+template<typename T>
+static QtPrivate::QMetaTypeInterface *getInterfaceFromType()
+{
+ if constexpr (std::is_same_v<T, void>) {
+ return nullptr;
+ } else if constexpr (QtMetaTypePrivate::TypeDefinition<T>::IsAvailable) {
+ return &QtPrivate::QMetaTypeForType<T>::metaType;
+ }
+ return nullptr;
+}
+
+#define QT_METATYPE_CONVERT_ID_TO_TYPE(MetaTypeName, MetaTypeId, RealName) \
+ case QMetaType::MetaTypeName: \
+ return QtMetaTypePrivate::getInterfaceFromType<RealName>();
+
+#define QT_METATYPE_DATASTREAM_SAVE(MetaTypeName, MetaTypeId, RealName) \
+ case QMetaType::MetaTypeName: \
+ QtMetaTypePrivate::QMetaTypeFunctionHelper<RealName, QtMetaTypePrivate::TypeDefinition<RealName>::IsAvailable>::Save(stream, data); \
+ return true;
+
+#define QT_METATYPE_DATASTREAM_LOAD(MetaTypeName, MetaTypeId, RealName) \
+ case QMetaType::MetaTypeName: \
+ QtMetaTypePrivate::QMetaTypeFunctionHelper<RealName, QtMetaTypePrivate::TypeDefinition<RealName>::IsAvailable>::Load(stream, data); \
+ return true;
+
} //namespace QtMetaTypePrivate
QT_END_NAMESPACE
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index dabd417a32..bfda2aa9b6 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -127,27 +127,31 @@ QDBusMetaObjectGenerator::QDBusMetaObjectGenerator(const QString &interfaceName,
}
}
-static int registerComplexDBusType(const char *typeName)
+static int registerComplexDBusType(const QByteArray &typeName)
{
- struct QDBusRawTypeHandler {
- static void destruct(void *)
- {
- qFatal("Cannot destruct placeholder type QDBusRawType");
- }
-
- static void *construct(void *, const void *)
- {
- qFatal("Cannot construct placeholder type QDBusRawType");
- return nullptr;
- }
+ struct QDBusRawTypeHandler : QtPrivate::QMetaTypeInterface
+ {
+ const QByteArray name;
+ QDBusRawTypeHandler(const QByteArray &name)
+ : QtPrivate::QMetaTypeInterface {
+ 0, sizeof(void *), sizeof(void *), QMetaType::MovableType, nullptr,
+ name.constData(), 0, QtPrivate::RefCount{0},
+ [](QtPrivate::QMetaTypeInterface *self) {
+ delete static_cast<QDBusRawTypeHandler *>(self);
+ },
+ nullptr, nullptr, nullptr, nullptr, nullptr
+ },
+ name(name)
+ {}
};
- return QMetaType::registerNormalizedType(typeName,
- QDBusRawTypeHandler::destruct,
- QDBusRawTypeHandler::construct,
- sizeof(void *),
- QMetaType::MovableType,
- nullptr);
+ static QBasicMutex mutex;
+ static QHash<QByteArray, QMetaType> hash;
+ QMutexLocker lock(&mutex);
+ QMetaType &metatype = hash[typeName];
+ if (!metatype.isValid())
+ metatype = QMetaType(new QDBusRawTypeHandler(typeName));
+ return metatype.id();
}
Q_DBUS_EXPORT bool qt_dbus_metaobject_skip_annotations = false;
diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp
index f06a3721a1..f0d74f590b 100644
--- a/src/gui/kernel/qguivariant.cpp
+++ b/src/gui/kernel/qguivariant.cpp
@@ -338,19 +338,41 @@ const QVariant::Handler qt_gui_variant_handler = {
#define QT_IMPL_METATYPEINTERFACE_GUI_TYPES(MetaTypeName, MetaTypeId, RealName) \
QT_METATYPE_INTERFACE_INIT(RealName),
-static const QMetaTypeInterface qVariantGuiHelper[] = {
- QT_FOR_EACH_STATIC_GUI_CLASS(QT_IMPL_METATYPEINTERFACE_GUI_TYPES)
-};
+static const struct : QMetaTypeModuleHelper
+{
+ QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
+ switch (type) {
+ QT_FOR_EACH_STATIC_GUI_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ default: return nullptr;
+ }
+ }
+#ifndef QT_NO_DATASTREAM
+ bool save(QDataStream &stream, int type, const void *data) const override {
+ switch (type) {
+ QT_FOR_EACH_STATIC_GUI_CLASS(QT_METATYPE_DATASTREAM_SAVE)
+ default: return false;
+ }
+ }
+ bool load(QDataStream &stream, int type, void *data) const override {
+ switch (type) {
+ QT_FOR_EACH_STATIC_GUI_CLASS(QT_METATYPE_DATASTREAM_LOAD)
+ default: return false;
+ }
+ }
+#endif
+
+} qVariantGuiHelper;
+
#undef QT_IMPL_METATYPEINTERFACE_GUI_TYPES
} // namespace used to hide QVariant handler
-extern Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper;
+extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper;
void qRegisterGuiVariant()
{
QVariantPrivate::registerHandler(QModulesPrivate::Gui, &qt_gui_variant_handler);
- qMetaTypeGuiHelper = qVariantGuiHelper;
+ qMetaTypeGuiHelper = &qVariantGuiHelper;
}
Q_CONSTRUCTOR_FUNCTION(qRegisterGuiVariant)
diff --git a/src/widgets/kernel/qwidgetsvariant.cpp b/src/widgets/kernel/qwidgetsvariant.cpp
index edb166e8d5..02b426988f 100644
--- a/src/widgets/kernel/qwidgetsvariant.cpp
+++ b/src/widgets/kernel/qwidgetsvariant.cpp
@@ -138,23 +138,42 @@ static const QVariant::Handler widgets_handler = {
#endif
};
-#define QT_IMPL_METATYPEINTERFACE_WIDGETS_TYPES(MetaTypeName, MetaTypeId, RealName) \
- QT_METATYPE_INTERFACE_INIT(RealName),
+static const struct : QMetaTypeModuleHelper
+{
+ QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
+ switch (type) {
+ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
+ default: return nullptr;
+ }
+ }
+#ifndef QT_NO_DATASTREAM
+ bool save(QDataStream &stream, int type, const void *data) const override {
+ switch (type) {
+ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_METATYPE_DATASTREAM_SAVE)
+ default: return false;
+ }
+ }
+ bool load(QDataStream &stream, int type, void *data) const override {
+ switch (type) {
+ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_METATYPE_DATASTREAM_LOAD)
+ default: return false;
+ }
+ }
+#endif
+
+} qVariantWidgetsHelper;
-static const QMetaTypeInterface qVariantWidgetsHelper[] = {
- QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_IMPL_METATYPEINTERFACE_WIDGETS_TYPES)
-};
#undef QT_IMPL_METATYPEINTERFACE_WIDGETS_TYPES
} // namespace
-extern Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper;
+extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper;
void qRegisterWidgetsVariant()
{
qRegisterMetaType<QWidget*>();
- qMetaTypeWidgetsHelper = qVariantWidgetsHelper;
+ qMetaTypeWidgetsHelper = &qVariantWidgetsHelper;
QVariantPrivate::registerHandler(QModulesPrivate::Widgets, &widgets_handler);
}
Q_CONSTRUCTOR_FUNCTION(qRegisterWidgetsVariant)