summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2012-02-19 00:15:00 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-29 12:50:14 +0100
commitf95181c7bb340744a0ce172e8c5a8fcdc2543297 (patch)
tree98f564183796f3b271c3ebe5de437bef18675aed /src/tools
parent96f2365cf4cebc074c3171878dcd25ce19ee7486 (diff)
Long live Qt5 meta-object method/property descriptors
This commit introduces two significant changes to the meta-object data format: 1) Meta-type information (QMetaType type/name) information is stored directly in the meta-data for both properties and methods; 2) The original signature (string) of a method is no longer stored in the meta-data, since it can be reconstructed from the method name and parameter type info. The motivation for this change is to enable direct access to method names and type information (avoiding string-based lookup for types if possible), since that's typically the information language bindings (e.g. QML) need. (moc already had all the desired information about methods, but it threw it away!) This change keeps support for the older (6 and below) meta-object revisions, but the support will be removed after a short grace period. The following public QMetaMethod functions have been added: name() : QByteArray returnType() : int parameterCount() : int parameterType(int index) : int The following internal QMetaMethod function has been added: getParameterTypes(int *types) : void This commit extends the meta-method data to include explicit type/name data for methods. The new data follows the existing (5-word) method descriptors in the meta-data. The method descriptor format was modified to enable this. First, the descriptor now contains the meta-data index where the method's type/name information can be found. Second, the descriptor contains the number of parameters. Third, the descriptor has a reference to the name of the method, not the full signature. Each entry of a method's type/name array contains either the type id (if it could be determined at meta-object definition time), or a reference to the name of the type (so that the type id can be resolved at runtime). Lastly, instead of storing the method parameter names as a comma-separated list that needs to be parsed at runtime (which was how it was done prior to this commit), the names are now stored as separate entries in the meta-object string table, and their indexes are stored immediately after the method type info array. Hence, parameter names can be queried through the public API without parsing/allocating/copying, too. Task-number: QTBUG-24154 Change-Id: Idb7ab81f12d4bfd658b74e18a0fce594f580cba3 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/moc/generator.cpp183
-rw-r--r--src/tools/moc/generator.h3
-rw-r--r--src/tools/moc/moc.cpp5
-rw-r--r--src/tools/moc/moc.h3
4 files changed, 127 insertions, 67 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 9571af4bd5..73a0605028 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -54,7 +54,7 @@
QT_BEGIN_NAMESPACE
-uint qvariant_nameToType(const QByteArray &name)
+uint nameToBuiltinType(const QByteArray &name)
{
if (name.isEmpty())
return 0;
@@ -64,20 +64,27 @@ uint qvariant_nameToType(const QByteArray &name)
}
/*
- Returns true if the type is a QVariant types.
+ Returns true if the type is a built-in type.
*/
-bool isVariantType(const QByteArray &type)
-{
- return qvariant_nameToType(type) != 0;
+bool isBuiltinType(const QByteArray &type)
+ {
+ int id = QMetaType::type(type.constData());
+ if (!id && !type.isEmpty() && type != "void")
+ return false;
+ return (id < QMetaType::User);
}
-/*!
- Returns true if the type is qreal.
-*/
-static bool isQRealType(const QByteArray &type)
-{
- return (type == "qreal");
-}
+static const char *metaTypeEnumValueString(int type)
+ {
+#define RETURN_METATYPENAME_STRING(MetaTypeName, MetaTypeId, RealType) \
+ case QMetaType::MetaTypeName: return #MetaTypeName;
+
+ switch (type) {
+QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
+ }
+#undef RETURN_METATYPENAME_STRING
+ return 0;
+ }
Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile)
: out(outfile), cdef(classDef), metaTypes(metaTypes)
@@ -122,6 +129,17 @@ int Generator::stridx(const QByteArray &s)
return i;
}
+// Returns the sum of all parameters (including return type) for the given
+// \a list of methods. This is needed for calculating the size of the methods'
+// parameter type/name meta-data.
+static int aggregateParameterCount(const QList<FunctionDef> &list)
+{
+ int sum = 0;
+ for (int i = 0; i < list.count(); ++i)
+ sum += list.at(i).arguments.count() + 1; // +1 for return type
+ return sum;
+}
+
void Generator::generateCode()
{
bool isQt = (cdef->classname == "Qt");
@@ -266,6 +284,15 @@ void Generator::generateCode()
index += methodCount * 5;
if (cdef->revisionedMethods)
index += methodCount;
+ int paramsIndex = index;
+ int totalParameterCount = aggregateParameterCount(cdef->signalList)
+ + aggregateParameterCount(cdef->slotList)
+ + aggregateParameterCount(cdef->methodList)
+ + aggregateParameterCount(cdef->constructorList);
+ index += totalParameterCount * 2 // types and parameter names
+ - methodCount // return "parameters" don't have names
+ - cdef->constructorList.count(); // "this" parameters don't have names
+
fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0);
index += cdef->propertyList.count() * 3;
if(cdef->notifyableProperties)
@@ -292,17 +319,17 @@ void Generator::generateCode()
//
// Build signals array first, otherwise the signal indices would be wrong
//
- generateFunctions(cdef->signalList, "signal", MethodSignal);
+ generateFunctions(cdef->signalList, "signal", MethodSignal, paramsIndex);
//
// Build slots array
//
- generateFunctions(cdef->slotList, "slot", MethodSlot);
+ generateFunctions(cdef->slotList, "slot", MethodSlot, paramsIndex);
//
// Build method array
//
- generateFunctions(cdef->methodList, "method", MethodMethod);
+ generateFunctions(cdef->methodList, "method", MethodMethod, paramsIndex);
//
// Build method version arrays
@@ -314,6 +341,15 @@ void Generator::generateCode()
}
//
+// Build method parameters array
+//
+ generateFunctionParameters(cdef->signalList, "signal");
+ generateFunctionParameters(cdef->slotList, "slot");
+ generateFunctionParameters(cdef->methodList, "method");
+ if (isConstructible)
+ generateFunctionParameters(cdef->constructorList, "constructor");
+
+//
// Build property array
//
generateProperties();
@@ -327,7 +363,7 @@ void Generator::generateCode()
// Build constructors array
//
if (isConstructible)
- generateFunctions(cdef->constructorList, "constructor", MethodConstructor);
+ generateFunctions(cdef->constructorList, "constructor", MethodConstructor, paramsIndex);
//
// Terminate data array
@@ -346,7 +382,7 @@ void Generator::generateCode()
QList<QByteArray> extraList;
for (int i = 0; i < cdef->propertyList.count(); ++i) {
const PropertyDef &p = cdef->propertyList.at(i);
- if (!isVariantType(p.type) && !metaTypes.contains(p.type) && !p.type.contains('*') &&
+ if (!isBuiltinType(p.type) && !metaTypes.contains(p.type) && !p.type.contains('*') &&
!p.type.contains('<') && !p.type.contains('>')) {
int s = p.type.lastIndexOf("::");
if (s > 0) {
@@ -511,50 +547,29 @@ void Generator::registerFunctionStrings(const QList<FunctionDef>& list)
for (int i = 0; i < list.count(); ++i) {
const FunctionDef &f = list.at(i);
- QByteArray sig = f.name + '(';
- QByteArray arguments;
+ strreg(f.name);
+ if (!isBuiltinType(f.normalizedType))
+ strreg(f.normalizedType);
+ strreg(f.tag);
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;
+ if (!isBuiltinType(a.normalizedType))
+ strreg(a.normalizedType);
+ strreg(a.name);
}
- sig += ')';
-
- strreg(sig);
- strreg(arguments);
- strreg(f.normalizedType);
- strreg(f.tag);
}
}
-void Generator::generateFunctions(const QList<FunctionDef>& list, const char *functype, int type)
+void Generator::generateFunctions(const QList<FunctionDef>& list, const char *functype, int type, int &paramsIndex)
{
if (list.isEmpty())
return;
- fprintf(out, "\n // %ss: signature, parameters, type, tag, flags\n", functype);
+ fprintf(out, "\n // %ss: name, argc, parameters, tag, flags\n", functype);
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 += ')';
-
unsigned char flags = type;
if (f.access == FunctionDef::Private)
flags |= AccessPrivate;
@@ -576,8 +591,12 @@ void Generator::generateFunctions(const QList<FunctionDef>& list, const char *fu
flags |= MethodScriptable;
if (f.revision > 0)
flags |= MethodRevisioned;
- fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n", stridx(sig),
- stridx(arguments), stridx(f.normalizedType), stridx(f.tag), flags);
+
+ int argc = f.arguments.count();
+ fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n",
+ stridx(f.name), argc, paramsIndex, stridx(f.tag), flags);
+
+ paramsIndex += 1 + argc * 2;
}
}
@@ -591,12 +610,51 @@ void Generator::generateFunctionRevisions(const QList<FunctionDef>& list, const
}
}
+void Generator::generateFunctionParameters(const QList<FunctionDef>& list, const char *functype)
+{
+ if (list.isEmpty())
+ return;
+ fprintf(out, "\n // %ss: parameters\n", functype);
+ for (int i = 0; i < list.count(); ++i) {
+ const FunctionDef &f = list.at(i);
+ fprintf(out, " ");
+
+ // Types
+ for (int j = -1; j < f.arguments.count(); ++j) {
+ if (j > -1)
+ fputc(' ', out);
+ const QByteArray &typeName = (j < 0) ? f.normalizedType : f.arguments.at(j).normalizedType;
+ if (isBuiltinType(typeName)) {
+ int type = nameToBuiltinType(typeName);
+ const char *valueString = metaTypeEnumValueString(type);
+ if (valueString)
+ fprintf(out, "QMetaType::%s", valueString);
+ else
+ fprintf(out, "%4d", type);
+ } else {
+ Q_ASSERT(!typeName.isEmpty());
+ fprintf(out, "0x%.8x | %d", IsUnresolvedType, stridx(typeName));
+ }
+ fputc(',', out);
+ }
+
+ // Parameter names
+ for (int j = 0; j < f.arguments.count(); ++j) {
+ const ArgumentDef &arg = f.arguments.at(j);
+ fprintf(out, " %4d,", stridx(arg.name));
+ }
+
+ fprintf(out, "\n");
+ }
+}
+
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);
+ if (!isBuiltinType(p.type))
+ strreg(p.type);
}
}
@@ -611,11 +669,8 @@ void Generator::generateProperties()
for (int i = 0; i < cdef->propertyList.count(); ++i) {
const PropertyDef &p = cdef->propertyList.at(i);
uint flags = Invalid;
- if (!isVariantType(p.type)) {
+ if (!isBuiltinType(p.type))
flags |= EnumOrFlag;
- } else if (!isQRealType(p.type)) {
- flags |= qvariant_nameToType(p.type) << 24;
- }
if (!p.read.isEmpty())
flags |= Readable;
if (!p.write.isEmpty()) {
@@ -665,12 +720,20 @@ void Generator::generateProperties()
if (p.final)
flags |= Final;
- fprintf(out, " %4d, %4d, ",
- stridx(p.name),
- stridx(p.type));
- if (!(flags >> 24) && isQRealType(p.type))
- fprintf(out, "(QMetaType::QReal << 24) | ");
- fprintf(out, "0x%.8x,\n", flags);
+ fprintf(out, " %4d, ", stridx(p.name));
+
+ if (isBuiltinType(p.type)) {
+ int type = nameToBuiltinType(p.type);
+ const char *valueString = metaTypeEnumValueString(type);
+ if (valueString)
+ fprintf(out, "QMetaType::%s", valueString);
+ else
+ fprintf(out, "%4d", type);
+ } else {
+ fprintf(out, "0x%.8x | %d", IsUnresolvedType, stridx(p.type));
+ }
+
+ fprintf(out, ", 0x%.8x,\n", flags);
}
if(cdef->notifyableProperties) {
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index c5692f25ae..c85d24fd15 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -58,8 +58,9 @@ private:
void registerClassInfoStrings();
void generateClassInfos();
void registerFunctionStrings(const QList<FunctionDef> &list);
- void generateFunctions(const QList<FunctionDef> &list, const char *functype, int type);
+ void generateFunctions(const QList<FunctionDef> &list, const char *functype, int type, int &paramsIndex);
void generateFunctionRevisions(const QList<FunctionDef>& list, const char *functype);
+ void generateFunctionParameters(const QList<FunctionDef> &list, const char *functype);
void registerEnumStrings();
void generateEnums(int index);
void registerPropertyStrings();
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 385390d954..49fc29592d 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -819,8 +819,7 @@ void Moc::generate(FILE *out)
fprintf(out, "#include <QtCore/qobject.h>\n");
fprintf(out, "#include <QtCore/qbytearray.h>\n"); // For QByteArrayData
- if (mustIncludeQMetaTypeH)
- fprintf(out, "#include <QtCore/qmetatype.h>\n");
+ fprintf(out, "#include <QtCore/qmetatype.h>\n"); // For QMetaType::Type
if (mustIncludeQPluginH)
fprintf(out, "#include <QtCore/qplugin.h>\n");
@@ -977,8 +976,6 @@ void Moc::createPropertyDef(PropertyDef &propDef)
type = "qlonglong";
else if (type == "ULongLong")
type = "qulonglong";
- else if (type == "qreal")
- mustIncludeQMetaTypeH = true;
propDef.type = type;
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index aedb97b234..e20e29acb8 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -198,14 +198,13 @@ class Moc : public Parser
{
public:
Moc()
- : noInclude(false), generatedCode(false), mustIncludeQMetaTypeH(false), mustIncludeQPluginH(false)
+ : noInclude(false), generatedCode(false), mustIncludeQPluginH(false)
{}
QByteArray filename;
bool noInclude;
bool generatedCode;
- bool mustIncludeQMetaTypeH;
bool mustIncludeQPluginH;
QByteArray includePath;
QList<QByteArray> includeFiles;