More 7zip work (thanks, Dennis!)
authorRyan C. Gordon <icculus@icculus.org>
Sun, 05 Nov 2006 10:06:02 +0000
changeset 783 f14fc3210eca
parent 782 5633b9a0c6b6
child 784 fb4a01af9ff7
More 7zip work (thanks, Dennis!)
CHANGELOG
archivers/lzma.c
lzma/LZMA-LICENSE.txt
--- a/CHANGELOG	Wed Sep 27 09:21:56 2006 +0000
+++ b/CHANGELOG	Sun Nov 05 10:06:02 2006 +0000
@@ -2,6 +2,7 @@
  * CHANGELOG.
  */
 
+11052006 - More 7zip archiver work (thanks, Dennis!).
 09272006 - Reworked 7zip archiver (thanks, Dennis!).
 09232006 - Fixed typo in doxygen comment.
 04112006 - Added LZMA archiver...7zip support (thanks, Dennis!).
--- a/archivers/lzma.c	Wed Sep 27 09:21:56 2006 +0000
+++ b/archivers/lzma.c	Sun Nov 05 10:06:02 2006 +0000
@@ -51,16 +51,29 @@
     void *File;
 } CFileInStream;
 
-/* Set by LZMA_openArchive, except blockXXX which is handled by LZMA_read() */
+/*
+ * In LZMA the archive is splited in blocks, those are called folders
+ * Set by LZMA_read()
+*/
+typedef struct _LZMAfolder
+{
+    PHYSFS_uint8 *cache; /* Cached folder */
+    PHYSFS_uint32 size; /* Size of folder */
+    PHYSFS_uint32 index; /* Index of folder in archive */
+    PHYSFS_uint32 references; /* Number of files using this block */
+} LZMAfolder;
+
+/*
+ * Set by LZMA_openArchive(), except folder which gets it's values
+ *  in LZMA_read()
+ */
 typedef struct _LZMAarchive
 {
     struct _LZMAentry *firstEntry; /* Used for cleanup on shutdown */
     struct _LZMAentry *lastEntry;
+    LZMAfolder *folder; /* Array of folders */
     CArchiveDatabaseEx db; /* For 7z: Database */
     CFileInStream stream; /* For 7z: Input file incl. read and seek callbacks */
-    unsigned char *block; /* Currently cached block */
-    size_t blockSize; /* Size of current block */
-    PHYSFS_uint32 blockIndex; /* Index of current block */
 } LZMAarchive;
 
 /* Set by LZMA_openRead(), except offset which is set by LZMA_read() */
@@ -70,8 +83,9 @@
     struct _LZMAentry *previous;
     LZMAarchive *archive; /* Link to corresponding archive */
     CFileItem *file; /* For 7z: File info, eg. name, size */
-    PHYSFS_uint32 index; /* Index inside the archive */
-    size_t offset; /* Offset inside archive block */
+    PHYSFS_uint32 fileIndex; /* Index of file in archive */
+    PHYSFS_uint32 folderIndex; /* Index of folder in archive */
+    size_t offset; /* Offset in folder */
     PHYSFS_uint32 position; /* Current "virtual" position in file */
 } LZMAentry;
 
@@ -273,23 +287,30 @@
     allocTempImp.Alloc = SzAllocPhysicsFS;
     allocTempImp.Free = SzFreePhysicsFS;
 
-    if (lzma_err(SzExtract(
-        &entry->archive->stream.InStream, /* compressed data */
-        &entry->archive->db,
-        entry->index,
-        &entry->archive->blockIndex, /* Index of currently cached block, may be changed by SzExtract */
-        &entry->archive->block, /* Cache of current decompressed block, may be allocated/freed by SzExtract */
-        &entry->archive->blockSize, /* Size of current cache, may be changed by SzExtract */
-        &entry->offset, /* Offset of this file inside the cache block, set by SzExtract */
-        &fileSize, /* Size of this file */
-        &allocImp,
-        &allocTempImp
-            )) != SZ_OK)
-        return -1;
+    /* Only decompress the folder if it is not allready cached */
+    if (entry->archive->folder[entry->folderIndex].cache == NULL)
+        if (lzma_err(SzExtract(
+            &entry->archive->stream.InStream, /* compressed data */
+            &entry->archive->db,
+            entry->fileIndex,
+            /* Index of cached folder, will be changed by SzExtract */
+            &entry->archive->folder[entry->folderIndex].index,
+            /* Cache for decompressed folder, allocated/freed by SzExtract */
+            &entry->archive->folder[entry->folderIndex].cache,
+            /* Size of cache, will be changed by SzExtract */
+            &entry->archive->folder[entry->folderIndex].size,
+            /* Offset of this file inside the cache, set by SzExtract */
+            &entry->offset,
+            &fileSize, /* Size of this file */
+            &allocImp,
+            &allocTempImp
+                )) != SZ_OK)
+            return -1;
 
     /* Copy wanted bytes over from cache to outBuffer */
     strncpy(outBuffer,
-            (void*)(entry->archive->block + entry->offset + entry->position),
+            (void*) (entry->archive->folder[entry->folderIndex].cache +
+                     entry->offset + entry->position),
             wantedSize);
     entry->position += wantedSize;
     return objCount;
