summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2012-02-06 15:38:34 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-16 01:57:22 +0100
commite0d26ebe2e09c3d5756859972f9a71873786318a (patch)
tree5cff261a5bcc4c23533b9354daeabe40e72c05ca /src/corelib/kernel
parent6a6425dff5fb12bf7522dd3c0894a43336667263 (diff)
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>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp90
1 files changed, 53 insertions, 37 deletions
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index e22257b0d8..8bece6636b 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -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)