qmetaobjectbuilder: Store only unique strings in the string table
Do like moc: If the string has already been entered into the table, just return its position, don't make a new copy. This can save space, for example, if there are several properties of the same type; the typename only occurs once in the string table but will be referenced by several property descriptors. Change-Id: Ic0087697716cab1c6449ea51c0c758a6fd1a1c82 Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com> Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@nokia.com> Reviewed-by: Kent Hansen <kent.hansen@nokia.com>bb10
parent
6a6425dff5
commit
e0d26ebe2e
|
|
@ -1070,21 +1070,35 @@ int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
|
|||
#define ALIGN(size,type) \
|
||||
(size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
|
||||
|
||||
// Build a string into a QMetaObject representation. Returns the
|
||||
// position in the string table where the string was placed.
|
||||
static int buildString
|
||||
(char *buf, char *str, int *offset, const QByteArray& value, int empty)
|
||||
class MetaStringTable
|
||||
{
|
||||
if (value.size() == 0 && empty >= 0)
|
||||
return empty;
|
||||
if (buf) {
|
||||
memcpy(str + *offset, value.constData(), value.size());
|
||||
str[*offset + value.size()] = '\0';
|
||||
public:
|
||||
typedef QHash<QByteArray, int> Entries; // string --> offset mapping
|
||||
typedef Entries::const_iterator const_iterator;
|
||||
Entries::const_iterator constBegin() const
|
||||
{ return m_entries.constBegin(); }
|
||||
Entries::const_iterator constEnd() const
|
||||
{ return m_entries.constEnd(); }
|
||||
|
||||
MetaStringTable() : m_offset(0) {}
|
||||
|
||||
int enter(const QByteArray &value)
|
||||
{
|
||||
Entries::iterator it = m_entries.find(value);
|
||||
if (it != m_entries.end())
|
||||
return it.value();
|
||||
int pos = m_offset;
|
||||
m_entries.insert(value, pos);
|
||||
m_offset += value.size() + 1;
|
||||
return pos;
|
||||
}
|
||||
int posn = *offset;
|
||||
*offset += value.size() + 1;
|
||||
return posn;
|
||||
}
|
||||
|
||||
int arraySize() const { return m_offset; }
|
||||
|
||||
private:
|
||||
Entries m_entries;
|
||||
int m_offset;
|
||||
};
|
||||
|
||||
// Build the parameter array string for a method.
|
||||
static QByteArray buildParameterNames
|
||||
|
|
@ -1240,19 +1254,14 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
|||
// Reset the current data position to just past the QMetaObjectPrivate.
|
||||
dataIndex = MetaObjectPrivateFieldCount;
|
||||
|
||||
// Add the class name to the string table.
|
||||
int offset = 0;
|
||||
buildString(buf, str, &offset, d->className, -1);
|
||||
|
||||
// Add a common empty string, which is used to indicate "void"
|
||||
// method returns, empty tag strings, etc.
|
||||
int empty = buildString(buf, str, &offset, QByteArray(), -1);
|
||||
MetaStringTable strings;
|
||||
strings.enter(d->className);
|
||||
|
||||
// Output the class infos,
|
||||
Q_ASSERT(!buf || dataIndex == pmeta->classInfoData);
|
||||
for (index = 0; index < d->classInfoNames.size(); ++index) {
|
||||
int name = buildString(buf, str, &offset, d->classInfoNames[index], empty);
|
||||
int value = buildString(buf, str, &offset, d->classInfoValues[index], empty);
|
||||
int name = strings.enter(d->classInfoNames[index]);
|
||||
int value = strings.enter(d->classInfoValues[index]);
|
||||
if (buf) {
|
||||
data[dataIndex] = name;
|
||||
data[dataIndex + 1] = value;
|
||||
|
|
@ -1264,13 +1273,13 @@ 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 = buildString(buf, str, &offset, method->signature, empty);
|
||||
int sig = strings.enter(method->signature);
|
||||
int params;
|
||||
QByteArray names = buildParameterNames
|
||||
(method->signature, method->parameterNames);
|
||||
params = buildString(buf, str, &offset, names, empty);
|
||||
int ret = buildString(buf, str, &offset, method->returnType, empty);
|
||||
int tag = buildString(buf, str, &offset, method->tag, empty);
|
||||
params = strings.enter(names);
|
||||
int ret = strings.enter(method->returnType);
|
||||
int tag = strings.enter(method->tag);
|
||||
int attrs = method->attributes;
|
||||
if (buf) {
|
||||
data[dataIndex] = sig;
|
||||
|
|
@ -1296,8 +1305,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
|||
Q_ASSERT(!buf || dataIndex == pmeta->propertyData);
|
||||
for (index = 0; index < d->properties.size(); ++index) {
|
||||
QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
|
||||
int name = buildString(buf, str, &offset, prop->name, empty);
|
||||
int type = buildString(buf, str, &offset, prop->type, empty);
|
||||
int name = strings.enter(prop->name);
|
||||
int type = strings.enter(prop->type);
|
||||
int flags = prop->flags;
|
||||
|
||||
if (!isVariantType(prop->type)) {
|
||||
|
|
@ -1338,7 +1347,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
|||
Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData);
|
||||
for (index = 0; index < d->enumerators.size(); ++index) {
|
||||
QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
|
||||
int name = buildString(buf, str, &offset, enumerator->name, empty);
|
||||
int name = strings.enter(enumerator->name);
|
||||
int isFlag = (int)(enumerator->isFlag);
|
||||
int count = enumerator->keys.size();
|
||||
int enumOffset = enumIndex;
|
||||
|
|
@ -1349,7 +1358,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
|||
data[dataIndex + 3] = enumOffset;
|
||||
}
|
||||
for (int key = 0; key < count; ++key) {
|
||||
int keyIndex = buildString(buf, str, &offset, enumerator->keys[key], empty);
|
||||
int keyIndex = strings.enter(enumerator->keys[key]);
|
||||
if (buf) {
|
||||
data[enumOffset++] = keyIndex;
|
||||
data[enumOffset++] = enumerator->values[key];
|
||||
|
|
@ -1363,13 +1372,13 @@ 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 = buildString(buf, str, &offset, method->signature, empty);
|
||||
int sig = strings.enter(method->signature);
|
||||
int params;
|
||||
QByteArray names = buildParameterNames
|
||||
(method->signature, method->parameterNames);
|
||||
params = buildString(buf, str, &offset, names, empty);
|
||||
int ret = buildString(buf, str, &offset, method->returnType, empty);
|
||||
int tag = buildString(buf, str, &offset, method->tag, empty);
|
||||
params = strings.enter(names);
|
||||
int ret = strings.enter(method->returnType);
|
||||
int tag = strings.enter(method->tag);
|
||||
int attrs = method->attributes;
|
||||
if (buf) {
|
||||
data[dataIndex] = sig;
|
||||
|
|
@ -1381,9 +1390,16 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
|||
dataIndex += 5;
|
||||
}
|
||||
|
||||
// One more empty string to act as a terminator.
|
||||
buildString(buf, str, &offset, QByteArray(), -1);
|
||||
size += offset;
|
||||
size += strings.arraySize();
|
||||
|
||||
if (buf) {
|
||||
// Write strings to string data array.
|
||||
MetaStringTable::const_iterator it;
|
||||
for (it = strings.constBegin(); it != strings.constEnd(); ++it) {
|
||||
memcpy(str + it.value(), it.key().constData(), it.key().size());
|
||||
str[it.value() + it.key().size()] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// Output the zero terminator in the data array.
|
||||
if (buf)
|
||||
|
|
|
|||
Loading…
Reference in New Issue