From 92d75077d686fcad26b5ad02a40c3987fb1fc82b Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Mon, 29 Oct 2012 17:14:07 +0100 Subject: QTranslator: Use resource memory instead of copying it Previously, translations in resource files were loaded through QFile and the data was copied. Now, simply use the resource memory in-place. Change-Id: I55a06c1e7bb15c169cc69b908b3021136beac9d2 Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qtranslator.cpp | 101 ++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 35 deletions(-) diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index c4486d3ae6..f934202cf6 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -58,6 +58,7 @@ #include "qtranslator_p.h" #include "qlocale.h" #include "qendian.h" +#include "qresource.h" #if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) #define QT_USE_MMAP @@ -292,16 +293,19 @@ public: #if defined(QT_USE_MMAP) used_mmap(0), #endif - unmapPointer(0), unmapLength(0), + unmapPointer(0), unmapLength(0), resource(0), messageArray(0), offsetArray(0), contextArray(0), numerusRulesArray(0), messageLength(0), offsetLength(0), contextLength(0), numerusRulesLength(0) {} #if defined(QT_USE_MMAP) bool used_mmap : 1; #endif - char *unmapPointer; // owned memory (mmap or new) + char *unmapPointer; // used memory (mmap, new or resource file) quint32 unmapLength; + // The resource object in case we loaded the translations from a resource + QResource *resource; + // used if the translator has dependencies QList subTranslators; @@ -518,22 +522,42 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo QTranslatorPrivate *d = this; bool ok = false; - QFile file(realname); - if (!file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) - return false; + if (realname.startsWith(':')) { + // If the translation is in a non-compressed resource file, the data is already in + // memory, so no need to use QFile to copy it again. + Q_ASSERT(!d->resource); + d->resource = new QResource(realname); + if (resource->isValid() && !resource->isCompressed() && resource->size() > MagicLength + && !memcmp(resource->data(), magic, MagicLength)) { + d->unmapLength = resource->size(); + d->unmapPointer = reinterpret_cast(const_cast(resource->data())); +#if defined(QT_USE_MMAP) + d->used_mmap = false; +#endif + ok = true; + } else { + delete resource; + resource = 0; + } + } - qint64 fileSize = file.size(); - if (fileSize <= MagicLength || quint32(-1) <= fileSize) - return false; + if (!ok) { + QFile file(realname); + if (!file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) + return false; - { - char magicBuffer[MagicLength]; - if (MagicLength != file.read(magicBuffer, MagicLength) - || memcmp(magicBuffer, magic, MagicLength)) + qint64 fileSize = file.size(); + if (fileSize <= MagicLength || quint32(-1) <= fileSize) return false; - } - d->unmapLength = quint32(fileSize); + { + char magicBuffer[MagicLength]; + if (MagicLength != file.read(magicBuffer, MagicLength) + || memcmp(magicBuffer, magic, MagicLength)) + return false; + } + + d->unmapLength = quint32(fileSize); #ifdef QT_USE_MMAP @@ -544,30 +568,31 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo #define MAP_FAILED -1 #endif - int fd = file.handle(); - if (fd >= 0) { - char *ptr; - ptr = reinterpret_cast( - mmap(0, d->unmapLength, // any address, whole file - PROT_READ, // read-only memory - MAP_FILE | MAP_PRIVATE, // swap-backed map from file - fd, 0)); // from offset 0 of fd - if (ptr && ptr != reinterpret_cast(MAP_FAILED)) { - file.close(); - d->used_mmap = true; - d->unmapPointer = ptr; - ok = true; + int fd = file.handle(); + if (fd >= 0) { + char *ptr; + ptr = reinterpret_cast( + mmap(0, d->unmapLength, // any address, whole file + PROT_READ, // read-only memory + MAP_FILE | MAP_PRIVATE, // swap-backed map from file + fd, 0)); // from offset 0 of fd + if (ptr && ptr != reinterpret_cast(MAP_FAILED)) { + file.close(); + d->used_mmap = true; + d->unmapPointer = ptr; + ok = true; + } } - } #endif // QT_USE_MMAP - if (!ok) { - d->unmapPointer = new char[d->unmapLength]; - if (d->unmapPointer) { - file.seek(0); - qint64 readResult = file.read(d->unmapPointer, d->unmapLength); - if (readResult == qint64(unmapLength)) - ok = true; + if (!ok) { + d->unmapPointer = new char[d->unmapLength]; + if (d->unmapPointer) { + file.seek(0); + qint64 readResult = file.read(d->unmapPointer, d->unmapLength); + if (readResult == qint64(unmapLength)) + ok = true; + } } } @@ -580,8 +605,11 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo munmap(unmapPointer, unmapLength); } else #endif + if (!d->resource) delete [] unmapPointer; + delete d->resource; + d->resource = 0; d->unmapPointer = 0; d->unmapLength = 0; @@ -1030,9 +1058,12 @@ void QTranslatorPrivate::clear() munmap(unmapPointer, unmapLength); } else #endif + if (!resource) delete [] unmapPointer; } + delete resource; + resource = 0; unmapPointer = 0; unmapLength = 0; messageArray = 0; -- cgit v1.2.3