@@ -352,6 +373,13 @@
     if (entry->next != NULL)
         entry->next->previous = entry->previous;
 
+    entry->archive->folder[entry->folderIndex].references--;
+    if (entry->archive->folder[entry->folderIndex].references == 0)
+    {
+        allocator.Free(entry->archive->folder[entry->folderIndex].cache);
+        entry->archive->folder[entry->folderIndex].cache = NULL;
+    }
+
     allocator.Free(entry);
     entry = NULL;
 
@@ -384,17 +412,17 @@
 
 static void *LZMA_openArchive(const char *name, int forWriting)
 {
+    PHYSFS_uint64 len;
     LZMAarchive *archive = NULL;
     ISzAlloc allocImp;
     ISzAlloc allocTempImp;
 
     BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
-    BAIL_IF_MACRO(!LZMA_isArchive(name, forWriting), ERR_UNSUPPORTED_ARCHIVE, 0);
+    BAIL_IF_MACRO(!LZMA_isArchive(name,forWriting), ERR_UNSUPPORTED_ARCHIVE, 0);
 
     archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
     BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);
 
-    archive->block = NULL;
     archive->firstEntry = NULL;
     archive->lastEntry = NULL;
 
@@ -424,6 +452,16 @@
         return NULL;
     } /* if */
 
+    len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
+    archive->folder = (LZMAfolder *) allocator.Malloc(len);
+    BAIL_IF_MACRO(archive->folder == NULL, ERR_OUT_OF_MEMORY, NULL);
+
+    /*
+     * Init with 0 so we know when a folder is already cached
+     * Values will be set by LZMA_read()
+     */
+    memset(archive->folder, 0, len);
+
     return(archive);
 } /* LZMA_openArchive */
 
@@ -529,20 +567,27 @@
 {
     LZMAarchive *archive = (LZMAarchive *) opaque;
     LZMAentry *entry = NULL;
-    PHYSFS_uint32 index = 0;
+    PHYSFS_uint32 fileIndex = 0;
+    PHYSFS_uint32 folderIndex = 0;
 
-    *fileExists = lzma_find_entry(archive, name, &index);
+    *fileExists = lzma_find_entry(archive, name, &fileIndex);
     BAIL_IF_MACRO(!*fileExists, ERR_NO_SUCH_FILE, NULL);
 
+    folderIndex = archive->db.FileIndexToFolderIndexMap[fileIndex];
+    BAIL_IF_MACRO(folderIndex == (PHYSFS_uint32)-1, ERR_UNKNOWN_ERROR, NULL);
+
     entry = (LZMAentry *) allocator.Malloc(sizeof (LZMAentry));
     BAIL_IF_MACRO(entry == NULL, ERR_OUT_OF_MEMORY, NULL);
 
-    entry->index = index;
+    entry->fileIndex = fileIndex;
+    entry->folderIndex = folderIndex;
     entry->archive = archive;
-    entry->file = archive->db.Database.Files + entry->index;
+    entry->file = archive->db.Database.Files + entry->fileIndex;
     entry->offset = 0; /* Offset will be set by LZMA_read() */
     entry->position = 0;
 
+    archive->folder[folderIndex].references++;
+
     entry->next = NULL;
     entry->previous = entry->archive->lastEntry;
     if (entry->previous != NULL)
@@ -584,7 +629,7 @@
     __PHYSFS_platformClose(archive->stream.File);
 
     /* Free the cache which might have been allocated by LZMA_read() */
-    allocator.Free(archive->block);
+    allocator.Free(archive->folder);
     allocator.Free(archive);
 } /* LZMA_dirClose */
 
--- a/lzma/LZMA-LICENSE.txt	Wed Sep 27 09:21:56 2006 +0000
+++ b/lzma/LZMA-LICENSE.txt	Sun Nov 05 10:06:02 2006 +0000
@@ -92,4 +92,3 @@
 
 You should have received a copy of the Common Public License
 along with this library.
-k