diff options
author | kh1 <karsten.heimrich@digia.com> | 2013-09-04 12:59:11 +0200 |
---|---|---|
committer | Karsten Heimrich <karsten.heimrich@digia.com> | 2013-09-10 13:43:29 +0200 |
commit | d48ffdd2982999873d9a2bdbe0adbd005659d10b (patch) | |
tree | aa1a1da4fd3f9a1cb3f479451371cf7dc3465688 | |
parent | 9d97d133ccb3c0b091639cf58fd3dcf69fa6e39b (diff) |
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 <niels.weber@digia.com>
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
Reviewed-by: Tim Jenssen <tim.jenssen@digia.com>
-rw-r--r-- | src/libs/installer/binaryformat.cpp | 46 | ||||
-rw-r--r-- | tests/auto/installer/binaryformat/tst_binaryformat.cpp | 4 |
2 files changed, 22 insertions, 28 deletions
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 <QTemporaryFile> #include <errno.h> +#include <string.h> 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<quint64>(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 } diff --git a/tests/auto/installer/binaryformat/tst_binaryformat.cpp b/tests/auto/installer/binaryformat/tst_binaryformat.cpp index 40509fd18..6e520dc3e 100644 --- a/tests/auto/installer/binaryformat/tst_binaryformat.cpp +++ b/tests/auto/installer/binaryformat/tst_binaryformat.cpp @@ -92,7 +92,7 @@ private slots: void testFindMagicCookieWithError() { - QTest::ignoreMessage(QtDebugMsg, "create Error-Exception: \"Searched whole file, no marker found\" "); + QTest::ignoreMessage(QtDebugMsg, "create Error-Exception: \"No marker found, stopped after 50.00 KiB.\" "); QTemporaryFile file; file.open(); @@ -103,7 +103,7 @@ private slots: // throws QInstaller::findMagicCookie(&file, QInstaller::MagicCookie); } catch (const QInstaller::Error &error) { - QCOMPARE(qPrintable(error.message()), "Searched whole file, no marker found"); + QCOMPARE(qPrintable(error.message()), "No marker found, stopped after 50.00 KiB."); } catch (...) { QFAIL("Unexpected error."); } |