[Libreoffice-commits] core.git: shell/source

Michael Meeks michael.meeks at collabora.com
Fri Oct 11 09:46:44 PDT 2013


 shell/source/win32/zipfile/zipfile.cxx |   51 +++++++++++++++++++++++++--------
 1 file changed, 40 insertions(+), 11 deletions(-)

New commits:
commit 53138c9968e28a25a8cd6d2b5e3d31cbb3257852
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Fri Oct 11 17:43:19 2013 +0100

    fdo#56007 - fast zip directory find to accelerate Windows Explorer thumbnail.
    
    Change-Id: Id9436def56f40d2bb54dea35bea916bd99964653

diff --git a/shell/source/win32/zipfile/zipfile.cxx b/shell/source/win32/zipfile/zipfile.cxx
index fb7dc88..cf05a56 100644
--- a/shell/source/win32/zipfile/zipfile.cxx
+++ b/shell/source/win32/zipfile/zipfile.cxx
@@ -102,6 +102,9 @@ struct CentralDirectoryEnd
 #define LOC_FILE_HEADER_SIG 0x04034b50
 #define CDIR_END_SIG 0x06054b50
 
+// This little lot performs in a truly appalling way without
+// buffering eg. on an IStream.
+
 static unsigned char readByte(StreamInterface *stream)
 {
     if (!stream || stream->stell() == -1)
@@ -250,31 +253,57 @@ static bool areHeadersConsistent(const LocalFileHeader &header, const CentralDir
     return true;
 }
 
+#define BLOCK_SIZE 0x800
+
+static bool findSignatureAtOffset(StreamInterface *stream, unsigned long nOffset)
+{
+    // read in reasonably sized chunk, and read more, to get overlapping sigs
+    unsigned char aBuffer[ BLOCK_SIZE + 4 ];
+
+    stream->sseek(nOffset, SEEK_SET);
+
+    unsigned long nBytesRead = stream->sread(aBuffer, sizeof(aBuffer));
+    if (nBytesRead < 0)
+        return false;
+
+    for (long n = nBytesRead - 4; n >= 0; n--)
+    {
+        if (aBuffer[n  ] == 0x50 && aBuffer[n+1] == 0x4b &&
+            aBuffer[n+2] == 0x05 && aBuffer[n+3] == 0x06)
+        { // a palpable hit ...
+            stream->sseek(nOffset + n, SEEK_SET);
+            return true;
+        }
+    }
+
+    return false;
+}
+
 static bool findCentralDirectoryEnd(StreamInterface *stream)
 {
     if (!stream)
         return false;
-    stream->sseek(0, SEEK_SET);
-    if (stream->sseek(-1024, SEEK_END)) stream->sseek(0, SEEK_SET);
+
+    stream->sseek(0,SEEK_END);
+
+    long nLength = stream->stell();
+    if (nLength == -1)
+        return false;
+
     try
     {
-        while (stream->stell() != -1)
+        for (long nOffset = nLength - BLOCK_SIZE;
+             nOffset > 0; nOffset -= BLOCK_SIZE)
         {
-            unsigned signature = readInt(stream);
-            if (signature == CDIR_END_SIG)
-            {
-                stream->sseek(-4, SEEK_CUR);
+            if (findSignatureAtOffset(stream, nOffset))
                 return true;
-            }
-            else
-                stream->sseek(-3, SEEK_CUR);
         }
+        return findSignatureAtOffset(stream, 0);
     }
     catch (...)
     {
         return false;
     }
-    return false;
 }
 
 static bool isZipStream(StreamInterface *stream)


More information about the Libreoffice-commits mailing list