From d48ffdd2982999873d9a2bdbe0adbd005659d10b Mon Sep 17 00:00:00 2001 From: kh1 Date: Wed, 4 Sep 2013 12:59:11 +0200 Subject: Rewrite function to use QFile::map(). Once the data is mapped into memory, searching backwards is way faster. Change-Id: I31667095712cfba95a8255e04d217ed9242fd2a8 Reviewed-by: Niels Weber Reviewed-by: Kai Koehne Reviewed-by: Tim Jenssen --- src/libs/installer/binaryformat.cpp | 46 ++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/libs/installer/binaryformat.cpp b/src/libs/installer/binaryformat.cpp index b07cc90de..8e79e84c3 100644 --- a/src/libs/installer/binaryformat.cpp +++ b/src/libs/installer/binaryformat.cpp @@ -55,6 +55,7 @@ #include #include +#include using namespace QInstaller; using namespace QInstallerCreator; @@ -220,33 +221,26 @@ qint64 QInstaller::findMagicCookie(QFile *in, quint64 magicCookie) Q_ASSERT(in); Q_ASSERT(in->isOpen()); Q_ASSERT(in->isReadable()); - const qint64 oldPos = in->pos(); - const qint64 MAX_SEARCH = 1024 * 1024; // stop searching after one MB - qint64 searched = 0; - try { - while (searched < MAX_SEARCH) { - const qint64 pos = in->size() - searched - sizeof(qint64); - if (pos < 0) - throw Error(QObject::tr("Searched whole file, no marker found")); - if (!in->seek(pos)) { - throw Error(QObject::tr("Could not seek to %1 in file %2: %3").arg(QString::number(pos), - in->fileName(), in->errorString())); - } - const quint64 num = static_cast(retrieveInt64(in)); - if (num == magicCookie) { - in->seek(oldPos); - return pos; - } - searched += 1; - } - throw Error(QObject::tr("No marker found, stopped after %1.").arg(humanReadableSize(MAX_SEARCH))); - } catch (const Error& err) { - in->seek(oldPos); - throw err; - } catch (...) { - in->seek(oldPos); - throw Error(QObject::tr("No marker found, unknown exception caught.")); + + const qint64 fileSize = in->size(); + const size_t markerSize = sizeof(qint64); + + // Search through 1MB, if smaller through the whole file. Note: QFile::map() does not change QFile::pos(). + const qint64 maxSearch = qMin((1024LL * 1024LL), fileSize); + const uchar *const mapped = in->map(fileSize - maxSearch, maxSearch); + if (!mapped) { + throw Error(QObject::tr("Could not map %1 from file %2: %3").arg(QString::number(maxSearch), + in->fileName(), in->errorString())); + } + + qint64 searched = maxSearch - markerSize; + while (searched >= 0) { + if (memcmp(&magicCookie, (mapped + searched), markerSize) == 0) + return (fileSize - maxSearch) + searched; + searched -= markerSize; } + throw Error(QObject::tr("No marker found, stopped after %1.").arg(humanReadableSize(maxSearch))); + return -1; // never reached } -- cgit v1.2.3