diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2012-08-27 10:39:16 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-03-29 04:04:40 +0100 |
commit | c400e16a58357c01fcc1567a42537be0767efadf (patch) | |
tree | b639c991675938995e3c3fed9c6d63caff580a22 | |
parent | 04ebd8e56f0a5b07fe419548b0ecc8b7845ce49c (diff) | |
download | qtbase-c400e16a58357c01fcc1567a42537be0767efadf.tar.gz |
QMetaTypeId: use QByteArray, not QVarLengthArray, to construct type names
So far, type-name strings for class template instantiations were constructed
in QMetaTypeId::qt_metatype_id() by concatenating various bits and pieces
into a QVarLengthArray<char>, presumably to avoid the dynamic memory
allocation for small strings.
Yet, when passing the result to qRegisterNormalisedMetaType, which takes
a QByteArray, the QVarLengthArray was copied from, not by
QByteArray::fromRawData(), but by QByteArray(const char*,int), which
unconditionally results in a dynamic memory allocation after all.
What's worse: the characters are copied twice: First into the QVarLengthArray,
and then into the QByteArray.
Remove the first of these copies by using QByteArray+reserve() to copy
directly into the final QByteArray.
Change-Id: Id915798a318fe97279a7cc0aca176544f99c7e86
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
-rw-r--r-- | src/corelib/kernel/qmetatype.h | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 16ea1042a2..83f2057eee 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -670,12 +670,12 @@ struct QMetaTypeIdQObject<T*, /* isPointerToTypeDerivedFromQObject */ true> static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); if (const int id = metatype_id.loadAcquire()) return id; - const int len = int(strlen(T::staticMetaObject.className())); - QVarLengthArray<char, 16> classNameStar; - classNameStar.append(T::staticMetaObject.className(), len); - classNameStar.append('*'); - const int newId = qRegisterNormalizedMetaType<T*>( \ - QByteArray(classNameStar.constData(), classNameStar.size()), + const char * const cName = T::staticMetaObject.className(); + QByteArray typeName; + typeName.reserve(strlen(cName) + 1); + typeName.append(cName).append('*'); + const int newId = qRegisterNormalizedMetaType<T*>( + typeName, reinterpret_cast<T**>(quintptr(-1))); metatype_id.storeRelease(newId); return newId; @@ -757,17 +757,18 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \ static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ if (const int id = metatype_id.load()) \ return id; \ - QVarLengthArray<char, 24> name; \ - name.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1); \ - name.append('<'); \ const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \ Q_ASSERT(tName); \ - name.append(tName, int(strlen(tName))); \ - if (name.last() == '>') \ - name.append(' '); \ - name.append('>'); \ - const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >( \ - QByteArray(name.constData(), name.size()), \ + const int tNameLen = qstrlen(tName); \ + QByteArray typeName; \ + typeName.reserve(sizeof(#SINGLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + 1); \ + typeName.append(#SINGLE_ARG_TEMPLATE, 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; \ @@ -786,21 +787,21 @@ struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \ static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ if (const int id = metatype_id.loadAcquire()) \ return id; \ - QVarLengthArray<char, 24> name; \ - name.append(#DOUBLE_ARG_TEMPLATE, sizeof(#DOUBLE_ARG_TEMPLATE) - 1); \ - name.append('<'); \ const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \ - Q_ASSERT(tName); \ - name.append(tName, int(strlen(tName))); \ - name.append(','); \ const char *uName = QMetaType::typeName(qMetaTypeId<U>()); \ + Q_ASSERT(tName); \ Q_ASSERT(uName); \ - name.append(uName, int(strlen(uName))); \ - if (name.last() == '>') \ - name.append(' '); \ - name.append('>'); \ + const int tNameLen = qstrlen(tName); \ + const int uNameLen = qstrlen(uName); \ + QByteArray typeName; \ + typeName.reserve(sizeof(#DOUBLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \ + typeName.append(#DOUBLE_ARG_TEMPLATE, 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> >(\ - QByteArray(name.constData(), name.size()), \ + typeName, \ reinterpret_cast< DOUBLE_ARG_TEMPLATE<T, U> *>(quintptr(-1))); \ metatype_id.storeRelease(newId); \ return newId; \ @@ -827,7 +828,13 @@ struct QMetaTypeId_ ## SMART_POINTER ## _QObjectStar<T, true> \ static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ if (const int id = metatype_id.loadAcquire()) \ return id; \ - const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >( #SMART_POINTER "<" + QByteArray(T::staticMetaObject.className()) + ">", \ + const char * const cName = T::staticMetaObject.className(); \ + QByteArray typeName; \ + typeName.reserve(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1); \ + typeName.append(#SMART_POINTER, 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; \ |