Provide API for "placement new" construction of meta-types
By making it possible to specify the place in memory where a type should be constructed, any meta-type can be allocated on the stack, for example. In the QML/JS QObject binding, this makes it possible to call slots and access properties from JavaScript without having to perform any mallocs (e.g. due to QVariant creation) in the C++ <--> JS value conversion, in the best case. In addition to QMetaType::construct() and QMetaType::destruct(), this change introduces QMetaType::typeSize(), which returns the size of a type in bytes. This can be used to prepare a suitable buffer for constructing a type using construct(). Benchmarks indicate that in-place construction is 2-5x faster than normal construction for core and GUI types on linux-g++. Note that there is already a QMetaType::construct() function in Qt 4, which has been renamed to QMetaType::create() in Qt 5. In order to avoid existing usages of construct() in user code to call the Qt 5 construct() (when they really meant to call create()), the third argument ("copy") of construct() is made mandatory. Hence, calls to QMetaType::construct() written for Qt 4 will cause a compile error when compiled with Qt 5, and the user must adapt his code. Task-number: QTBUG-12574 Change-Id: I836f06f6ee1c1c3edbd199a03424c78c942bdd3e Reviewed-by: João Abecasis <joao.abecasis@nokia.com> Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
This commit is contained in:
parent
ae30d71413
commit
9e92ecde74
@ -337,6 +337,9 @@ struct QMetaTypeGuiHelper
|
||||
QMetaType::SaveOperator saveOp;
|
||||
QMetaType::LoadOperator loadOp;
|
||||
#endif
|
||||
QMetaType::Constructor constructor;
|
||||
QMetaType::Destructor destructor;
|
||||
int size;
|
||||
};
|
||||
Q_CORE_EXPORT const QMetaTypeGuiHelper *qMetaTypeGuiHelper = 0;
|
||||
Q_CORE_EXPORT const QMetaTypeGuiHelper *qMetaTypeWidgetsHelper = 0;
|
||||
@ -348,6 +351,7 @@ public:
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
, saveOp(0), loadOp(0)
|
||||
#endif
|
||||
, constructor(0), destructor(0), size(0)
|
||||
{}
|
||||
|
||||
QByteArray typeName;
|
||||
@ -358,6 +362,9 @@ public:
|
||||
QMetaType::LoadOperator loadOp;
|
||||
#endif
|
||||
int alias;
|
||||
QMetaType::Constructor constructor;
|
||||
QMetaType::Destructor destructor;
|
||||
int size;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
|
||||
@ -460,12 +467,28 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
|
||||
|
||||
/*! \internal
|
||||
|
||||
Registers a user type for marshalling, with \a typeName, a \a
|
||||
destructor, and a \a constructor. Returns the type's handle,
|
||||
or -1 if the type could not be registered.
|
||||
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, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*! \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)
|
||||
{
|
||||
QVector<QCustomTypeInfo> *ct = customTypes();
|
||||
if (!ct || !typeName || !deleter || !creator)
|
||||
@ -490,6 +513,9 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
|
||||
inf.creator = creator;
|
||||
inf.deleter = deleter;
|
||||
inf.alias = -1;
|
||||
inf.constructor = constructor;
|
||||
inf.destructor = destructor;
|
||||
inf.size = size;
|
||||
idx = ct->size() + User;
|
||||
ct->append(inf);
|
||||
}
|
||||
@ -1416,6 +1442,443 @@ void QMetaType::destroy(int type, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.0
|
||||
|
||||
Constructs a value of the given \a type in the existing memory
|
||||
addressed by \a where, that is a copy of \a copy, and returns
|
||||
\a where. If \a copy is zero, the value is default constructed.
|
||||
|
||||
This is a low-level function for explicitly managing the memory
|
||||
used to store the type. Consider calling create() if you don't
|
||||
need this level of control (that is, use "new" rather than
|
||||
"placement new").
|
||||
|
||||
You must ensure that \a where points to a location that can store
|
||||
a value of type \a type, and that \a where is suitably aligned.
|
||||
The type's size can be queried by calling sizeOf().
|
||||
|
||||
The rule of thumb for alignment is that a type is aligned to its
|
||||
natural boundary, which is the smallest power of 2 that is bigger
|
||||
than the type, unless that alignment is larger than the maximum
|
||||
useful alignment for the platform. For practical purposes,
|
||||
alignment larger than 2 * sizeof(void*) is only necessary for
|
||||
special hardware instructions (e.g., aligned SSE loads and stores
|
||||
on x86).
|
||||
|
||||
\sa destruct(), sizeOf()
|
||||
*/
|
||||
void *QMetaType::construct(int type, void *where, const void *copy)
|
||||
{
|
||||
if (!where)
|
||||
return 0;
|
||||
switch (type) {
|
||||
case QMetaType::VoidStar:
|
||||
case QMetaType::QObjectStar:
|
||||
case QMetaType::QWidgetStar:
|
||||
return qMetaTypeConstructHelper<void*>(where, static_cast<void* const *>(copy));
|
||||
case QMetaType::Long:
|
||||
return qMetaTypeConstructHelper<long>(where, static_cast<const long *>(copy));
|
||||
case QMetaType::Int:
|
||||
return qMetaTypeConstructHelper<int>(where, static_cast<const int *>(copy));
|
||||
case QMetaType::Short:
|
||||
return qMetaTypeConstructHelper<short>(where, static_cast<const short *>(copy));
|
||||
case QMetaType::Char:
|
||||
return qMetaTypeConstructHelper<char>(where, static_cast<const char *>(copy));
|
||||
case QMetaType::ULong:
|
||||
return qMetaTypeConstructHelper<ulong>(where, static_cast<const ulong *>(copy));
|
||||
case QMetaType::UInt:
|
||||
return qMetaTypeConstructHelper<uint>(where, static_cast<const uint *>(copy));
|
||||
case QMetaType::LongLong:
|
||||
return qMetaTypeConstructHelper<qlonglong>(where, static_cast<const qlonglong *>(copy));
|
||||
case QMetaType::ULongLong:
|
||||
return qMetaTypeConstructHelper<qulonglong>(where, static_cast<const qulonglong *>(copy));
|
||||
case QMetaType::UShort:
|
||||
return qMetaTypeConstructHelper<ushort>(where, static_cast<const ushort *>(copy));
|
||||
case QMetaType::UChar:
|
||||
return qMetaTypeConstructHelper<uchar>(where, static_cast<const uchar *>(copy));
|
||||
case QMetaType::Bool:
|
||||
return qMetaTypeConstructHelper<bool>(where, static_cast<const bool *>(copy));
|
||||
case QMetaType::Float:
|
||||
return qMetaTypeConstructHelper<float>(where, static_cast<const float *>(copy));
|
||||
case QMetaType::Double:
|
||||
return qMetaTypeConstructHelper<double>(where, static_cast<const double *>(copy));
|
||||
case QMetaType::QChar:
|
||||
return qMetaTypeConstructHelper<NS(QChar)>(where, static_cast<const NS(QChar) *>(copy));
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QVariantMap:
|
||||
return qMetaTypeConstructHelper<NS(QVariantMap)>(where, static_cast<const NS(QVariantMap) *>(copy));
|
||||
case QMetaType::QVariantHash:
|
||||
return qMetaTypeConstructHelper<NS(QVariantHash)>(where, static_cast<const NS(QVariantHash) *>(copy));
|
||||
case QMetaType::QVariantList:
|
||||
return qMetaTypeConstructHelper<NS(QVariantList)>(where, static_cast<const NS(QVariantList) *>(copy));
|
||||
case QMetaType::QVariant:
|
||||
return qMetaTypeConstructHelper<NS(QVariant)>(where, static_cast<const NS(QVariant) *>(copy));
|
||||
#endif
|
||||
case QMetaType::QByteArray:
|
||||
return qMetaTypeConstructHelper<NS(QByteArray)>(where, static_cast<const NS(QByteArray) *>(copy));
|
||||
case QMetaType::QString:
|
||||
return qMetaTypeConstructHelper<NS(QString)>(where, static_cast<const NS(QString) *>(copy));
|
||||
case QMetaType::QStringList:
|
||||
return qMetaTypeConstructHelper<NS(QStringList)>(where, static_cast<const NS(QStringList) *>(copy));
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QBitArray:
|
||||
return qMetaTypeConstructHelper<NS(QBitArray)>(where, static_cast<const NS(QBitArray) *>(copy));
|
||||
#endif
|
||||
case QMetaType::QDate:
|
||||
return qMetaTypeConstructHelper<NS(QDate)>(where, static_cast<const NS(QDate) *>(copy));
|
||||
case QMetaType::QTime:
|
||||
return qMetaTypeConstructHelper<NS(QTime)>(where, static_cast<const NS(QTime) *>(copy));
|
||||
case QMetaType::QDateTime:
|
||||
return qMetaTypeConstructHelper<NS(QDateTime)>(where, static_cast<const NS(QDateTime) *>(copy));
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QUrl:
|
||||
return qMetaTypeConstructHelper<NS(QUrl)>(where, static_cast<const NS(QUrl) *>(copy));
|
||||
#endif
|
||||
case QMetaType::QLocale:
|
||||
return qMetaTypeConstructHelper<NS(QLocale)>(where, static_cast<const NS(QLocale) *>(copy));
|
||||
#ifndef QT_NO_GEOM_VARIANT
|
||||
case QMetaType::QRect:
|
||||
return qMetaTypeConstructHelper<NS(QRect)>(where, static_cast<const NS(QRect) *>(copy));
|
||||
case QMetaType::QRectF:
|
||||
return qMetaTypeConstructHelper<NS(QRectF)>(where, static_cast<const NS(QRectF) *>(copy));
|
||||
case QMetaType::QSize:
|
||||
return qMetaTypeConstructHelper<NS(QSize)>(where, static_cast<const NS(QSize) *>(copy));
|
||||
case QMetaType::QSizeF:
|
||||
return qMetaTypeConstructHelper<NS(QSizeF)>(where, static_cast<const NS(QSizeF) *>(copy));
|
||||
case QMetaType::QLine:
|
||||
return qMetaTypeConstructHelper<NS(QLine)>(where, static_cast<const NS(QLine) *>(copy));
|
||||
case QMetaType::QLineF:
|
||||
return qMetaTypeConstructHelper<NS(QLineF)>(where, static_cast<const NS(QLineF) *>(copy));
|
||||
case QMetaType::QPoint:
|
||||
return qMetaTypeConstructHelper<NS(QPoint)>(where, static_cast<const NS(QPoint) *>(copy));
|
||||
case QMetaType::QPointF:
|
||||
return qMetaTypeConstructHelper<NS(QPointF)>(where, static_cast<const NS(QPointF) *>(copy));
|
||||
#endif
|
||||
#ifndef QT_NO_REGEXP
|
||||
case QMetaType::QRegExp:
|
||||
return qMetaTypeConstructHelper<NS(QRegExp)>(where, static_cast<const NS(QRegExp) *>(copy));
|
||||
#endif
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QEasingCurve:
|
||||
return qMetaTypeConstructHelper<NS(QEasingCurve)>(where, static_cast<const NS(QEasingCurve) *>(copy));
|
||||
#endif
|
||||
case QMetaType::Void:
|
||||
return where;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
Constructor ctor = 0;
|
||||
if (type >= FirstGuiType && type <= LastGuiType) {
|
||||
Q_ASSERT(qMetaTypeGuiHelper);
|
||||
if (!qMetaTypeGuiHelper)
|
||||
return 0;
|
||||
ctor = qMetaTypeGuiHelper[type - FirstGuiType].constructor;
|
||||
} else if (type >= FirstWidgetsType && type <= LastWidgetsType) {
|
||||
Q_ASSERT(qMetaTypeWidgetsHelper);
|
||||
if (!qMetaTypeWidgetsHelper)
|
||||
return 0;
|
||||
ctor = qMetaTypeWidgetsHelper[type - FirstWidgetsType].constructor;
|
||||
} else {
|
||||
const QVector<QCustomTypeInfo> * const ct = customTypes();
|
||||
QReadLocker locker(customTypesLock());
|
||||
if (type < User || !ct || ct->count() <= type - User)
|
||||
return 0;
|
||||
ctor = ct->at(type - User).constructor;
|
||||
if (!ctor)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ctor(where, copy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.0
|
||||
|
||||
Destructs the value of the given \a type, located at \a where.
|
||||
|
||||
Unlike destroy(), this function only invokes the type's
|
||||
destructor, it doesn't invoke the delete operator.
|
||||
|
||||
\sa construct()
|
||||
*/
|
||||
void QMetaType::destruct(int type, void *where)
|
||||
{
|
||||
if (!where)
|
||||
return;
|
||||
switch (type) {
|
||||
case QMetaType::VoidStar:
|
||||
case QMetaType::QObjectStar:
|
||||
case QMetaType::QWidgetStar:
|
||||
break;
|
||||
case QMetaType::Long:
|
||||
break;
|
||||
case QMetaType::Int:
|
||||
break;
|
||||
case QMetaType::Short:
|
||||
break;
|
||||
case QMetaType::Char:
|
||||
break;
|
||||
case QMetaType::ULong:
|
||||
break;
|
||||
case QMetaType::LongLong:
|
||||
break;
|
||||
case QMetaType::ULongLong:
|
||||
break;
|
||||
case QMetaType::UInt:
|
||||
break;
|
||||
case QMetaType::UShort:
|
||||
break;
|
||||
case QMetaType::UChar:
|
||||
break;
|
||||
case QMetaType::Bool:
|
||||
break;
|
||||
case QMetaType::Float:
|
||||
break;
|
||||
case QMetaType::Double:
|
||||
break;
|
||||
case QMetaType::QChar:
|
||||
static_cast< NS(QChar)* >(where)->NS(QChar)::~QChar();
|
||||
break;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QVariantMap:
|
||||
static_cast< NS(QVariantMap)* >(where)->NS(QVariantMap)::~QVariantMap();
|
||||
break;
|
||||
case QMetaType::QVariantHash:
|
||||
static_cast< NS(QVariantHash)* >(where)->NS(QVariantHash)::~QVariantHash();
|
||||
break;
|
||||
case QMetaType::QVariantList:
|
||||
static_cast< NS(QVariantList)* >(where)->NS(QVariantList)::~QVariantList();
|
||||
break;
|
||||
case QMetaType::QVariant:
|
||||
static_cast< NS(QVariant)* >(where)->NS(QVariant)::~QVariant();
|
||||
break;
|
||||
#endif
|
||||
case QMetaType::QByteArray:
|
||||
static_cast< NS(QByteArray)* >(where)->NS(QByteArray)::~QByteArray();
|
||||
break;
|
||||
case QMetaType::QString:
|
||||
static_cast< NS(QString)* >(where)->NS(QString)::~QString();
|
||||
break;
|
||||
case QMetaType::QStringList:
|
||||
static_cast< NS(QStringList)* >(where)->NS(QStringList)::~QStringList();
|
||||
break;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QBitArray:
|
||||
static_cast< NS(QBitArray)* >(where)->NS(QBitArray)::~QBitArray();
|
||||
break;
|
||||
#endif
|
||||
case QMetaType::QDate:
|
||||
static_cast< NS(QDate)* >(where)->NS(QDate)::~QDate();
|
||||
break;
|
||||
case QMetaType::QTime:
|
||||
static_cast< NS(QTime)* >(where)->NS(QTime)::~QTime();
|
||||
break;
|
||||
case QMetaType::QDateTime:
|
||||
static_cast< NS(QDateTime)* >(where)->NS(QDateTime)::~QDateTime();
|
||||
break;
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QUrl:
|
||||
static_cast< NS(QUrl)* >(where)->NS(QUrl)::~QUrl();
|
||||
#endif
|
||||
break;
|
||||
case QMetaType::QLocale:
|
||||
static_cast< NS(QLocale)* >(where)->NS(QLocale)::~QLocale();
|
||||
break;
|
||||
#ifndef QT_NO_GEOM_VARIANT
|
||||
case QMetaType::QRect:
|
||||
static_cast< NS(QRect)* >(where)->NS(QRect)::~QRect();
|
||||
break;
|
||||
case QMetaType::QRectF:
|
||||
static_cast< NS(QRectF)* >(where)->NS(QRectF)::~QRectF();
|
||||
break;
|
||||
case QMetaType::QSize:
|
||||
static_cast< NS(QSize)* >(where)->NS(QSize)::~QSize();
|
||||
break;
|
||||
case QMetaType::QSizeF:
|
||||
static_cast< NS(QSizeF)* >(where)->NS(QSizeF)::~QSizeF();
|
||||
break;
|
||||
case QMetaType::QLine:
|
||||
static_cast< NS(QLine)* >(where)->NS(QLine)::~QLine();
|
||||
break;
|
||||
case QMetaType::QLineF:
|
||||
static_cast< NS(QLineF)* >(where)->NS(QLineF)::~QLineF();
|
||||
break;
|
||||
case QMetaType::QPoint:
|
||||
static_cast< NS(QPoint)* >(where)->NS(QPoint)::~QPoint();
|
||||
break;
|
||||
case QMetaType::QPointF:
|
||||
static_cast< NS(QPointF)* >(where)->NS(QPointF)::~QPointF();
|
||||
break;
|
||||
#endif
|
||||
#ifndef QT_NO_REGEXP
|
||||
case QMetaType::QRegExp:
|
||||
static_cast< NS(QRegExp)* >(where)->NS(QRegExp)::~QRegExp();
|
||||
break;
|
||||
#endif
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QEasingCurve:
|
||||
static_cast< NS(QEasingCurve)* >(where)->NS(QEasingCurve)::~QEasingCurve();
|
||||
break;
|
||||
#endif
|
||||
case QMetaType::Void:
|
||||
break;
|
||||
default: {
|
||||
const QVector<QCustomTypeInfo> * const ct = customTypes();
|
||||
Destructor dtor = 0;
|
||||
if (type >= FirstGuiType && type <= LastGuiType) {
|
||||
Q_ASSERT(qMetaTypeGuiHelper);
|
||||
if (!qMetaTypeGuiHelper)
|
||||
return;
|
||||
dtor = qMetaTypeGuiHelper[type - FirstGuiType].destructor;
|
||||
} else if (type >= FirstWidgetsType && type <= LastWidgetsType) {
|
||||
Q_ASSERT(qMetaTypeWidgetsHelper);
|
||||
if (!qMetaTypeWidgetsHelper)
|
||||
return;
|
||||
dtor = qMetaTypeWidgetsHelper[type - FirstWidgetsType].destructor;
|
||||
} else {
|
||||
QReadLocker locker(customTypesLock());
|
||||
if (type < User || !ct || ct->count() <= type - User)
|
||||
break;
|
||||
dtor = ct->at(type - User).destructor;
|
||||
if (!dtor)
|
||||
break;
|
||||
}
|
||||
dtor(where);
|
||||
break; }
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.0
|
||||
|
||||
Returns the size of the given \a type in bytes (i.e., sizeof(T),
|
||||
where T is the actual type identified by the \a type argument).
|
||||
|
||||
This function is typically used together with construct()
|
||||
to perform low-level management of the memory used by a type.
|
||||
|
||||
\sa construct()
|
||||
*/
|
||||
int QMetaType::sizeOf(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case QMetaType::VoidStar:
|
||||
case QMetaType::QObjectStar:
|
||||
case QMetaType::QWidgetStar:
|
||||
return sizeof(void *);
|
||||
case QMetaType::Long:
|
||||
return sizeof(long);
|
||||
case QMetaType::Int:
|
||||
return sizeof(int);
|
||||
case QMetaType::Short:
|
||||
return sizeof(short);
|
||||
case QMetaType::Char:
|
||||
return sizeof(char);
|
||||
case QMetaType::ULong:
|
||||
return sizeof(ulong);
|
||||
case QMetaType::UInt:
|
||||
return sizeof(uint);
|
||||
case QMetaType::LongLong:
|
||||
return sizeof(qlonglong);
|
||||
case QMetaType::ULongLong:
|
||||
return sizeof(qulonglong);
|
||||
case QMetaType::UShort:
|
||||
return sizeof(ushort);
|
||||
case QMetaType::UChar:
|
||||
return sizeof(uchar);
|
||||
case QMetaType::Bool:
|
||||
return sizeof(bool);
|
||||
case QMetaType::Float:
|
||||
return sizeof(float);
|
||||
case QMetaType::Double:
|
||||
return sizeof(double);
|
||||
case QMetaType::QChar:
|
||||
return sizeof(NS(QChar));
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QVariantMap:
|
||||
return sizeof(NS(QVariantMap));
|
||||
case QMetaType::QVariantHash:
|
||||
return sizeof(NS(QVariantHash));
|
||||
case QMetaType::QVariantList:
|
||||
return sizeof(NS(QVariantList));
|
||||
case QMetaType::QVariant:
|
||||
return sizeof(NS(QVariant));
|
||||
#endif
|
||||
case QMetaType::QByteArray:
|
||||
return sizeof(NS(QByteArray));
|
||||
case QMetaType::QString:
|
||||
return sizeof(NS(QString));
|
||||
case QMetaType::QStringList:
|
||||
return sizeof(NS(QStringList));
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QBitArray:
|
||||
return sizeof(NS(QBitArray));
|
||||
#endif
|
||||
case QMetaType::QDate:
|
||||
return sizeof(NS(QDate));
|
||||
case QMetaType::QTime:
|
||||
return sizeof(NS(QTime));
|
||||
case QMetaType::QDateTime:
|
||||
return sizeof(NS(QDateTime));
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QUrl:
|
||||
return sizeof(NS(QUrl));
|
||||
#endif
|
||||
case QMetaType::QLocale:
|
||||
return sizeof(NS(QLocale));
|
||||
#ifndef QT_NO_GEOM_VARIANT
|
||||
case QMetaType::QRect:
|
||||
return sizeof(NS(QRect));
|
||||
case QMetaType::QRectF:
|
||||
return sizeof(NS(QRectF));
|
||||
case QMetaType::QSize:
|
||||
return sizeof(NS(QSize));
|
||||
case QMetaType::QSizeF:
|
||||
return sizeof(NS(QSizeF));
|
||||
case QMetaType::QLine:
|
||||
return sizeof(NS(QLine));
|
||||
case QMetaType::QLineF:
|
||||
return sizeof(NS(QLineF));
|
||||
case QMetaType::QPoint:
|
||||
return sizeof(NS(QPoint));
|
||||
case QMetaType::QPointF:
|
||||
return sizeof(NS(QPointF));
|
||||
#endif
|
||||
#ifndef QT_NO_REGEXP
|
||||
case QMetaType::QRegExp:
|
||||
return sizeof(NS(QRegExp));
|
||||
#endif
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
case QMetaType::QEasingCurve:
|
||||
return sizeof(NS(QEasingCurve));
|
||||
#endif
|
||||
case QMetaType::Void:
|
||||
return 0;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if (type >= FirstGuiType && type <= LastGuiType) {
|
||||
Q_ASSERT(qMetaTypeGuiHelper);
|
||||
if (!qMetaTypeGuiHelper)
|
||||
return 0;
|
||||
return qMetaTypeGuiHelper[type - FirstGuiType].size;
|
||||
} else if (type >= FirstWidgetsType && type <= LastWidgetsType) {
|
||||
Q_ASSERT(qMetaTypeWidgetsHelper);
|
||||
if (!qMetaTypeWidgetsHelper)
|
||||
return 0;
|
||||
return qMetaTypeWidgetsHelper[type - FirstWidgetsType].size;
|
||||
}
|
||||
|
||||
const QVector<QCustomTypeInfo> * const ct = customTypes();
|
||||
QReadLocker locker(customTypesLock());
|
||||
if (type < User || !ct || ct->count() <= type - User)
|
||||
return 0;
|
||||
return ct->at(type - User).size;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int qRegisterMetaType(const char *typeName)
|
||||
\relates QMetaType
|
||||
@ -1475,6 +1938,12 @@ void QMetaType::destroy(int type, void *data)
|
||||
/*! \typedef QMetaType::LoadOperator
|
||||
\internal
|
||||
*/
|
||||
/*! \typedef QMetaType::Destructor
|
||||
\internal
|
||||
*/
|
||||
/*! \typedef QMetaType::Constructor
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn int qRegisterMetaType()
|
||||
|
@ -49,6 +49,8 @@
|
||||
#include <QtCore/qdatastream.h>
|
||||
#endif
|
||||
|
||||
#include <new>
|
||||
|
||||
#ifdef Bool
|
||||
#error qmetatype.h must be included before any header file that defines Bool
|
||||
#endif
|
||||
@ -106,6 +108,9 @@ public:
|
||||
typedef void (*Deleter)(void *);
|
||||
typedef void *(*Creator)(const void *);
|
||||
|
||||
typedef void (*Destructor)(void *);
|
||||
typedef void *(*Constructor)(void *, const void *);
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
typedef void (*SaveOperator)(QDataStream &, const void *);
|
||||
typedef void (*LoadOperator)(QDataStream &, void *);
|
||||
@ -116,16 +121,20 @@ public:
|
||||
#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);
|
||||
static int registerTypedef(const char *typeName, int aliasId);
|
||||
static int type(const char *typeName);
|
||||
static const char *typeName(int type);
|
||||
static int sizeOf(int type);
|
||||
static bool isRegistered(int type);
|
||||
static void *create(int type, const void *copy = 0);
|
||||
#ifdef QT_DEPRECATED
|
||||
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);
|
||||
static void unregisterType(const char *typeName);
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
@ -148,6 +157,21 @@ void *qMetaTypeCreateHelper(const T *t)
|
||||
return new T(*static_cast<const T*>(t));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void qMetaTypeDestructHelper(T *t)
|
||||
{
|
||||
t->~T();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void *qMetaTypeConstructHelper(void *where, const T *t)
|
||||
{
|
||||
if (!t)
|
||||
return new (where) T;
|
||||
else
|
||||
return new (where) T(*static_cast<const T*>(t));
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
template <typename T>
|
||||
void qMetaTypeSaveHelper(QDataStream &stream, const T *t)
|
||||
@ -202,9 +226,16 @@ int qRegisterMetaType(const char *typeName
|
||||
CreatePtr cptr = qMetaTypeCreateHelper<T>;
|
||||
typedef void(*DeletePtr)(T*);
|
||||
DeletePtr dptr = qMetaTypeDeleteHelper<T>;
|
||||
typedef void*(*ConstructPtr)(void *, const T*);
|
||||
ConstructPtr ipcptr = qMetaTypeConstructHelper<T>;
|
||||
typedef void(*DestructPtr)(T*);
|
||||
DestructPtr ipdptr = qMetaTypeDestructHelper<T>;
|
||||
|
||||
return QMetaType::registerType(typeName, reinterpret_cast<QMetaType::Deleter>(dptr),
|
||||
reinterpret_cast<QMetaType::Creator>(cptr));
|
||||
reinterpret_cast<QMetaType::Creator>(cptr),
|
||||
reinterpret_cast<QMetaType::Destructor>(ipdptr),
|
||||
reinterpret_cast<QMetaType::Constructor>(ipcptr),
|
||||
sizeof(T));
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
|
@ -643,6 +643,9 @@ struct QMetaTypeGuiHelper
|
||||
QMetaType::SaveOperator saveOp;
|
||||
QMetaType::LoadOperator loadOp;
|
||||
#endif
|
||||
QMetaType::Constructor constructor;
|
||||
QMetaType::Destructor destructor;
|
||||
int size;
|
||||
};
|
||||
|
||||
extern Q_CORE_EXPORT const QMetaTypeGuiHelper *qMetaTypeGuiHelper;
|
||||
@ -653,13 +656,21 @@ extern Q_CORE_EXPORT const QMetaTypeGuiHelper *qMetaTypeGuiHelper;
|
||||
typedef void *(*QCreate##TYPE)(const TYPE *); \
|
||||
static const QCreate##TYPE qCreate##TYPE = qMetaTypeCreateHelper<TYPE>; \
|
||||
typedef void (*QDelete##TYPE)(TYPE *); \
|
||||
static const QDelete##TYPE qDelete##TYPE = qMetaTypeDeleteHelper<TYPE>;
|
||||
static const QDelete##TYPE qDelete##TYPE = qMetaTypeDeleteHelper<TYPE>; \
|
||||
typedef void *(*QConstruct##TYPE)(void *, const TYPE *); \
|
||||
static const QConstruct##TYPE qConstruct##TYPE = qMetaTypeConstructHelper<TYPE>; \
|
||||
typedef void (*QDestruct##TYPE)(TYPE *); \
|
||||
static const QDestruct##TYPE qDestruct##TYPE = qMetaTypeDestructHelper<TYPE>;
|
||||
#else
|
||||
# define Q_DECL_METATYPE_HELPER(TYPE) \
|
||||
typedef void *(*QCreate##TYPE)(const TYPE *); \
|
||||
static const QCreate##TYPE qCreate##TYPE = qMetaTypeCreateHelper<TYPE>; \
|
||||
typedef void (*QDelete##TYPE)(TYPE *); \
|
||||
static const QDelete##TYPE qDelete##TYPE = qMetaTypeDeleteHelper<TYPE>; \
|
||||
typedef void *(*QConstruct##TYPE)(void *, const TYPE *); \
|
||||
static const QConstruct##TYPE qConstruct##TYPE = qMetaTypeConstructHelper<TYPE>; \
|
||||
typedef void (*QDestruct##TYPE)(TYPE *); \
|
||||
static const QDestruct##TYPE qDestruct##TYPE = qMetaTypeDestructHelper<TYPE>; \
|
||||
typedef void (*QSave##TYPE)(QDataStream &, const TYPE *); \
|
||||
static const QSave##TYPE qSave##TYPE = qMetaTypeSaveHelper<TYPE>; \
|
||||
typedef void (*QLoad##TYPE)(QDataStream &, TYPE *); \
|
||||
@ -705,13 +716,20 @@ Q_DECL_METATYPE_HELPER(QQuaternion)
|
||||
#ifdef QT_NO_DATASTREAM
|
||||
# define Q_IMPL_METATYPE_HELPER(TYPE) \
|
||||
{ reinterpret_cast<QMetaType::Creator>(qCreate##TYPE), \
|
||||
reinterpret_cast<QMetaType::Deleter>(qDelete##TYPE) }
|
||||
reinterpret_cast<QMetaType::Deleter>(qDelete##TYPE), \
|
||||
reinterpret_cast<QMetaType::Constructor>(qConstruct##TYPE), \
|
||||
reinterpret_cast<QMetaType::Destructor>(qDestruct##TYPE), \
|
||||
sizeof(TYPE) \
|
||||
}
|
||||
#else
|
||||
# define Q_IMPL_METATYPE_HELPER(TYPE) \
|
||||
{ reinterpret_cast<QMetaType::Creator>(qCreate##TYPE), \
|
||||
reinterpret_cast<QMetaType::Deleter>(qDelete##TYPE), \
|
||||
reinterpret_cast<QMetaType::SaveOperator>(qSave##TYPE), \
|
||||
reinterpret_cast<QMetaType::LoadOperator>(qLoad##TYPE) \
|
||||
reinterpret_cast<QMetaType::LoadOperator>(qLoad##TYPE), \
|
||||
reinterpret_cast<QMetaType::Constructor>(qConstruct##TYPE), \
|
||||
reinterpret_cast<QMetaType::Destructor>(qDestruct##TYPE), \
|
||||
sizeof(TYPE) \
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -726,12 +744,12 @@ static const QMetaTypeGuiHelper qVariantGuiHelper[] = {
|
||||
Q_IMPL_METATYPE_HELPER(QRegion),
|
||||
Q_IMPL_METATYPE_HELPER(QBitmap),
|
||||
#ifdef QT_NO_CURSOR
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
#else
|
||||
Q_IMPL_METATYPE_HELPER(QCursor),
|
||||
#endif
|
||||
#ifdef QT_NO_SHORTCUT
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
#else
|
||||
Q_IMPL_METATYPE_HELPER(QKeySequence),
|
||||
#endif
|
||||
@ -743,27 +761,27 @@ static const QMetaTypeGuiHelper qVariantGuiHelper[] = {
|
||||
#ifndef QT_NO_MATRIX4X4
|
||||
Q_IMPL_METATYPE_HELPER(QMatrix4x4),
|
||||
#else
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
#endif
|
||||
#ifndef QT_NO_VECTOR2D
|
||||
Q_IMPL_METATYPE_HELPER(QVector2D),
|
||||
#else
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
#endif
|
||||
#ifndef QT_NO_VECTOR3D
|
||||
Q_IMPL_METATYPE_HELPER(QVector3D),
|
||||
#else
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
#endif
|
||||
#ifndef QT_NO_VECTOR4D
|
||||
Q_IMPL_METATYPE_HELPER(QVector4D),
|
||||
#else
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
#endif
|
||||
#ifndef QT_NO_QUATERNION
|
||||
Q_IMPL_METATYPE_HELPER(QQuaternion)
|
||||
#else
|
||||
{0, 0, 0, 0}
|
||||
{0, 0, 0, 0, 0, 0, 0}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -141,6 +141,9 @@ struct QMetaTypeGuiHelper
|
||||
QMetaType::SaveOperator saveOp;
|
||||
QMetaType::LoadOperator loadOp;
|
||||
#endif
|
||||
QMetaType::Constructor constructor;
|
||||
QMetaType::Destructor destructor;
|
||||
int size;
|
||||
};
|
||||
|
||||
extern Q_CORE_EXPORT const QMetaTypeGuiHelper *qMetaTypeWidgetsHelper;
|
||||
@ -151,13 +154,21 @@ extern Q_CORE_EXPORT const QMetaTypeGuiHelper *qMetaTypeWidgetsHelper;
|
||||
typedef void *(*QCreate##TYPE)(const TYPE *); \
|
||||
static const QCreate##TYPE qCreate##TYPE = qMetaTypeCreateHelper<TYPE>; \
|
||||
typedef void (*QDelete##TYPE)(TYPE *); \
|
||||
static const QDelete##TYPE qDelete##TYPE = qMetaTypeDeleteHelper<TYPE>;
|
||||
static const QDelete##TYPE qDelete##TYPE = qMetaTypeDeleteHelper<TYPE>; \
|
||||
typedef void *(*QConstruct##TYPE)(void *, const TYPE *); \
|
||||
static const QConstruct##TYPE qConstruct##TYPE = qMetaTypeConstructHelper<TYPE>; \
|
||||
typedef void (*QDestruct##TYPE)(TYPE *); \
|
||||
static const QDestruct##TYPE qDestruct##TYPE = qMetaTypeDestructHelper<TYPE>;
|
||||
#else
|
||||
# define Q_DECL_METATYPE_HELPER(TYPE) \
|
||||
typedef void *(*QCreate##TYPE)(const TYPE *); \
|
||||
static const QCreate##TYPE qCreate##TYPE = qMetaTypeCreateHelper<TYPE>; \
|
||||
typedef void (*QDelete##TYPE)(TYPE *); \
|
||||
static const QDelete##TYPE qDelete##TYPE = qMetaTypeDeleteHelper<TYPE>; \
|
||||
typedef void *(*QConstruct##TYPE)(void *, const TYPE *); \
|
||||
static const QConstruct##TYPE qConstruct##TYPE = qMetaTypeConstructHelper<TYPE>; \
|
||||
typedef void (*QDestruct##TYPE)(TYPE *); \
|
||||
static const QDestruct##TYPE qDestruct##TYPE = qMetaTypeDestructHelper<TYPE>; \
|
||||
typedef void (*QSave##TYPE)(QDataStream &, const TYPE *); \
|
||||
static const QSave##TYPE qSave##TYPE = qMetaTypeSaveHelper<TYPE>; \
|
||||
typedef void (*QLoad##TYPE)(QDataStream &, TYPE *); \
|
||||
@ -172,13 +183,20 @@ Q_DECL_METATYPE_HELPER(QSizePolicy)
|
||||
#ifdef QT_NO_DATASTREAM
|
||||
# define Q_IMPL_METATYPE_HELPER(TYPE) \
|
||||
{ reinterpret_cast<QMetaType::Creator>(qCreate##TYPE), \
|
||||
reinterpret_cast<QMetaType::Deleter>(qDelete##TYPE) }
|
||||
reinterpret_cast<QMetaType::Deleter>(qDelete##TYPE), \
|
||||
reinterpret_cast<QMetaType::Constructor>(qConstruct##TYPE), \
|
||||
reinterpret_cast<QMetaType::Destructor>(qDestruct##TYPE), \
|
||||
sizeof(TYPE) \
|
||||
}
|
||||
#else
|
||||
# define Q_IMPL_METATYPE_HELPER(TYPE) \
|
||||
{ reinterpret_cast<QMetaType::Creator>(qCreate##TYPE), \
|
||||
reinterpret_cast<QMetaType::Deleter>(qDelete##TYPE), \
|
||||
reinterpret_cast<QMetaType::SaveOperator>(qSave##TYPE), \
|
||||
reinterpret_cast<QMetaType::LoadOperator>(qLoad##TYPE) \
|
||||
reinterpret_cast<QMetaType::LoadOperator>(qLoad##TYPE), \
|
||||
reinterpret_cast<QMetaType::Constructor>(qConstruct##TYPE), \
|
||||
reinterpret_cast<QMetaType::Destructor>(qDestruct##TYPE), \
|
||||
sizeof(TYPE) \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -76,6 +76,12 @@ private slots:
|
||||
void create();
|
||||
void createCopy_data();
|
||||
void createCopy();
|
||||
void sizeOf_data();
|
||||
void sizeOf();
|
||||
void construct_data();
|
||||
void construct();
|
||||
void constructCopy_data();
|
||||
void constructCopy();
|
||||
void typedefs();
|
||||
void isRegistered_data();
|
||||
void isRegistered();
|
||||
@ -552,6 +558,139 @@ FOR_EACH_CORE_METATYPE(RETURN_CREATE_COPY_FUNCTION)
|
||||
TypeTestFunctionGetter::get(type)();
|
||||
}
|
||||
|
||||
void tst_QMetaType::sizeOf_data()
|
||||
{
|
||||
QTest::addColumn<QMetaType::Type>("type");
|
||||
QTest::addColumn<int>("size");
|
||||
#define ADD_METATYPE_TEST_ROW(TYPE, ID) \
|
||||
QTest::newRow(QMetaType::typeName(QMetaType::ID)) << QMetaType::ID << int(sizeof(TYPE));
|
||||
FOR_EACH_CORE_METATYPE(ADD_METATYPE_TEST_ROW)
|
||||
#undef ADD_METATYPE_TEST_ROW
|
||||
}
|
||||
|
||||
void tst_QMetaType::sizeOf()
|
||||
{
|
||||
QFETCH(QMetaType::Type, type);
|
||||
QFETCH(int, size);
|
||||
QCOMPARE(QMetaType::sizeOf(type), size);
|
||||
}
|
||||
|
||||
void tst_QMetaType::construct_data()
|
||||
{
|
||||
create_data();
|
||||
}
|
||||
|
||||
#ifndef Q_ALIGNOF
|
||||
template<uint N>
|
||||
struct RoundToNextHighestPowerOfTwo
|
||||
{
|
||||
private:
|
||||
enum { V1 = N-1 };
|
||||
enum { V2 = V1 | (V1 >> 1) };
|
||||
enum { V3 = V2 | (V2 >> 2) };
|
||||
enum { V4 = V3 | (V3 >> 4) };
|
||||
enum { V5 = V4 | (V4 >> 8) };
|
||||
enum { V6 = V5 | (V5 >> 16) };
|
||||
public:
|
||||
enum { Value = V6 + 1 };
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
struct TypeAlignment
|
||||
{
|
||||
#ifdef Q_ALIGNOF
|
||||
enum { Value = Q_ALIGNOF(T) };
|
||||
#else
|
||||
enum { Value = RoundToNextHighestPowerOfTwo<sizeof(T)>::Value };
|
||||
#endif
|
||||
};
|
||||
|
||||
template<int ID>
|
||||
static void testConstructHelper()
|
||||
{
|
||||
typedef typename MetaEnumToType<ID>::Type Type;
|
||||
int size = QMetaType::sizeOf(ID);
|
||||
void *storage = qMallocAligned(size, TypeAlignment<Type>::Value);
|
||||
void *actual = QMetaType::construct(ID, storage, /*copy=*/0);
|
||||
QCOMPARE(actual, storage);
|
||||
if (DefaultValueTraits<ID>::IsInitialized) {
|
||||
Type *expected = DefaultValueFactory<ID>::create();
|
||||
QCOMPARE(*static_cast<Type *>(actual), *expected);
|
||||
delete expected;
|
||||
}
|
||||
QMetaType::destruct(ID, actual);
|
||||
qFreeAligned(storage);
|
||||
|
||||
QVERIFY(QMetaType::construct(ID, 0, /*copy=*/0) == 0);
|
||||
QMetaType::destruct(ID, 0);
|
||||
}
|
||||
|
||||
void tst_QMetaType::construct()
|
||||
{
|
||||
struct TypeTestFunctionGetter
|
||||
{
|
||||
static TypeTestFunction get(int type)
|
||||
{
|
||||
switch (type) {
|
||||
#define RETURN_CONSTRUCT_FUNCTION(TYPE, ID) \
|
||||
case QMetaType::ID: \
|
||||
return testConstructHelper<QMetaType::ID>;
|
||||
FOR_EACH_CORE_METATYPE(RETURN_CONSTRUCT_FUNCTION)
|
||||
#undef RETURN_CONSTRUCT_FUNCTION
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
QFETCH(QMetaType::Type, type);
|
||||
TypeTestFunctionGetter::get(type)();
|
||||
}
|
||||
|
||||
template<int ID>
|
||||
static void testConstructCopyHelper()
|
||||
{
|
||||
typedef typename MetaEnumToType<ID>::Type Type;
|
||||
Type *expected = TestValueFactory<ID>::create();
|
||||
int size = QMetaType::sizeOf(ID);
|
||||
void *storage = qMallocAligned(size, TypeAlignment<Type>::Value);
|
||||
void *actual = QMetaType::construct(ID, storage, expected);
|
||||
QCOMPARE(actual, storage);
|
||||
QCOMPARE(*static_cast<Type *>(actual), *expected);
|
||||
QMetaType::destruct(ID, actual);
|
||||
qFreeAligned(storage);
|
||||
|
||||
QVERIFY(QMetaType::construct(ID, 0, expected) == 0);
|
||||
|
||||
delete expected;
|
||||
}
|
||||
|
||||
void tst_QMetaType::constructCopy_data()
|
||||
{
|
||||
create_data();
|
||||
}
|
||||
|
||||
void tst_QMetaType::constructCopy()
|
||||
{
|
||||
struct TypeTestFunctionGetter
|
||||
{
|
||||
static TypeTestFunction get(int type)
|
||||
{
|
||||
switch (type) {
|
||||
#define RETURN_CONSTRUCT_COPY_FUNCTION(TYPE, ID) \
|
||||
case QMetaType::ID: \
|
||||
return testConstructCopyHelper<QMetaType::ID>;
|
||||
FOR_EACH_CORE_METATYPE(RETURN_CONSTRUCT_COPY_FUNCTION)
|
||||
#undef RETURN_CONSTRUCT_COPY_FUNCTION
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
QFETCH(QMetaType::Type, type);
|
||||
TypeTestFunctionGetter::get(type)();
|
||||
}
|
||||
|
||||
typedef QString CustomString;
|
||||
Q_DECLARE_METATYPE(CustomString) //this line is useless
|
||||
|
||||
|
@ -54,6 +54,12 @@ private slots:
|
||||
void create();
|
||||
void createCopy_data();
|
||||
void createCopy();
|
||||
void sizeOf_data();
|
||||
void sizeOf();
|
||||
void construct_data();
|
||||
void construct();
|
||||
void constructCopy_data();
|
||||
void constructCopy();
|
||||
};
|
||||
|
||||
#define FOR_EACH_GUI_METATYPE(F) \
|
||||
@ -271,5 +277,130 @@ FOR_EACH_GUI_METATYPE(RETURN_CREATE_COPY_FUNCTION)
|
||||
TypeTestFunctionGetter::get(type)();
|
||||
}
|
||||
|
||||
void tst_QGuiMetaType::sizeOf_data()
|
||||
{
|
||||
QTest::addColumn<QMetaType::Type>("type");
|
||||
QTest::addColumn<int>("size");
|
||||
#define ADD_METATYPE_TEST_ROW(TYPE, ID) \
|
||||
QTest::newRow(QMetaType::typeName(QMetaType::ID)) << QMetaType::ID << int(sizeof(TYPE));
|
||||
FOR_EACH_GUI_METATYPE(ADD_METATYPE_TEST_ROW)
|
||||
#undef ADD_METATYPE_TEST_ROW
|
||||
}
|
||||
|
||||
void tst_QGuiMetaType::sizeOf()
|
||||
{
|
||||
QFETCH(QMetaType::Type, type);
|
||||
QFETCH(int, size);
|
||||
QCOMPARE(QMetaType::sizeOf(type), size);
|
||||
}
|
||||
|
||||
#ifndef Q_ALIGNOF
|
||||
template<uint N>
|
||||
struct RoundToNextHighestPowerOfTwo
|
||||
{
|
||||
private:
|
||||
enum { V1 = N-1 };
|
||||
enum { V2 = V1 | (V1 >> 1) };
|
||||
enum { V3 = V2 | (V2 >> 2) };
|
||||
enum { V4 = V3 | (V3 >> 4) };
|
||||
enum { V5 = V4 | (V4 >> 8) };
|
||||
enum { V6 = V5 | (V5 >> 16) };
|
||||
public:
|
||||
enum { Value = V6 + 1 };
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
struct TypeAlignment
|
||||
{
|
||||
#ifdef Q_ALIGNOF
|
||||
enum { Value = Q_ALIGNOF(T) };
|
||||
#else
|
||||
enum { Value = RoundToNextHighestPowerOfTwo<sizeof(T)>::Value };
|
||||
#endif
|
||||
};
|
||||
|
||||
void tst_QGuiMetaType::construct_data()
|
||||
{
|
||||
create_data();
|
||||
}
|
||||
|
||||
template <int ID>
|
||||
static void testConstructHelper()
|
||||
{
|
||||
typedef typename MetaEnumToType<ID>::Type Type;
|
||||
int size = QMetaType::sizeOf(ID);
|
||||
void *storage = qMallocAligned(size, TypeAlignment<Type>::Value);
|
||||
void *actual = QMetaType::construct(ID, storage, /*copy=*/0);
|
||||
QCOMPARE(actual, storage);
|
||||
Type *expected = DefaultValueFactory<ID>::create();
|
||||
QVERIFY2(TypeComparator<ID>::equal(*static_cast<Type *>(actual), *expected), QMetaType::typeName(ID));
|
||||
delete expected;
|
||||
QMetaType::destruct(ID, actual);
|
||||
qFreeAligned(storage);
|
||||
}
|
||||
|
||||
void tst_QGuiMetaType::construct()
|
||||
{
|
||||
struct TypeTestFunctionGetter
|
||||
{
|
||||
static TypeTestFunction get(int type)
|
||||
{
|
||||
switch (type) {
|
||||
#define RETURN_CONSTRUCT_FUNCTION(TYPE, ID) \
|
||||
case QMetaType::ID: \
|
||||
return testConstructHelper<QMetaType::ID>;
|
||||
FOR_EACH_GUI_METATYPE(RETURN_CONSTRUCT_FUNCTION)
|
||||
#undef RETURN_CONSTRUCT_FUNCTION
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
QFETCH(QMetaType::Type, type);
|
||||
TypeTestFunctionGetter::get(type)();
|
||||
}
|
||||
|
||||
void tst_QGuiMetaType::constructCopy_data()
|
||||
{
|
||||
create_data();
|
||||
}
|
||||
|
||||
template <int ID>
|
||||
static void testConstructCopyHelper()
|
||||
{
|
||||
typedef typename MetaEnumToType<ID>::Type Type;
|
||||
Type *expected = TestValueFactory<ID>::create();
|
||||
int size = QMetaType::sizeOf(ID);
|
||||
void *storage = qMallocAligned(size, TypeAlignment<Type>::Value);
|
||||
void *actual = QMetaType::construct(ID, storage, expected);
|
||||
QCOMPARE(actual, storage);
|
||||
QVERIFY2(TypeComparator<ID>::equal(*static_cast<Type*>(actual), *expected), QMetaType::typeName(ID));
|
||||
QMetaType::destruct(ID, actual);
|
||||
qFreeAligned(storage);
|
||||
delete expected;
|
||||
}
|
||||
|
||||
void tst_QGuiMetaType::constructCopy()
|
||||
{
|
||||
struct TypeTestFunctionGetter
|
||||
{
|
||||
static TypeTestFunction get(int type)
|
||||
{
|
||||
switch (type) {
|
||||
#define RETURN_CONSTRUCT_COPY_FUNCTION(TYPE, ID) \
|
||||
case QMetaType::ID: \
|
||||
return testConstructCopyHelper<QMetaType::ID>;
|
||||
FOR_EACH_GUI_METATYPE(RETURN_CONSTRUCT_COPY_FUNCTION)
|
||||
#undef RETURN_CONSTRUCT_COPY_FUNCTION
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
QFETCH(QMetaType::Type, type);
|
||||
TypeTestFunctionGetter::get(type)();
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QGuiMetaType)
|
||||
#include "tst_qguimetatype.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user