From 3f7a222414fc9d3e9f2e2cfdd05f33740c5afb7e Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Sat, 18 Feb 2012 20:36:06 +0100 Subject: Change the representation of meta-object string data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Up to and including meta-object revision 6, string data have been stored as 0-terminated C-style strings, that were made directly accessible as const char pointers through the public API (QMetaMethod and friends). This commit changes moc to generate an array of QByteArrayData instead, and adapts the QObject kernel accordingly. Generating an array of QByteArrayData (byte array literals) means that the strings can now be returned from public (or private) API as QByteArrays, rather than const char *, with zero allocation or copying. Also, the string length is now computed at compile time (it's part of the QByteArrayData). This commit only changes the internal representation, and does not affect existing public API. The actual (C) string data that the byte array literals reference still consists of zero-terminated strings. The benefit of having the QByteArrayData array will only become apparent in the upcoming meta-object data format change, which changes the format of property and method descriptors. Support for the old meta-object string data format was kept; the codepaths for old revisions (6 and below) will be removed in a separate commit, once all the other meta-object changes are done and affected code has been adapted accordingly. Task-number: QTBUG-24154 Change-Id: I4ec3b363bbc31b8192e5d8915ef091c442c2efad Reviewed-by: Lars Knoll Reviewed-by: Olivier Goffart Reviewed-by: João Abecasis Reviewed-by: Bradley T. Hughes --- src/corelib/kernel/qmetaobject.cpp | 114 ++++++---- src/corelib/kernel/qmetaobject_p.h | 5 +- src/corelib/kernel/qobject.cpp | 4 +- src/corelib/kernel/qobjectdefs.h | 8 +- src/tools/moc/generator.cpp | 252 +++++++++++++++------ src/tools/moc/generator.h | 7 +- src/tools/moc/moc.cpp | 1 + src/tools/moc/outputrevision.h | 2 +- .../kernel/qobject/moc_oldnormalizeobject.cpp | 2 +- 9 files changed, 274 insertions(+), 121 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index d53ba707f7..ce30e34f73 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -146,6 +146,43 @@ QT_BEGIN_NAMESPACE static inline const QMetaObjectPrivate *priv(const uint* data) { return reinterpret_cast(data); } +static inline const QByteArrayData &stringData(const QMetaObject *mo, int index) +{ + Q_ASSERT(priv(mo->d.data)->revision >= 7); + const QByteArrayData &data = mo->d.stringdata[index]; + Q_ASSERT(data.ref.isStatic()); + Q_ASSERT(data.alloc == 0); + Q_ASSERT(data.capacityReserved == 0); + Q_ASSERT(data.size >= 0); + return data; +} + +static inline const char *legacyString(const QMetaObject *mo, int index) +{ + Q_ASSERT(priv(mo->d.data)->revision <= 6); + return reinterpret_cast(mo->d.stringdata) + index; +} + +static inline const char *rawStringData(const QMetaObject *mo, int index) +{ + if (priv(mo->d.data)->revision >= 7) + return stringData(mo, index).data(); + else + return legacyString(mo, index); +} + +const char *QMetaObjectPrivate::rawStringData(const QMetaObject *mo, int index) +{ + return QT_PREPEND_NAMESPACE(rawStringData)(mo, index); +} + +static inline int stringSize(const QMetaObject *mo, int index) +{ + if (priv(mo->d.data)->revision >= 7) + return stringData(mo, index).size; + else + return qstrlen(legacyString(mo, index)); +} /*! \since 4.5 @@ -249,12 +286,14 @@ int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv) } /*! - \fn const char *QMetaObject::className() const - Returns the class name. \sa superClass() */ +const char *QMetaObject::className() const +{ + return rawStringData(this, 0); +} /*! \fn QMetaObject *QMetaObject::superClass() const @@ -307,7 +346,7 @@ const QObject *QMetaObject::cast(const QObject *obj) const */ QString QMetaObject::tr(const char *s, const char *c, int n) const { - return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr, n); + return QCoreApplication::translate(rawStringData(this, 0), s, c, QCoreApplication::CodecForTr, n); } /*! @@ -315,7 +354,7 @@ QString QMetaObject::tr(const char *s, const char *c, int n) const */ QString QMetaObject::trUtf8(const char *s, const char *c, int n) const { - return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8, n); + return QCoreApplication::translate(rawStringData(this, 0), s, c, QCoreApplication::UnicodeUTF8, n); } #endif // QT_NO_TRANSLATION @@ -513,7 +552,7 @@ static inline int indexOfMethodRelative(const QMetaObject **baseObject, ? (priv(m->d.data)->signalCount) : 0; if (!normalizeStringData) { for (; i >= end; --i) { - const char *stringdata = m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5*i]; + const char *stringdata = rawStringData(m, m->d.data[priv(m->d.data)->methodData + 5*i]); if (method[0] == stringdata[0] && strcmp(method + 1, stringdata + 1) == 0) { *baseObject = m; return i; @@ -521,7 +560,7 @@ static inline int indexOfMethodRelative(const QMetaObject **baseObject, } } else if (priv(m->d.data)->revision < 5) { for (; i >= end; --i) { - const char *stringdata = (m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5 * i]); + const char *stringdata = legacyString(m, m->d.data[priv(m->d.data)->methodData + 5 * i]); const QByteArray normalizedSignature = QMetaObject::normalizedSignature(stringdata); if (normalizedSignature == method) { *baseObject = m; @@ -549,7 +588,7 @@ int QMetaObject::indexOfConstructor(const char *constructor) const if (priv(d.data)->revision < 2) return -1; for (int i = priv(d.data)->constructorCount-1; i >= 0; --i) { - const char *data = d.stringdata + d.data[priv(d.data)->constructorData + 5*i]; + const char *data = rawStringData(this, d.data[priv(d.data)->constructorData + 5*i]); if (data[0] == constructor[0] && strcmp(constructor + 1, data + 1) == 0) { return i; } @@ -618,7 +657,7 @@ int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject, int conflict = m->d.superdata->indexOfMethod(signal); if (conflict >= 0) qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s", - signal, m->d.superdata->d.stringdata, m->d.stringdata); + signal, rawStringData(m->d.superdata, 0), rawStringData(m, 0)); } #endif return i; @@ -654,7 +693,7 @@ int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m, static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name) { while (self) { - if (strcmp(self->d.stringdata, name) == 0) + if (strcmp(rawStringData(self, 0), name) == 0) return self; if (self->d.extradata) { const QMetaObject **e; @@ -690,7 +729,7 @@ int QMetaObject::indexOfEnumerator(const char *name) const while (m) { const QMetaObjectPrivate *d = priv(m->d.data); for (int i = d->enumeratorCount - 1; i >= 0; --i) { - const char *prop = m->d.stringdata + m->d.data[d->enumeratorData + 4*i]; + const char *prop = rawStringData(m, m->d.data[d->enumeratorData + 4*i]); if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) { i += m->enumeratorOffset(); return i; @@ -713,7 +752,7 @@ int QMetaObject::indexOfProperty(const char *name) const while (m) { const QMetaObjectPrivate *d = priv(m->d.data); for (int i = d->propertyCount-1; i >= 0; --i) { - const char *prop = m->d.stringdata + m->d.data[d->propertyData + 3*i]; + const char *prop = rawStringData(m, m->d.data[d->propertyData + 3*i]); if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) { i += m->propertyOffset(); return i; @@ -744,8 +783,7 @@ int QMetaObject::indexOfClassInfo(const char *name) const const QMetaObject *m = this; while (m && i < 0) { for (i = priv(m->d.data)->classInfoCount-1; i >= 0; --i) - if (strcmp(name, m->d.stringdata - + m->d.data[priv(m->d.data)->classInfoData + 2*i]) == 0) { + if (strcmp(name, rawStringData(m, m->d.data[priv(m->d.data)->classInfoData + 2*i])) == 0) { i += m->classInfoOffset(); break; } @@ -829,7 +867,7 @@ QMetaProperty QMetaObject::property(int index) const if (i >= 0 && i < priv(d.data)->propertyCount) { int handle = priv(d.data)->propertyData + 3*i; int flags = d.data[handle + 2]; - const char *type = d.stringdata + d.data[handle + 1]; + const char *type = rawStringData(this, d.data[handle + 1]); result.mobj = this; result.handle = handle; result.idx = i; @@ -838,7 +876,7 @@ QMetaProperty QMetaObject::property(int index) const result.menum = enumerator(indexOfEnumerator(type)); if (!result.menum.isValid()) { const char *enum_name = type; - const char *scope_name = d.stringdata; + const char *scope_name = rawStringData(this, 0); char *scope_buffer = 0; const char *colon = strrchr(enum_name, ':'); @@ -1285,7 +1323,7 @@ const char *QMetaMethod::signature() const { if (!mobj) return 0; - return mobj->d.stringdata + mobj->d.data[handle]; + return rawStringData(mobj, mobj->d.data[handle]); } /*! @@ -1298,7 +1336,7 @@ QList QMetaMethod::parameterTypes() const if (!mobj) return QList(); return QMetaObjectPrivate::parameterTypeNamesFromSignature( - mobj->d.stringdata + mobj->d.data[handle]); + rawStringData(mobj, mobj->d.data[handle])); } /*! @@ -1311,10 +1349,10 @@ QList QMetaMethod::parameterNames() const QList list; if (!mobj) return list; - const char *names = mobj->d.stringdata + mobj->d.data[handle + 1]; + const char *names = rawStringData(mobj, mobj->d.data[handle + 1]); if (*names == 0) { // do we have one or zero arguments? - const char *signature = mobj->d.stringdata + mobj->d.data[handle]; + const char *signature = rawStringData(mobj, mobj->d.data[handle]); while (*signature && *signature != '(') ++signature; if (*++signature != ')') @@ -1340,7 +1378,7 @@ const char *QMetaMethod::typeName() const { if (!mobj) return 0; - return mobj->d.stringdata + mobj->d.data[handle + 2]; + return rawStringData(mobj, mobj->d.data[handle + 2]); } /*! @@ -1377,7 +1415,7 @@ const char *QMetaMethod::tag() const { if (!mobj) return 0; - return mobj->d.stringdata + mobj->d.data[handle + 3]; + return rawStringData(mobj, mobj->d.data[handle + 3]); } @@ -1580,10 +1618,10 @@ bool QMetaMethod::invoke(QObject *object, int metaMethodArgumentCount = 0; { // based on QMetaObject::parameterNames() - const char *names = mobj->d.stringdata + mobj->d.data[handle + 1]; + const char *names = rawStringData(mobj, mobj->d.data[handle + 1]); if (*names == 0) { // do we have one or zero arguments? - const char *signature = mobj->d.stringdata + mobj->d.data[handle]; + const char *signature = rawStringData(mobj, mobj->d.data[handle]); while (*signature && *signature != '(') ++signature; if (*++signature != ')') @@ -1803,7 +1841,7 @@ const char *QMetaEnum::name() const { if (!mobj) return 0; - return mobj->d.stringdata + mobj->d.data[handle]; + return rawStringData(mobj, mobj->d.data[handle]); } /*! @@ -1831,7 +1869,7 @@ const char *QMetaEnum::key(int index) const int count = mobj->d.data[handle + 2]; int data = mobj->d.data[handle + 3]; if (index >= 0 && index < count) - return mobj->d.stringdata + mobj->d.data[data + 2*index]; + return rawStringData(mobj, mobj->d.data[data + 2*index]); return 0; } @@ -1878,7 +1916,7 @@ bool QMetaEnum::isFlag() const */ const char *QMetaEnum::scope() const { - return mobj?mobj->d.stringdata : 0; + return mobj?rawStringData(mobj, 0) : 0; } /*! @@ -1910,8 +1948,8 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const int count = mobj->d.data[handle + 2]; int data = mobj->d.data[handle + 3]; for (int i = 0; i < count; ++i) { - if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key, mobj->d.stringdata, scope) == 0)) - && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0) { + if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key, rawStringData(mobj, 0), scope) == 0)) + && strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) { if (ok != 0) *ok = true; return mobj->d.data[data + 2*i + 1]; @@ -1936,7 +1974,7 @@ const char* QMetaEnum::valueToKey(int value) const int data = mobj->d.data[handle + 3]; for (int i = 0; i < count; ++i) if (value == (int)mobj->d.data[data + 2*i + 1]) - return mobj->d.stringdata + mobj->d.data[data + 2*i]; + return rawStringData(mobj, mobj->d.data[data + 2*i]); return 0; } @@ -1979,8 +2017,8 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const } int i; for (i = count-1; i >= 0; --i) - if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key.constData(), mobj->d.stringdata, scope) == 0)) - && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0) { + if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key.constData(), rawStringData(mobj, 0), scope) == 0)) + && strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) { value |= mobj->d.data[data + 2*i + 1]; break; } @@ -2013,7 +2051,7 @@ QByteArray QMetaEnum::valueToKeys(int value) const v = v & ~k; if (!keys.isEmpty()) keys += '|'; - keys += mobj->d.stringdata + mobj->d.data[data + 2*i]; + keys += rawStringData(mobj, mobj->d.data[data + 2*i]); } } return keys; @@ -2092,7 +2130,7 @@ const char *QMetaProperty::name() const if (!mobj) return 0; int handle = priv(mobj->d.data)->propertyData + 3*idx; - return mobj->d.stringdata + mobj->d.data[handle]; + return rawStringData(mobj, mobj->d.data[handle]); } /*! @@ -2105,7 +2143,7 @@ const char *QMetaProperty::typeName() const if (!mobj) return 0; int handle = priv(mobj->d.data)->propertyData + 3*idx; - return mobj->d.stringdata + mobj->d.data[handle + 1]; + return rawStringData(mobj, mobj->d.data[handle + 1]); } /*! @@ -2254,7 +2292,7 @@ QVariant QMetaProperty::read(const QObject *object) const } else { int handle = priv(mobj->d.data)->propertyData + 3*idx; uint flags = mobj->d.data[handle + 2]; - const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1]; + const char *typeName = rawStringData(mobj, mobj->d.data[handle + 1]); t = (flags >> 24); if (t == QVariant::Invalid) t = QMetaType::type(typeName); @@ -2325,7 +2363,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const uint flags = mobj->d.data[handle + 2]; t = flags >> 24; if (t == QVariant::Invalid) { - const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1]; + const char *typeName = rawStringData(mobj, mobj->d.data[handle + 1]); const char *vtypeName = value.typeName(); if (vtypeName && strcmp(typeName, vtypeName) == 0) t = value.userType(); @@ -2691,7 +2729,7 @@ const char *QMetaClassInfo::name() const { if (!mobj) return 0; - return mobj->d.stringdata + mobj->d.data[handle]; + return rawStringData(mobj, mobj->d.data[handle]); } /*! @@ -2703,7 +2741,7 @@ const char* QMetaClassInfo::value() const { if (!mobj) return 0; - return mobj->d.stringdata + mobj->d.data[handle + 1]; + return rawStringData(mobj, mobj->d.data[handle + 1]); } /*! diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 59a5c5f280..d789711bb4 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -109,7 +109,7 @@ class QMutex; struct QMetaObjectPrivate { - enum { OutputRevision = 6 }; // Used by moc and qmetaobjectbuilder + enum { OutputRevision = 7 }; // Used by moc, qmetaobjectbuilder and qdbus int revision; int className; @@ -122,10 +122,13 @@ struct QMetaObjectPrivate int signalCount; //since revision 4 // revision 5 introduces changes in normalized signatures, no new members // revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself + // revision 7 is Qt 5 static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject) { return reinterpret_cast(metaobject->d.data); } + static const char *rawStringData(const QMetaObject *mo, int index); + static int indexOfSignalRelative(const QMetaObject **baseObject, const char* name, bool normalizeStringData); diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8fa5dcdcff..d8c82ddc9f 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4036,9 +4036,9 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa locker.unlock(); // reconstruct the signature to call connectNotify - const char *sig = senderMetaObject->d.stringdata + senderMetaObject->d.data[ + const char *sig = QMetaObjectPrivate::rawStringData(senderMetaObject, senderMetaObject->d.data[ reinterpret_cast(senderMetaObject->d.data)->methodData - + 5 * (signal_index - signalOffset)]; + + 5 * (signal_index - signalOffset)]); QVarLengthArray signalSignature(qstrlen(sig) + 2); signalSignature.data()[0] = char(QSIGNAL_CODE + '0'); strcpy(signalSignature.data() + 1 , sig); diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index ec51251531..6c40733877 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -50,11 +50,12 @@ QT_BEGIN_NAMESPACE class QByteArray; +struct QByteArrayData; class QString; #ifndef Q_MOC_OUTPUT_REVISION -#define Q_MOC_OUTPUT_REVISION 64 +#define Q_MOC_OUTPUT_REVISION 65 #endif // The following macros are our "extensions" to C++ @@ -437,7 +438,7 @@ struct Q_CORE_EXPORT QMetaObject struct { // private data const QMetaObject *superdata; - const char *stringdata; + const QByteArrayData *stringdata; const uint *data; const void *extradata; } d; @@ -478,9 +479,6 @@ struct QMetaObjectExtraData StaticMetacallFunction static_metacall; }; -inline const char *QMetaObject::className() const -{ return d.stringdata; } - inline const QMetaObject *QMetaObject::superClass() const { return d.superdata; } diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index ac602fd6e8..9571af4bd5 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -109,24 +109,17 @@ static inline int lengthOfEscapeSequence(const QByteArray &s, int i) return i - startPos; } -int Generator::strreg(const QByteArray &s) +void Generator::strreg(const QByteArray &s) { - int idx = 0; - for (int i = 0; i < strings.size(); ++i) { - const QByteArray &str = strings.at(i); - if (str == s) - return idx; - idx += str.length() + 1; - for (int i = 0; i < str.length(); ++i) { - if (str.at(i) == '\\') { - int cnt = lengthOfEscapeSequence(str, i) - 1; - idx -= cnt; - i += cnt; - } - } - } - strings.append(s); - return idx; + if (!strings.contains(s)) + strings.append(s); +} + +int Generator::stridx(const QByteArray &s) +{ + int i = strings.indexOf(s); + Q_ASSERT_X(i != -1, Q_FUNC_INFO, "We forgot to register some strings"); + return i; } void Generator::generateCode() @@ -135,10 +128,6 @@ void Generator::generateCode() bool isQObject = (cdef->classname == "QObject"); bool isConstructible = !cdef->constructorList.isEmpty(); -// -// build the data array -// - // filter out undeclared enumerators and sets { QList enumList; @@ -156,15 +145,119 @@ void Generator::generateCode() cdef->enumList = enumList; } +// +// Register all strings used in data section +// + strreg(cdef->qualified); + registerClassInfoStrings(); + registerFunctionStrings(cdef->signalList); + registerFunctionStrings(cdef->slotList); + registerFunctionStrings(cdef->methodList); + registerFunctionStrings(cdef->constructorList); + registerPropertyStrings(); + registerEnumStrings(); QByteArray qualifiedClassNameIdentifier = cdef->qualified; qualifiedClassNameIdentifier.replace(':', '_'); +// +// Build stringdata struct +// + fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData()); + fprintf(out, " QByteArrayData data[%d];\n", strings.size()); + { + int len = 0; + for (int i = 0; i < strings.size(); ++i) + len += strings.at(i).length() + 1; + fprintf(out, " char stringdata[%d];\n", len + 1); + } + fprintf(out, "};\n"); + + // Macro that expands into a QByteArrayData. The offset member is + // calculated from 1) the offset of the actual characters in the + // stringdata.stringdata member, and 2) the stringdata.data index of the + // QByteArrayData being defined. This calculation relies on the + // QByteArrayData::data() implementation returning simply "this + offset". + fprintf(out, "#define QT_MOC_LITERAL(idx, ofs, len) { \\\n" + " Q_REFCOUNT_INITIALIZE_STATIC, len, 0, 0, \\\n" + " offsetof(qt_meta_stringdata_%s_t, stringdata) + ofs \\\n" + " - idx * sizeof(QByteArrayData) \\\n" + " }\n", + qualifiedClassNameIdentifier.constData()); + + fprintf(out, "static const qt_meta_stringdata_%s_t qt_meta_stringdata_%s = {\n", + qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData()); + fprintf(out, " {\n"); + { + int idx = 0; + for (int i = 0; i < strings.size(); ++i) { + if (i) + fprintf(out, ",\n"); + const QByteArray &str = strings.at(i); + fprintf(out, "QT_MOC_LITERAL(%d, %d, %d)", i, idx, str.length()); + idx += str.length() + 1; + for (int j = 0; j < str.length(); ++j) { + if (str.at(j) == '\\') { + int cnt = lengthOfEscapeSequence(str, j) - 1; + idx -= cnt; + j += cnt; + } + } + } + fprintf(out, "\n },\n"); + } + +// +// Build stringdata array +// + fprintf(out, " \""); + int col = 0; + int len = 0; + for (int i = 0; i < strings.size(); ++i) { + QByteArray s = strings.at(i); + len = s.length(); + if (col && col + len >= 72) { + fprintf(out, "\"\n \""); + col = 0; + } else if (len && s.at(0) >= '0' && s.at(0) <= '9') { + fprintf(out, "\"\""); + len += 2; + } + int idx = 0; + while (idx < s.length()) { + if (idx > 0) { + col = 0; + fprintf(out, "\"\n \""); + } + int spanLen = qMin(70, s.length() - idx); + // don't cut escape sequences at the end of a line + int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1); + if (backSlashPos >= idx) { + int escapeLen = lengthOfEscapeSequence(s, backSlashPos); + spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx); + } + fwrite(s.constData() + idx, 1, spanLen, out); + idx += spanLen; + col += spanLen; + } + + fputs("\\0", out); + col += len + 2; + } + +// Terminate stringdata struct + fprintf(out, "\"\n};\n"); + fprintf(out, "#undef QT_MOC_LITERAL\n\n"); + +// +// build the data array +// + int index = MetaObjectPrivateFieldCount; fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData()); fprintf(out, "\n // content:\n"); fprintf(out, " %4d, // revision\n", int(QMetaObjectPrivate::OutputRevision)); - fprintf(out, " %4d, // classname\n", strreg(cdef->qualified)); + fprintf(out, " %4d, // classname\n", stridx(cdef->qualified)); fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0); index += cdef->classInfoList.count() * 2; @@ -241,46 +334,6 @@ void Generator::generateCode() // fprintf(out, "\n 0 // eod\n};\n\n"); -// -// Build stringdata array -// - fprintf(out, "static const char qt_meta_stringdata_%s[] = {\n", qualifiedClassNameIdentifier.constData()); - fprintf(out, " \""); - int col = 0; - int len = 0; - for (int i = 0; i < strings.size(); ++i) { - QByteArray s = strings.at(i); - len = s.length(); - if (col && col + len >= 72) { - fprintf(out, "\"\n \""); - col = 0; - } else if (len && s.at(0) >= '0' && s.at(0) <= '9') { - fprintf(out, "\"\""); - len += 2; - } - int idx = 0; - while (idx < s.length()) { - if (idx > 0) { - col = 0; - fprintf(out, "\"\n \""); - } - int spanLen = qMin(70, s.length() - idx); - // don't cut escape sequences at the end of a line - int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1); - if (backSlashPos >= idx) { - int escapeLen = lengthOfEscapeSequence(s, backSlashPos); - spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx); - } - fwrite(s.constData() + idx, 1, spanLen, out); - idx += spanLen; - col += spanLen; - } - - fputs("\\0", out); - col += len + 2; - } - fprintf(out, "\"\n};\n\n"); - // // Generate internal qt_static_metacall() function // @@ -356,8 +409,9 @@ void Generator::generateCode() fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData()); else fprintf(out, " { 0, "); - fprintf(out, "qt_meta_stringdata_%s,\n qt_meta_data_%s, ", - qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData()); + fprintf(out, "qt_meta_stringdata_%s.data,\n" + " qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(), + qualifiedClassNameIdentifier.constData()); if (!hasExtraData) fprintf(out, "0 }\n"); else @@ -379,7 +433,7 @@ void Generator::generateCode() // fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData()); fprintf(out, " if (!_clname) return 0;\n"); - fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s))\n" + fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata))\n" " return static_cast(const_cast< %s*>(this));\n", qualifiedClassNameIdentifier.constData(), cdef->classname.constData()); for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one @@ -430,6 +484,15 @@ void Generator::generateCode() } +void Generator::registerClassInfoStrings() +{ + for (int i = 0; i < cdef->classInfoList.size(); ++i) { + const ClassInfoDef &c = cdef->classInfoList.at(i); + strreg(c.name); + strreg(c.value); + } +} + void Generator::generateClassInfos() { if (cdef->classInfoList.isEmpty()) @@ -439,7 +502,33 @@ void Generator::generateClassInfos() for (int i = 0; i < cdef->classInfoList.size(); ++i) { const ClassInfoDef &c = cdef->classInfoList.at(i); - fprintf(out, " %4d, %4d,\n", strreg(c.name), strreg(c.value)); + fprintf(out, " %4d, %4d,\n", stridx(c.name), stridx(c.value)); + } +} + +void Generator::registerFunctionStrings(const QList& list) +{ + for (int i = 0; i < list.count(); ++i) { + const FunctionDef &f = list.at(i); + + QByteArray sig = f.name + '('; + QByteArray arguments; + + for (int j = 0; j < f.arguments.count(); ++j) { + const ArgumentDef &a = f.arguments.at(j); + if (j) { + sig += ","; + arguments += ","; + } + sig += a.normalizedType; + arguments += a.name; + } + sig += ')'; + + strreg(sig); + strreg(arguments); + strreg(f.normalizedType); + strreg(f.tag); } } @@ -487,8 +576,8 @@ void Generator::generateFunctions(const QList& list, const char *fu flags |= MethodScriptable; if (f.revision > 0) flags |= MethodRevisioned; - fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n", strreg(sig), - strreg(arguments), strreg(f.normalizedType), strreg(f.tag), flags); + fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n", stridx(sig), + stridx(arguments), stridx(f.normalizedType), stridx(f.tag), flags); } } @@ -502,6 +591,15 @@ void Generator::generateFunctionRevisions(const QList& list, const } } +void Generator::registerPropertyStrings() +{ + for (int i = 0; i < cdef->propertyList.count(); ++i) { + const PropertyDef &p = cdef->propertyList.at(i); + strreg(p.name); + strreg(p.type); + } +} + void Generator::generateProperties() { // @@ -568,8 +666,8 @@ void Generator::generateProperties() flags |= Final; fprintf(out, " %4d, %4d, ", - strreg(p.name), - strreg(p.type)); + stridx(p.name), + stridx(p.type)); if (!(flags >> 24) && isQRealType(p.type)) fprintf(out, "(QMetaType::QReal << 24) | "); fprintf(out, "0x%.8x,\n", flags); @@ -596,6 +694,16 @@ void Generator::generateProperties() } } +void Generator::registerEnumStrings() +{ + for (int i = 0; i < cdef->enumList.count(); ++i) { + const EnumDef &e = cdef->enumList.at(i); + strreg(e.name); + for (int j = 0; j < e.values.count(); ++j) + strreg(e.values.at(j)); + } +} + void Generator::generateEnums(int index) { if (cdef->enumDeclarations.isEmpty()) @@ -607,7 +715,7 @@ void Generator::generateEnums(int index) for (i = 0; i < cdef->enumList.count(); ++i) { const EnumDef &e = cdef->enumList.at(i); fprintf(out, " %4d, 0x%.1x, %4d, %4d,\n", - strreg(e.name), + stridx(e.name), cdef->enumDeclarations.value(e.name) ? 1 : 0, e.values.count(), index); @@ -624,7 +732,7 @@ void Generator::generateEnums(int index) code += "::" + e.name; code += "::" + val; fprintf(out, " %4d, uint(%s),\n", - strreg(val), code.constData()); + stridx(val), code.constData()); } } } diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h index 46eee4ca06..c5692f25ae 100644 --- a/src/tools/moc/generator.h +++ b/src/tools/moc/generator.h @@ -55,17 +55,22 @@ public: Generator(ClassDef *classDef, const QList &metaTypes, FILE *outfile = 0); void generateCode(); private: + void registerClassInfoStrings(); void generateClassInfos(); + void registerFunctionStrings(const QList &list); void generateFunctions(const QList &list, const char *functype, int type); void generateFunctionRevisions(const QList& list, const char *functype); + void registerEnumStrings(); void generateEnums(int index); + void registerPropertyStrings(); void generateProperties(); void generateMetacall(); void generateStaticMetacall(); void generateSignal(FunctionDef *def, int index); void generatePluginMetaData(); - int strreg(const QByteArray &); // registers a string and returns its id + void strreg(const QByteArray &); // registers a string + int stridx(const QByteArray &); // returns a string's id QList strings; QByteArray purestSuperClass; QList metaTypes; diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 7b358c1ae8..385390d954 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -818,6 +818,7 @@ void Moc::generate(FILE *out) if (classList.size() && classList.first().classname == "Qt") fprintf(out, "#include \n"); + fprintf(out, "#include \n"); // For QByteArrayData if (mustIncludeQMetaTypeH) fprintf(out, "#include \n"); if (mustIncludeQPluginH) diff --git a/src/tools/moc/outputrevision.h b/src/tools/moc/outputrevision.h index 2ce5b9b765..cff0f98fca 100644 --- a/src/tools/moc/outputrevision.h +++ b/src/tools/moc/outputrevision.h @@ -43,6 +43,6 @@ #define OUTPUTREVISION_H // if the output revision changes, you MUST change it in qobjectdefs.h too -enum { mocOutputRevision = 64 }; // moc format output revision +enum { mocOutputRevision = 65 }; // moc format output revision #endif // OUTPUTREVISION_H diff --git a/tests/auto/corelib/kernel/qobject/moc_oldnormalizeobject.cpp b/tests/auto/corelib/kernel/qobject/moc_oldnormalizeobject.cpp index 2d180b88ea..021079a8e7 100644 --- a/tests/auto/corelib/kernel/qobject/moc_oldnormalizeobject.cpp +++ b/tests/auto/corelib/kernel/qobject/moc_oldnormalizeobject.cpp @@ -90,7 +90,7 @@ static const char qt_meta_stringdata_OldNormalizeObject[] = { }; const QMetaObject OldNormalizeObject::staticMetaObject = { - { &QObject::staticMetaObject, qt_meta_stringdata_OldNormalizeObject, + { &QObject::staticMetaObject, reinterpret_cast(qt_meta_stringdata_OldNormalizeObject), qt_meta_data_OldNormalizeObject, 0 } }; -- cgit v1.2.3