summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2019-12-02 09:52:41 +0100
committerOlivier Goffart <ogoffart@woboq.com>2020-02-20 16:11:02 +0100
commit33cd680ddbaccf6139e215d851a39e657ae36394 (patch)
tree85f0fe036e840221ee3e3a91c2e9423bd61f8d43 /src/corelib
parent14f1ec186f87ce50037044ccb079463676518ec5 (diff)
New QMetaType representation
the QMetaType is represented as a pointer to a "vtable" in the form of a QtPrivate::QMetaTypeInterface* The recomanded use of QMetaType is to construct an object with QMetaType::fromType. This does not require any registration. There is still an id() function which will do some registration for compatibility with Qt5. Also the patch does not really touch the other extra things that can be registered (data stream operator, comparison operator, iteratable, ...) and this still uses the previous system. This is only the change in QMetaType, other changes to use it in QVariant and QMetaObject will follow Change-Id: Iffad20085cf33f33447f58a68236013a8b60fdbf Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/corelib')
-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
3 files changed, 528 insertions, 1361 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