Port QMetaObjectBuilder to Qt5 meta-property/method descriptor format

This adapts QMOB to be in sync with the moc/meta-object changes for
property and method descriptors (storing the name and argument count
of methods, and more elaborate type information).

Change-Id: Ia32a115643e99e39d76e46a9171219cbba522233
Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
bb10
Kent Hansen 2012-02-19 13:09:24 +01:00 committed by Qt by Nokia
parent dc6b8112e3
commit 4a28fecd36
1 changed files with 88 additions and 77 deletions

View File

@ -78,26 +78,17 @@ QT_BEGIN_NAMESPACE
*/
// copied from moc's generator.cpp
uint qvariant_nameToType(const char* name)
bool isBuiltinType(const QByteArray &type)
{
if (!name)
return 0;
uint tp = QMetaType::type(name);
return tp < QMetaType::User ? tp : 0;
}
/*
Returns true if the type is a QVariant types.
*/
bool isVariantType(const char* type)
{
return qvariant_nameToType(type) != 0;
int id = QMetaType::type(type);
if (!id && !type.isEmpty() && type != "void")
return false;
return (id < QMetaType::User);
}
// copied from qmetaobject.cpp
static inline const QMetaObjectPrivate *priv(const uint* data)
{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
// end of copied lines from qmetaobject.cpp
class QMetaMethodBuilderPrivate
{
@ -141,6 +132,16 @@ public:
{
return QMetaObjectPrivate::parameterTypeNamesFromSignature(signature);
}
int parameterCount() const
{
return parameterTypes().size();
}
QByteArray name() const
{
return signature.left(qMax(signature.indexOf('('), 0));
}
};
class QMetaPropertyBuilderPrivate
@ -1142,45 +1143,15 @@ void QMetaStringTable::writeBlob(char *out)
}
}
// Build the parameter array string for a method.
static QByteArray buildParameterNames
(const QByteArray& signature, const QList<QByteArray>& parameterNames)
// Returns the sum of all parameters (including return type) for the given
// \a methods. This is needed for calculating the size of the methods'
// parameter type/name meta-data.
static int aggregateParameterCount(const QList<QMetaMethodBuilderPrivate> &methods)
{
// If the parameter name list is specified, then concatenate them.
if (!parameterNames.isEmpty()) {
QByteArray names;
bool first = true;
foreach (const QByteArray &name, parameterNames) {
if (first)
first = false;
else
names += (char)',';
names += name;
}
return names;
}
// Count commas in the signature, excluding those inside template arguments.
int index = signature.indexOf('(');
if (index < 0)
return QByteArray();
++index;
if (index >= signature.size())
return QByteArray();
if (signature[index] == ')')
return QByteArray();
int count = 1;
int brackets = 0;
while (index < signature.size() && signature[index] != ',') {
char ch = signature[index++];
if (ch == '<')
++brackets;
else if (ch == '>')
--brackets;
else if (ch == ',' && brackets <= 0)
++count;
}
return QByteArray(count - 1, ',');
int sum = 0;
for (int i = 0; i < methods.size(); ++i)
sum += methods.at(i).parameterCount() + 1; // +1 for return type
return sum;
}
// Build a QMetaObject in "buf" based on the information in "d".
@ -1193,6 +1164,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_UNUSED(expectedSize); // Avoid warning in release mode
int size = 0;
int dataIndex;
int paramsIndex;
int enumIndex;
int index;
bool hasRevisionedMethods = d->hasRevisionedMethods();
@ -1223,6 +1195,11 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
break;
}
}
int methodParametersDataSize =
((aggregateParameterCount(d->methods)
+ aggregateParameterCount(d->constructors)) * 2) // types and parameter names
- d->methods.size() // return "parameters" don't have names
- d->constructors.size(); // "this" parameters don't have names
if (buf) {
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QMetaObjectBuilder should generate the same version as moc");
pmeta->revision = QMetaObjectPrivate::OutputRevision;
@ -1239,6 +1216,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
dataIndex += 5 * d->methods.size();
if (hasRevisionedMethods)
dataIndex += d->methods.size();
paramsIndex = dataIndex;
dataIndex += methodParametersDataSize;
pmeta->propertyCount = d->properties.size();
pmeta->propertyData = dataIndex;
@ -1260,6 +1239,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
dataIndex += 5 * d->methods.size();
if (hasRevisionedMethods)
dataIndex += d->methods.size();
paramsIndex = dataIndex;
dataIndex += methodParametersDataSize;
dataIndex += 3 * d->properties.size();
if (hasNotifySignals)
dataIndex += d->properties.size();
@ -1316,24 +1297,21 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->methodData);
for (index = 0; index < d->methods.size(); ++index) {
QMetaMethodBuilderPrivate *method = &(d->methods[index]);
int sig = strings.enter(method->signature);
int params;
QByteArray names = buildParameterNames
(method->signature, method->parameterNames);
params = strings.enter(names);
int ret = strings.enter(method->returnType);
int name = strings.enter(method->name());
int argc = method->parameterCount();
int tag = strings.enter(method->tag);
int attrs = method->attributes;
if (buf) {
data[dataIndex] = sig;
data[dataIndex + 1] = params;
data[dataIndex + 2] = ret;
data[dataIndex] = name;
data[dataIndex + 1] = argc;
data[dataIndex + 2] = paramsIndex;
data[dataIndex + 3] = tag;
data[dataIndex + 4] = attrs;
if (method->methodType() == QMetaMethod::Signal)
pmeta->signalCount++;
}
dataIndex += 5;
paramsIndex += 1 + argc * 2;
}
if (hasRevisionedMethods) {
for (index = 0; index < d->methods.size(); ++index) {
@ -1344,23 +1322,59 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
}
}
// Output the method parameters in the class.
Q_ASSERT(!buf || dataIndex == pmeta->methodData + d->methods.size() * 5
+ (hasRevisionedMethods ? d->methods.size() : 0));
for (int x = 0; x < 2; ++x) {
QList<QMetaMethodBuilderPrivate> &methods = (x == 0) ? d->methods : d->constructors;
for (index = 0; index < methods.size(); ++index) {
QMetaMethodBuilderPrivate *method = &(methods[index]);
QList<QByteArray> paramTypeNames = method->parameterTypes();
int paramCount = paramTypeNames.size();
for (int i = -1; i < paramCount; ++i) {
const QByteArray &typeName = (i < 0) ? method->returnType : paramTypeNames.at(i);
int typeInfo;
if (isBuiltinType(typeName))
typeInfo = QMetaType::type(typeName);
else
typeInfo = IsUnresolvedType | strings.enter(typeName);
if (buf)
data[dataIndex] = typeInfo;
++dataIndex;
}
QList<QByteArray> paramNames = method->parameterNames;
while (paramNames.size() < paramCount)
paramNames.append(QByteArray());
for (int i = 0; i < paramCount; ++i) {
int stringIndex = strings.enter(paramNames.at(i));
if (buf)
data[dataIndex] = stringIndex;
++dataIndex;
}
}
}
// Output the properties in the class.
Q_ASSERT(!buf || dataIndex == pmeta->propertyData);
for (index = 0; index < d->properties.size(); ++index) {
QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
int name = strings.enter(prop->name);
int type = strings.enter(prop->type);
int typeInfo;
if (isBuiltinType(prop->type))
typeInfo = QMetaType::type(prop->type);
else
typeInfo = IsUnresolvedType | strings.enter(prop->type);
int flags = prop->flags;
if (!isVariantType(prop->type)) {
if (!isBuiltinType(prop->type))
flags |= EnumOrFlag;
} else {
flags |= qvariant_nameToType(prop->type) << 24;
}
if (buf) {
data[dataIndex] = name;
data[dataIndex + 1] = type;
data[dataIndex + 1] = typeInfo;
data[dataIndex + 2] = flags;
}
dataIndex += 3;
@ -1415,22 +1429,19 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->constructorData);
for (index = 0; index < d->constructors.size(); ++index) {
QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
int sig = strings.enter(method->signature);
int params;
QByteArray names = buildParameterNames
(method->signature, method->parameterNames);
params = strings.enter(names);
int ret = strings.enter(method->returnType);
int name = strings.enter(method->name());
int argc = method->parameterCount();
int tag = strings.enter(method->tag);
int attrs = method->attributes;
if (buf) {
data[dataIndex] = sig;
data[dataIndex + 1] = params;
data[dataIndex + 2] = ret;
data[dataIndex] = name;
data[dataIndex + 1] = argc;
data[dataIndex + 2] = paramsIndex;
data[dataIndex + 3] = tag;
data[dataIndex + 4] = attrs;
}
dataIndex += 5;
paramsIndex += 1 + argc * 2;
}
size += strings.blobSize();