| /**************************************************************************** |
| ** |
| ** Copyright (C) 2015 The Qt Company Ltd. |
| ** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com> |
| ** Contact: http://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtCore module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL21$ |
| ** 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 http://www.qt.io/terms-conditions. For further |
| ** information use the contact form at http://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 2.1 or version 3 as published by the Free |
| ** Software Foundation and appearing in the file LICENSE.LGPLv21 and |
| ** LICENSE.LGPLv3 included in the packaging of this file. Please review the |
| ** following information to ensure the GNU Lesser General Public License |
| ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and |
| ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** As a special exception, The Qt Company gives you certain additional |
| ** rights. These rights are described in The Qt Company LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #ifndef QMETATYPE_H |
| #define QMETATYPE_H |
| |
| #include <QtCore/qglobal.h> |
| #include <QtCore/qatomic.h> |
| #include <QtCore/qbytearray.h> |
| #include <QtCore/qvarlengtharray.h> |
| #include <QtCore/qisenum.h> |
| #include <QtCore/qtypetraits.h> |
| #ifndef QT_NO_QOBJECT |
| #include <QtCore/qobjectdefs.h> |
| #endif |
| #include <new> |
| |
| #include <vector> |
| #include <list> |
| #include <map> |
| |
| #ifdef Bool |
| #error qmetatype.h must be included before any header file that defines Bool |
| #endif |
| |
| QT_BEGIN_NAMESPACE |
| |
| template <typename T> |
| struct QMetaTypeId2; |
| |
| template <typename T> |
| inline Q_DECL_CONSTEXPR int qMetaTypeId(); |
| |
| // F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType) |
| // ### Qt6: reorder the types to match the C++ integral type ranking |
| #define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\ |
| F(Void, 43, void) \ |
| F(Bool, 1, bool) \ |
| F(Int, 2, int) \ |
| F(UInt, 3, uint) \ |
| F(LongLong, 4, qlonglong) \ |
| F(ULongLong, 5, qulonglong) \ |
| F(Double, 6, double) \ |
| F(Long, 32, long) \ |
| F(Short, 33, short) \ |
| F(Char, 34, char) \ |
| F(ULong, 35, ulong) \ |
| F(UShort, 36, ushort) \ |
| F(UChar, 37, uchar) \ |
| F(Float, 38, float) \ |
| F(SChar, 40, signed char) \ |
| |
| #define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\ |
| F(VoidStar, 31, void*) \ |
| |
| #define QT_FOR_EACH_STATIC_CORE_CLASS(F)\ |
| F(QChar, 7, QChar) \ |
| F(QString, 10, QString) \ |
| F(QStringList, 11, QStringList) \ |
| F(QByteArray, 12, QByteArray) \ |
| F(QBitArray, 13, QBitArray) \ |
| F(QDate, 14, QDate) \ |
| F(QTime, 15, QTime) \ |
| F(QDateTime, 16, QDateTime) \ |
| F(QUrl, 17, QUrl) \ |
| F(QLocale, 18, QLocale) \ |
| F(QRect, 19, QRect) \ |
| F(QRectF, 20, QRectF) \ |
| F(QSize, 21, QSize) \ |
| F(QSizeF, 22, QSizeF) \ |
| F(QLine, 23, QLine) \ |
| F(QLineF, 24, QLineF) \ |
| F(QPoint, 25, QPoint) \ |
| F(QPointF, 26, QPointF) \ |
| F(QRegExp, 27, QRegExp) \ |
| F(QEasingCurve, 29, QEasingCurve) \ |
| F(QUuid, 30, QUuid) \ |
| F(QVariant, 41, QVariant) \ |
| F(QModelIndex, 42, QModelIndex) \ |
| F(QRegularExpression, 44, QRegularExpression) \ |
| F(QJsonValue, 45, QJsonValue) \ |
| F(QJsonObject, 46, QJsonObject) \ |
| F(QJsonArray, 47, QJsonArray) \ |
| F(QJsonDocument, 48, QJsonDocument) \ |
| F(QPersistentModelIndex, 50, QPersistentModelIndex) \ |
| |
| #define QT_FOR_EACH_STATIC_CORE_POINTER(F)\ |
| F(QObjectStar, 39, QObject*) |
| |
| #define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\ |
| F(QVariantMap, 8, QVariantMap) \ |
| F(QVariantList, 9, QVariantList) \ |
| F(QVariantHash, 28, QVariantHash) \ |
| F(QByteArrayList, 49, QByteArrayList) \ |
| |
| #define QT_FOR_EACH_STATIC_GUI_CLASS(F)\ |
| F(QFont, 64, QFont) \ |
| F(QPixmap, 65, QPixmap) \ |
| F(QBrush, 66, QBrush) \ |
| F(QColor, 67, QColor) \ |
| F(QPalette, 68, QPalette) \ |
| F(QIcon, 69, QIcon) \ |
| F(QImage, 70, QImage) \ |
| F(QPolygon, 71, QPolygon) \ |
| F(QRegion, 72, QRegion) \ |
| F(QBitmap, 73, QBitmap) \ |
| F(QCursor, 74, QCursor) \ |
| F(QKeySequence, 75, QKeySequence) \ |
| F(QPen, 76, QPen) \ |
| F(QTextLength, 77, QTextLength) \ |
| F(QTextFormat, 78, QTextFormat) \ |
| F(QMatrix, 79, QMatrix) \ |
| F(QTransform, 80, QTransform) \ |
| F(QMatrix4x4, 81, QMatrix4x4) \ |
| F(QVector2D, 82, QVector2D) \ |
| F(QVector3D, 83, QVector3D) \ |
| F(QVector4D, 84, QVector4D) \ |
| F(QQuaternion, 85, QQuaternion) \ |
| F(QPolygonF, 86, QPolygonF) \ |
| |
| |
| #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") \ |
| F(UInt, -1, uint, "unsigned int") \ |
| F(UShort, -1, ushort, "unsigned short") \ |
| F(UChar, -1, uchar, "unsigned char") \ |
| F(LongLong, -1, qlonglong, "long long") \ |
| F(ULongLong, -1, qulonglong, "unsigned long long") \ |
| F(SChar, -1, signed char, "qint8") \ |
| F(UChar, -1, uchar, "quint8") \ |
| F(Short, -1, short, "qint16") \ |
| F(UShort, -1, ushort, "quint16") \ |
| F(Int, -1, int, "qint32") \ |
| F(UInt, -1, uint, "quint32") \ |
| F(LongLong, -1, qlonglong, "qint64") \ |
| F(ULongLong, -1, qulonglong, "quint64") \ |
| 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>") \ |
| |
| #define QT_FOR_EACH_STATIC_TYPE(F)\ |
| QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\ |
| QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\ |
| QT_FOR_EACH_STATIC_CORE_CLASS(F)\ |
| QT_FOR_EACH_STATIC_CORE_POINTER(F)\ |
| QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\ |
| QT_FOR_EACH_STATIC_GUI_CLASS(F)\ |
| QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\ |
| |
| #define QT_DEFINE_METATYPE_ID(TypeName, Id, Name) \ |
| TypeName = Id, |
| |
| #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \ |
| F(QList) \ |
| F(QVector) \ |
| F(QQueue) \ |
| F(QStack) \ |
| F(QSet) \ |
| F(QLinkedList) |
| |
| #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \ |
| F(QHash, class) \ |
| F(QMap, class) \ |
| F(QPair, struct) |
| |
| #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F) \ |
| F(QSharedPointer) \ |
| F(QWeakPointer) \ |
| F(QPointer) |
| |
| class QDataStream; |
| class QMetaTypeInterface; |
| struct QMetaObject; |
| |
| namespace QtPrivate |
| { |
| /*! |
| This template is used for implicit conversion from type From to type To. |
| \internal |
| */ |
| template<typename From, typename To> |
| To convertImplicit(const From& from) |
| { |
| return from; |
| } |
| |
| #ifndef QT_NO_DEBUG_STREAM |
| struct AbstractDebugStreamFunction |
| { |
| typedef void (*Stream)(const AbstractDebugStreamFunction *, QDebug&, const void *); |
| typedef void (*Destroy)(AbstractDebugStreamFunction *); |
| explicit AbstractDebugStreamFunction(Stream s = 0, Destroy d = 0) |
| : stream(s), destroy(d) {} |
| Q_DISABLE_COPY(AbstractDebugStreamFunction) |
| Stream stream; |
| Destroy destroy; |
| }; |
| |
| template<typename T> |
| struct BuiltInDebugStreamFunction : public AbstractDebugStreamFunction |
| { |
| BuiltInDebugStreamFunction() |
| : AbstractDebugStreamFunction(stream, destroy) {} |
| static void stream(const AbstractDebugStreamFunction *, QDebug& dbg, const void *r) |
| { |
| const T *rhs = static_cast<const T *>(r); |
| operator<<(dbg, *rhs); |
| } |
| |
| static void destroy(AbstractDebugStreamFunction *_this) |
| { |
| delete static_cast<BuiltInDebugStreamFunction *>(_this); |
| } |
| }; |
| #endif |
| |
| struct AbstractComparatorFunction |
| { |
| typedef bool (*LessThan)(const AbstractComparatorFunction *, const void *, const void *); |
| typedef bool (*Equals)(const AbstractComparatorFunction *, const void *, const void *); |
| typedef void (*Destroy)(AbstractComparatorFunction *); |
| explicit AbstractComparatorFunction(LessThan lt = 0, Equals e = 0, Destroy d = 0) |
| : lessThan(lt), equals(e), destroy(d) {} |
| Q_DISABLE_COPY(AbstractComparatorFunction) |
| LessThan lessThan; |
| Equals equals; |
| Destroy destroy; |
| }; |
| |
| template<typename T> |
| struct BuiltInComparatorFunction : public AbstractComparatorFunction |
| { |
| BuiltInComparatorFunction() |
| : AbstractComparatorFunction(lessThan, equals, destroy) {} |
| static bool lessThan(const AbstractComparatorFunction *, const void *l, const void *r) |
| { |
| const T *lhs = static_cast<const T *>(l); |
| const T *rhs = static_cast<const T *>(r); |
| return *lhs < *rhs; |
| } |
| |
| static bool equals(const AbstractComparatorFunction *, const void *l, const void *r) |
| { |
| const T *lhs = static_cast<const T *>(l); |
| const T *rhs = static_cast<const T *>(r); |
| return *lhs == *rhs; |
| } |
| |
| static void destroy(AbstractComparatorFunction *_this) |
| { |
| delete static_cast<BuiltInComparatorFunction *>(_this); |
| } |
| }; |
| |
| template<typename T> |
| struct BuiltInEqualsComparatorFunction : public AbstractComparatorFunction |
| { |
| BuiltInEqualsComparatorFunction() |
| : AbstractComparatorFunction(0, equals, destroy) {} |
| static bool equals(const AbstractComparatorFunction *, const void *l, const void *r) |
| { |
| const T *lhs = static_cast<const T *>(l); |
| const T *rhs = static_cast<const T *>(r); |
| return *lhs == *rhs; |
| } |
| |
| static void destroy(AbstractComparatorFunction *_this) |
| { |
| delete static_cast<BuiltInEqualsComparatorFunction *>(_this); |
| } |
| }; |
| |
| struct AbstractConverterFunction |
| { |
| typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*); |
| explicit AbstractConverterFunction(Converter c = 0) |
| : convert(c) {} |
| Q_DISABLE_COPY(AbstractConverterFunction) |
| Converter convert; |
| }; |
| |
| template<typename From, typename To> |
| struct ConverterMemberFunction : public AbstractConverterFunction |
| { |
| explicit ConverterMemberFunction(To(From::*function)() const) |
| : AbstractConverterFunction(convert), |
| m_function(function) {} |
| ~ConverterMemberFunction(); |
| static bool convert(const AbstractConverterFunction *_this, const void *in, void *out) |
| { |
| const From *f = static_cast<const From *>(in); |
| To *t = static_cast<To *>(out); |
| const ConverterMemberFunction *_typedThis = |
| static_cast<const ConverterMemberFunction *>(_this); |
| *t = (f->*_typedThis->m_function)(); |
| return true; |
| } |
| |
| To(From::* const m_function)() const; |
| }; |
| |
| template<typename From, typename To> |
| struct ConverterMemberFunctionOk : public AbstractConverterFunction |
| { |
| explicit ConverterMemberFunctionOk(To(From::*function)(bool *) const) |
| : AbstractConverterFunction(convert), |
| m_function(function) {} |
| ~ConverterMemberFunctionOk(); |
| static bool convert(const AbstractConverterFunction *_this, const void *in, void *out) |
| { |
| const From *f = static_cast<const From *>(in); |
| To *t = static_cast<To *>(out); |
| bool ok = false; |
| const ConverterMemberFunctionOk *_typedThis = |
| static_cast<const ConverterMemberFunctionOk *>(_this); |
| *t = (f->*_typedThis->m_function)(&ok); |
| if (!ok) |
| *t = To(); |
| return ok; |
| } |
| |
| To(From::* const m_function)(bool*) const; |
| }; |
| |
| template<typename From, typename To, typename UnaryFunction> |
| struct ConverterFunctor : public AbstractConverterFunction |
| { |
| explicit ConverterFunctor(UnaryFunction function) |
| : AbstractConverterFunction(convert), |
| m_function(function) {} |
| ~ConverterFunctor(); |
| static bool convert(const AbstractConverterFunction *_this, const void *in, void *out) |
| { |
| const From *f = static_cast<const From *>(in); |
| To *t = static_cast<To *>(out); |
| const ConverterFunctor *_typedThis = |
| static_cast<const ConverterFunctor *>(_this); |
| *t = _typedThis->m_function(*f); |
| return true; |
| } |
| |
| UnaryFunction m_function; |
| }; |
| |
| template<typename T, bool> |
| struct ValueTypeIsMetaType; |
| template<typename T, bool> |
| struct AssociativeValueTypeIsMetaType; |
| template<typename T, bool> |
| struct IsMetaTypePair; |
| template<typename, typename> |
| struct MetaTypeSmartPointerHelper; |
| } |
| |
| 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_QDOC |
| // The code that actually gets compiled. |
| enum Type { |
| // these are merged with QVariant |
| QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID) |
| |
| FirstCoreType = Bool, |
| LastCoreType = QPersistentModelIndex, |
| FirstGuiType = QFont, |
| LastGuiType = QPolygonF, |
| FirstWidgetsType = QSizePolicy, |
| LastWidgetsType = QSizePolicy, |
| HighestInternalId = LastWidgetsType, |
| |
| QReal = sizeof(qreal) == sizeof(double) ? Double : Float, |
| |
| UnknownType = 0, |
| User = 1024 |
| }; |
| #else |
| // If we are using QDoc it fakes the Type enum looks like this. |
| enum Type { |
| UnknownType = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5, |
| Double = 6, Long = 32, Short = 33, Char = 34, ULong = 35, UShort = 36, |
| UChar = 37, Float = 38, |
| VoidStar = 31, |
| QChar = 7, QString = 10, QStringList = 11, QByteArray = 12, |
| QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17, |
| QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22, |
| QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26, QRegExp = 27, |
| QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42, |
| QPersistentModelIndex = 50, QRegularExpression = 44, |
| QJsonValue = 45, QJsonObject = 46, QJsonArray = 47, QJsonDocument = 48, |
| QByteArrayList = 49, QObjectStar = 39, SChar = 40, |
| Void = 43, |
| QVariantMap = 8, QVariantList = 9, QVariantHash = 28, |
| QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68, |
| QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73, |
| QCursor = 74, QKeySequence = 75, QPen = 76, QTextLength = 77, QTextFormat = 78, |
| QMatrix = 79, QTransform = 80, QMatrix4x4 = 81, QVector2D = 82, |
| QVector3D = 83, QVector4D = 84, QQuaternion = 85, QPolygonF = 86, |
| QSizePolicy = 121, |
| User = 1024 |
| }; |
| #endif |
| |
| enum TypeFlag { |
| NeedsConstruction = 0x1, |
| NeedsDestruction = 0x2, |
| MovableType = 0x4, |
| PointerToQObject = 0x8, |
| IsEnumeration = 0x10, |
| SharedPointerToQObject = 0x20, |
| WeakPointerToQObject = 0x40, |
| TrackingPointerToQObject = 0x80, |
| WasDeclaredAsMetaType = 0x100, |
| IsGadget = 0x200 |
| }; |
| Q_DECLARE_FLAGS(TypeFlags, TypeFlag) |
| |
| typedef void (*Deleter)(void *); |
| typedef void *(*Creator)(const void *); |
| |
| typedef void (*Destructor)(void *); |
| typedef void *(*Constructor)(void *, const void *); |
| |
| typedef void (*SaveOperator)(QDataStream &, const void *); |
| typedef void (*LoadOperator)(QDataStream &, void *); |
| #ifndef QT_NO_DATASTREAM |
| static void registerStreamOperators(const char *typeName, SaveOperator saveOp, |
| LoadOperator loadOp); |
| 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 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 registerTypedef(const char *typeName, int aliasId); |
| static int registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, int aliasId); |
| static int type(const char *typeName); |
| #ifndef Q_QDOC |
| static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName); |
| #else |
| static int type(const QByteArray &typeName); |
| #endif |
| static const char *typeName(int type); |
| static int sizeOf(int type); |
| static TypeFlags typeFlags(int type); |
| static const QMetaObject *metaObjectForType(int type); |
| static bool isRegistered(int type); |
| static void *create(int type, const void *copy = 0); |
| #if QT_DEPRECATED_SINCE(5, 0) |
| QT_DEPRECATED static void *construct(int type, const void *copy = 0) |
| { 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); |
| |
| #ifndef QT_NO_DATASTREAM |
| static bool save(QDataStream &stream, int type, const void *data); |
| static bool load(QDataStream &stream, int type, void *data); |
| #endif |
| |
| explicit QMetaType(const int type); |
| inline ~QMetaType(); |
| |
| inline bool isValid() const; |
| inline bool isRegistered() const; |
| inline int sizeOf() const; |
| inline TypeFlags flags() const; |
| inline const QMetaObject *metaObject() const; |
| |
| inline void *create(const void *copy = 0) const; |
| inline void destroy(void *data) const; |
| inline void *construct(void *where, const void *copy = 0) const; |
| inline void destruct(void *data) const; |
| |
| public: |
| template<typename T> |
| static bool registerComparators() |
| { |
| Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn), |
| "QMetaType::registerComparators: The type must be a custom type."); |
| |
| const int typeId = qMetaTypeId<T>(); |
| static const QtPrivate::BuiltInComparatorFunction<T> f; |
| return registerComparatorFunction( &f, typeId); |
| } |
| template<typename T> |
| static bool registerEqualsComparator() |
| { |
| Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn), |
| "QMetaType::registerEqualsComparator: The type must be a custom type."); |
| const int typeId = qMetaTypeId<T>(); |
| static const QtPrivate::BuiltInEqualsComparatorFunction<T> f; |
| return registerComparatorFunction( &f, typeId); |
| } |
| |
| template<typename T> |
| static bool hasRegisteredComparators() |
| { |
| return hasRegisteredComparators(qMetaTypeId<T>()); |
| } |
| static bool hasRegisteredComparators(int typeId); |
| |
| |
| #ifndef QT_NO_DEBUG_STREAM |
| template<typename T> |
| static bool registerDebugStreamOperator() |
| { |
| Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn), |
| "QMetaType::registerDebugStreamOperator: The type must be a custom type."); |
| |
| const int typeId = qMetaTypeId<T>(); |
| static const QtPrivate::BuiltInDebugStreamFunction<T> f; |
| return registerDebugStreamOperatorFunction(&f, typeId); |
| } |
| template<typename T> |
| static bool hasRegisteredDebugStreamOperator() |
| { |
| return hasRegisteredDebugStreamOperator(qMetaTypeId<T>()); |
| } |
| static bool hasRegisteredDebugStreamOperator(int typeId); |
| #endif |
| |
| // implicit conversion supported like double -> float |
| template<typename From, typename To> |
| static bool registerConverter() |
| { |
| return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>); |
| } |
| |
| #ifdef Q_QDOC |
| static bool registerConverter(MemberFunction function); |
| static bool registerConverter(MemberFunctionOk function); |
| static bool registerConverter(UnaryFunction function); |
| #else |
| // member function as in "QString QFont::toString() const" |
| template<typename From, typename To> |
| static bool registerConverter(To(From::*function)() const) |
| { |
| Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn), |
| "QMetaType::registerConverter: At least one of the types must be a custom type."); |
| |
| const int fromTypeId = qMetaTypeId<From>(); |
| const int toTypeId = qMetaTypeId<To>(); |
| static const QtPrivate::ConverterMemberFunction<From, To> f(function); |
| return registerConverterFunction(&f, fromTypeId, toTypeId); |
| } |
| |
| // member function as in "double QString::toDouble(bool *ok = 0) const" |
| template<typename From, typename To> |
| static bool registerConverter(To(From::*function)(bool*) const) |
| { |
| Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn), |
| "QMetaType::registerConverter: At least one of the types must be a custom type."); |
| |
| const int fromTypeId = qMetaTypeId<From>(); |
| const int toTypeId = qMetaTypeId<To>(); |
| static const QtPrivate::ConverterMemberFunctionOk<From, To> f(function); |
| return registerConverterFunction(&f, fromTypeId, toTypeId); |
| } |
| |
| // functor or function pointer |
| template<typename From, typename To, typename UnaryFunction> |
| static bool registerConverter(UnaryFunction function) |
| { |
| Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn), |
| "QMetaType::registerConverter: At least one of the types must be a custom type."); |
| |
| const int fromTypeId = qMetaTypeId<From>(); |
| const int toTypeId = qMetaTypeId<To>(); |
| static const QtPrivate::ConverterFunctor<From, To, UnaryFunction> f(function); |
| return registerConverterFunction(&f, fromTypeId, toTypeId); |
| } |
| #endif |
| |
| static bool convert(const void *from, int fromTypeId, void *to, int toTypeId); |
| static bool compare(const void *lhs, const void *rhs, int typeId, int* result); |
| static bool equals(const void *lhs, const void *rhs, int typeId, int* result); |
| static bool debugStream(QDebug& dbg, const void *rhs, int typeId); |
| |
| template<typename From, typename To> |
| static bool hasRegisteredConverterFunction() |
| { |
| return hasRegisteredConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>()); |
| } |
| |
| static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId); |
| |
| private: |
| static QMetaType typeInfo(const int type); |
| inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info, |
| Creator creator, |
| Deleter 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 = 0) const; |
| void destroyExtended(void *data) const; |
| void *constructExtended(void *where, const void *copy = 0) 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_QDOC |
| template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType; |
| template<typename, typename> friend struct QtPrivate::ConverterMemberFunction; |
| template<typename, typename> friend struct QtPrivate::ConverterMemberFunctionOk; |
| template<typename, typename, typename> friend struct QtPrivate::ConverterFunctor; |
| template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType; |
| 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: |
| |
| Creator m_creator_unused; |
| Deleter m_deleter_unused; |
| 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; |
| }; |
| |
| #undef QT_DEFINE_METATYPE_ID |
| |
| Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags) |
| |
| namespace QtPrivate { |
| |
| template<typename From, typename To> |
| ConverterMemberFunction<From, To>::~ConverterMemberFunction() |
| { |
| QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>()); |
| } |
| template<typename From, typename To> |
| ConverterMemberFunctionOk<From, To>::~ConverterMemberFunctionOk() |
| { |
| QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>()); |
| } |
| template<typename From, typename To, typename UnaryFunction> |
| ConverterFunctor<From, To, UnaryFunction>::~ConverterFunctor() |
| { |
| QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>()); |
| } |
| |
| } |
| |
| namespace QtMetaTypePrivate { |
| template <typename T, bool Accepted = true> |
| struct QMetaTypeFunctionHelper { |
| static void Destruct(void *t) |
| { |
| Q_UNUSED(t) // Silence MSVC that warns for POD types. |
| static_cast<T*>(t)->~T(); |
| } |
| |
| static void *Construct(void *where, const void *t) |
| { |
| if (t) |
| return new (where) T(*static_cast<const T*>(t)); |
| return new (where) T; |
| } |
| #ifndef QT_NO_DATASTREAM |
| static void Save(QDataStream &stream, const void *t) |
| { |
| stream << *static_cast<const T*>(t); |
| } |
| |
| static void Load(QDataStream &stream, void *t) |
| { |
| stream >> *static_cast<T*>(t); |
| } |
| #endif // QT_NO_DATASTREAM |
| }; |
| |
| template <typename T> |
| struct QMetaTypeFunctionHelper<T, /* Accepted */ false> { |
| static void Destruct(void *) {} |
| static void *Construct(void *, const void *) { return 0; } |
| #ifndef QT_NO_DATASTREAM |
| static void Save(QDataStream &, const void *) {} |
| static void Load(QDataStream &, void *) {} |
| #endif // QT_NO_DATASTREAM |
| }; |
| template <> |
| struct QMetaTypeFunctionHelper<void, /* Accepted */ true> |
| : public QMetaTypeFunctionHelper<void, /* Accepted */ false> |
| {}; |
| |
| struct VariantData |
| { |
| VariantData(const int metaTypeId_, |
| const void *data_, |
| const uint flags_) |
| : metaTypeId(metaTypeId_) |
| , data(data_) |
| , flags(flags_) |
| { |
| } |
| VariantData(const VariantData &other) |
| : metaTypeId(other.metaTypeId), data(other.data), flags(other.flags){} |
| const int metaTypeId; |
| const void *data; |
| const uint flags; |
| private: |
| // copy constructor allowed to be implicit to silence level 4 warning from MSVC |
| VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE; |
| }; |
| |
| template<typename const_iterator> |
| struct IteratorOwnerCommon |
| { |
| static void assign(void **ptr, const_iterator iterator) |
| { |
| *ptr = new const_iterator(iterator); |
| } |
| static void assign(void **ptr, void * const * src) |
| { |
| *ptr = new const_iterator(*static_cast<const_iterator*>(*src)); |
| } |
| |
| static void advance(void **iterator, int step) |
| { |
| const_iterator &it = *static_cast<const_iterator*>(*iterator); |
| std::advance(it, step); |
| } |
| |
| static void destroy(void **ptr) |
| { |
| delete static_cast<const_iterator*>(*ptr); |
| } |
| |
| static bool equal(void * const *it, void * const *other) |
| { |
| return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other); |
| } |
| }; |
| |
| template<typename const_iterator> |
| struct IteratorOwner : IteratorOwnerCommon<const_iterator> |
| { |
| static const void *getData(void * const *iterator) |
| { |
| return &**static_cast<const_iterator*>(*iterator); |
| } |
| |
| static const void *getData(const_iterator it) |
| { |
| return &*it; |
| } |
| }; |
| |
| struct Q_CORE_EXPORT VectorBoolElements |
| { |
| static const bool true_element; |
| static const bool false_element; |
| }; |
| |
| template<> |
| struct IteratorOwner<std::vector<bool>::const_iterator> : IteratorOwnerCommon<std::vector<bool>::const_iterator> |
| { |
| public: |
| static const void *getData(void * const *iterator) |
| { |
| return **static_cast<std::vector<bool>::const_iterator*>(*iterator) ? |
| &VectorBoolElements::true_element : &VectorBoolElements::false_element; |
| } |
| |
| static const void *getData(const std::vector<bool>::const_iterator& it) |
| { |
| return *it ? &VectorBoolElements::true_element : &VectorBoolElements::false_element; |
| } |
| }; |
| |
| template<typename value_type> |
| struct IteratorOwner<const value_type*> |
| { |
| private: |
| // We need to disable typed overloads of assign() and getData() if the value_type |
| // is void* to avoid overloads conflicts. We do it by injecting unaccessible Dummy |
| // type as part of the overload signature. |
| struct Dummy {}; |
| typedef typename QtPrivate::if_<QtPrivate::is_same<value_type, void*>::value, Dummy, value_type>::type value_type_OR_Dummy; |
| public: |
| static void assign(void **ptr, const value_type_OR_Dummy *iterator ) |
| { |
| *ptr = const_cast<value_type*>(iterator); |
| } |
| static void assign(void **ptr, void * const * src) |
| { |
| *ptr = static_cast<value_type*>(*src); |
| } |
| |
| static void advance(void **iterator, int step) |
| { |
| value_type *it = static_cast<value_type*>(*iterator); |
| std::advance(it, step); |
| *iterator = it; |
| } |
| |
| static void destroy(void **) |
| { |
| } |
| |
| static const void *getData(void * const *iterator) |
| { |
| return *iterator; |
| } |
| |
| static const void *getData(const value_type_OR_Dummy *it) |
| { |
| return it; |
| } |
| |
| static bool equal(void * const *it, void * const *other) |
| { |
| return static_cast<value_type*>(*it) == static_cast<value_type*>(*other); |
| } |
| }; |
| |
| enum IteratorCapability |
| { |
| ForwardCapability = 1, |
| BiDirectionalCapability = 2, |
| RandomAccessCapability = 4 |
| }; |
| |
| template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category> |
| struct CapabilitiesImpl; |
| |
| template<typename T> |
| struct CapabilitiesImpl<T, std::forward_iterator_tag> |
| { enum { IteratorCapabilities = ForwardCapability }; }; |
| template<typename T> |
| struct CapabilitiesImpl<T, std::bidirectional_iterator_tag> |
| { enum { IteratorCapabilities = BiDirectionalCapability | ForwardCapability }; }; |
| template<typename T> |
| struct CapabilitiesImpl<T, std::random_access_iterator_tag> |
| { enum { IteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability }; }; |
| |
| template<typename T> |
| struct ContainerAPI : CapabilitiesImpl<T> |
| { |
| static int size(const T *t) { return int(std::distance(t->begin(), t->end())); } |
| }; |
| |
| 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(); } }; |
| |
| template<typename T> |
| struct ContainerAPI<std::vector<T> > : CapabilitiesImpl<std::vector<T> > |
| { static int size(const std::vector<T> *t) { return int(t->size()); } }; |
| |
| template<typename T> |
| struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> > |
| { static int size(const std::list<T> *t) { return int(t->size()); } }; |
| |
| class QSequentialIterableImpl |
| { |
| public: |
| const void * _iterable; |
| void *_iterator; |
| int _metaType_id; |
| uint _metaType_flags; |
| uint _iteratorCapabilities; |
| typedef int(*sizeFunc)(const void *p); |
| typedef const void * (*atFunc)(const void *p, int); |
| typedef void (*moveIteratorFunc)(const void *p, void **); |
| typedef void (*advanceFunc)(void **p, int); |
| typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags); |
| typedef void (*destroyIterFunc)(void **p); |
| typedef bool (*equalIterFunc)(void * const *p, void * const *other); |
| typedef void (*copyIterFunc)(void **, void * const *); |
| |
| sizeFunc _size; |
| atFunc _at; |
| moveIteratorFunc _moveToBegin; |
| moveIteratorFunc _moveToEnd; |
| advanceFunc _advance; |
| getFunc _get; |
| destroyIterFunc _destroyIter; |
| equalIterFunc _equalIter; |
| copyIterFunc _copyIter; |
| |
| template<class T> |
| static int sizeImpl(const void *p) |
| { return ContainerAPI<T>::size(static_cast<const T*>(p)); } |
| |
| template<class T> |
| static const void* atImpl(const void *p, int idx) |
| { |
| typename T::const_iterator i = static_cast<const T*>(p)->begin(); |
| std::advance(i, idx); |
| return IteratorOwner<typename T::const_iterator>::getData(i); |
| } |
| |
| template<class T> |
| static void moveToBeginImpl(const void *container, void **iterator) |
| { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); } |
| |
| template<class T> |
| static void moveToEndImpl(const void *container, void **iterator) |
| { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); } |
| |
| template<class T> |
| static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags) |
| { return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); } |
| |
| public: |
| template<class T> QSequentialIterableImpl(const T*p) |
| : _iterable(p) |
| , _iterator(0) |
| , _metaType_id(qMetaTypeId<typename T::value_type>()) |
| , _metaType_flags(QTypeInfo<typename T::value_type>::isPointer) |
| , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities) |
| , _size(sizeImpl<T>) |
| , _at(atImpl<T>) |
| , _moveToBegin(moveToBeginImpl<T>) |
| , _moveToEnd(moveToEndImpl<T>) |
| , _advance(IteratorOwner<typename T::const_iterator>::advance) |
| , _get(getImpl<T>) |
| , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy) |
| , _equalIter(IteratorOwner<typename T::const_iterator>::equal) |
| , _copyIter(IteratorOwner<typename T::const_iterator>::assign) |
| { |
| } |
| |
| QSequentialIterableImpl() |
| : _iterable(0) |
| , _iterator(0) |
| , _metaType_id(QMetaType::UnknownType) |
| , _metaType_flags(0) |
| , _iteratorCapabilities(0) |
| , _size(0) |
| , _at(0) |
| , _moveToBegin(0) |
| , _moveToEnd(0) |
| , _advance(0) |
| , _get(0) |
| , _destroyIter(0) |
| , _equalIter(0) |
| , _copyIter(0) |
| { |
| } |
| |
| inline void moveToBegin() { _moveToBegin(_iterable, &_iterator); } |
| inline void moveToEnd() { _moveToEnd(_iterable, &_iterator); } |
| inline bool equal(const QSequentialIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); } |
| inline QSequentialIterableImpl &advance(int i) { |
| Q_ASSERT(i > 0 || _iteratorCapabilities & BiDirectionalCapability); |
| _advance(&_iterator, i); |
| return *this; |
| } |
| |
| inline VariantData getCurrent() const { return _get(&_iterator, _metaType_id, _metaType_flags); } |
| |
| VariantData at(int idx) const |
| { return VariantData(_metaType_id, _at(_iterable, idx), _metaType_flags); } |
| |
| int size() const { Q_ASSERT(_iterable); return _size(_iterable); } |
| |
| inline void destroyIter() { _destroyIter(&_iterator); } |
| |
| void copy(const QSequentialIterableImpl &other) |
| { |
| *this = other; |
| _copyIter(&_iterator, &other._iterator); |
| } |
| }; |
| |
| template<typename From> |
| struct QSequentialIterableConvertFunctor |
| { |
| QSequentialIterableImpl operator()(const From &f) const |
| { |
| return QSequentialIterableImpl(&f); |
| } |
| }; |
| } |
| |
| namespace QtMetaTypePrivate { |
| template<typename T, bool = QtPrivate::is_same<typename T::const_iterator::value_type, typename T::mapped_type>::value> |
| struct AssociativeContainerAccessor |
| { |
| static const typename T::key_type& getKey(const typename T::const_iterator &it) |
| { |
| return it.key(); |
| } |
| |
| static const typename T::mapped_type& getValue(const typename T::const_iterator &it) |
| { |
| return it.value(); |
| } |
| }; |
| |
| template<typename T, bool = QtPrivate::is_same<typename T::const_iterator::value_type, std::pair<const typename T::key_type, typename T::mapped_type> >::value> |
| struct StlStyleAssociativeContainerAccessor; |
| |
| template<typename T> |
| struct StlStyleAssociativeContainerAccessor<T, true> |
| { |
| static const typename T::key_type& getKey(const typename T::const_iterator &it) |
| { |
| return it->first; |
| } |
| |
| static const typename T::mapped_type& getValue(const typename T::const_iterator &it) |
| { |
| return it->second; |
| } |
| }; |
| |
| template<typename T> |
| struct AssociativeContainerAccessor<T, false> : public StlStyleAssociativeContainerAccessor<T> |
| { |
| }; |
| |
| class QAssociativeIterableImpl |
| { |
| public: |
| const void *_iterable; |
| void *_iterator; |
| int _metaType_id_key; |
| uint _metaType_flags_key; |
| int _metaType_id_value; |
| uint _metaType_flags_value; |
| typedef int(*sizeFunc)(const void *p); |
| typedef void (*findFunc)(const void *container, const void *p, void **iterator); |
| typedef void (*beginFunc)(const void *p, void **); |
| typedef void (*advanceFunc)(void **p, int); |
| typedef VariantData (*getFunc)(void * const *p, int metaTypeId, uint flags); |
| typedef void (*destroyIterFunc)(void **p); |
| typedef bool (*equalIterFunc)(void * const *p, void * const *other); |
| typedef void (*copyIterFunc)(void **, void * const *); |
| |
| sizeFunc _size; |
| findFunc _find; |
| beginFunc _begin; |
| beginFunc _end; |
| advanceFunc _advance; |
| getFunc _getKey; |
| getFunc _getValue; |
| destroyIterFunc _destroyIter; |
| equalIterFunc _equalIter; |
| copyIterFunc _copyIter; |
| |
| template<class T> |
| static int sizeImpl(const void *p) |
| { return int(std::distance(static_cast<const T*>(p)->begin(), |
| static_cast<const T*>(p)->end())); } |
| |
| template<class T> |
| static void findImpl(const void *container, const void *p, void **iterator) |
| { IteratorOwner<typename T::const_iterator>::assign(iterator, |
| static_cast<const T*>(container)->find(*static_cast<const typename T::key_type*>(p))); } |
| |
| template<class T> |
| static void advanceImpl(void **p, int step) |
| { std::advance(*static_cast<typename T::const_iterator*>(*p), step); } |
| |
| template<class T> |
| static void beginImpl(const void *container, void **iterator) |
| { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); } |
| |
| template<class T> |
| static void endImpl(const void *container, void **iterator) |
| { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); } |
| |
| template<class T> |
| static VariantData getKeyImpl(void * const *iterator, int metaTypeId, uint flags) |
| { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getKey(*static_cast<typename T::const_iterator*>(*iterator)), flags); } |
| |
| template<class T> |
| static VariantData getValueImpl(void * const *iterator, int metaTypeId, uint flags) |
| { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getValue(*static_cast<typename T::const_iterator*>(*iterator)), flags); } |
| |
| public: |
| template<class T> QAssociativeIterableImpl(const T*p) |
| : _iterable(p) |
| , _metaType_id_key(qMetaTypeId<typename T::key_type>()) |
| , _metaType_flags_key(QTypeInfo<typename T::key_type>::isPointer) |
| , _metaType_id_value(qMetaTypeId<typename T::mapped_type>()) |
| , _metaType_flags_value(QTypeInfo<typename T::mapped_type>::isPointer) |
| , _size(sizeImpl<T>) |
| , _find(findImpl<T>) |
| , _begin(beginImpl<T>) |
| , _end(endImpl<T>) |
| , _advance(advanceImpl<T>) |
| , _getKey(getKeyImpl<T>) |
| , _getValue(getValueImpl<T>) |
| , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy) |
| , _equalIter(IteratorOwner<typename T::const_iterator>::equal) |
| , _copyIter(IteratorOwner<typename T::const_iterator>::assign) |
| { |
| } |
| |
| QAssociativeIterableImpl() |
| : _iterable(0) |
| , _metaType_id_key(QMetaType::UnknownType) |
| , _metaType_flags_key(0) |
| , _metaType_id_value(QMetaType::UnknownType) |
| , _metaType_flags_value(0) |
| , _size(0) |
| , _find(0) |
| , _begin(0) |
| , _end(0) |
| , _advance(0) |
| , _getKey(0) |
| , _getValue(0) |
| , _destroyIter(0) |
| , _equalIter(0) |
| , _copyIter(0) |
| { |
| } |
| |
| inline void begin() { _begin(_iterable, &_iterator); } |
| inline void end() { _end(_iterable, &_iterator); } |
| inline bool equal(const QAssociativeIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); } |
| inline QAssociativeIterableImpl &advance(int i) { _advance(&_iterator, i); return *this; } |
| |
| inline void destroyIter() { _destroyIter(&_iterator); } |
| |
| inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_value); } |
| inline VariantData getCurrentValue() const { return _getValue(&_iterator, _metaType_id_value, _metaType_flags_value); } |
| |
| inline void find(const VariantData &key) |
| { _find(_iterable, key.data, &_iterator); } |
| |
| int size() const { Q_ASSERT(_iterable); return _size(_iterable); } |
| |
| void copy(const QAssociativeIterableImpl &other) |
| { |
| *this = other; |
| _copyIter(&_iterator, &other._iterator); |
| } |
| }; |
| |
| template<typename From> |
| struct QAssociativeIterableConvertFunctor |
| { |
| QAssociativeIterableImpl operator()(const From& f) const |
| { |
| return QAssociativeIterableImpl(&f); |
| } |
| }; |
| |
| class QPairVariantInterfaceImpl |
| { |
| const void *_pair; |
| int _metaType_id_first; |
| uint _metaType_flags_first; |
| int _metaType_id_second; |
| uint _metaType_flags_second; |
| |
| typedef VariantData (*getFunc)(const void * const *p, int metaTypeId, uint flags); |
| |
| getFunc _getFirst; |
| getFunc _getSecond; |
| |
| template<class T> |
| static VariantData getFirstImpl(const void * const *pair, int metaTypeId, uint flags) |
| { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->first, flags); } |
| template<class T> |
| static VariantData getSecondImpl(const void * const *pair, int metaTypeId, uint flags) |
| { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->second, flags); } |
| |
| public: |
| template<class T> QPairVariantInterfaceImpl(const T*p) |
| : _pair(p) |
| , _metaType_id_first(qMetaTypeId<typename T::first_type>()) |
| , _metaType_flags_first(QTypeInfo<typename T::first_type>::isPointer) |
| , _metaType_id_second(qMetaTypeId<typename T::second_type>()) |
| , _metaType_flags_second(QTypeInfo<typename T::second_type>::isPointer) |
| , _getFirst(getFirstImpl<T>) |
| , _getSecond(getSecondImpl<T>) |
| { |
| } |
| |
| QPairVariantInterfaceImpl() |
| : _pair(0) |
| , _getFirst(0) |
| , _getSecond(0) |
| { |
| } |
| |
| inline VariantData first() const { return _getFirst(&_pair, _metaType_id_first, _metaType_flags_first); } |
| inline VariantData second() const { return _getSecond(&_pair, _metaType_id_second, _metaType_flags_second); } |
| }; |
| |
| template<typename From> |
| struct QPairVariantInterfaceConvertFunctor; |
| |
| template<typename T, typename U> |
| struct QPairVariantInterfaceConvertFunctor<QPair<T, U> > |
| { |
| QPairVariantInterfaceImpl operator()(const QPair<T, U>& f) const |
| { |
| return QPairVariantInterfaceImpl(&f); |
| } |
| }; |
| |
| template<typename T, typename U> |
| struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> > |
| { |
| QPairVariantInterfaceImpl operator()(const std::pair<T, U>& f) const |
| { |
| return QPairVariantInterfaceImpl(&f); |
| } |
| }; |
| |
| } |
| |
| class QObject; |
| class QWidget; |
| |
| #define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name) \ |
| template <class T> class Name; \ |
| |
| QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER) |
| |
| namespace QtPrivate |
| { |
| template<typename T> |
| struct IsPointerToTypeDerivedFromQObject |
| { |
| enum { Value = false }; |
| }; |
| |
| // Specialize to avoid sizeof(void) warning |
| template<> |
| struct IsPointerToTypeDerivedFromQObject<void*> |
| { |
| enum { Value = false }; |
| }; |
| template<> |
| struct IsPointerToTypeDerivedFromQObject<const void*> |
| { |
| enum { Value = false }; |
| }; |
| template<> |
| struct IsPointerToTypeDerivedFromQObject<QObject*> |
| { |
| enum { Value = true }; |
| }; |
| |
| template<typename T> |
| struct IsPointerToTypeDerivedFromQObject<T*> |
| { |
| typedef qint8 yes_type; |
| typedef qint64 no_type; |
| |
| #ifndef QT_NO_QOBJECT |
| static yes_type checkType(QObject* ); |
| #endif |
| static no_type checkType(...); |
| Q_STATIC_ASSERT_X(sizeof(T), "Type argument of Q_DECLARE_METATYPE(T*) must be fully defined"); |
| enum { Value = sizeof(checkType(static_cast<T*>(0))) == sizeof(yes_type) }; |
| }; |
| |
| template<typename T, typename Enable = void> |
| struct IsGadgetHelper { enum { Value = false }; }; |
| |
| template<typename T> |
| struct IsGadgetHelper<T, typename T::QtGadgetHelper> |
| { |
| template <typename X> |
| static char checkType(void (X::*)()); |
| static void *checkType(void (T::*)()); |
| enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) }; |
| }; |
| |
| |
| QT_WARNING_PUSH |
| // In C++03 mode, clang consider local or unnamed type and throw a warning instead of ignoring them |
| QT_WARNING_DISABLE_CLANG("-Wunnamed-type-template-args") |
| QT_WARNING_DISABLE_CLANG("-Wlocal-type-template-args") |
| template<typename T> char qt_getEnumMetaObject(const T&); |
| |
| template<typename T> |
| struct IsQEnumHelper { |
| static const T &declval(); |
| // If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject() declared in the |
| // Q_ENUM macro will be chosen by ADL, and the return type will be QMetaObject*. |
| // Otherwise the chosen overload will be the catch all template function |
| // qt_getEnumMetaObject(T) which returns 'char' |
| enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) }; |
| }; |
| template<> struct IsQEnumHelper<void> { enum { Value = false }; }; |
| QT_WARNING_POP |
| |
| template<typename T, typename Enable = void> |
| struct MetaObjectForType |
| { |
| static inline const QMetaObject *value() { return 0; } |
| }; |
| template<> |
| struct MetaObjectForType<void> |
| { |
| static inline const QMetaObject *value() { return Q_NULLPTR; } |
| }; |
| template<typename T> |
| struct MetaObjectForType<T*, typename QEnableIf<IsPointerToTypeDerivedFromQObject<T*>::Value>::Type> |
| { |
| static inline const QMetaObject *value() { return &T::staticMetaObject; } |
| }; |
| template<typename T> |
| struct MetaObjectForType<T, typename QEnableIf<IsGadgetHelper<T>::Value>::Type> |
| { |
| static inline const QMetaObject *value() { return &T::staticMetaObject; } |
| }; |
| template<typename T> |
| struct MetaObjectForType<T, typename QEnableIf<IsQEnumHelper<T>::Value>::Type > |
| { |
| static inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); } |
| }; |
| |
| template<typename T> |
| struct IsSharedPointerToTypeDerivedFromQObject |
| { |
| enum { Value = false }; |
| }; |
| |
| template<typename T> |
| struct IsSharedPointerToTypeDerivedFromQObject<QSharedPointer<T> > : IsPointerToTypeDerivedFromQObject<T*> |
| { |
| }; |
| |
| template<typename T> |
| struct IsWeakPointerToTypeDerivedFromQObject |
| { |
| enum { Value = false }; |
| }; |
| |
| template<typename T> |
| struct IsWeakPointerToTypeDerivedFromQObject<QWeakPointer<T> > : IsPointerToTypeDerivedFromQObject<T*> |
| { |
| }; |
| |
| template<typename T> |
| struct IsTrackingPointerToTypeDerivedFromQObject |
| { |
| enum { Value = false }; |
| }; |
| |
| template<typename T> |
| struct IsTrackingPointerToTypeDerivedFromQObject<QPointer<T> > |
| { |
| enum { Value = true }; |
| }; |
| |
| template<typename T> |
| struct IsSequentialContainer |
| { |
| enum { Value = false }; |
| }; |
| |
| template<typename T> |
| struct IsAssociativeContainer |
| { |
| enum { Value = false }; |
| }; |
| |
| template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value> |
| struct SequentialContainerConverterHelper |
| { |
| static bool registerConverter(int) |
| { |
| return false; |
| } |
| }; |
| |
| template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined> |
| struct ValueTypeIsMetaType |
| { |
| static bool registerConverter(int) |
| { |
| return false; |
| } |
| }; |
| |
| template<typename T> |
| struct SequentialContainerConverterHelper<T, true> : ValueTypeIsMetaType<T> |
| { |
| }; |
| |
| template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value> |
| struct AssociativeContainerConverterHelper |
| { |
| static bool registerConverter(int) |
| { |
| return false; |
| } |
| }; |
| |
| template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined> |
| struct AssociativeValueTypeIsMetaType |
| { |
| static bool registerConverter(int) |
| { |
| return false; |
| } |
| }; |
| |
| template<typename T, bool = QMetaTypeId2<typename T::key_type>::Defined> |
| struct KeyAndValueTypeIsMetaType |
| { |
| static bool registerConverter(int) |
| { |
| return false; |
| } |
| }; |
| |
| template<typename T> |
| struct KeyAndValueTypeIsMetaType<T, true> : AssociativeValueTypeIsMetaType<T> |
| { |
| }; |
| |
| template<typename T> |
| struct AssociativeContainerConverterHelper<T, true> : KeyAndValueTypeIsMetaType<T> |
| { |
| }; |
| |
| template<typename T, bool = QMetaTypeId2<typename T::first_type>::Defined |
| && QMetaTypeId2<typename T::second_type>::Defined> |
| struct IsMetaTypePair |
| { |
| static bool registerConverter(int) |
| { |
| return false; |
| } |
| }; |
| |
| template<typename T> |
| struct IsMetaTypePair<T, true> |
| { |
| inline static bool registerConverter(int id); |
| }; |
| |
| template<typename T> |
| struct IsPair |
| { |
| static bool registerConverter(int) |
| { |
| return false; |
| } |
| }; |
| template<typename T, typename U> |
| struct IsPair<QPair<T, U> > : IsMetaTypePair<QPair<T, U> > {}; |
| template<typename T, typename U> |
| struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {}; |
| |
| template<typename T> |
| struct MetaTypePairHelper : IsPair<T> {}; |
| |
| template<typename T, typename = void> |
| struct MetaTypeSmartPointerHelper |
| { |
| static bool registerConverter(int) { return false; } |
| }; |
| |
| Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type); |
| } // namespace QtPrivate |
| |
| template <typename T, int = |
| QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : |
| QtPrivate::IsGadgetHelper<T>::Value ? QMetaType::IsGadget : |
| QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0> |
| struct QMetaTypeIdQObject |
| { |
| enum { |
| Defined = 0 |
| }; |
| }; |
| |
| template <typename T> |
| struct QMetaTypeId : public QMetaTypeIdQObject<T> |
| { |
| }; |
| |
| template <typename T> |
| struct QMetaTypeId2 |
| { |
| enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false }; |
| static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); } |
| }; |
| |
| template <typename T> |
| struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {}; |
| |
| template <typename T> |
| struct QMetaTypeId2<T&> { enum {Defined = false }; }; |
| |
| namespace QtPrivate { |
| template <typename T, bool Defined = QMetaTypeId2<T>::Defined> |
| struct QMetaTypeIdHelper { |
| static inline Q_DECL_CONSTEXPR int qt_metatype_id() |
| { return QMetaTypeId2<T>::qt_metatype_id(); } |
| }; |
| template <typename T> struct QMetaTypeIdHelper<T, false> { |
| static inline Q_DECL_CONSTEXPR int qt_metatype_id() |
| { return -1; } |
| }; |
| |
| #ifndef Q_COMPILER_VARIADIC_TEMPLATES |
| // Function pointers don't derive from QObject |
| template <class Result> struct IsPointerToTypeDerivedFromQObject<Result(*)()> { enum { Value = false }; }; |
| template <class Result, class Arg0> struct IsPointerToTypeDerivedFromQObject<Result(*)(Arg0)> { enum { Value = false }; }; |
| template <class Result, class Arg0, class Arg1> struct IsPointerToTypeDerivedFromQObject<Result(*)(Arg0, Arg1)> { enum { Value = false }; }; |
| template <class Result, class Arg0, class Arg1, class Arg2> struct IsPointerToTypeDerivedFromQObject<Result(*)(Arg0, Arg1, Arg2)> { enum { Value = false }; }; |
| #else |
| template <typename Result, typename... Args> |
| struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; }; |
| #endif |
| |
| template<typename T> |
| struct QMetaTypeTypeFlags |
| { |
| enum { Flags = (!QTypeInfo<T>::isStatic ? QMetaType::MovableType : 0) |
| | (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0) |
| | (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0) |
| | (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 0) |
| | (IsSharedPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::SharedPointerToQObject : 0) |
| | (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0) |
| | (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0) |
| | (Q_IS_ENUM(T) ? QMetaType::IsEnumeration : 0) |
| | (IsGadgetHelper<T>::Value ? QMetaType::IsGadget : 0) |
| }; |
| }; |
| |
| template<typename T, bool defined> |
| struct MetaTypeDefinedHelper |
| { |
| enum DefinedType { Defined = defined }; |
| }; |
| |
| template<typename SmartPointer> |
| struct QSmartPointerConvertFunctor |
| { |
| QObject* operator()(const SmartPointer &p) const |
| { |
| return p.operator->(); |
| } |
| }; |
| |
| template<typename T> |
| struct QSmartPointerConvertFunctor<QWeakPointer<T> > |
| { |
| QObject* operator()(const QWeakPointer<T> &p) const |
| { |
| return p.data(); |
| } |
| }; |
| } |
| |
| template <typename T> |
| int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName |
| #ifndef Q_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 |
| #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()); |
| |
| if (id > 0) { |
| QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id); |
| QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id); |
| QtPrivate::MetaTypePairHelper<T>::registerConverter(id); |
| QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id); |
| } |
| |
| return id; |
| } |
| |
| template <typename T> |
| int qRegisterMetaType(const char *typeName |
| #ifndef Q_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 |
| #endif |
| ) |
| { |
| #ifdef QT_NO_QOBJECT |
| QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName; |
| #else |
| QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); |
| #endif |
| return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined); |
| } |
| |
| #ifndef QT_NO_DATASTREAM |
| template <typename T> |
| void qRegisterMetaTypeStreamOperators(const char *typeName |
| #ifndef Q_QDOC |
| , T * /* dummy */ = 0 |
| #endif |
| ) |
| { |
| qRegisterMetaType<T>(typeName); |
| QMetaType::registerStreamOperators(typeName, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save, |
| QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load); |
| } |
| #endif // QT_NO_DATASTREAM |
| |
| 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(); |
| } |
| |
| template <typename T> |
| inline Q_DECL_CONSTEXPR int qRegisterMetaType() |
| { |
| return qMetaTypeId<T>(); |
| } |
| |
| #if QT_DEPRECATED_SINCE(5, 1) && !defined(Q_QDOC) |
| // There used to be a T *dummy = 0 argument in Qt 4.0 to support MSVC6 |
| template <typename T> |
| QT_DEPRECATED inline Q_DECL_CONSTEXPR int qMetaTypeId(T *) |
| { return qMetaTypeId<T>(); } |
| #ifndef Q_CC_SUN |
| template <typename T> |
| QT_DEPRECATED inline Q_DECL_CONSTEXPR int qRegisterMetaType(T *) |
| { return qRegisterMetaType<T>(); } |
| #endif |
| #endif |
| |
| #ifndef QT_NO_QOBJECT |
| template <typename T> |
| struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject> |
| { |
| enum { |
| Defined = 1 |
| }; |
| |
| static int qt_metatype_id() |
| { |
| static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); |
| if (const int id = metatype_id.loadAcquire()) |
| return id; |
| const char * const cName = T::staticMetaObject.className(); |
| QByteArray typeName; |
| typeName.reserve(int(strlen(cName)) + 1); |
| typeName.append(cName).append('*'); |
| const int newId = qRegisterNormalizedMetaType<T*>( |
| typeName, |
| reinterpret_cast<T**>(quintptr(-1))); |
| metatype_id.storeRelease(newId); |
| return newId; |
| } |
| }; |
| |
| template <typename T> |
| struct QMetaTypeIdQObject<T, QMetaType::IsGadget> |
| { |
| enum { |
| Defined = QtPrivate::is_default_constructible<T>::value |
| }; |
| |
| static int qt_metatype_id() |
| { |
| static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); |
| if (const int id = metatype_id.loadAcquire()) |
| return id; |
| const char * const cName = T::staticMetaObject.className(); |
| const int newId = qRegisterNormalizedMetaType<T>( |
| cName, |
| reinterpret_cast<T*>(quintptr(-1))); |
| metatype_id.storeRelease(newId); |
| return newId; |
| } |
| }; |
| |
| template <typename T> |
| struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration> |
| { |
| enum { |
| Defined = 1 |
| }; |
| |
| static int qt_metatype_id() |
| { |
| static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); |
| if (const int id = metatype_id.loadAcquire()) |
| return id; |
| const char *eName = qt_getEnumName(T()); |
| const char *cName = qt_getEnumMetaObject(T())->className(); |
| QByteArray typeName; |
| typeName.reserve(int(strlen(cName) + 2 + strlen(eName))); |
| typeName.append(cName).append("::").append(eName); |
| const int newId = qRegisterNormalizedMetaType<T>( |
| typeName, |
| reinterpret_cast<T*>(quintptr(-1))); |
| metatype_id.storeRelease(newId); |
| return newId; |
| } |
| }; |
| #endif |
| |
| #ifndef QT_NO_DATASTREAM |
| template <typename T> |
| inline int qRegisterMetaTypeStreamOperators() |
| { |
| int id = qMetaTypeId<T>(); |
| QMetaType::registerStreamOperators(id, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save, |
| QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load); |
| return id; |
| } |
| #endif |
| |
| #define Q_DECLARE_OPAQUE_POINTER(POINTER) \ |
| QT_BEGIN_NAMESPACE namespace QtPrivate { \ |
| template <> \ |
| struct IsPointerToTypeDerivedFromQObject<POINTER > \ |
| { \ |
| enum { Value = false }; \ |
| }; \ |
| } QT_END_NAMESPACE \ |
| /**/ |
| |
| #define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE) |
| #define Q_DECLARE_METATYPE_IMPL(TYPE) \ |
| QT_BEGIN_NAMESPACE \ |
| template <> \ |
| struct QMetaTypeId< TYPE > \ |
| { \ |
| enum { Defined = 1 }; \ |
| static int qt_metatype_id() \ |
| { \ |
| static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ |
| if (const int id = metatype_id.loadAcquire()) \ |
| return id; \ |
| const int newId = qRegisterMetaType< TYPE >(#TYPE, \ |
| reinterpret_cast< TYPE *>(quintptr(-1))); \ |
| metatype_id.storeRelease(newId); \ |
| return newId; \ |
| } \ |
| }; \ |
| QT_END_NAMESPACE |
| |
| |
| #define Q_DECLARE_BUILTIN_METATYPE(TYPE, METATYPEID, NAME) \ |
| QT_BEGIN_NAMESPACE \ |
| template<> struct QMetaTypeId2<NAME> \ |
| { \ |
| enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID }; \ |
| static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return METATYPEID; } \ |
| }; \ |
| QT_END_NAMESPACE |
| |
| #define QT_FORWARD_DECLARE_STATIC_TYPES_ITER(TypeName, TypeId, Name) \ |
| class Name; |
| |
| QT_FOR_EACH_STATIC_CORE_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER) |
| QT_FOR_EACH_STATIC_GUI_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER) |
| QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER) |
| |
| #undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER |
| |
| typedef QList<QVariant> QVariantList; |
| typedef QMap<QString, QVariant> QVariantMap; |
| typedef QHash<QString, QVariant> QVariantHash; |
| typedef QList<QByteArray> QByteArrayList; |
| |
| #define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \ |
| QT_BEGIN_NAMESPACE \ |
| template <typename T> \ |
| struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \ |
| { \ |
| enum { \ |
| Defined = QMetaTypeId2<T>::Defined \ |
| }; \ |
| static int qt_metatype_id() \ |
| { \ |
| static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ |
| if (const int id = metatype_id.load()) \ |
| return id; \ |
| const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \ |
| Q_ASSERT(tName); \ |
| const int tNameLen = int(qstrlen(tName)); \ |
| QByteArray typeName; \ |
| 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, \ |
| reinterpret_cast< SINGLE_ARG_TEMPLATE<T> *>(quintptr(-1))); \ |
| metatype_id.storeRelease(newId); \ |
| return newId; \ |
| } \ |
| }; \ |
| namespace QtPrivate { \ |
| template<typename T> \ |
| struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \ |
| { \ |
| enum { Value = true }; \ |
| }; \ |
| } \ |
| QT_END_NAMESPACE |
| |
| #define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \ |
| QT_BEGIN_NAMESPACE \ |
| template<typename T, typename U> \ |
| struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \ |
| { \ |
| enum { \ |
| Defined = QMetaTypeId2<T>::Defined && QMetaTypeId2<U>::Defined \ |
| }; \ |
| static int qt_metatype_id() \ |
| { \ |
| static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ |
| if (const int id = metatype_id.loadAcquire()) \ |
| return id; \ |
| const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \ |
| const char *uName = QMetaType::typeName(qMetaTypeId<U>()); \ |
| Q_ASSERT(tName); \ |
| Q_ASSERT(uName); \ |
| const int tNameLen = int(qstrlen(tName)); \ |
| const int uNameLen = int(qstrlen(uName)); \ |
| QByteArray typeName; \ |
| 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, \ |
| reinterpret_cast< DOUBLE_ARG_TEMPLATE<T, U> *>(quintptr(-1))); \ |
| metatype_id.storeRelease(newId); \ |
| return newId; \ |
| } \ |
| }; \ |
| QT_END_NAMESPACE |
| |
| namespace QtPrivate { |
| |
| template<typename T, bool /* isSharedPointerToQObjectDerived */ = false> |
| struct SharedPointerMetaTypeIdHelper |
| { |
| enum { |
| Defined = 0 |
| }; |
| static int qt_metatype_id() |
| { |
| return -1; |
| } |
| }; |
| |
| } |
| |
| #define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER) \ |
| QT_BEGIN_NAMESPACE \ |
| namespace QtPrivate { \ |
| template<typename T> \ |
| struct SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \ |
| { \ |
| enum { \ |
| Defined = 1 \ |
| }; \ |
| static int qt_metatype_id() \ |
| { \ |
| static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ |
| if (const int id = metatype_id.loadAcquire()) \ |
| return id; \ |
| const char * const cName = T::staticMetaObject.className(); \ |
| QByteArray typeName; \ |
| typeName.reserve(int(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1)); \ |
| typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1) \ |
| .append('<').append(cName).append('>'); \ |
| const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >( \ |
| typeName, \ |
| reinterpret_cast< SMART_POINTER<T> *>(quintptr(-1))); \ |
| metatype_id.storeRelease(newId); \ |
| return newId; \ |
| } \ |
| }; \ |
| template<typename T> \ |
| struct MetaTypeSmartPointerHelper<SMART_POINTER<T> , \ |
| typename QEnableIf<IsPointerToTypeDerivedFromQObject<T*>::Value >::Type> \ |
| { \ |
| static bool registerConverter(int id) \ |
| { \ |
| const int toId = QMetaType::QObjectStar; \ |
| if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { \ |
| QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o; \ |
| static const QtPrivate::ConverterFunctor<SMART_POINTER<T>, \ |
| QObject*, \ |
| QSmartPointerConvertFunctor<SMART_POINTER<T> > > f(o); \ |
| return QMetaType::registerConverterFunction(&f, id, toId); \ |
| } \ |
| return true; \ |
| } \ |
| }; \ |
| } \ |
| template <typename T> \ |
| struct QMetaTypeId< SMART_POINTER<T> > \ |
| : QtPrivate::SharedPointerMetaTypeIdHelper< SMART_POINTER<T>, \ |
| QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value> \ |
| { \ |
| };\ |
| QT_END_NAMESPACE |
| |
| #define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \ |
| QT_BEGIN_NAMESPACE \ |
| template <class T> class TEMPLATENAME; \ |
| QT_END_NAMESPACE \ |
| Q_DECLARE_METATYPE_TEMPLATE_1ARG(TEMPLATENAME) |
| |
| QT_END_NAMESPACE |
| |
| QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER) |
| |
| #undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER |
| |
| #define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE Q_DECLARE_METATYPE_TEMPLATE_1ARG |
| |
| Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector) |
| Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list) |
| |
| #define Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \ |
| QT_BEGIN_NAMESPACE \ |
| template <class T1, class T2> CPPTYPE TEMPLATENAME; \ |
| QT_END_NAMESPACE \ |
| |
| QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER) |
| |
| #undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER |
| |
| #define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \ |
| QT_BEGIN_NAMESPACE \ |
| namespace QtPrivate { \ |
| template<typename T, typename U> \ |
| struct IsAssociativeContainer<TEMPLATENAME<T, U> > \ |
| { \ |
| enum { Value = true }; \ |
| }; \ |
| } \ |
| QT_END_NAMESPACE \ |
| Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME) |
| |
| Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash) |
| Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMap) |
| Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::map) |
| |
| Q_DECLARE_METATYPE_TEMPLATE_2ARG(QPair) |
| Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair) |
| |
| #define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \ |
| Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME) |
| |
| |
| QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER) |
| |
| QT_BEGIN_NAMESPACE |
| |
| #undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER |
| |
| inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info, |
| Creator creator, |
| Deleter deleter, |
| SaveOperator saveOp, |
| LoadOperator loadOp, |
| Constructor constructor, |
| Destructor destructor, |
| uint size, |
| uint theTypeFlags, |
| int typeId, |
| const QMetaObject *_metaObject) |
| : m_creator_unused(creator) |
| , m_deleter_unused(deleter) |
| , m_saveOp(saveOp) |
| , m_loadOp(loadOp) |
| , m_constructor(constructor) |
| , m_destructor(destructor) |
| , m_extension(0) |
| , 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 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 |
| |
| |
| QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE) |
| |
| Q_DECLARE_METATYPE(QtMetaTypePrivate::QSequentialIterableImpl) |
| Q_DECLARE_METATYPE(QtMetaTypePrivate::QAssociativeIterableImpl) |
| Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl) |
| |
| QT_BEGIN_NAMESPACE |
| |
| template <typename T> |
| inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id) |
| { |
| const int toId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>(); |
| if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { |
| QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o; |
| static const QtPrivate::ConverterFunctor<T, |
| QtMetaTypePrivate::QPairVariantInterfaceImpl, |
| QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> > f(o); |
| return QMetaType::registerConverterFunction(&f, id, toId); |
| } |
| return true; |
| } |
| |
| namespace QtPrivate { |
| template<typename T> |
| struct ValueTypeIsMetaType<T, true> |
| { |
| static bool registerConverter(int id) |
| { |
| const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>(); |
| if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { |
| QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o; |
| static const QtPrivate::ConverterFunctor<T, |
| QtMetaTypePrivate::QSequentialIterableImpl, |
| QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> > f(o); |
| return QMetaType::registerConverterFunction(&f, id, toId); |
| } |
| return true; |
| } |
| }; |
| |
| template<typename T> |
| struct AssociativeValueTypeIsMetaType<T, true> |
| { |
| static bool registerConverter(int id) |
| { |
| const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>(); |
| if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { |
| QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o; |
| static const QtPrivate::ConverterFunctor<T, |
| QtMetaTypePrivate::QAssociativeIterableImpl, |
| QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> > f(o); |
| return QMetaType::registerConverterFunction(&f, id, toId); |
| } |
| return true; |
| } |
| }; |
| } |
| |
| namespace QtMetaTypePrivate { |
| inline Q_DECL_CONSTEXPR bool isBuiltinSequentialType(int typeId) |
| { |
| return typeId == qMetaTypeId<QStringList>() |
| || typeId == qMetaTypeId<QByteArrayList>() |
| || typeId == qMetaTypeId<QVariantList>(); |
| } |
| |
| inline Q_DECL_CONSTEXPR bool isBuiltinAssociativeType(int typeId) |
| { |
| return typeId == qMetaTypeId<QVariantHash>() |
| || typeId == qMetaTypeId<QVariantMap>(); |
| } |
| } // QtMetaTypePrivate |
| |
| QT_END_NAMESPACE |
| |
| #endif // QMETATYPE_H |