Add QMetaType::type(QByteArray) function

QMetaType::type(const char *) requires that the string argument is
0-terminated. This new overload makes it possible to query the type
of a string with an explicit length.

In particular, QByteArrays constructed by QByteArray::fromRawData(),
for example from a substring of a normalized method signature (the
"int" part of "mySlot(int"), can now be queried without making a copy
of the string.

Also, Qt5 meta-objects represent type names as QByteArray literals,
which can be fed directly to this new QMetaType::type() overload (no
need to call strlen).

Change-Id: I60d35aa6bdc0f77e0997f98b0e30e12fd3d5e100
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Kent Hansen 2012-02-11 07:02:13 +01:00 committed by Jędrzej Nowacki
parent 3de0f442b5
commit 0678d7c43c
4 changed files with 101 additions and 6 deletions

View File

@ -801,7 +801,7 @@ static inline int qMetaTypeStaticType(const char *typeName, int length)
{
int i = 0;
while (types[i].typeName && ((length != types[i].typeNameLength)
|| strcmp(typeName, types[i].typeName))) {
|| memcmp(typeName, types[i].typeName, length))) {
++i;
}
return types[i].type;
@ -821,7 +821,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
for (int v = 0; v < ct->count(); ++v) {
const QCustomTypeInfo &customInfo = ct->at(v);
if ((length == customInfo.typeName.size())
&& !strcmp(typeName, customInfo.typeName.constData())) {
&& !memcmp(typeName, customInfo.typeName.constData(), length)) {
if (customInfo.alias >= 0)
return customInfo.alias;
return v + QMetaType::User;
@ -1048,9 +1048,8 @@ bool QMetaType::isRegistered(int type)
Implementation of QMetaType::type().
*/
template <bool tryNormalizedType>
static inline int qMetaTypeTypeImpl(const char *typeName)
static inline int qMetaTypeTypeImpl(const char *typeName, int length)
{
int length = qstrlen(typeName);
if (!length)
return QMetaType::UnknownType;
int type = qMetaTypeStaticType(typeName, length);
@ -1080,7 +1079,7 @@ static inline int qMetaTypeTypeImpl(const char *typeName)
*/
int QMetaType::type(const char *typeName)
{
return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName);
return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName, qstrlen(typeName));
}
/*!
@ -1092,7 +1091,21 @@ int QMetaType::type(const char *typeName)
*/
int qMetaTypeTypeInternal(const char *typeName)
{
return qMetaTypeTypeImpl</*tryNormalizedType=*/false>(typeName);
return qMetaTypeTypeImpl</*tryNormalizedType=*/false>(typeName, qstrlen(typeName));
}
/*!
\since 5.5
\overload
Returns a handle to the type called \a typeName, or 0 if there is
no such type.
\sa isRegistered(), typeName()
*/
int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
{
return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName.constData(), typeName.size());
}
#ifndef QT_NO_DATASTREAM

View File

@ -472,6 +472,11 @@ public:
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);

View File

@ -79,6 +79,10 @@ private slots:
void normalizedTypes();
void typeName_data();
void typeName();
void type_data();
void type();
void type_fromSubString_data();
void type_fromSubString();
void create_data();
void create();
void createCopy_data();
@ -385,6 +389,61 @@ void tst_QMetaType::typeName()
QCOMPARE(name.toLatin1(), QMetaObject::normalizedType(name.toLatin1().constData()));
}
void tst_QMetaType::type_data()
{
QTest::addColumn<QMetaType::Type>("aType");
QTest::addColumn<QByteArray>("aTypeName");
#define TST_QMETATYPE_TYPE_DATA(MetaTypeName, MetaTypeId, RealType)\
QTest::newRow(#RealType) << QMetaType::MetaTypeName << QByteArray( #RealType );
#define TST_QMETATYPE_TYPE_DATA_ALIAS(MetaTypeName, MetaTypeId, AliasType, RealTypeString)\
QTest::newRow(RealTypeString) << QMetaType::MetaTypeName << QByteArray( #AliasType );
QTest::newRow("empty") << QMetaType::UnknownType << QByteArray();
QT_FOR_EACH_STATIC_TYPE(TST_QMETATYPE_TYPE_DATA)
QT_FOR_EACH_STATIC_ALIAS_TYPE(TST_QMETATYPE_TYPE_DATA_ALIAS)
#undef TST_QMETATYPE_TYPE_DATA
#undef TST_METATYPE_TYPE_DATA_ALIAS
}
void tst_QMetaType::type()
{
QFETCH(QMetaType::Type, aType);
QFETCH(QByteArray, aTypeName);
// QMetaType::type(QByteArray)
QCOMPARE(QMetaType::type(aTypeName), int(aType));
// QMetaType::type(const char *)
QCOMPARE(QMetaType::type(aTypeName.constData()), int(aType));
}
void tst_QMetaType::type_fromSubString_data()
{
QTest::addColumn<int>("offset");
QTest::addColumn<int>("size");
QTest::addColumn<int>("expectedType");
// The test string is defined in the test function below
QTest::newRow("int") << 0 << 3 << int(QMetaType::Int);
QTest::newRow("boo") << 3 << 3 << 0;
QTest::newRow("bool") << 3 << 4 << int(QMetaType::Bool);
QTest::newRow("intbool") << 0 << 7 << 0;
QTest::newRow("QMetaType::Type") << 7 << 15 << ::qMetaTypeId<QMetaType::Type>();
QTest::newRow("double") << 22 << 6 << int(QMetaType::Double);
}
void tst_QMetaType::type_fromSubString()
{
static const char *types = "intboolQMetaType::Typedoublexxx";
QFETCH(int, offset);
QFETCH(int, size);
QFETCH(int, expectedType);
QByteArray ba = QByteArray::fromRawData(types + offset, size);
QCOMPARE(QMetaType::type(ba), expectedType);
}
#define FOR_EACH_PRIMITIVE_METATYPE(F) \
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \
QT_FOR_EACH_STATIC_CORE_POINTER(F) \

View File

@ -45,6 +45,8 @@ public:
private slots:
void typeBuiltin_data();
void typeBuiltin();
void typeBuiltin_QByteArray_data();
void typeBuiltin_QByteArray();
void typeBuiltinNotNormalized_data();
void typeBuiltinNotNormalized();
void typeCustom();
@ -94,6 +96,7 @@ void tst_QMetaType::typeBuiltin_data()
}
}
// QMetaType::type(const char *)
void tst_QMetaType::typeBuiltin()
{
QFETCH(QByteArray, typeName);
@ -104,6 +107,21 @@ void tst_QMetaType::typeBuiltin()
}
}
void tst_QMetaType::typeBuiltin_QByteArray_data()
{
typeBuiltin_data();
}
// QMetaType::type(QByteArray)
void tst_QMetaType::typeBuiltin_QByteArray()
{
QFETCH(QByteArray, typeName);
QBENCHMARK {
for (int i = 0; i < 100000; ++i)
QMetaType::type(typeName);
}
}
void tst_QMetaType::typeBuiltinNotNormalized_data()
{
QTest::addColumn<QByteArray>("typeName");