diff options
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 6 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_win.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 221 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject_moc_p.h | 164 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobjectbuilder.cpp | 37 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.cpp | 1298 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 854 | ||||
-rw-r--r-- | src/corelib/kernel/qmetatype_p.h | 103 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 96 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.h | 30 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 12 | ||||
-rw-r--r-- | src/corelib/kernel/qobjectdefs.h | 197 | ||||
-rw-r--r-- | src/corelib/kernel/qsignalmapper.cpp | 59 | ||||
-rw-r--r-- | src/corelib/kernel/qsignalmapper.h | 10 | ||||
-rw-r--r-- | src/corelib/kernel/qtmetamacros.h | 234 | ||||
-rw-r--r-- | src/corelib/kernel/qtranslator.cpp | 8 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 576 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.h | 96 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant_p.h | 109 |
20 files changed, 1593 insertions, 2523 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 34f54d8f94..dc46695f80 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -138,10 +138,10 @@ QT_BEGIN_NAMESPACE extern QString qAppFileName(); #endif -#if QT_VERSION >= 0x060000 -# error "Bump QCoreApplicatoinPrivate::app_compile_version to 0x060000" +#if QT_VERSION >= 0x070000 +# error "Bump QCoreApplicatoinPrivate::app_compile_version to 0x070000" #endif -int QCoreApplicationPrivate::app_compile_version = 0x050000; //we don't know exactly, but it's at least 5.0.0 +int QCoreApplicationPrivate::app_compile_version = 0x060000; //we don't know exactly, but it's at least 6.0.0 bool QCoreApplicationPrivate::setuidAllowed = false; diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 765f129758..824c0535ed 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -772,7 +772,7 @@ QString decodeMSG(const MSG& msg) auto rect = reinterpret_cast<const RECT *>(lParam); QTextStream(¶meters) << "DPI: " << HIWORD(wParam) << ',' << LOWORD(wParam) << ' ' << (rect->right - rect->left) << 'x' - << (rect->bottom - rect->top) << forcesign << rect->left << rect->top; + << (rect->bottom - rect->top) << Qt::forcesign << rect->left << rect->top; } break; case WM_IME_NOTIFY: diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 1661520b78..9be99d8c6a 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -154,20 +154,29 @@ QT_BEGIN_NAMESPACE static inline const QMetaObjectPrivate *priv(const uint* data) { return reinterpret_cast<const QMetaObjectPrivate*>(data); } +static inline const char *rawStringData(const QMetaObject *mo, int index) +{ + Q_ASSERT(priv(mo->d.data)->revision >= 7); + uint offset = mo->d.stringdata[2*index]; + return reinterpret_cast<const char *>(mo->d.stringdata) + offset; +} + static inline const QByteArray stringData(const QMetaObject *mo, int index) { Q_ASSERT(priv(mo->d.data)->revision >= 7); - const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo->d.stringdata[index]) }; - Q_ASSERT(data.ptr->ref.isStatic()); - Q_ASSERT(data.ptr->alloc == 0); - Q_ASSERT(data.ptr->capacityReserved == 0); - Q_ASSERT(data.ptr->size >= 0); - return data; + uint offset = mo->d.stringdata[2*index]; + uint length = mo->d.stringdata[2*index + 1]; + const char *string = reinterpret_cast<const char *>(mo->d.stringdata) + offset; + return QByteArray::fromRawData(string, length); } -static inline const char *rawStringData(const QMetaObject *mo, int index) +static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo) { - return stringData(mo, index).data(); + if (typeInfo & IsUnresolvedType) { + return rawStringData(mo, typeInfo & TypeNameIndexMask); + } else { + return QMetaType::typeName(typeInfo); + } } static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo) @@ -181,16 +190,11 @@ static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeIn } } -static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo) -{ - return typeNameFromTypeInfo(mo, typeInfo).constData(); -} - static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo) { if (!(typeInfo & IsUnresolvedType)) return typeInfo; - return QMetaType::type(stringData(mo, typeInfo & TypeNameIndexMask)); + return QMetaType::type(rawStringData(mo, typeInfo & TypeNameIndexMask)); } class QMetaMethodPrivate : public QMetaMethod @@ -577,7 +581,7 @@ static bool methodMatch(const QMetaObject *m, int handle, if (int(m->d.data[handle + 1]) != argc) return false; - if (stringData(m, m->d.data[handle]) != name) + if (rawStringData(m, m->d.data[handle]) != name) return false; int paramsIndex = m->d.data[handle + 2] + 1; @@ -682,7 +686,9 @@ static void argumentTypesFromString(const char *str, const char *end, --level; ++str; } - types += QArgumentType(QByteArray(begin, str - begin)); + QByteArray argType(begin, str - begin); + argType.replace("QList<", "QVector<"); + types += QArgumentType(std::move(argType)); } } @@ -1161,7 +1167,7 @@ QMetaProperty QMetaObject::property(int index) const const QMetaObject *scope = nullptr; if (qstrcmp(scope_name, "Qt") == 0) - scope = &QObject::staticQtMetaObject; + scope = &Qt::staticMetaObject; else scope = QMetaObject_findMetaObject(this, scope_name); if (scope) @@ -1309,17 +1315,7 @@ static char *qNormalizeType(char *d, int &templdepth, QByteArray &result) */ QByteArray QMetaObject::normalizedType(const char *type) { - QByteArray result; - - if (!type || !*type) - return result; - - QVarLengthArray<char> stackbuf(qstrlen(type) + 1); - qRemoveWhitespace(type, stackbuf.data()); - int templdepth = 0; - qNormalizeType(stackbuf.data(), templdepth, result); - - return result; + return normalizeTypeInternal(type, type + qstrlen(type)); } /*! @@ -2837,10 +2833,6 @@ QByteArray QMetaEnum::valueToKeys(int value) const The enum needs to be declared with Q_ENUM. */ -static QByteArray qualifiedName(const QMetaEnum &e) -{ - return QByteArray(e.scope()) + "::" + e.name(); -} /*! \class QMetaProperty @@ -2931,65 +2923,45 @@ const char *QMetaProperty::typeName() const Returns this property's type. The return value is one of the values of the QVariant::Type enumeration. - \sa userType(), typeName(), name() + \sa userType(), typeName(), name(), metaType() */ QVariant::Type QMetaProperty::type() const { - if (!mobj) - return QVariant::Invalid; - int handle = priv(mobj->d.data)->propertyData + 3*idx; - - Q_ASSERT(priv(mobj->d.data)->revision >= 7); - uint type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]); + uint type = userType(); if (type >= QMetaType::User) return QVariant::UserType; - if (type != QMetaType::UnknownType) - return QVariant::Type(type); - if (isEnumType()) { - int enumMetaTypeId = QMetaType::type(qualifiedName(menum)); - if (enumMetaTypeId == QMetaType::UnknownType) - return QVariant::Int; - } -#ifdef QT_COORD_TYPE - // qreal metatype must be resolved at runtime. - if (strcmp(typeName(), "qreal") == 0) - return QVariant::Type(qMetaTypeId<qreal>()); -#endif - - return QVariant::UserType; + return QVariant::Type(type); } /*! \since 4.2 Returns this property's user type. The return value is one - of the values that are registered with QMetaType, or QMetaType::UnknownType if - the type is not registered. + of the values that are registered with QMetaType. + + This is equivalent to metaType().id() - \sa type(), QMetaType, typeName() + \sa type(), QMetaType, typeName(), metaType() */ int QMetaProperty::userType() const { if (!mobj) return QMetaType::UnknownType; - Q_ASSERT(priv(mobj->d.data)->revision >= 7); - int handle = priv(mobj->d.data)->propertyData + 3*idx; - int type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]); - if (type != QMetaType::UnknownType) - return type; - if (isEnumType()) { - type = QMetaType::type(qualifiedName(menum)); - if (type == QMetaType::UnknownType) { - type = registerPropertyType(); - if (type == QMetaType::UnknownType) - return QMetaType::Int; // Match behavior of QMetaType::type() - } - return type; - } - type = QMetaType::type(typeName()); - if (type != QMetaType::UnknownType) - return type; - return registerPropertyType(); + return QMetaType(mobj->d.metaTypes[idx]).id(); +} + +/*! + \since 6.0 + + Returns this property's QMetaType. + + \sa QMetaType + */ +QMetaType QMetaProperty::metaType() const +{ + if (!mobj) + return {}; + return QMetaType(mobj->d.metaTypes[idx]); } /*! @@ -3100,37 +3072,6 @@ QVariant QMetaProperty::read(const QObject *object) const if (!object || !mobj) return QVariant(); - uint t = QMetaType::Int; - if (isEnumType()) { - /* - try to create a QVariant that can be converted to this enum - type (only works if the enum has already been registered - with QMetaType) - */ - int enumMetaTypeId = QMetaType::type(qualifiedName(menum)); - if (enumMetaTypeId != QMetaType::UnknownType) - t = enumMetaTypeId; - } else { - int handle = priv(mobj->d.data)->propertyData + 3*idx; - const char *typeName = nullptr; - Q_ASSERT(priv(mobj->d.data)->revision >= 7); - uint typeInfo = mobj->d.data[handle + 1]; - if (!(typeInfo & IsUnresolvedType)) - t = typeInfo; - else { - typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask); - t = QMetaType::type(typeName); - } - if (t == QMetaType::UnknownType) { - // Try to register the type and try again before reporting an error. - t = registerPropertyType(); - if (t == QMetaType::UnknownType) { - qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name()); - return QVariant(); - } - } - } - // the status variable is changed by qt_metacall to indicate what it did // this feature is currently only used by Qt D-Bus and should not be depended // upon. Don't change it without looking into QDBusAbstractInterface first @@ -3139,10 +3080,11 @@ QVariant QMetaProperty::read(const QObject *object) const int status = -1; QVariant value; void *argv[] = { nullptr, &value, &status }; - if (t == QMetaType::QVariant) { + QMetaType t(mobj->d.metaTypes[idx]); + if (t == QMetaType::fromType<QVariant>()) { argv[0] = &value; } else { - value = QVariant(t, (void*)nullptr); + value = QVariant(t, nullptr); argv[0] = value.data(); } if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall) { @@ -3154,9 +3096,9 @@ QVariant QMetaProperty::read(const QObject *object) const if (status != -1) return value; - if (t != QMetaType::QVariant && argv[0] != value.data()) + if (t != QMetaType::fromType<QVariant>() && argv[0] != value.data()) // pointer or reference - return QVariant((QVariant::Type)t, argv[0]); + return QVariant(t, argv[0]); return value; } @@ -3177,9 +3119,10 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const return false; QVariant v = value; - uint t = QMetaType::UnknownType; - if (isEnumType()) { - if (v.userType() == QMetaType::QString) { + QMetaType t(mobj->d.metaTypes[idx]); + if (t != QMetaType::fromType<QVariant>() && t != v.metaType()) { + if (isEnumType() && !t.metaObject() && v.userType() == QMetaType::QString) { + // Assigning a string to a property of type Q_ENUMS (instead of Q_ENUM) bool ok; if (isFlagType()) v = QVariant(menum.keysToValue(value.toByteArray(), &ok)); @@ -3187,39 +3130,14 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const v = QVariant(menum.keyToValue(value.toByteArray(), &ok)); if (!ok) return false; - } else if (v.userType() != QMetaType::Int && v.userType() != QMetaType::UInt) { - int enumMetaTypeId = QMetaType::type(qualifiedName(menum)); - if ((enumMetaTypeId == QMetaType::UnknownType) || (v.userType() != enumMetaTypeId) || !v.constData()) - return false; - v = QVariant(*reinterpret_cast<const int *>(v.constData())); - } - v.convert(QMetaType::Int); - } else { - int handle = priv(mobj->d.data)->propertyData + 3*idx; - const char *typeName = nullptr; - Q_ASSERT(priv(mobj->d.data)->revision >= 7); - uint typeInfo = mobj->d.data[handle + 1]; - if (!(typeInfo & IsUnresolvedType)) - t = typeInfo; - else { - typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask); - t = QMetaType::type(typeName); - if (t == QMetaType::UnknownType) - t = registerPropertyType(); - if (t == QMetaType::UnknownType) - return false; - } - if (t != QMetaType::QVariant && int(t) != value.userType()) { - if (!value.isValid()) { - if (isResettable()) - return reset(object); - v = QVariant(t, nullptr); - } else if (!v.convert(t)) { - return false; - } + } else if (!value.isValid()) { + if (isResettable()) + return reset(object); + v = QVariant(t, nullptr); + } else if (!v.convert(t.id())) { + return false; } } - // the status variable is changed by qt_metacall to indicate what it did // this feature is currently only used by Qt D-Bus and should not be depended // upon. Don't change it without looking into QDBusAbstractInterface first @@ -3230,7 +3148,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const // interception of property writes. int flags = 0; void *argv[] = { nullptr, &v, &status, &flags }; - if (t == QMetaType::QVariant) + if (t == QMetaType::fromType<QVariant>()) argv[0] = &v; else argv[0] = v.data(); @@ -3670,6 +3588,21 @@ const char* QMetaClassInfo::value() const } /*! + \class QMethodRawArguments + \internal + + A wrapper class for the void ** arguments array used by the meta + object system. If a slot uses a single argument of this type, + the meta object system will pass the raw arguments array directly + to the slot and set the arguments count in the slot description to + zero, so that any signal can connect to it. + + This is used internally to implement signal relay functionality in + our state machine and dbus. +*/ + + +/*! \macro QGenericArgument Q_ARG(Type, const Type &value) \relates QMetaObject diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index beb85becae..08adc495e0 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -46,9 +46,6 @@ QT_BEGIN_NAMESPACE - -template <typename T> class QList; - #define Q_METAMETHOD_INVOKE_MAX_ARGS 10 class Q_CORE_EXPORT QMetaMethod @@ -253,6 +250,7 @@ public: const char *typeName() const; QVariant::Type type() const; int userType() const; + QMetaType metaType() const; int propertyIndex() const; int relativePropertyIndex() const; diff --git a/src/corelib/kernel/qmetaobject_moc_p.h b/src/corelib/kernel/qmetaobject_moc_p.h index 8c7900767b..9770d9c576 100644 --- a/src/corelib/kernel/qmetaobject_moc_p.h +++ b/src/corelib/kernel/qmetaobject_moc_p.h @@ -52,167 +52,19 @@ // We mean it. // -#include <QtCore/private/qglobal_p.h> +#include <QtCore/qbytearray.h> QT_BEGIN_NAMESPACE // This function is shared with moc.cpp. This file should be included where needed. -static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixScope = false, bool adjustConst = true) +static QByteArray normalizeTypeInternal(const char *t, const char *e) { - int len = e - t; - /* - Convert 'char const *' into 'const char *'. Start at index 1, - not 0, because 'const char *' is already OK. - */ - QByteArray constbuf; - for (int i = 1; i < len; i++) { - if ( t[i] == 'c' - && strncmp(t + i + 1, "onst", 4) == 0 - && (i + 5 >= len || !is_ident_char(t[i + 5])) - && !is_ident_char(t[i-1]) - ) { - constbuf = QByteArray(t, len); - if (is_space(t[i-1])) - constbuf.remove(i-1, 6); - else - constbuf.remove(i, 5); - constbuf.prepend("const "); - t = constbuf.data(); - e = constbuf.data() + constbuf.length(); - break; - } - /* - We mustn't convert 'char * const *' into 'const char **' - and we must beware of 'Bar<const Bla>'. - */ - if (t[i] == '&' || t[i] == '*' ||t[i] == '<') - break; - } - if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) { - if (*(e-1) == '&') { // treat const reference as value - t += 6; - --e; - } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { // treat const value as value - t += 6; - } - } - QByteArray result; - result.reserve(len); - -#if 1 - // consume initial 'const ' - if (strncmp("const ", t, 6) == 0) { - t+= 6; - result += "const "; - } -#endif - - // some type substitutions for 'unsigned x' - if (strncmp("unsigned", t, 8) == 0) { - // make sure "unsigned" is an isolated word before making substitutions - if (!t[8] || !is_ident_char(t[8])) { - if (strncmp(" int", t+8, 4) == 0) { - t += 8+4; - result += "uint"; - } else if (strncmp(" long", t+8, 5) == 0) { - if ((strlen(t + 8 + 5) < 4 || strncmp(t + 8 + 5, " int", 4) != 0) // preserve '[unsigned] long int' - && (strlen(t + 8 + 5) < 5 || strncmp(t + 8 + 5, " long", 5) != 0) // preserve '[unsigned] long long' - ) { - t += 8+5; - result += "ulong"; - } - } else if (strncmp(" short", t+8, 6) != 0 // preserve unsigned short - && strncmp(" char", t+8, 5) != 0) { // preserve unsigned char - // treat rest (unsigned) as uint - t += 8; - result += "uint"; - } - } - } else { - // discard 'struct', 'class', and 'enum'; they are optional - // and we don't want them in the normalized signature - struct { - const char *keyword; - int len; - } optional[] = { - { "struct ", 7 }, - { "class ", 6 }, - { "enum ", 5 }, - { nullptr, 0 } - }; - int i = 0; - do { - if (strncmp(optional[i].keyword, t, optional[i].len) == 0) { - t += optional[i].len; - break; - } - } while (optional[++i].keyword != nullptr); - } - - bool star = false; - while (t != e) { - char c = *t++; - if (fixScope && c == ':' && *t == ':' ) { - ++t; - c = *t++; - int i = result.size() - 1; - while (i >= 0 && is_ident_char(result.at(i))) - --i; - result.resize(i + 1); - } - star = star || c == '*'; - result += c; - if (c == '<') { - //template recursion - const char* tt = t; - int templdepth = 1; - int scopeDepth = 0; - while (t != e) { - c = *t++; - if (c == '{' || c == '(' || c == '[') - ++scopeDepth; - if (c == '}' || c == ')' || c == ']') - --scopeDepth; - if (scopeDepth == 0) { - if (c == '<') - ++templdepth; - if (c == '>') - --templdepth; - if (templdepth == 0 || (templdepth == 1 && c == ',')) { - result += normalizeTypeInternal(tt, t-1, fixScope, false); - result += c; - if (templdepth == 0) { - if (*t == '>') - result += ' '; // avoid >> - break; - } - tt = t; - } - } - } - } - - // cv qualifers can appear after the type as well - if (!is_ident_char(c) && t != e && (e - t >= 5 && strncmp("const", t, 5) == 0) - && (e - t == 5 || !is_ident_char(t[5]))) { - t += 5; - while (t != e && is_space(*t)) - ++t; - if (adjustConst && t != e && *t == '&') { - // treat const ref as value - ++t; - } else if (adjustConst && !star) { - // treat const as value - } else if (!star) { - // move const to the front (but not if const comes after a *) - result.prepend("const "); - } else { - // keep const after a * - result += "const"; - } - } - } - + int len = QtPrivate::qNormalizeType(t, e, nullptr); + if (len == 0) + return QByteArray(); + QByteArray result(len, Qt::Uninitialized); + len = QtPrivate::qNormalizeType(t, e, result.data()); + Q_ASSERT(len == result.size()); return result; } diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index 4ecc340787..cd5caad0a7 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -1103,13 +1103,13 @@ int QMetaStringTable::enter(const QByteArray &value) int QMetaStringTable::preferredAlignment() { - return Q_ALIGNOF(QByteArrayData); + return alignof(uint); } // Returns the size (in bytes) required for serializing this string table. int QMetaStringTable::blobSize() const { - int size = m_entries.size() * sizeof(QByteArrayData); + int size = m_entries.size() * 2*sizeof(uint); Entries::const_iterator it; for (it = m_entries.constBegin(); it != m_entries.constEnd(); ++it) size += it.key().size() + 1; @@ -1120,14 +1120,12 @@ static void writeString(char *out, int i, const QByteArray &str, const int offsetOfStringdataMember, int &stringdataOffset) { int size = str.size(); - qptrdiff offset = offsetOfStringdataMember + stringdataOffset - - i * sizeof(QByteArrayData); - const QByteArrayData data = - Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset); + int offset = offsetOfStringdataMember + stringdataOffset; + uint offsetLen[2] = { uint(offset), uint(size) }; - memcpy(out + i * sizeof(QByteArrayData), &data, sizeof(QByteArrayData)); + memcpy(out + 2 * i * sizeof(uint), &offsetLen, 2*sizeof(uint)); - memcpy(out + offsetOfStringdataMember + stringdataOffset, str.constData(), size); + memcpy(out + offset, str.constData(), size); out[offsetOfStringdataMember + stringdataOffset + size] = '\0'; stringdataOffset += size + 1; @@ -1141,7 +1139,7 @@ void QMetaStringTable::writeBlob(char *out) const { Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (preferredAlignment()-1))); - int offsetOfStringdataMember = m_entries.size() * sizeof(QByteArrayData); + int offsetOfStringdataMember = m_entries.size() * 2*sizeof(uint); int stringdataOffset = 0; // qt_metacast expects the first string in the string table to be the class name. @@ -1198,6 +1196,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, if (!relocatable) meta->d.superdata = d->superClass; meta->d.relatedMetaObjects = nullptr; meta->d.extradata = nullptr; + meta->d.metaTypes = nullptr; meta->d.static_metacall = d->staticMetacallFunction; } @@ -1282,10 +1281,10 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, char *str = reinterpret_cast<char *>(buf + size); if (buf) { if (relocatable) { - meta->d.stringdata = reinterpret_cast<const QByteArrayData *>((quintptr)size); + meta->d.stringdata = reinterpret_cast<const uint *>((quintptr)size); meta->d.data = reinterpret_cast<uint *>((quintptr)pmetaSize); } else { - meta->d.stringdata = reinterpret_cast<const QByteArrayData *>(str); + meta->d.stringdata = reinterpret_cast<const uint *>(str); meta->d.data = reinterpret_cast<uint *>(data); } } @@ -1476,6 +1475,20 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, size += sizeof(SuperData) * (d->relatedMetaObjects.size() + 1); } + if (d->properties.size() > 0) { + ALIGN(size, QtPrivate::QMetaTypeInterface *); + auto types = reinterpret_cast<QtPrivate::QMetaTypeInterface **>(buf + size); + if (buf) { + meta->d.metaTypes = types; + for (const auto &prop : d->properties) { + QMetaType mt(QMetaType::type(prop.type)); + *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt); + types++; + } + } + size += sizeof(QMetaType) * d->properties.size(); + } + // Align the final size and return it. ALIGN(size, void *); Q_ASSERT(!buf || size == expectedSize); @@ -1553,7 +1566,7 @@ void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output, quintptr dataOffset = (quintptr)dataMo->d.data; output->d.superdata = superclass; - output->d.stringdata = reinterpret_cast<const QByteArrayData *>(buf + stringdataOffset); + output->d.stringdata = reinterpret_cast<const uint *>(buf + stringdataOffset); output->d.data = reinterpret_cast<const uint *>(buf + dataOffset); output->d.extradata = nullptr; output->d.relatedMetaObjects = nullptr; diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 71eec11e01..4c1f9f20f7 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -85,6 +85,9 @@ # include "qline.h" #endif +#include <bitset> +#include <new> + QT_BEGIN_NAMESPACE #define NS(x) QT_PREPEND_NAMESPACE(x) @@ -97,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 /*! @@ -153,7 +238,7 @@ struct DefinedTypesFilter { \list \li Pointers to classes derived from QObject - \li QList<T>, QVector<T>, QQueue<T>, QStack<T>, QSet<T> or QLinkedList<T> + \li QList<T>, QVector<T>, QQueue<T>, QStack<T> or QSet<T> where T is a registered meta type \li QHash<T1, T2>, QMap<T1, T2> or QPair<T1, T2> where T1 and T2 are registered meta types @@ -371,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 @@ -379,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 @@ -386,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 @@ -400,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 @@ -409,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 @@ -430,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 @@ -441,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 @@ -451,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 @@ -488,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 @@ -500,12 +650,53 @@ 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; + } +} + +void QtMetaTypePrivate::derefAndDestroy(QtPrivate::QMetaTypeInterface *d_ptr) +{ + 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); + } +} /*! \fn QMetaType::~QMetaType() Destructs this object. */ +QMetaType::~QMetaType() +{ + QtMetaTypePrivate::derefAndDestroy(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() @@ -538,32 +729,26 @@ struct DefinedTypesFilter { #define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \ { RealNameStr, sizeof(RealNameStr) - 1, QMetaType::MetaTypeName }, -#define QT_ADD_STATIC_METATYPE_HACKS_ITER(MetaTypeName, TypeId, Name) \ - QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeName, Name) + static const struct { const char * typeName; int typeNameLength; int type; } types[] = { QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE) QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER) - QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER) + QT_ADD_STATIC_METATYPE(_, QMetaTypeId2<qreal>::MetaType, qreal) {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 @@ -615,11 +800,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) @@ -862,13 +1042,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(®->lock); + reg->dataStreamOp[idx] = { saveOp, loadOp }; + } } #endif // QT_NO_DATASTREAM @@ -967,13 +1145,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; } /*! @@ -987,7 +1163,7 @@ const char *QMetaType::typeName(int typeId) */ QByteArray QMetaType::name() const { - return QMetaType::typeName(m_typeId); + return d_ptr ? d_ptr->name : nullptr; } /* @@ -1006,338 +1182,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) -{ -#ifdef QT_NO_QOBJECT - NS(QByteArray) normalizedTypeName = typeName; -#else - NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); -#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) +*/ +static int qMetaTypeCustomType_unlocked(const char *typeName, int length) { - 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; + if (auto reg = customTypeRegistery()) { +#if QT_CONFIG(thread) + Q_ASSERT(!reg->lock.tryLockForWrite()); #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(®->lock); + auto &al = reg->aliases[normalizedTypeName]; + if (al) + return; + al = metaType.d_ptr; } - return idx; } /*! @@ -1348,16 +1226,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> @@ -1367,7 +1236,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) { @@ -1422,7 +1291,6 @@ int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName) } #ifndef QT_NO_DATASTREAM - namespace { @@ -1466,30 +1334,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; } @@ -1524,17 +1391,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; } @@ -1575,17 +1442,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; } @@ -1646,10 +1513,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); } /*! @@ -1659,73 +1523,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 @@ -1754,75 +1554,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 @@ -1835,58 +1570,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 @@ -1900,61 +1586,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 @@ -1964,61 +1598,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 @@ -2029,13 +1611,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(); } /*! @@ -2093,25 +1669,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 @@ -2168,85 +1725,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); } /*! @@ -2257,212 +1753,24 @@ 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; -} -} +QMetaType::QMetaType(int typeId) : QMetaType(interfaceForType(typeId)) {} namespace QtMetaTypePrivate { const bool VectorBoolElements::true_element = true; const bool VectorBoolElements::false_element = false; } +namespace QtPrivate { +#ifndef QT_BOOTSTRAPPED +// Explicit instantiation definition +#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) template class QMetaTypeForType<Name>; +QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER) +QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER) +QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_TEMPLATE_ITER) +QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER) +QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_TEMPLATE_ITER) +#undef QT_METATYPE_DECLARE_TEMPLATE_ITER +#endif +} + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 59ec8de0e9..32d45b34ff 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -46,11 +46,13 @@ #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 -#include <new> +#include <array> +#include <new> #include <vector> #include <list> #include <map> @@ -151,6 +153,13 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); F(QVariantHash, 28, QVariantHash) \ F(QByteArrayList, 49, QByteArrayList) \ +#if QT_CONFIG(shortcut) +#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)\ + F(QKeySequence, 75, QKeySequence) +#else +#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) +#endif + #define QT_FOR_EACH_STATIC_GUI_CLASS(F)\ F(QFont, 64, QFont) \ F(QPixmap, 65, QPixmap) \ @@ -163,7 +172,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); F(QRegion, 72, QRegion) \ F(QBitmap, 73, QBitmap) \ F(QCursor, 74, QCursor) \ - F(QKeySequence, 75, QKeySequence) \ + QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) \ F(QPen, 76, QPen) \ F(QTextLength, 77, QTextLength) \ F(QTextFormat, 78, QTextFormat) \ @@ -181,10 +190,6 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); #define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\ F(QSizePolicy, 121, QSizePolicy) \ -// ### FIXME kill that set -#define QT_FOR_EACH_STATIC_HACKS_TYPE(F)\ - F(QMetaTypeId2<qreal>::MetaType, -1, qreal) - // F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType") #define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)\ F(ULong, -1, ulong, "unsigned long") \ @@ -201,10 +206,11 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); F(UInt, -1, uint, "quint32") \ F(LongLong, -1, qlonglong, "qint64") \ F(ULongLong, -1, qulonglong, "quint64") \ + F(QVariantList, -1, QVariantList, "QVector<QVariant>") \ F(QVariantList, -1, QVariantList, "QList<QVariant>") \ F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \ F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \ - F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \ + F(QByteArrayList, -1, QByteArrayList, "QVector<QByteArray>") \ #define QT_FOR_EACH_STATIC_TYPE(F)\ QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\ @@ -219,7 +225,6 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); TypeName = Id, #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \ - F(QList) \ F(QVector) \ F(QQueue) \ F(QStack) \ @@ -242,6 +247,9 @@ struct QMetaObject; namespace QtPrivate { + +class QMetaTypeInterface; + /*! This template is used for implicit conversion from type From to type To. \internal @@ -421,13 +429,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. @@ -494,20 +495,11 @@ public: TrackingPointerToQObject = 0x80, WasDeclaredAsMetaType = 0x100, IsGadget = 0x200, - PointerToGadget = 0x400 + PointerToGadget = 0x400, + IsPointer = 0x800, }; Q_DECLARE_FLAGS(TypeFlags, TypeFlag) - typedef void (*Deleter)(void *); - typedef void *(*Creator)(const void *); - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - 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 @@ -516,41 +508,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); @@ -560,10 +519,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); @@ -573,32 +528,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> @@ -716,41 +676,11 @@ 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); #endif -// ### Qt6: FIXME: Remove the special Q_CC_MSVC handling, it was introduced to maintain BC. -#if !defined(Q_NO_TEMPLATE_FRIENDS) && !defined(Q_CC_MSVC) #ifndef Q_CLANG_QDOC template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType; template<typename, typename> friend struct QtPrivate::ConverterMemberFunction; @@ -760,25 +690,11 @@ private: template<typename, bool> friend struct QtPrivate::IsMetaTypePair; template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper; #endif -#else -public: -#endif 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; + friend class QVariant; + QtPrivate::QMetaTypeInterface *d_ptr = nullptr; }; #undef QT_DEFINE_METATYPE_ID @@ -1034,10 +950,6 @@ struct ContainerAPI : CapabilitiesImpl<T> }; template<typename T> -struct ContainerAPI<QList<T> > : CapabilitiesImpl<QList<T> > -{ static int size(const QList<T> *t) { return t->size(); } }; - -template<typename T> struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> > { static int size(const QVector<T> *t) { return t->size(); } }; @@ -1559,33 +1471,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 @@ -1731,6 +1648,7 @@ namespace QtPrivate static bool registerConverter(int) { return false; } }; + template<class T> Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type); } // namespace QtPrivate @@ -1792,6 +1710,7 @@ namespace QtPrivate { | (std::is_enum<T>::value ? QMetaType::IsEnumeration : 0) | (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0) | (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0) + | (QTypeInfo<T>::isPointer ? QMetaType::IsPointer : 0) }; }; @@ -1828,31 +1747,20 @@ namespace QtPrivate { template <typename T> 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 ) { #ifndef QT_NO_QOBJECT 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); @@ -1895,8 +1803,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> @@ -2062,6 +1973,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 @@ -2080,7 +1992,7 @@ typedef QHash<QString, QVariant> QVariantHash; #ifdef Q_CLANG_QDOC class QByteArrayList; #else -typedef QList<QByteArray> QByteArrayList; +typedef QVector<QByteArray> QByteArrayList; #endif #define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \ @@ -2103,8 +2015,6 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \ typeName.reserve(int(sizeof(#SINGLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + 1); \ typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1) \ .append('<').append(tName, tNameLen); \ - if (typeName.endsWith('>')) \ - typeName.append(' '); \ typeName.append('>'); \ const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >( \ typeName, \ @@ -2145,8 +2055,6 @@ struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \ typeName.reserve(int(sizeof(#DOUBLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \ typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1) \ .append('<').append(tName, tNameLen).append(',').append(uName, uNameLen); \ - if (typeName.endsWith('>')) \ - typeName.append(' '); \ typeName.append('>'); \ const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(\ typeName, \ @@ -2280,104 +2188,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 @@ -2439,6 +2249,526 @@ 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; +}; + +struct QTypeNormalizer +{ + char *output; + int len = 0; + char last = 0; + +private: + static constexpr bool is_ident_char(char s) + { + return ((s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || (s >= '0' && s <= '9') + || s == '_'); + } + static constexpr bool is_space(char s) { return (s == ' ' || s == '\t' || s == '\n'); } + static constexpr bool is_number(char s) { return s >= '0' && s <= '9'; }; + static constexpr bool starts_with_token(const char *b, const char *e, const char *token, + bool msvcKw = false) + { + while (b != e && *token && *b == *token) { + b++; + token++; + } + if (*token) + return false; +#ifdef Q_CC_MSVC + /// On MSVC, keywords like class or struct are not separated with spaces in constexpr + /// context + if (msvcKw) + return true; +#endif + Q_UNUSED(msvcKw); + return b == e || !is_ident_char(*b); + } + static constexpr bool skipToken(const char *&x, const char *e, const char *token, + bool msvcKw = false) + { + if (!starts_with_token(x, e, token, msvcKw)) + return false; + while (*token++) + x++; + while (x != e && is_space(*x)) + x++; + return true; + } + static constexpr const char *skipString(const char *x, const char *e) + { + char delim = *x; + x++; + while (x != e && *x != delim) { + if (*x == '\\') { + x++; + if (x == e) + return e; + } + x++; + } + if (x != e) + x++; + return x; + }; + static constexpr const char *skipTemplate(const char *x, const char *e, bool stopAtComa = false) + { + int scopeDepth = 0; + int templateDepth = 0; + while (x != e) { + switch (*x) { + case '<': + if (!scopeDepth) + templateDepth++; + break; + case ',': + if (stopAtComa && !scopeDepth && !templateDepth) + return x; + break; + case '>': + if (!scopeDepth) + if (--templateDepth < 0) + return x; + break; + case '(': + case '[': + case '{': + scopeDepth++; + break; + case '}': + case ']': + case ')': + scopeDepth--; + break; + case '\'': + if (is_number(x[-1])) + break; + Q_FALLTHROUGH(); + case '\"': + x = skipString(x, e); + continue; + } + x++; + } + return x; + }; + + constexpr void append(char x) + { + last = x; + len++; + if (output) + *output++ = x; + } + + constexpr void appendStr(const char *x) + { + while (*x) + append(*x++); + }; + +public: + constexpr int normalizeType(const char *begin, const char *end, bool adjustConst = true) + { + // Trim spaces + while (begin != end && is_space(*begin)) + begin++; + while (begin != end && is_space(*(end - 1))) + end--; + + // Convert 'char const *' into 'const char *'. Start at index 1, + // not 0, because 'const char *' is already OK. + const char *cst = begin + 1; + if (*begin == '\'' || *begin == '"') + cst = skipString(begin, end); + bool seenStar = false; + bool hasMiddleConst = false; + while (cst < end) { + if (*cst == '\"' || (*cst == '\'' && !is_number(cst[-1]))) { + cst = skipString(cst, end); + if (cst == end) + break; + } + + // We mustn't convert 'char * const *' into 'const char **' + // and we must beware of 'Bar<const Bla>'. + if (*cst == '&' || *cst == '*' || *cst == '[') { + seenStar = *cst != '&' || cst != (end - 1); + break; + } + if (*cst == '<') { + cst = skipTemplate(cst + 1, end); + if (cst == end) + break; + } + cst++; + const char *skipedCst = cst; + if (!is_ident_char(*(cst - 1)) && skipToken(skipedCst, end, "const")) { + const char *testEnd = end; + while (skipedCst < testEnd--) { + if (*testEnd == '*' || *testEnd == '[' + || (*testEnd == '&' && testEnd != (end - 1))) { + seenStar = true; + break; + } + if (*testEnd == '>') + break; + } + if (adjustConst && !seenStar) { + if (*(end - 1) == '&') + end--; + } else { + appendStr("const "); + } + normalizeType(begin, cst, false); + begin = skipedCst; + hasMiddleConst = true; + break; + } + } + if (skipToken(begin, end, "const")) { + if (adjustConst && !seenStar) { + if (*(end - 1) == '&') + end--; + } else { + appendStr("const "); + } + } + if (seenStar && adjustConst) { + const char *e = end; + if (*(end - 1) == '&' && *(end - 2) != '&') + e--; + while (begin != e && is_space(*(e - 1))) + e--; + const char *token = "tsnoc"; // 'const' reverse, to check if it ends with const + while (*token && begin != e && *(--e) == *token++) + ; + if (!*token && begin != e && !is_ident_char(*(e - 1))) { + while (begin != e && is_space(*(e - 1))) + e--; + end = e; + } + } + + // discard 'struct', 'class', and 'enum'; they are optional + // and we don't want them in the normalized signature + skipToken(begin, end, "struct", true) || skipToken(begin, end, "class", true) + || skipToken(begin, end, "enum", true); + +#ifdef QT_NAMESPACE + const char *nsbeg = begin; + if (skipToken(nsbeg, end, QT_STRINGIFY(QT_NAMESPACE)) && nsbeg + 2 < end && nsbeg[0] == ':' + && nsbeg[1] == ':') { + begin = nsbeg + 2; + while (begin != end && is_space(*begin)) + begin++; + } +#endif + + if (skipToken(begin, end, "QList")) { + // Replace QList by QVector + appendStr("QVector"); + } + if (!hasMiddleConst) { + // Normalize the integer types + int numLong = 0; + int numSigned = 0; + int numUnsigned = 0; + int numInt = 0; + int numShort = 0; + int numChar = 0; + while (begin < end) { + if (skipToken(begin, end, "long")) { + numLong++; + continue; + } + if (skipToken(begin, end, "int")) { + numInt++; + continue; + } + if (skipToken(begin, end, "short")) { + numShort++; + continue; + } + if (skipToken(begin, end, "unsigned")) { + numUnsigned++; + continue; + } + if (skipToken(begin, end, "signed")) { + numSigned++; + continue; + } + if (skipToken(begin, end, "char")) { + numChar++; + continue; + } + break; + } + if (numChar || numShort) { + if (numSigned && numChar) + appendStr("signed "); + if (numUnsigned) + appendStr("unsigned "); + if (numChar) + appendStr("char"); + else + appendStr("short"); + } else if (numLong) { + if (numLong == 1) { + if (numUnsigned) + append('u'); + appendStr("long"); + } else { + if (numUnsigned) + appendStr("unsigned "); + appendStr("long long"); + } + } else if (numUnsigned || numSigned || numInt) { + if (numUnsigned) + append('u'); + appendStr("int"); + } + } + + bool spaceSkiped = true; + while (begin != end) { + char c = *begin++; + if (is_space(c)) { + spaceSkiped = true; + } else if ((c == '\'' && !is_number(last)) || c == '\"') { + begin--; + auto x = skipString(begin, end); + while (begin < x) + append(*begin++); + } else { + if (spaceSkiped && is_ident_char(last) && is_ident_char(c)) + append(' '); + append(c); + spaceSkiped = false; + if (c == '<') { + do { + // template recursion + const char *tpl = skipTemplate(begin, end, true); + normalizeType(begin, tpl, false); + if (tpl == end) + return len; + append(*tpl); + begin = tpl; + } while (*begin++ == ','); + } + } + } + return len; + } +}; + +// Normalize the type between begin and end, and store the data in the output. Returns the length. +// The idea is to first run this function with nullptr as output to allocate the output with the +// size +constexpr int qNormalizeType(const char *begin, const char *end, char *output) +{ + return QTypeNormalizer { output }.normalizeType(begin, end); +} + +template<typename T> +constexpr auto typenameHelper() +{ + constexpr auto prefix = sizeof( +#ifdef QT_NAMESPACE + QT_STRINGIFY(QT_NAMESPACE) "::" +#endif +#ifdef Q_CC_MSVC + "auto __cdecl QtPrivate::typenameHelper<" +#elif defined(Q_CC_CLANG) + "auto QtPrivate::typenameHelper() [T = " +#else + "constexpr auto QtPrivate::typenameHelper() [with T = " +#endif + ) - 1; +#ifdef Q_CC_MSVC + constexpr int suffix = sizeof(">(void)"); +#else + constexpr int suffix = sizeof("]"); +#endif + +#if !(defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)) + constexpr auto func = Q_FUNC_INFO; + constexpr const char *begin = func + prefix; + constexpr const char *end = func + sizeof(Q_FUNC_INFO) - suffix; + constexpr int len = qNormalizeType(begin, end, nullptr); +#else // GCC < 8.1 did not have Q_FUNC_INFO as constexpr, and GCC 9 has a precompiled header bug + auto func = Q_FUNC_INFO; + const char *begin = func + prefix; + const char *end = func + sizeof(Q_FUNC_INFO) - suffix; + // This is an upper bound of the size since the normalized signature should always be smaller + // (Unless there is a QList -> QVector change, but that should not happen) + constexpr int len = sizeof(Q_FUNC_INFO) - suffix - prefix; +#endif + std::array<char, len + 1> result {}; + qNormalizeType(begin, end, result.data()); + 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) +// Workaround a bug with 'if constexpr' not working in lambda that are not generic in MSVC +#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<> +class QMetaTypeForType<void> +{ +}; + +#ifndef QT_BOOTSTRAPPED +#define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \ + extern template class Q_CORE_EXPORT QMetaTypeForType<Name>; +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wattributes") // false positive because of QMetaTypeForType<void> +QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) +QT_WARNING_POP +QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) +QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) +QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) +QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER) +#undef QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER +#endif + +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>()); +} + +template<typename... T> +QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = { + 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 d743d5a5c7..00d57a7e68 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> @@ -232,9 +170,6 @@ template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = fals #if !QT_CONFIG(regularexpression) template<> struct TypeDefinition<QRegularExpression> { static const bool IsAvailable = false; }; #endif -#ifdef QT_NO_SHORTCUT -template<> struct TypeDefinition<QKeySequence> { static const bool IsAvailable = false; }; -#endif #ifdef QT_NO_CURSOR template<> struct TypeDefinition<QCursor> { static const bool IsAvailable = false; }; #endif @@ -256,6 +191,34 @@ 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; + +void derefAndDestroy(QtPrivate::QMetaTypeInterface *d_ptr); + } //namespace QtMetaTypePrivate QT_END_NAMESPACE diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8be10ed601..2fdf94c38b 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -164,7 +164,6 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) #endif void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = nullptr; -void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = nullptr; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = nullptr; void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = nullptr; int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = nullptr; @@ -229,10 +228,6 @@ QObjectPrivate::~QObjectPrivate() if (metaObject) metaObject->objectDestroyed(q_ptr); -#ifndef QT_NO_USERDATA - if (extraData) - qDeleteAll(extraData->userData); -#endif delete extraData; } @@ -992,15 +987,8 @@ QObject::~QObject() emit destroyed(this); } - if (d->declarativeData) { - if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) { - if (QAbstractDeclarativeData::destroyed_qml1) - QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this); - } else { - if (QAbstractDeclarativeData::destroyed) - QAbstractDeclarativeData::destroyed(d->declarativeData, this); - } - } + if (d->declarativeData && QAbstractDeclarativeData::destroyed) + QAbstractDeclarativeData::destroyed(d->declarativeData, this); QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed(); if (cd) { @@ -4277,58 +4265,6 @@ void QObject::dumpObjectInfo() const } } -#ifndef QT_NO_USERDATA -static QBasicAtomicInteger<uint> user_data_registration = Q_BASIC_ATOMIC_INITIALIZER(0); - -/*! - \internal - */ -uint QObject::registerUserData() -{ - return user_data_registration.fetchAndAddRelaxed(1); -} - -/*! - \fn QObjectUserData::QObjectUserData() - \internal - */ - -/*! - \internal - */ -QObjectUserData::~QObjectUserData() -{ -} - -/*! - \internal - */ -void QObject::setUserData(uint id, QObjectUserData* data) -{ - Q_D(QObject); - if (!d->extraData) - d->extraData = new QObjectPrivate::ExtraData; - - if (d->extraData->userData.size() <= (int) id) - d->extraData->userData.resize((int) id + 1); - d->extraData->userData[id] = data; -} - -/*! - \internal - */ -QObjectUserData* QObject::userData(uint id) const -{ - Q_D(const QObject); - if (!d->extraData) - return nullptr; - if ((int)id < d->extraData->userData.size()) - return d->extraData->userData.at(id); - return nullptr; -} - -#endif // QT_NO_USERDATA - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QObject *o) @@ -4635,6 +4571,23 @@ QDebug operator<<(QDebug dbg, const QObject *o) */ /*! + \macro Q_MOC_INCLUDE + \relates QObject + \since 6.0 + + The Q_MOC_INCLUDE macro can be used within or outside a class, and tell the + \l{moc}{Meta Object Compiler} to add an include. + + \code + // Put this in your code and the generated code will include this header. + Q_MOC_INCLUDE("myheader.h") + \endcode + + This is useful if the types you use as properties or signal/slots arguments + are forward declared. +*/ + +/*! \macro Q_SIGNALS \relates QObject @@ -4749,10 +4702,15 @@ QDebug operator<<(QDebug dbg, const QObject *o) Using the same Window class as the previous example, the newProperty and newMethod would only be exposed in this code when the expected version is - 1 or greater. + \c{2.1} or greater. + + Since all methods are considered to be in revision \c{0} if untagged, a tag + of \c{Q_REVISION(0)} or \c{Q_REVISION(0, 0)} is invalid and ignored. - Since all methods are considered to be in revision 0 if untagged, a tag - of Q_REVISION(0) is invalid and ignored. + You can pass one or two integer parameters to \c{Q_REVISION}. If you pass + one parameter, it denotes the minor version only. This means that the major + version is unspecified. If you pass two, the first parameter is the major + version and the second parameter is the minor version. This tag is not used by the meta-object system itself. Currently this is only used by the QtQml module. diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index f5d7c22e3a..8d9cc3ab83 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -78,12 +78,6 @@ class QRegExp; #if QT_CONFIG(regularexpression) class QRegularExpression; #endif -#if !QT_DEPRECATED_SINCE(5, 14) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) -# define QT_NO_USERDATA -#endif -#ifndef QT_NO_USERDATA -class QObjectUserData; -#endif struct QDynamicMetaObjectData; typedef QList<QObject*> QObjectList; @@ -408,15 +402,6 @@ public: QList<QByteArray> dynamicPropertyNames() const; #endif // QT_NO_PROPERTIES -#ifndef QT_NO_USERDATA - QT_DEPRECATED_VERSION_5_14 - static uint registerUserData(); - QT_DEPRECATED_VERSION_X_5_14("Use setProperty()") - void setUserData(uint id, QObjectUserData* data); - QT_DEPRECATED_VERSION_X_5_14("Use property()") - QObjectUserData* userData(uint id) const; -#endif // QT_NO_USERDATA - Q_SIGNALS: void destroyed(QObject * = nullptr); void objectNameChanged(const QString &objectName, QPrivateSignal); @@ -449,9 +434,6 @@ protected: protected: QScopedPointer<QObjectData> d_ptr; - static const QMetaObject staticQtMetaObject; - friend inline const QMetaObject *qt_getQtMetaObject() noexcept; - friend struct QMetaObject; friend struct QMetaObjectPrivate; friend class QMetaCallEvent; @@ -482,18 +464,6 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch const char *amember, Qt::ConnectionType atype) const { return connect(asender, asignal, this, amember, atype); } -inline const QMetaObject *qt_getQtMetaObject() noexcept -{ return &QObject::staticQtMetaObject; } - -#ifndef QT_NO_USERDATA -class Q_CORE_EXPORT QObjectUserData { - Q_DISABLE_COPY(QObjectUserData) -public: - QObjectUserData() = default; - virtual ~QObjectUserData(); -}; -#endif - #if QT_DEPRECATED_SINCE(5, 0) template<typename T> inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString()) diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 34b7447d5d..97b492360c 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -89,7 +89,6 @@ class Q_CORE_EXPORT QAbstractDeclarativeData { public: static void (*destroyed)(QAbstractDeclarativeData *, QObject *); - static void (*destroyed_qml1)(QAbstractDeclarativeData *, QObject *); static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *); static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **); static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int); @@ -97,14 +96,6 @@ public: static void (*setWidgetParent)(QObject *, QObject *); // Used by the QML engine to specify parents for widgets. Set by QtWidgets. }; -// This is an implementation of QAbstractDeclarativeData that is identical with -// the implementation in QtDeclarative and QtQml for the first bit -struct QAbstractDeclarativeDataImpl : public QAbstractDeclarativeData -{ - quint32 ownedByQml1:1; - quint32 unused: 31; -}; - class Q_CORE_EXPORT QObjectPrivate : public QObjectData { Q_DECLARE_PUBLIC(QObject) @@ -113,9 +104,6 @@ public: struct ExtraData { ExtraData() {} - #ifndef QT_NO_USERDATA - QVector<QObjectUserData *> userData; - #endif QList<QByteArray> propertyNames; QVector<QVariant> propertyValues; QVector<int> runningTimers; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index becbb90a61..fd7c081e88 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -46,199 +46,15 @@ #endif #include <QtCore/qnamespace.h> - #include <QtCore/qobjectdefs_impl.h> +#include <QtCore/qtmetamacros.h> QT_BEGIN_NAMESPACE - class QByteArray; struct QArrayData; -typedef QArrayData QByteArrayData; class QString; -#ifndef Q_MOC_OUTPUT_REVISION -#define Q_MOC_OUTPUT_REVISION 67 -#endif - -// The following macros can be defined by tools that understand Qt -// to have the information from the macro. -#ifndef QT_ANNOTATE_CLASS -# define QT_ANNOTATE_CLASS(type, ...) -#endif -#ifndef QT_ANNOTATE_CLASS2 -# define QT_ANNOTATE_CLASS2(type, a1, a2) -#endif -#ifndef QT_ANNOTATE_FUNCTION -# define QT_ANNOTATE_FUNCTION(x) -#endif -#ifndef QT_ANNOTATE_ACCESS_SPECIFIER -# define QT_ANNOTATE_ACCESS_SPECIFIER(x) -#endif - -// The following macros are our "extensions" to C++ -// They are used, strictly speaking, only by the moc. - -#ifndef Q_MOC_RUN -#ifndef QT_NO_META_MACROS -# if defined(QT_NO_KEYWORDS) -# define QT_NO_EMIT -# else -# ifndef QT_NO_SIGNALS_SLOTS_KEYWORDS -# define slots Q_SLOTS -# define signals Q_SIGNALS -# endif -# endif -# define Q_SLOTS QT_ANNOTATE_ACCESS_SPECIFIER(qt_slot) -# define Q_SIGNALS public QT_ANNOTATE_ACCESS_SPECIFIER(qt_signal) -# define Q_PRIVATE_SLOT(d, signature) QT_ANNOTATE_CLASS2(qt_private_slot, d, signature) -# define Q_EMIT -#ifndef QT_NO_EMIT -# define emit -#endif -#ifndef Q_CLASSINFO -# define Q_CLASSINFO(name, value) -#endif -#define Q_PLUGIN_METADATA(x) QT_ANNOTATE_CLASS(qt_plugin_metadata, x) -#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x) -#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__) -#define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text) -#ifndef Q_REVISION -# define Q_REVISION(v) -#endif -#define Q_OVERRIDE(text) QT_ANNOTATE_CLASS(qt_override, text) -#define QDOC_PROPERTY(text) QT_ANNOTATE_CLASS(qt_qdoc_property, text) -#define Q_ENUMS(x) QT_ANNOTATE_CLASS(qt_enums, x) -#define Q_FLAGS(x) QT_ANNOTATE_CLASS(qt_enums, x) -#define Q_ENUM_IMPL(ENUM) \ - friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \ - friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; } -#define Q_ENUM(x) Q_ENUMS(x) Q_ENUM_IMPL(x) -#define Q_FLAG(x) Q_FLAGS(x) Q_ENUM_IMPL(x) -#define Q_ENUM_NS_IMPL(ENUM) \ - inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \ - inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; } -#define Q_ENUM_NS(x) Q_ENUMS(x) Q_ENUM_NS_IMPL(x) -#define Q_FLAG_NS(x) Q_FLAGS(x) Q_ENUM_NS_IMPL(x) -#define Q_SCRIPTABLE QT_ANNOTATE_FUNCTION(qt_scriptable) -#define Q_INVOKABLE QT_ANNOTATE_FUNCTION(qt_invokable) -#define Q_SIGNAL QT_ANNOTATE_FUNCTION(qt_signal) -#define Q_SLOT QT_ANNOTATE_FUNCTION(qt_slot) -#endif // QT_NO_META_MACROS - -#ifndef QT_NO_TRANSLATION -// full set of tr functions -# define QT_TR_FUNCTIONS \ - static inline QString tr(const char *s, const char *c = nullptr, int n = -1) \ - { return staticMetaObject.tr(s, c, n); } \ - QT_DEPRECATED static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) \ - { return staticMetaObject.tr(s, c, n); } -#else -// inherit the ones from QObject -# define QT_TR_FUNCTIONS -#endif - -#ifdef Q_CLANG_QDOC -#define QT_TR_FUNCTIONS -#endif - -// ### Qt6: remove -#define Q_OBJECT_CHECK /* empty, unused since Qt 5.2 */ - -#if defined(Q_CC_INTEL) -// Cannot redefine the visibility of a method in an exported class -# define Q_DECL_HIDDEN_STATIC_METACALL -#else -# define Q_DECL_HIDDEN_STATIC_METACALL Q_DECL_HIDDEN -#endif - -#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306 -# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override") -#elif defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 501 -# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_GCC("-Wsuggest-override") -#else -# define Q_OBJECT_NO_OVERRIDE_WARNING -#endif - -#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 600 -# define Q_OBJECT_NO_ATTRIBUTES_WARNING QT_WARNING_DISABLE_GCC("-Wattributes") -#else -# define Q_OBJECT_NO_ATTRIBUTES_WARNING -#endif - -/* qmake ignore Q_OBJECT */ -#define Q_OBJECT \ -public: \ - QT_WARNING_PUSH \ - Q_OBJECT_NO_OVERRIDE_WARNING \ - static const QMetaObject staticMetaObject; \ - virtual const QMetaObject *metaObject() const; \ - virtual void *qt_metacast(const char *); \ - virtual int qt_metacall(QMetaObject::Call, int, void **); \ - QT_TR_FUNCTIONS \ -private: \ - Q_OBJECT_NO_ATTRIBUTES_WARNING \ - Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \ - QT_WARNING_POP \ - struct QPrivateSignal {}; \ - QT_ANNOTATE_CLASS(qt_qobject, "") - -/* qmake ignore Q_OBJECT */ -#define Q_OBJECT_FAKE Q_OBJECT QT_ANNOTATE_CLASS(qt_fake, "") - -#ifndef QT_NO_META_MACROS -/* qmake ignore Q_GADGET */ -#define Q_GADGET \ -public: \ - static const QMetaObject staticMetaObject; \ - void qt_check_for_QGADGET_macro(); \ - typedef void QtGadgetHelper; \ -private: \ - QT_WARNING_PUSH \ - Q_OBJECT_NO_ATTRIBUTES_WARNING \ - Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \ - QT_WARNING_POP \ - QT_ANNOTATE_CLASS(qt_qgadget, "") \ - /*end*/ - -/* qmake ignore Q_NAMESPACE_EXPORT */ -#define Q_NAMESPACE_EXPORT(...) \ - extern __VA_ARGS__ const QMetaObject staticMetaObject; \ - QT_ANNOTATE_CLASS(qt_qnamespace, "") \ - /*end*/ - -/* qmake ignore Q_NAMESPACE */ -#define Q_NAMESPACE Q_NAMESPACE_EXPORT() \ - /*end*/ - -#endif // QT_NO_META_MACROS - -#else // Q_MOC_RUN -#define slots slots -#define signals signals -#define Q_SLOTS Q_SLOTS -#define Q_SIGNALS Q_SIGNALS -#define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value) -#define Q_INTERFACES(x) Q_INTERFACES(x) -#define Q_PROPERTY(text) Q_PROPERTY(text) -#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text) -#define Q_REVISION(v) Q_REVISION(v) -#define Q_OVERRIDE(text) Q_OVERRIDE(text) -#define Q_ENUMS(x) Q_ENUMS(x) -#define Q_FLAGS(x) Q_FLAGS(x) -#define Q_ENUM(x) Q_ENUM(x) -#define Q_FLAGS(x) Q_FLAGS(x) - /* qmake ignore Q_OBJECT */ -#define Q_OBJECT Q_OBJECT - /* qmake ignore Q_OBJECT */ -#define Q_OBJECT_FAKE Q_OBJECT_FAKE - /* qmake ignore Q_GADGET */ -#define Q_GADGET Q_GADGET -#define Q_SCRIPTABLE Q_SCRIPTABLE -#define Q_INVOKABLE Q_INVOKABLE -#define Q_SIGNAL Q_SIGNAL -#define Q_SLOT Q_SLOT -#endif //Q_MOC_RUN #ifndef QT_NO_META_MACROS // macro for onaming members @@ -285,6 +101,14 @@ class QMetaEnum; class QMetaProperty; class QMetaClassInfo; +namespace QtPrivate { +class QMetaTypeInterface; +} + +struct QMethodRawArguments +{ + void **arguments; +}; class Q_CORE_EXPORT QGenericArgument { @@ -603,11 +427,12 @@ struct Q_CORE_EXPORT QMetaObject struct { // private data SuperData superdata; - const QByteArrayData *stringdata; + const uint *stringdata; const uint *data; typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); StaticMetacallFunction static_metacall; const SuperData *relatedMetaObjects; + QtPrivate::QMetaTypeInterface *const *metaTypes; void *extradata; //reserved for future use } d; diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp index dc0dfe8f40..0dc9666df6 100644 --- a/src/corelib/kernel/qsignalmapper.cpp +++ b/src/corelib/kernel/qsignalmapper.cpp @@ -60,15 +60,8 @@ public: Q_Q(QSignalMapper); auto it = mappedValues.find(sender); - if (it != mappedValues.end()) { -#if QT_DEPRECATED_SINCE(5, 15) -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - Q_EMIT q->mapped(*it); -QT_WARNING_POP -#endif + if (it != mappedValues.end()) Q_EMIT (q->*signal)(*it); - } } void emitMappedValues(QObject *sender) @@ -288,56 +281,6 @@ void QSignalMapper::map(QObject *sender) d_func()->emitMappedValues(sender); } -#if QT_DEPRECATED_SINCE(5, 15) -/*! - \fn void QSignalMapper::mapped(int i) - \obsolete - \overload - - This signal is emitted when map() is signalled from an object that - has an integer mapping set. The object's mapped integer is passed - in \a i. - - \sa setMapping() -*/ - -/*! - \fn void QSignalMapper::mapped(const QString &text) - \obsolete - \overload - - This signal is emitted when map() is signalled from an object that - has a string mapping set. The object's mapped string is passed in - \a text. - - \sa setMapping() -*/ - -/*! - \fn void QSignalMapper::mapped(QWidget *widget) - \obsolete - \overload - - This signal is emitted when map() is signalled from an object that - has a widget mapping set. The object's mapped widget is passed in - \a widget. - - \sa setMapping() -*/ - -/*! - \fn void QSignalMapper::mapped(QObject *object) - \obsolete - \overload - - This signal is emitted when map() is signalled from an object that - has an object mapping set. The object provided by the map is passed in - \a object. - - \sa setMapping() -*/ -#endif - /*! \fn void QSignalMapper::mappedInt(int i) \since 5.15 diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h index 592986e6a5..bd100a2467 100644 --- a/src/corelib/kernel/qsignalmapper.h +++ b/src/corelib/kernel/qsignalmapper.h @@ -66,16 +66,6 @@ public: QObject *mapping(QObject *object) const; Q_SIGNALS: -#if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_VERSION_X_5_15("Use QSignalMapper::mappedInt(int) instead") - void mapped(int); - QT_DEPRECATED_VERSION_X_5_15("Use QSignalMapper::mappedString(const QString&) instead") - void mapped(const QString &); - QT_DEPRECATED_VERSION_X_5_15("Use QSignalMapper::mappedWidget(QWidget *) instead") - void mapped(QWidget *); - QT_DEPRECATED_VERSION_X_5_15("Use QSignalMapper::mappedObject(QObject *) instead") - void mapped(QObject *); -#endif void mappedInt(int); void mappedString(const QString &); void mappedWidget(QWidget *); diff --git a/src/corelib/kernel/qtmetamacros.h b/src/corelib/kernel/qtmetamacros.h new file mode 100644 index 0000000000..2dcd6948aa --- /dev/null +++ b/src/corelib/kernel/qtmetamacros.h @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2019 Olivier Goffart <ogoffart@woboq.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTMETAMACROS_H +#define QTMETAMACROS_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +#ifndef Q_MOC_OUTPUT_REVISION +#define Q_MOC_OUTPUT_REVISION 67 +#endif + +// The following macros can be defined by tools that understand Qt +// to have the information from the macro. +#ifndef QT_ANNOTATE_CLASS +# define QT_ANNOTATE_CLASS(type, ...) +#endif +#ifndef QT_ANNOTATE_CLASS2 +# define QT_ANNOTATE_CLASS2(type, a1, a2) +#endif +#ifndef QT_ANNOTATE_FUNCTION +# define QT_ANNOTATE_FUNCTION(x) +#endif +#ifndef QT_ANNOTATE_ACCESS_SPECIFIER +# define QT_ANNOTATE_ACCESS_SPECIFIER(x) +#endif + +// The following macros are our "extensions" to C++ +// They are used, strictly speaking, only by the moc. + +#ifndef Q_MOC_RUN +#ifndef QT_NO_META_MACROS +# if defined(QT_NO_KEYWORDS) +# define QT_NO_EMIT +# else +# ifndef QT_NO_SIGNALS_SLOTS_KEYWORDS +# define slots Q_SLOTS +# define signals Q_SIGNALS +# endif +# endif +# define Q_SLOTS QT_ANNOTATE_ACCESS_SPECIFIER(qt_slot) +# define Q_SIGNALS public QT_ANNOTATE_ACCESS_SPECIFIER(qt_signal) +# define Q_PRIVATE_SLOT(d, signature) QT_ANNOTATE_CLASS2(qt_private_slot, d, signature) +# define Q_EMIT +#ifndef QT_NO_EMIT +# define emit +#endif +#ifndef Q_CLASSINFO +# define Q_CLASSINFO(name, value) +#endif +#define Q_PLUGIN_METADATA(x) QT_ANNOTATE_CLASS(qt_plugin_metadata, x) +#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x) +#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__) +#define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text) +#ifndef Q_REVISION +# define Q_REVISION(...) +#endif +#define Q_OVERRIDE(text) QT_ANNOTATE_CLASS(qt_override, text) +#define QDOC_PROPERTY(text) QT_ANNOTATE_CLASS(qt_qdoc_property, text) +#define Q_ENUMS(x) QT_ANNOTATE_CLASS(qt_enums, x) +#define Q_FLAGS(x) QT_ANNOTATE_CLASS(qt_enums, x) +#define Q_ENUM_IMPL(ENUM) \ + friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \ + friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; } +#define Q_ENUM(x) Q_ENUMS(x) Q_ENUM_IMPL(x) +#define Q_FLAG(x) Q_FLAGS(x) Q_ENUM_IMPL(x) +#define Q_ENUM_NS_IMPL(ENUM) \ + inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \ + inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; } +#define Q_ENUM_NS(x) Q_ENUMS(x) Q_ENUM_NS_IMPL(x) +#define Q_FLAG_NS(x) Q_FLAGS(x) Q_ENUM_NS_IMPL(x) +#define Q_SCRIPTABLE QT_ANNOTATE_FUNCTION(qt_scriptable) +#define Q_INVOKABLE QT_ANNOTATE_FUNCTION(qt_invokable) +#define Q_SIGNAL QT_ANNOTATE_FUNCTION(qt_signal) +#define Q_SLOT QT_ANNOTATE_FUNCTION(qt_slot) +#define Q_MOC_INCLUDE(...) QT_ANNOTATE_CLASS(qt_moc_include, __VA_ARGS__) +#endif // QT_NO_META_MACROS + +#ifndef QT_NO_TRANSLATION +// full set of tr functions +# define QT_TR_FUNCTIONS \ + static inline QString tr(const char *s, const char *c = nullptr, int n = -1) \ + { return staticMetaObject.tr(s, c, n); } \ + QT_DEPRECATED static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) \ + { return staticMetaObject.tr(s, c, n); } +#else +// inherit the ones from QObject +# define QT_TR_FUNCTIONS +#endif + +#ifdef Q_CLANG_QDOC +#define QT_TR_FUNCTIONS +#endif + +// ### Qt6: remove +#define Q_OBJECT_CHECK /* empty, unused since Qt 5.2 */ + +#if defined(Q_CC_INTEL) +// Cannot redefine the visibility of a method in an exported class +# define Q_DECL_HIDDEN_STATIC_METACALL +#else +# define Q_DECL_HIDDEN_STATIC_METACALL Q_DECL_HIDDEN +#endif + +#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306 +# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override") +#elif defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 501 +# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_GCC("-Wsuggest-override") +#else +# define Q_OBJECT_NO_OVERRIDE_WARNING +#endif + +#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 600 +# define Q_OBJECT_NO_ATTRIBUTES_WARNING QT_WARNING_DISABLE_GCC("-Wattributes") +#else +# define Q_OBJECT_NO_ATTRIBUTES_WARNING +#endif + +/* qmake ignore Q_OBJECT */ +#define Q_OBJECT \ +public: \ + QT_WARNING_PUSH \ + Q_OBJECT_NO_OVERRIDE_WARNING \ + static const QMetaObject staticMetaObject; \ + virtual const QMetaObject *metaObject() const; \ + virtual void *qt_metacast(const char *); \ + virtual int qt_metacall(QMetaObject::Call, int, void **); \ + QT_TR_FUNCTIONS \ +private: \ + Q_OBJECT_NO_ATTRIBUTES_WARNING \ + Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \ + QT_WARNING_POP \ + struct QPrivateSignal {}; \ + QT_ANNOTATE_CLASS(qt_qobject, "") + +/* qmake ignore Q_OBJECT */ +#define Q_OBJECT_FAKE Q_OBJECT QT_ANNOTATE_CLASS(qt_fake, "") + +#ifndef QT_NO_META_MACROS +/* qmake ignore Q_GADGET */ +#define Q_GADGET \ +public: \ + static const QMetaObject staticMetaObject; \ + void qt_check_for_QGADGET_macro(); \ + typedef void QtGadgetHelper; \ +private: \ + QT_WARNING_PUSH \ + Q_OBJECT_NO_ATTRIBUTES_WARNING \ + Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \ + QT_WARNING_POP \ + QT_ANNOTATE_CLASS(qt_qgadget, "") \ + /*end*/ + +/* qmake ignore Q_NAMESPACE_EXPORT */ +#define Q_NAMESPACE_EXPORT(...) \ + extern __VA_ARGS__ const QMetaObject staticMetaObject; \ + QT_ANNOTATE_CLASS(qt_qnamespace, "") \ + /*end*/ + +/* qmake ignore Q_NAMESPACE */ +#define Q_NAMESPACE Q_NAMESPACE_EXPORT() \ + /*end*/ + +#endif // QT_NO_META_MACROS + +#else // Q_MOC_RUN +#define slots slots +#define signals signals +#define Q_SLOTS Q_SLOTS +#define Q_SIGNALS Q_SIGNALS +#define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value) +#define Q_INTERFACES(x) Q_INTERFACES(x) +#define Q_PROPERTY(text) Q_PROPERTY(text) +#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text) +#define Q_REVISION(...) Q_REVISION(__VA_ARGS__) +#define Q_OVERRIDE(text) Q_OVERRIDE(text) +#define Q_ENUMS(x) Q_ENUMS(x) +#define Q_FLAGS(x) Q_FLAGS(x) +#define Q_ENUM(x) Q_ENUM(x) +#define Q_FLAGS(x) Q_FLAGS(x) + /* qmake ignore Q_OBJECT */ +#define Q_OBJECT Q_OBJECT + /* qmake ignore Q_OBJECT */ +#define Q_OBJECT_FAKE Q_OBJECT_FAKE + /* qmake ignore Q_GADGET */ +#define Q_GADGET Q_GADGET +#define Q_SCRIPTABLE Q_SCRIPTABLE +#define Q_INVOKABLE Q_INVOKABLE +#define Q_SIGNAL Q_SIGNAL +#define Q_SLOT Q_SLOT +#endif //Q_MOC_RUN + +QT_END_NAMESPACE + +#endif // QTMETAMACROS_H diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 2205366696..5767d52f6a 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -58,11 +58,11 @@ #include "qendian.h" #include "qresource.h" -#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) -#define QT_USE_MMAP -#include "private/qcore_unix_p.h" +#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY) +# define QT_USE_MMAP +# include "private/qcore_unix_p.h" // for mmap -#include <sys/mman.h> +# include <sys/mman.h> #endif #include <stdlib.h> diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 3be9a02248..3fe2be2a7c 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -118,22 +118,10 @@ struct CoreTypesFilter { namespace { // annonymous used to hide QVariant handlers -static void construct(QVariant::Private *x, const void *copy) -{ - QVariantConstructor<CoreTypesFilter> constructor(x, copy); - QMetaTypeSwitcher::switcher<void>(constructor, x->type); -} - -static void clear(QVariant::Private *d) -{ - QVariantDestructor<CoreTypesFilter> cleaner(d); - QMetaTypeSwitcher::switcher<void>(cleaner, d->type); -} - static bool isNull(const QVariant::Private *d) { QVariantIsNull<CoreTypesFilter> isNull(d); - return QMetaTypeSwitcher::switcher<bool>(isNull, d->type); + return QMetaTypeSwitcher::switcher<bool>(isNull, d->type().id()); } /*! @@ -145,7 +133,7 @@ static bool isNull(const QVariant::Private *d) static bool compare(const QVariant::Private *a, const QVariant::Private *b) { QVariantComparator<CoreTypesFilter> comparator(a, b); - return QMetaTypeSwitcher::switcher<bool>(comparator, a->type); + return QMetaTypeSwitcher::switcher<bool>(comparator, a->type().id()); } /*! @@ -153,7 +141,7 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b) */ static qlonglong qMetaTypeNumber(const QVariant::Private *d) { - switch (d->type) { + switch (d->type().id()) { case QMetaType::Int: return d->data.i; case QMetaType::LongLong: @@ -183,7 +171,7 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d) static qulonglong qMetaTypeUNumber(const QVariant::Private *d) { - switch (d->type) { + switch (d->type().id()) { case QMetaType::UInt: return d->data.u; case QMetaType::ULongLong: @@ -203,7 +191,7 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok) { *ok = true; - switch (uint(d->type)) { + switch (uint(d->type().id())) { case QMetaType::QString: return v_cast<QString>(d)->toLongLong(ok); case QMetaType::QChar: @@ -240,8 +228,9 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok) return qlonglong(qMetaTypeUNumber(d)); } - QMetaType typeInfo(d->type); - if (typeInfo.flags() & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) { + QMetaType typeInfo = d->type(); + if (typeInfo.flags() & QMetaType::IsEnumeration + || d->type().id() == QMetaType::QCborSimpleType) { switch (typeInfo.sizeOf()) { case 1: return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc; @@ -261,7 +250,7 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok) static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok) { *ok = true; - switch (uint(d->type)) { + switch (uint(d->type().id())) { case QMetaType::Double: return qreal(d->data.d); case QMetaType::Float: @@ -288,7 +277,7 @@ static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok) { *ok = true; - switch (uint(d->type)) { + switch (uint(d->type().id())) { case QMetaType::QString: return v_cast<QString>(d)->toULongLong(ok); case QMetaType::QChar: @@ -326,7 +315,7 @@ static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok) return qMetaTypeUNumber(d); } - QMetaType typeInfo(d->type); + QMetaType typeInfo = d->type(); if (typeInfo.flags() & QMetaType::IsEnumeration) { switch (typeInfo.sizeOf()) { case 1: @@ -366,16 +355,14 @@ static const void *constData(const QVariant::Private &d) \internal returns a QMetaEnum for a given meta tape type id if possible */ -static QMetaEnum metaEnumFromType(int type) +static QMetaEnum metaEnumFromType(QMetaType t) { - QMetaType t(type); if (t.flags() & QMetaType::IsEnumeration) { if (const QMetaObject *metaObject = t.metaObject()) { - const char *enumName = QMetaType::typeName(type); + const QByteArray enumName = t.name(); const char *lastColon = std::strrchr(enumName, ':'); - if (lastColon) - enumName = lastColon + 1; - return metaObject->enumerator(metaObject->indexOfEnumerator(enumName)); + return metaObject->enumerator(metaObject->indexOfEnumerator( + lastColon ? lastColon + 1 : enumName.constData())); } } return QMetaEnum(); @@ -389,11 +376,11 @@ static QMetaEnum metaEnumFromType(int type) */ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) { - Q_ASSERT(d->type != uint(t)); + Q_ASSERT(d->type().id() != t); Q_ASSERT(result); - if (d->type >= QMetaType::User || t >= QMetaType::User) { - const bool isOk = QMetaType::convert(constData(*d), d->type, result, t); + if (d->type().id() >= QMetaType::User || t >= QMetaType::User) { + const bool isOk = QMetaType::convert(constData(*d), d->type().id(), result, t); if (ok) *ok = isOk; if (isOk) @@ -407,7 +394,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) switch (uint(t)) { #ifndef QT_BOOTSTRAPPED case QMetaType::QUrl: - switch (d->type) { + switch (d->type().id()) { case QMetaType::QString: *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d)); break; @@ -424,7 +411,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) #endif // QT_BOOTSTRAPPED #if QT_CONFIG(itemmodel) case QMetaType::QModelIndex: - switch (d->type) { + switch (d->type().id()) { case QMetaType::QPersistentModelIndex: *static_cast<QModelIndex *>(result) = QModelIndex(*v_cast<QPersistentModelIndex>(d)); break; @@ -433,7 +420,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } break; case QMetaType::QPersistentModelIndex: - switch (d->type) { + switch (d->type().id()) { case QMetaType::QModelIndex: *static_cast<QPersistentModelIndex *>(result) = QPersistentModelIndex(*v_cast<QModelIndex>(d)); break; @@ -444,7 +431,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) #endif // QT_CONFIG(itemmodel) case QMetaType::QString: { QString *str = static_cast<QString *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::QChar: *str = *v_cast<QChar>(d); break; @@ -517,7 +504,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) default: #ifndef QT_NO_QOBJECT { - QMetaEnum en = metaEnumFromType(d->type); + QMetaEnum en = metaEnumFromType(d->type()); if (en.isValid()) { *str = QString::fromUtf8(en.valueToKey(qConvertToNumber(d, ok))); return *ok; @@ -530,7 +517,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } case QMetaType::QChar: { QChar *c = static_cast<QChar *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::Int: case QMetaType::LongLong: case QMetaType::Char: @@ -555,7 +542,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) #ifndef QT_NO_GEOM_VARIANT case QMetaType::QSize: { QSize *s = static_cast<QSize *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::QSizeF: *s = v_cast<QSizeF>(d)->toSize(); break; @@ -567,7 +554,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) case QMetaType::QSizeF: { QSizeF *s = static_cast<QSizeF *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::QSize: *s = QSizeF(*(v_cast<QSize>(d))); break; @@ -579,7 +566,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) case QMetaType::QLine: { QLine *s = static_cast<QLine *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::QLineF: *s = v_cast<QLineF>(d)->toLine(); break; @@ -591,7 +578,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) case QMetaType::QLineF: { QLineF *s = static_cast<QLineF *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::QLine: *s = QLineF(*(v_cast<QLine>(d))); break; @@ -602,14 +589,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } #endif case QMetaType::QStringList: - if (d->type == QMetaType::QVariantList) { + if (d->type().id() == QMetaType::QVariantList) { QStringList *slst = static_cast<QStringList *>(result); const QVariantList *list = v_cast<QVariantList >(d); const int size = list->size(); slst->reserve(size); for (int i = 0; i < size; ++i) slst->append(list->at(i).toString()); - } else if (d->type == QMetaType::QString) { + } else if (d->type().id() == QMetaType::QString) { QStringList *slst = static_cast<QStringList *>(result); *slst = QStringList(*v_cast<QString>(d)); } else { @@ -618,10 +605,10 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) break; case QMetaType::QDate: { QDate *dt = static_cast<QDate *>(result); - if (d->type == QMetaType::QDateTime) + if (d->type().id() == QMetaType::QDateTime) *dt = v_cast<QDateTime>(d)->date(); #if QT_CONFIG(datestring) - else if (d->type == QMetaType::QString) + else if (d->type().id() == QMetaType::QString) *dt = QDate::fromString(*v_cast<QString>(d), Qt::ISODate); #endif else @@ -631,7 +618,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } case QMetaType::QTime: { QTime *t = static_cast<QTime *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::QDateTime: *t = v_cast<QDateTime>(d)->time(); break; @@ -647,7 +634,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } case QMetaType::QDateTime: { QDateTime *dt = static_cast<QDateTime *>(result); - switch (d->type) { + switch (d->type().id()) { #if QT_CONFIG(datestring) case QMetaType::QString: *dt = QDateTime::fromString(*v_cast<QString>(d), Qt::ISODate); @@ -671,7 +658,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } case QMetaType::QByteArray: { QByteArray *ba = static_cast<QByteArray *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::QString: *ba = v_cast<QString>(d)->toUtf8(); break; @@ -718,7 +705,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) default: #ifndef QT_NO_QOBJECT { - QMetaEnum en = metaEnumFromType(d->type); + QMetaEnum en = metaEnumFromType(d->type()); if (en.isValid()) { *ba = en.valueToKey(qConvertToNumber(d, ok)); return *ok; @@ -765,7 +752,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } case QMetaType::Bool: { bool *b = static_cast<bool *>(result); - switch(d->type) { + switch (d->type().id()) { case QMetaType::QByteArray: *b = qt_convertToBool<QByteArray, const char*>(d); break; @@ -812,7 +799,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } case QMetaType::Double: { double *f = static_cast<double *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::QString: *f = v_cast<QString>(d)->toDouble(ok); break; @@ -860,7 +847,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } case QMetaType::Float: { float *f = static_cast<float *>(result); - switch (d->type) { + switch (d->type().id()) { case QMetaType::QString: *f = v_cast<QString>(d)->toFloat(ok); break; @@ -907,28 +894,25 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) break; } case QMetaType::QVariantList: - if (d->type == QMetaType::QStringList) { + if (d->type().id() == QMetaType::QStringList) { QVariantList *lst = static_cast<QVariantList *>(result); const QStringList *slist = v_cast<QStringList>(d); const int size = slist->size(); lst->reserve(size); for (int i = 0; i < size; ++i) lst->append(QVariant(slist->at(i))); - } else if (qstrcmp(QMetaType::typeName(d->type), "QList<QVariant>") == 0) { - *static_cast<QVariantList *>(result) = - *static_cast<QList<QVariant> *>(d->data.shared->ptr); #ifndef QT_BOOTSTRAPPED - } else if (d->type == QMetaType::QCborValue) { + } else if (d->type().id() == QMetaType::QCborValue) { if (!v_cast<QCborValue>(d)->isArray()) return false; *static_cast<QVariantList *>(result) = v_cast<QCborValue>(d)->toArray().toVariantList(); - } else if (d->type == QMetaType::QCborArray) { + } else if (d->type().id() == QMetaType::QCborArray) { *static_cast<QVariantList *>(result) = v_cast<QCborArray>(d)->toVariantList(); - } else if (d->type == QMetaType::QJsonValue) { + } else if (d->type().id() == QMetaType::QJsonValue) { if (!v_cast<QJsonValue>(d)->isArray()) return false; *static_cast<QVariantList *>(result) = v_cast<QJsonValue>(d)->toArray().toVariantList(); - } else if (d->type == QMetaType::QJsonArray) { + } else if (d->type().id() == QMetaType::QJsonArray) { *static_cast<QVariantList *>(result) = v_cast<QJsonArray>(d)->toVariantList(); #endif } else { @@ -936,27 +920,24 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } break; case QMetaType::QVariantMap: - if (qstrcmp(QMetaType::typeName(d->type), "QMap<QString, QVariant>") == 0) { - *static_cast<QVariantMap *>(result) = - *static_cast<QMap<QString, QVariant> *>(d->data.shared->ptr); - } else if (d->type == QMetaType::QVariantHash) { + if (d->type().id() == QMetaType::QVariantHash) { QVariantMap *map = static_cast<QVariantMap *>(result); const QVariantHash *hash = v_cast<QVariantHash>(d); const auto end = hash->end(); for (auto it = hash->begin(); it != end; ++it) static_cast<QMultiMap<QString, QVariant> *>(map)->insert(it.key(), it.value()); #ifndef QT_BOOTSTRAPPED - } else if (d->type == QMetaType::QCborValue) { + } else if (d->type().id() == QMetaType::QCborValue) { if (!v_cast<QCborValue>(d)->isMap()) return false; *static_cast<QVariantMap *>(result) = v_cast<QCborValue>(d)->toMap().toVariantMap(); - } else if (d->type == QMetaType::QCborMap) { + } else if (d->type().id() == QMetaType::QCborMap) { *static_cast<QVariantMap *>(result) = v_cast<QCborMap>(d)->toVariantMap(); - } else if (d->type == QMetaType::QJsonValue) { + } else if (d->type().id() == QMetaType::QJsonValue) { if (!v_cast<QJsonValue>(d)->isObject()) return false; *static_cast<QVariantMap *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantMap(); - } else if (d->type == QMetaType::QJsonObject) { + } else if (d->type().id() == QMetaType::QJsonObject) { *static_cast<QVariantMap *>(result) = v_cast<QJsonObject>(d)->toVariantMap(); #endif } else { @@ -964,27 +945,24 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } break; case QMetaType::QVariantHash: - if (qstrcmp(QMetaType::typeName(d->type), "QHash<QString, QVariant>") == 0) { - *static_cast<QVariantHash *>(result) = - *static_cast<QHash<QString, QVariant> *>(d->data.shared->ptr); - } else if (d->type == QMetaType::QVariantMap) { + if (d->type().id() == QMetaType::QVariantMap) { QVariantHash *hash = static_cast<QVariantHash *>(result); const QVariantMap *map = v_cast<QVariantMap>(d); const auto end = map->end(); for (auto it = map->begin(); it != end; ++it) - static_cast<QMultiHash<QString, QVariant> *>(hash)->insert(it.key(), it.value()); + hash->insert(it.key(), it.value()); #ifndef QT_BOOTSTRAPPED - } else if (d->type == QMetaType::QCborValue) { + } else if (d->type().id() == QMetaType::QCborValue) { if (!v_cast<QCborValue>(d)->isMap()) return false; *static_cast<QVariantHash *>(result) = v_cast<QCborValue>(d)->toMap().toVariantHash(); - } else if (d->type == QMetaType::QCborMap) { + } else if (d->type().id() == QMetaType::QCborMap) { *static_cast<QVariantHash *>(result) = v_cast<QCborMap>(d)->toVariantHash(); - } else if (d->type == QMetaType::QJsonValue) { + } else if (d->type().id() == QMetaType::QJsonValue) { if (!v_cast<QJsonValue>(d)->isObject()) return false; *static_cast<QVariantHash *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantHash(); - } else if (d->type == QMetaType::QJsonObject) { + } else if (d->type().id() == QMetaType::QJsonObject) { *static_cast<QVariantHash *>(result) = v_cast<QJsonObject>(d)->toVariantHash(); #endif } else { @@ -993,25 +971,25 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) break; #ifndef QT_NO_GEOM_VARIANT case QMetaType::QRect: - if (d->type == QMetaType::QRectF) + if (d->type().id() == QMetaType::QRectF) *static_cast<QRect *>(result) = (v_cast<QRectF>(d))->toRect(); else return false; break; case QMetaType::QRectF: - if (d->type == QMetaType::QRect) + if (d->type().id() == QMetaType::QRect) *static_cast<QRectF *>(result) = *v_cast<QRect>(d); else return false; break; case QMetaType::QPointF: - if (d->type == QMetaType::QPoint) + if (d->type().id() == QMetaType::QPoint) *static_cast<QPointF *>(result) = *v_cast<QPoint>(d); else return false; break; case QMetaType::QPoint: - if (d->type == QMetaType::QPointF) + if (d->type().id() == QMetaType::QPointF) *static_cast<QPoint *>(result) = (v_cast<QPointF>(d))->toPoint(); else return false; @@ -1023,7 +1001,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } #endif case QMetaType::QUuid: - switch (d->type) { + switch (d->type().id()) { case QMetaType::QString: *static_cast<QUuid *>(result) = QUuid(*v_cast<QString>(d)); break; @@ -1044,12 +1022,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) case QMetaType::Nullptr: *static_cast<std::nullptr_t *>(result) = nullptr; if (QMetaType::typeFlags(t) & (QMetaType::PointerToGadget | QMetaType::PointerToQObject) - || d->type == QMetaType::VoidStar) { + || d->type().id() == QMetaType::VoidStar) { if (v_cast<const void *>(d) == nullptr) break; } #ifndef QT_BOOTSTRAPPED - if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isNull()) + if (d->type().id() == QMetaType::QCborValue && v_cast<QCborValue>(d)->isNull()) break; #endif return false; @@ -1057,13 +1035,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) #ifndef QT_BOOTSTRAPPED #if QT_CONFIG(regularexpression) case QMetaType::QRegularExpression: - if (d->type != QMetaType::QCborValue || !v_cast<QCborValue>(d)->isRegularExpression()) + if (d->type().id() != QMetaType::QCborValue + || !v_cast<QCborValue>(d)->isRegularExpression()) return false; *static_cast<QRegularExpression *>(result) = v_cast<QCborValue>(d)->toRegularExpression(); break; #endif case QMetaType::QJsonValue: - switch (d->type) { + switch (d->type().id()) { case QMetaType::Nullptr: *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Null); break; @@ -1127,7 +1106,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } break; case QMetaType::QJsonArray: - switch (d->type) { + switch (d->type().id()) { case QMetaType::QStringList: *static_cast<QJsonArray *>(result) = QJsonArray::fromStringList(*v_cast<QStringList>(d)); break; @@ -1157,7 +1136,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } break; case QMetaType::QJsonObject: - switch (d->type) { + switch (d->type().id()) { case QMetaType::QVariantMap: *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantMap(*v_cast<QVariantMap>(d)); break; @@ -1187,13 +1166,13 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } break; case QMetaType::QCborSimpleType: - if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isSimpleType()) { + if (d->type().id() == QMetaType::QCborValue && v_cast<QCborValue>(d)->isSimpleType()) { *static_cast<QCborSimpleType *>(result) = v_cast<QCborValue>(d)->toSimpleType(); break; } return false; case QMetaType::QCborValue: - switch (d->type) { + switch (d->type().id()) { case QMetaType::Nullptr: *static_cast<QCborValue *>(result) = QCborValue(QCborValue::Null); break; @@ -1286,7 +1265,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } break; case QMetaType::QCborArray: - switch (d->type) { + switch (d->type().id()) { case QMetaType::QStringList: *static_cast<QCborArray *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d)); break; @@ -1316,7 +1295,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } break; case QMetaType::QCborMap: - switch (d->type) { + switch (d->type().id()) { case QMetaType::QVariantMap: *static_cast<QCborMap *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d)); break; @@ -1349,10 +1328,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) default: #ifndef QT_NO_QOBJECT - if (d->type == QMetaType::QString || d->type == QMetaType::QByteArray) { - QMetaEnum en = metaEnumFromType(t); + if (d->type().id() == QMetaType::QString || d->type().id() == QMetaType::QByteArray) { + QMetaEnum en = metaEnumFromType(QMetaType(t)); if (en.isValid()) { - QByteArray keys = (d->type == QMetaType::QString) ? v_cast<QString>(d)->toUtf8() : *v_cast<QByteArray>(d); + QByteArray keys = (d->type().id() == QMetaType::QString) + ? v_cast<QString>(d)->toUtf8() + : *v_cast<QByteArray>(d); int value = en.keysToValue(keys.constData(), ok); if (*ok) { switch (QMetaType::sizeOf(t)) { @@ -1373,7 +1354,8 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } } #endif - if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) { + if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration + || d->type().id() == QMetaType::QCborSimpleType) { qlonglong value = qConvertToNumber(d, ok); if (*ok) { switch (QMetaType::sizeOf(t)) { @@ -1403,13 +1385,11 @@ static void streamDebug(QDebug dbg, const QVariant &v) { QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr()); QVariantDebugStream<CoreTypesFilter> stream(dbg, d); - QMetaTypeSwitcher::switcher<void>(stream, d->type); + QMetaTypeSwitcher::switcher<void>(stream, d->type().id()); } #endif const QVariant::Handler qt_kernel_variant_handler = { - construct, - clear, isNull, #ifndef QT_NO_DATASTREAM nullptr, @@ -1425,8 +1405,6 @@ const QVariant::Handler qt_kernel_variant_handler = { #endif }; -static void dummyConstruct(QVariant::Private *, const void *) { Q_ASSERT_X(false, "QVariant", "Trying to construct an unknown type"); } -static void dummyClear(QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to clear an unknown type"); } static bool dummyIsNull(const QVariant::Private *d) { Q_ASSERT_X(false, "QVariant::isNull", "Trying to call isNull on an unknown type"); return d->is_null; } static bool dummyCompare(const QVariant::Private *, const QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to compare an unknown types"); return false; } static bool dummyConvert(const QVariant::Private *, int, void *, bool *) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); return false; } @@ -1434,8 +1412,6 @@ static bool dummyConvert(const QVariant::Private *, int, void *, bool *) { Q_ASS static void dummyStreamDebug(QDebug, const QVariant &) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); } #endif const QVariant::Handler qt_dummy_variant_handler = { - dummyConstruct, - dummyClear, dummyIsNull, #ifndef QT_NO_DATASTREAM nullptr, @@ -1451,43 +1427,42 @@ const QVariant::Handler qt_dummy_variant_handler = { #endif }; +// the type of d has already been set, but other field are not set static void customConstruct(QVariant::Private *d, const void *copy) { - const QMetaType type(d->type); + const QMetaType type = d->type(); const uint size = type.sizeOf(); if (!size) { - qWarning("Trying to construct an instance of an invalid type, type id: %i", d->type); - d->type = QMetaType::UnknownType; + *d = QVariant::Private(); return; } // this logic should match with QVariantIntegrator::CanUseInternalSpace if (size <= sizeof(QVariant::Private::Data) && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) { - type.construct(&d->data.ptr, copy); - d->is_null = d->data.ptr == nullptr; + type.construct(&d->data, copy); d->is_shared = false; } else { // Private::Data contains long long, and long double is the biggest standard type. const size_t maxAlignment = - qMax(Q_ALIGNOF(QVariant::Private::Data), Q_ALIGNOF(long double)); + qMax(alignof(QVariant::Private::Data), alignof(long double)); const size_t s = sizeof(QVariant::PrivateShared); const size_t offset = s + ((s * maxAlignment - s) % maxAlignment); void *data = operator new(offset + size); void *ptr = static_cast<char *>(data) + offset; type.construct(ptr, copy); - d->is_null = ptr == nullptr; d->is_shared = true; d->data.shared = new (data) QVariant::PrivateShared(ptr); } + d->is_null = !copy; } static void customClear(QVariant::Private *d) { if (!d->is_shared) { - QMetaType::destruct(d->type, &d->data.ptr); + d->type().destruct(&d->data); } else { - QMetaType::destruct(d->type, d->data.shared->ptr); + d->type().destruct(d->data.shared->ptr); d->data.shared->~PrivateShared(); operator delete(d->data.shared); } @@ -1497,12 +1472,8 @@ static bool customIsNull(const QVariant::Private *d) { if (d->is_null) return true; - const char *const typeName = QMetaType::typeName(d->type); - if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(d->type))) - qFatal("QVariant::isNull: type %d unknown to QVariant.", d->type); - uint typeNameLen = qstrlen(typeName); - if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*') { - const void *d_ptr = d->is_shared ? d->data.shared->ptr : &(d->data.ptr); + if (d->type().flags() & QMetaType::IsPointer) { + const void *d_ptr = d->is_shared ? d->data.shared->ptr : &(d->data); return *static_cast<void *const *>(d_ptr) == nullptr; } return false; @@ -1510,27 +1481,19 @@ static bool customIsNull(const QVariant::Private *d) static bool customCompare(const QVariant::Private *a, const QVariant::Private *b) { - const char *const typeName = QMetaType::typeName(a->type); - if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(a->type))) - qFatal("QVariant::compare: type %d unknown to QVariant.", a->type); - - const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data.ptr); - const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data.ptr); - - uint typeNameLen = qstrlen(typeName); - if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*') - return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr); + const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data); + const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data); if (a->is_null && b->is_null) return true; - return !memcmp(a_ptr, b_ptr, QMetaType::sizeOf(a->type)); + return !memcmp(a_ptr, b_ptr, a->type().sizeOf()); } static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok) { - if (d->type >= QMetaType::User || t >= QMetaType::User) { - if (QMetaType::convert(constData(*d), d->type, result, t)) { + if (d->type().id() >= QMetaType::User || t >= QMetaType::User) { + if (QMetaType::convert(constData(*d), d->type().id(), result, t)) { if (ok) *ok = true; return true; @@ -1553,8 +1516,6 @@ static void customStreamDebug(QDebug dbg, const QVariant &variant) { #endif const QVariant::Handler qt_custom_variant_handler = { - customConstruct, - customClear, customIsNull, #ifndef QT_NO_DATASTREAM nullptr, @@ -1573,6 +1534,7 @@ const QVariant::Handler qt_custom_variant_handler = { } // annonymous used to hide QVariant handlers static HandlersManager handlerManager; + Q_STATIC_ASSERT_X(!QModulesPrivate::Core, "Initialization assumes that ModulesNames::Core is 0"); const QVariant::Handler *HandlersManager::Handlers[QModulesPrivate::ModulesCount] = { &qt_kernel_variant_handler, &qt_dummy_variant_handler, @@ -1807,8 +1769,11 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names void QVariant::create(int type, const void *copy) { - d.type = type; - handlerManager[type]->construct(&d, copy); + d = Private(QMetaType(type)); + if (Q_UNLIKELY(type && !d.type().isValid())) { + qWarning("Trying to construct an instance of an invalid type, type id: %i", type); + } + customConstruct(&d, copy); } /*! @@ -1824,8 +1789,8 @@ void QVariant::create(int type, const void *copy) QVariant::~QVariant() { - if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char)) - handlerManager[d.type]->clear(&d); + if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared)) + customClear(&d); } /*! @@ -1840,8 +1805,8 @@ QVariant::QVariant(const QVariant &p) { if (d.is_shared) { d.data.shared->ref.ref(); - } else if (p.d.type > Char) { - handlerManager[d.type]->construct(&d, p.constData()); + } else if (d.type().isValid()) { + customConstruct(&d, p.constData()); d.is_null = p.d.is_null; } } @@ -2128,8 +2093,6 @@ QVariant::QVariant(const char *val) QVariant::QVariant(Type type) { create(type, nullptr); } -QVariant::QVariant(int typeId, const void *copy) -{ create(typeId, copy); d.is_null = false; } /*! \internal @@ -2138,7 +2101,7 @@ QVariant::QVariant(int typeId, const void *copy) QVariant::QVariant(int typeId, const void *copy, uint flags) { if (flags) { //type is a pointer type - d.type = typeId; + d = Private(QMetaType(typeId)); d.data.ptr = *reinterpret_cast<void *const*>(copy); } else { create(typeId, copy); @@ -2146,6 +2109,16 @@ QVariant::QVariant(int typeId, const void *copy, uint flags) d.is_null = false; } +/*! + \internal + flags is true if it is a pointer type + */ +QVariant::QVariant(QMetaType type, const void *copy) : d(type) +{ + customConstruct(&d, copy); + d.is_null = false; +} + QVariant::QVariant(int val) : d(Int) { d.data.i = val; } @@ -2310,23 +2283,31 @@ QVariant::QVariant(const QPersistentModelIndex &modelIndex) To test whether an instance of QVariant contains a data type that is compatible with the data type you are interested in, use canConvert(). -*/ + \sa userType(), metaType() +*/ QVariant::Type QVariant::type() const { - return d.type >= QMetaType::User ? UserType : static_cast<Type>(d.type); + int type = d.type().id(); + return type >= QMetaType::User ? UserType : static_cast<Type>(type); } - /*! Returns the storage type of the value stored in the variant. For non-user types, this is the same as type(). - \sa type() + \sa type(), metaType() */ - int QVariant::userType() const { - return d.type; + return d.type().id(); +} + +/*! + Returns the QMetaType of the value stored in the variant. +*/ +QMetaType QVariant::metaType() const +{ + return d.type(); } /*! @@ -2341,12 +2322,10 @@ QVariant& QVariant::operator=(const QVariant &variant) if (variant.d.is_shared) { variant.d.data.shared->ref.ref(); d = variant.d; - } else if (variant.d.type > Char) { - d.type = variant.d.type; - handlerManager[d.type]->construct(&d, variant.constData()); - d.is_null = variant.d.is_null; } else { d = variant.d; + customConstruct(&d, reinterpret_cast<const void *>(&variant.d.data)); + d.is_null = variant.d.is_null; } return *this; @@ -2371,11 +2350,10 @@ void QVariant::detach() if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1) return; - Private dd; - dd.type = d.type; - handlerManager[d.type]->construct(&dd, constData()); + Private dd(d.type()); + customConstruct(&dd, constData()); if (!d.data.shared->ref.deref()) - handlerManager[d.type]->clear(&d); + customClear(&d); d.data.shared = dd.data.shared; } @@ -2393,7 +2371,8 @@ void QVariant::detach() */ const char *QVariant::typeName() const { - return QMetaType::typeName(d.type); + // Cannot use d.type().name because we must return a char* + return QMetaType::typeName(d.type().id()); } /*! @@ -2402,11 +2381,9 @@ const char *QVariant::typeName() const */ void QVariant::clear() { - if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char)) - handlerManager[d.type]->clear(&d); - d.type = Invalid; - d.is_null = true; - d.is_shared = false; + if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared)) + customClear(&d); + d = {}; } /*! @@ -2469,7 +2446,11 @@ static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] = QMetaType::QDateTime, QMetaType::QByteArray, QMetaType::QBitArray, +#if QT_CONFIG(shortcut) QMetaType::QKeySequence, +#else + 0, // QKeySequence +#endif QMetaType::QPen, QMetaType::LongLong, QMetaType::ULongLong, @@ -2537,9 +2518,9 @@ void QVariant::load(QDataStream &s) } // const cast is safe since we operate on a newly constructed variant - if (!QMetaType::load(s, d.type, const_cast<void *>(constData()))) { + if (!QMetaType::load(s, d.type().id(), const_cast<void *>(constData()))) { s.setStatus(QDataStream::ReadCorruptData); - qWarning("QVariant::load: unable to load type %d.", d.type); + qWarning("QVariant::load: unable to load type %d.", d.type().id()); } } @@ -2551,7 +2532,9 @@ void QVariant::load(QDataStream &s) */ void QVariant::save(QDataStream &s) const { - quint32 typeId = d.type >= QMetaType::User ? QMetaType::User : userType(); + quint32 typeId = d.type().id(); + if (typeId >= QMetaType::User) + typeId = QMetaType::User; bool fakeUserType = false; if (s.version() < QDataStream::Qt_4_0) { int i; @@ -2574,7 +2557,11 @@ void QVariant::save(QDataStream &s) const typeId += 97; } else if (typeId == QMetaType::QSizePolicy) { typeId = 75; +#if QT_CONFIG(shortcut) } else if (typeId >= QMetaType::QKeySequence && typeId <= QMetaType::QQuaternion) { +#else + } else if (typeId >= QMetaType::QPen && typeId <= QMetaType::QQuaternion) { +#endif // and as a result these types received lower ids too typeId +=1; } else if (typeId == QMetaType::QPolygonF || typeId == QMetaType::QUuid) { @@ -2586,7 +2573,7 @@ void QVariant::save(QDataStream &s) const s << typeId; if (s.version() >= QDataStream::Qt_4_2) s << qint8(d.is_null); - if (d.type >= QVariant::UserType || fakeUserType) { + if (d.type().id() >= int(QVariant::UserType) || fakeUserType) { s << QMetaType::typeName(userType()); } @@ -2596,8 +2583,9 @@ void QVariant::save(QDataStream &s) const return; } - if (!QMetaType::save(s, d.type, constData())) { - qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n", QMetaType::typeName(d.type), d.type); + if (!QMetaType::save(s, d.type().id(), constData())) { + qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n", + QMetaType::typeName(d.type().id()), d.type().id()); Q_ASSERT_X(false, "QVariant::save", "Invalid type to save"); } } @@ -2657,21 +2645,21 @@ QDataStream& operator<<(QDataStream &s, const QVariant::Type p) QMetaType::UnknownType; otherwise returns \c false. */ -template <typename T> -inline T qVariantToHelper(const QVariant::Private &d, const HandlersManager &handlerManager) +template<typename T> +inline T qVariantToHelper(const QVariant::Private &d, HandlersManager &) { - const uint targetType = qMetaTypeId<T>(); - if (d.type == targetType) + QMetaType targetType = QMetaType::fromType<T>(); + if (d.type() == targetType) return *v_cast<T>(&d); T ret; - if (d.type >= QMetaType::User || targetType >= QMetaType::User) { + if (d.type().id() >= QMetaType::User || targetType.id() >= QMetaType::User) { const void * const from = constData(d); - if (QMetaType::convert(from, d.type, &ret, targetType)) + if (QMetaType::convert(from, d.type().id(), &ret, targetType.id())) return ret; } - handlerManager[d.type]->convert(&d, targetType, &ret, nullptr); + handlerManager[d.type().id()]->convert(&d, targetType.id(), &ret, nullptr); return ret; } @@ -3112,15 +3100,15 @@ inline T qNumVariantToHelper(const QVariant::Private &d, if (ok) *ok = true; - if (d.type == t) + if (d.type().id() == t) return val; T ret = 0; - if ((d.type >= QMetaType::User || t >= QMetaType::User) - && QMetaType::convert(constData(d), d.type, &ret, t)) + if ((d.type().id() >= QMetaType::User || t >= QMetaType::User) + && QMetaType::convert(constData(d), d.type().id(), &ret, t)) return ret; - if (!handlerManager[d.type]->convert(&d, t, &ret, ok) && ok) + if (!handlerManager[d.type().id()]->convert(&d, t, &ret, ok) && ok) *ok = false; return ret; } @@ -3217,11 +3205,11 @@ qulonglong QVariant::toULongLong(bool *ok) const */ bool QVariant::toBool() const { - if (d.type == Bool) + if (d.type() == QMetaType::fromType<bool>()) return d.data.b; bool res = false; - handlerManager[d.type]->convert(&d, Bool, &res, nullptr); + handlerManager[d.type().id()]->convert(&d, Bool, &res, nullptr); return res; } @@ -3496,45 +3484,45 @@ static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject) */ bool QVariant::canConvert(int targetTypeId) const { - if (d.type == targetTypeId) + if (d.type().id() == targetTypeId) return true; #if QT_CONFIG(itemmodel) - if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex) - || (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex)) + if ((targetTypeId == QMetaType::QModelIndex + && d.type().id() == QMetaType::QPersistentModelIndex) + || (targetTypeId == QMetaType::QPersistentModelIndex + && d.type().id() == QMetaType::QModelIndex)) return true; #endif if (targetTypeId == QMetaType::QVariantList - && (d.type == QMetaType::QVariantList - || d.type == QMetaType::QStringList - || d.type == QMetaType::QByteArrayList - || QMetaType::hasRegisteredConverterFunction(d.type, - qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))) { + && (d.type().id() == QMetaType::QVariantList || d.type().id() == QMetaType::QStringList + || d.type().id() == QMetaType::QByteArrayList + || QMetaType::hasRegisteredConverterFunction( + d.type().id(), qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))) { return true; } if ((targetTypeId == QMetaType::QVariantHash || targetTypeId == QMetaType::QVariantMap) - && (d.type == QMetaType::QVariantMap - || d.type == QMetaType::QVariantHash - || QMetaType::hasRegisteredConverterFunction(d.type, - qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))) { + && (d.type().id() == QMetaType::QVariantMap || d.type().id() == QMetaType::QVariantHash + || QMetaType::hasRegisteredConverterFunction( + d.type().id(), qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))) { return true; } - if (targetTypeId == qMetaTypeId<QPair<QVariant, QVariant> >() && - QMetaType::hasRegisteredConverterFunction(d.type, - qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) { + if (targetTypeId == qMetaTypeId<QPair<QVariant, QVariant>>() + && QMetaType::hasRegisteredConverterFunction( + d.type().id(), qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) { return true; } - if ((d.type >= QMetaType::User || targetTypeId >= QMetaType::User) - && QMetaType::hasRegisteredConverterFunction(d.type, targetTypeId)) { + if ((d.type().id() >= QMetaType::User || targetTypeId >= QMetaType::User) + && QMetaType::hasRegisteredConverterFunction(d.type().id(), targetTypeId)) { return true; } // TODO Reimplement this function, currently it works but it is a historical mess. - uint currentType = d.type; + uint currentType = d.type().id(); if (currentType == QMetaType::SChar || currentType == QMetaType::Char) currentType = QMetaType::UInt; if (targetTypeId == QMetaType::SChar || currentType == QMetaType::Char) @@ -3647,9 +3635,11 @@ bool QVariant::canConvert(int targetTypeId) const if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) { switch (uint(targetTypeId)) { case QVariant::Int: +#if QT_CONFIG(shortcut) if (currentType == QVariant::KeySequence) return true; Q_FALLTHROUGH(); +#endif case QVariant::UInt: case QVariant::LongLong: case QVariant::ULongLong: @@ -3672,11 +3662,16 @@ bool QVariant::canConvert(int targetTypeId) const return currentType == QVariant::Color || currentType == QMetaType::Nullptr || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType)); case QVariant::String: - return currentType == QVariant::KeySequence || currentType == QVariant::Font - || currentType == QVariant::Color || currentType == QMetaType::Nullptr - || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType)); + return currentType == QVariant::Font + || currentType == QVariant::Color || currentType == QMetaType::Nullptr +#if QT_CONFIG(shortcut) + || currentType == QVariant::KeySequence +#endif + || ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType)); +#if QT_CONFIG(shortcut) case QVariant::KeySequence: return currentType == QVariant::String || currentType == QVariant::Int; +#endif case QVariant::Font: return currentType == QVariant::String; case QVariant::Color: @@ -3730,7 +3725,7 @@ bool QVariant::canConvert(int targetTypeId) const bool QVariant::convert(int targetTypeId) { - if (d.type == uint(targetTypeId)) + if (d.type().id() == targetTypeId) return true; QVariant oldValue = *this; @@ -3741,7 +3736,7 @@ bool QVariant::convert(int targetTypeId) create(targetTypeId, nullptr); // Fail if the value is not initialized or was forced null by a previous failed convert. - if (oldValue.d.is_null && oldValue.d.type != QMetaType::Nullptr) + if (oldValue.d.is_null && oldValue.d.type().id() != QMetaType::Nullptr) return false; if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) { @@ -3827,72 +3822,6 @@ bool QVariant::convert(const int type, void *ptr) const QMetaType::registerComparators(). */ -/*! - \fn bool QVariant::operator<(const QVariant &v) const - \obsolete - - Compares this QVariant with \a v and returns \c true if this is less than \a v. - - \note Comparability might not be availabe for the type stored in this QVariant - or in \a v. - - \warning To make this function work with a custom type registered with - qRegisterMetaType(), its comparison operator must be registered using - QMetaType::registerComparators(). - - This operator is deprecated as it cannot establish a total order required - for most use of this operator, which is the reason you cannot use QVariant - as the key of a QMap. -*/ - -/*! - \fn bool QVariant::operator<=(const QVariant &v) const - \obsolete - - Compares this QVariant with \a v and returns \c true if this is less or equal than \a v. - - \note Comparability might not be available for the type stored in this QVariant - or in \a v. - - \warning To make this function work with a custom type registered with - qRegisterMetaType(), its comparison operator must be registered using - QMetaType::registerComparators(). - - This operator is deprecated as it cannot establish a total order. -*/ - -/*! - \fn bool QVariant::operator>(const QVariant &v) const - \obsolete - - Compares this QVariant with \a v and returns \c true if this is larger than \a v. - - \note Comparability might not be available for the type stored in this QVariant - or in \a v. - - \warning To make this function work with a custom type registered with - qRegisterMetaType(), its comparison operator must be registered using - QMetaType::registerComparators(). - - This operator is deprecated as it cannot establish a total order. -*/ - -/*! - \fn bool QVariant::operator>=(const QVariant &v) const - \obsolete - - Compares this QVariant with \a v and returns \c true if this is larger or equal than \a v. - - \note Comparability might not be available for the type stored in this QVariant - or in \a v. - - \warning To make this function work with a custom type registered with - qRegisterMetaType(), its comparison operator must be registered using - QMetaType::registerComparators(). - - This operator is deprecated as it cannot establish a total order. -*/ - static bool qIsNumericType(uint tp) { static const qulonglong numericTypeBits = @@ -4009,7 +3938,7 @@ static int integralCompare(uint promotedType, const QVariant::Private *d1, const static int numericCompare(const QVariant::Private *d1, const QVariant::Private *d2) { - uint promotedType = numericTypePromotion(d1->type, d2->type); + uint promotedType = numericTypePromotion(d1->type().id(), d2->type().id()); if (promotedType != QMetaType::QReal) return integralCompare(promotedType, d1, d2); @@ -4038,33 +3967,33 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private * */ bool QVariant::cmp(const QVariant &v) const { - auto cmp_helper = [] (const QVariant::Private &d1, const QVariant::Private &d2) - { - Q_ASSERT(d1.type == d2.type); - if (d1.type >= QMetaType::User) { + auto cmp_helper = [](const QVariant::Private &d1, const QVariant::Private &d2) { + Q_ASSERT(d1.type() == d2.type()); + if (d1.type().id() >= QMetaType::User) { int result; - if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)), QT_PREPEND_NAMESPACE(constData(d2)), d1.type, &result)) + if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)), + QT_PREPEND_NAMESPACE(constData(d2)), d1.type().id(), &result)) return result == 0; } - return handlerManager[d1.type]->compare(&d1, &d2); + return handlerManager[d1.type().id()]->compare(&d1, &d2); }; // try numerics first, with C++ type promotion rules (no conversion) - if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) + if (qIsNumericType(d.type().id()) && qIsNumericType(v.d.type().id())) return numericCompare(&d, &v.d) == 0; - if (d.type == v.d.type) + if (d.type() == v.d.type()) return cmp_helper(d, v.d); QVariant v1 = *this; QVariant v2 = v; - if (v2.canConvert(v1.d.type)) { - if (!v2.convert(v1.d.type)) + if (v2.canConvert(v1.d.type().id())) { + if (!v2.convert(v1.d.type().id())) return false; } else { // try the opposite conversion, it might work qSwap(v1, v2); - if (!v2.convert(v1.d.type)) + if (!v2.convert(v1.d.type().id())) return false; } return cmp_helper(v1.d, v2.d); @@ -4073,77 +4002,10 @@ bool QVariant::cmp(const QVariant &v) const /*! \internal */ -int QVariant::compare(const QVariant &v) const -{ - // try numerics first, with C++ type promotion rules (no conversion) - if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) - return numericCompare(&d, &v.d); - - // check for equality next, as more types implement operator== than operator< - if (cmp(v)) - return 0; - - const QVariant *v1 = this; - const QVariant *v2 = &v; - QVariant converted1; - QVariant converted2; - - if (d.type != v.d.type) { - // if both types differ, try to convert - if (v2->canConvert(v1->d.type)) { - converted2 = *v2; - if (converted2.convert(v1->d.type)) - v2 = &converted2; - } - if (v1->d.type != v2->d.type && v1->canConvert(v2->d.type)) { - converted1 = *v1; - if (converted1.convert(v2->d.type)) - v1 = &converted1; - } - if (v1->d.type != v2->d.type) { - // if conversion fails, default to toString - int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive); - if (r == 0) { - // cmp(v) returned false, so we should try to agree with it. - return (v1->d.type < v2->d.type) ? -1 : 1; - } - return r; - } - - // did we end up with two numerics? If so, restart - if (qIsNumericType(v1->d.type) && qIsNumericType(v2->d.type)) - return v1->compare(*v2); - } - if (v1->d.type >= QMetaType::User) { - int result; - if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2->d)), d.type, &result)) - return result; - } - switch (v1->d.type) { - case QVariant::Date: - return v1->toDate() < v2->toDate() ? -1 : 1; - case QVariant::Time: - return v1->toTime() < v2->toTime() ? -1 : 1; - case QVariant::DateTime: - return v1->toDateTime() < v2->toDateTime() ? -1 : 1; - case QVariant::StringList: - return v1->toStringList() < v2->toStringList() ? -1 : 1; - } - int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive); - if (r == 0) { - // cmp(v) returned false, so we should try to agree with it. - return (d.type < v.d.type) ? -1 : 1; - } - return r; -} - -/*! - \internal - */ const void *QVariant::constData() const { - return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr); + return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data); } /*! @@ -4176,14 +4038,14 @@ void* QVariant::data() */ bool QVariant::isNull() const { - return handlerManager[d.type]->isNull(&d); + return handlerManager[d.type().id()]->isNull(&d); } #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QVariant &v) { QDebugStateSaver saver(dbg); - const uint typeId = v.d.type; + const uint typeId = v.d.type().id(); dbg.nospace() << "QVariant("; if (typeId != QMetaType::UnknownType) { dbg << QMetaType::typeName(typeId) << ", "; @@ -4246,8 +4108,8 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) If the QVariant contains a pointer to a type derived from QObject then \c{T} may be any QObject type. If the pointer stored in the QVariant can be qobject_cast to T, then that result is returned. Otherwise \nullptr is - returned. Note that this only works for QObject subclasses which use the - Q_OBJECT macro. + returned. Note that this only works for QObject subclasses which use + the Q_OBJECT macro. If the QVariant contains a sequential container and \c{T} is QVariantList, the elements of the container will be converted into \l {QVariant}s and returned as a QVariantList. @@ -5110,4 +4972,10 @@ QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::opera return const_iterator(impl, new QAtomicInt(0)); } +QVariant::Private::~Private() +{ + QtMetaTypePrivate::derefAndDestroy( + reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2)); +} + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 24657818c5..b09c706df2 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -184,7 +184,9 @@ class Q_CORE_EXPORT QVariant Region = QMetaType::QRegion, Bitmap = QMetaType::QBitmap, Cursor = QMetaType::QCursor, +#if QT_CONFIG(shortcut) KeySequence = QMetaType::QKeySequence, +#endif Pen = QMetaType::QPen, TextLength = QMetaType::QTextLength, TextFormat = QMetaType::QTextFormat, @@ -208,8 +210,8 @@ class Q_CORE_EXPORT QVariant QVariant() noexcept : d() {} ~QVariant(); QVariant(Type type); - QVariant(int typeId, const void *copy); - QVariant(int typeId, const void *copy, uint flags); + QVariant(int typeId, const void *copy, uint flags = 0); // ### Qt6 TODO deprecate + explicit QVariant(QMetaType type, const void *copy); QVariant(const QVariant &other); #ifndef QT_NO_DATASTREAM @@ -283,6 +285,7 @@ class Q_CORE_EXPORT QVariant Type type() const; int userType() const; const char *typeName() const; + QMetaType metaType() const; bool canConvert(int targetTypeId) const; bool convert(int targetTypeId); @@ -368,7 +371,9 @@ class Q_CORE_EXPORT QVariant template<typename T> static inline QVariant fromValue(const T &value) - { return QVariant(qMetaTypeId<T>(), &value, QTypeInfo<T>::isPointer); } + { + return QVariant(QMetaType::fromType<T>(), &value); + } #if (__has_include(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC) template<typename... Types> @@ -393,23 +398,35 @@ class Q_CORE_EXPORT QVariant }; struct Private { - inline Private() noexcept : type(Invalid), is_shared(false), is_null(true) - { data.ptr = nullptr; } - - // Internal constructor for initialized variants. - explicit inline Private(uint variantType) noexcept - : type(variantType), is_shared(false), is_null(false) - {} + Private() noexcept : packedType(0), is_shared(false), is_null(true) {} + explicit Private(const QMetaType &type) noexcept : is_shared(false), is_null(false) + { + if (type.d_ptr) + type.d_ptr->ref.ref(); + quintptr mt = quintptr(type.d_ptr); + Q_ASSERT((mt & 0x3) == 0); + packedType = mt >> 2; + } + explicit Private(int type) noexcept : Private(QMetaType(type)) {} + Private(const Private &other) : Private(other.type()) + { + data = other.data; + is_shared = other.is_shared; + is_null = other.is_null; + } + Private &operator=(const Private &other) + { + if (&other != this) { + this->~Private(); + new (this) Private(other); + } + return *this; + } + Q_CORE_EXPORT ~Private(); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - Private(const Private &other) noexcept - : data(other.data), type(other.type), - is_shared(other.is_shared), is_null(other.is_null) - {} - Private &operator=(const Private &other) noexcept = default; -#endif union Data { + void *threeptr[3] = { nullptr, nullptr, nullptr }; char c; uchar uc; short s; @@ -429,13 +446,15 @@ class Q_CORE_EXPORT QVariant void *ptr; PrivateShared *shared; } data; - uint type : 30; - uint is_shared : 1; - uint is_null : 1; + quintptr packedType : sizeof(QMetaType) * 8 - 2; + quintptr is_shared : 1; + quintptr is_null : 1; + inline QMetaType type() const + { + return QMetaType(reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2)); + } }; public: - typedef void (*f_construct)(Private *, const void *); - typedef void (*f_clear)(Private *); typedef bool (*f_null)(const Private *); #ifndef QT_NO_DATASTREAM typedef void (*f_load)(Private *, QDataStream &); @@ -446,8 +465,6 @@ class Q_CORE_EXPORT QVariant typedef bool (*f_canConvert)(const QVariant::Private *d, int t); typedef void (*f_debugStream)(QDebug, const QVariant &); struct Handler { - f_construct construct; - f_clear clear; f_null isNull; #ifndef QT_NO_DATASTREAM f_load load; @@ -463,16 +480,6 @@ class Q_CORE_EXPORT QVariant { return cmp(v); } inline bool operator!=(const QVariant &v) const { return !cmp(v); } -#if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED inline bool operator<(const QVariant &v) const - { return compare(v) < 0; } - QT_DEPRECATED inline bool operator<=(const QVariant &v) const - { return compare(v) <= 0; } - QT_DEPRECATED inline bool operator>(const QVariant &v) const - { return compare(v) > 0; } - QT_DEPRECATED inline bool operator>=(const QVariant &v) const - { return compare(v) >= 0; } -#endif protected: friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &); @@ -491,7 +498,6 @@ public: Private d; void create(int type, const void *copy); bool cmp(const QVariant &other) const; - int compare(const QVariant &other) const; bool convert(const int t, void *ptr) const; // ### Qt6: drop const private: @@ -554,22 +560,20 @@ inline QVariant QVariant::fromValue(const std::monostate &) } #endif -inline bool QVariant::isValid() const { return d.type != Invalid; } +inline bool QVariant::isValid() const +{ + return d.type().isValid(); +} template<typename T> inline void QVariant::setValue(const T &avalue) { + QMetaType metaType = QMetaType::fromType<T>(); // If possible we reuse the current QVariant private. - const uint type = qMetaTypeId<T>(); - if (isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) { - d.type = type; - d.is_null = false; - T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr); - if (QTypeInfo<T>::isComplex) - old->~T(); - new (old) T(avalue); // call the copy constructor + if (isDetached() && d.type() == metaType) { + *reinterpret_cast<T *>(data()) = avalue; } else { - *this = QVariant(type, &avalue, QTypeInfo<T>::isPointer); + *this = QVariant::fromValue<T>(avalue); } } @@ -826,7 +830,7 @@ namespace QtPrivate { QVariantHash l; l.reserve(iter.size()); for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) - static_cast<QMultiHash<QString, QVariant> &>(l).insert(it.key().toString(), it.value()); + l.insert(it.key().toString(), it.value()); return l; } return QVariantValueHelper<QVariantHash>::invoke(v); diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 94781a9957..aa89d42092 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -234,7 +234,7 @@ public: QVariantComparator(const QVariant::Private *a, const QVariant::Private *b) : m_a(a), m_b(b) { - Q_ASSERT(a->type == b->type); + Q_ASSERT(a->type() == b->type()); } template<typename T> @@ -346,113 +346,6 @@ protected: const QVariant::Private *m_d; }; -template<class Filter> -class QVariantConstructor -{ - template<typename T, bool IsAcceptedType = Filter::template Acceptor<T>::IsAccepted> - struct FilteredConstructor { - FilteredConstructor(const QVariantConstructor &tc) - { - v_construct<T>(tc.m_x, tc.m_copy); - tc.m_x->is_null = !tc.m_copy; - } - }; - template<typename T> - struct FilteredConstructor<T, /* IsAcceptedType = */ false> { - FilteredConstructor(const QVariantConstructor &tc) - { - // ignore types that lives outside of the current library - tc.m_x->type = QMetaType::UnknownType; - } - }; -public: - QVariantConstructor(QVariant::Private *x, const void *copy) - : m_x(x) - , m_copy(copy) - {} - - template<typename T> - void delegate(const T*) - { - FilteredConstructor<T>(*this); - } - - void delegate(const QMetaTypeSwitcher::NotBuiltinType*) - { - // QVariantConstructor is used only for built-in types. - Q_ASSERT(false); - } - - void delegate(const void*) - { - qWarning("Trying to create a QVariant instance of QMetaType::Void type, an invalid QVariant will be constructed instead"); - m_x->type = QMetaType::UnknownType; - m_x->is_shared = false; - m_x->is_null = !m_copy; - } - - void delegate(const QMetaTypeSwitcher::UnknownType*) - { - if (m_x->type != QMetaType::UnknownType) { - qWarning("Trying to construct an instance of an invalid type, type id: %i", m_x->type); - m_x->type = QMetaType::UnknownType; - } - m_x->is_shared = false; - m_x->is_null = !m_copy; - } -private: - QVariant::Private *m_x; - const void *m_copy; -}; - -template<class Filter> -class QVariantDestructor -{ - template<typename T, bool IsAcceptedType = Filter::template Acceptor<T>::IsAccepted> - struct FilteredDestructor { - FilteredDestructor(QVariant::Private *d) - { - v_clear<T>(d); - } - }; - template<typename T> - struct FilteredDestructor<T, /* IsAcceptedType = */ false> { - FilteredDestructor(QVariant::Private *) - { - // It is not possible to create not accepted type - Q_ASSERT(false); - } - }; - -public: - QVariantDestructor(QVariant::Private *d) - : m_d(d) - {} - ~QVariantDestructor() - { - m_d->type = QMetaType::UnknownType; - m_d->is_null = true; - m_d->is_shared = false; - } - - template<typename T> - void delegate(const T*) - { - FilteredDestructor<T> cleaner(m_d); - } - - void delegate(const QMetaTypeSwitcher::NotBuiltinType*) - { - // QVariantDestructor class is used only for a built-in type - Q_ASSERT(false); - } - // Ignore nonconstructible type - void delegate(const QMetaTypeSwitcher::UnknownType*) {} - void delegate(const void*) { Q_ASSERT(false); } -private: - QVariant::Private *m_d; -}; - namespace QVariantPrivate { Q_CORE_EXPORT void registerHandler(const int /* Modules::Names */ name, const QVariant::Handler *handler); } |