More 7zip work (thanks, Dennis!)

This commit is contained in:
Ryan C. Gordon 2006-11-05 10:06:02 +00:00
parent 64cb8c260e
commit a9d65e6d59
3 changed files with 73 additions and 28 deletions

View File

@ -2,6 +2,7 @@
* CHANGELOG. * CHANGELOG.
*/ */
11052006 - More 7zip archiver work (thanks, Dennis!).
09272006 - Reworked 7zip archiver (thanks, Dennis!). 09272006 - Reworked 7zip archiver (thanks, Dennis!).
09232006 - Fixed typo in doxygen comment. 09232006 - Fixed typo in doxygen comment.
04112006 - Added LZMA archiver...7zip support (thanks, Dennis!). 04112006 - Added LZMA archiver...7zip support (thanks, Dennis!).

View File

@ -51,16 +51,29 @@ typedef struct _CFileInStream
void *File; void *File;
} CFileInStream; } 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 typedef struct _LZMAarchive
{ {
struct _LZMAentry *firstEntry; /* Used for cleanup on shutdown */ struct _LZMAentry *firstEntry; /* Used for cleanup on shutdown */
struct _LZMAentry *lastEntry; struct _LZMAentry *lastEntry;
LZMAfolder *folder; /* Array of folders */
CArchiveDatabaseEx db; /* For 7z: Database */ CArchiveDatabaseEx db; /* For 7z: Database */
CFileInStream stream; /* For 7z: Input file incl. read and seek callbacks */ 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; } LZMAarchive;
/* Set by LZMA_openRead(), except offset which is set by LZMA_read() */ /* Set by LZMA_openRead(), except offset which is set by LZMA_read() */
@ -70,8 +83,9 @@ typedef struct _LZMAentry
struct _LZMAentry *previous; struct _LZMAentry *previous;
LZMAarchive *archive; /* Link to corresponding archive */ LZMAarchive *archive; /* Link to corresponding archive */
CFileItem *file; /* For 7z: File info, eg. name, size */ CFileItem *file; /* For 7z: File info, eg. name, size */
PHYSFS_uint32 index; /* Index inside the archive */ PHYSFS_uint32 fileIndex; /* Index of file in archive */
size_t offset; /* Offset inside archive block */ PHYSFS_uint32 folderIndex; /* Index of folder in archive */
size_t offset; /* Offset in folder */
PHYSFS_uint32 position; /* Current "virtual" position in file */ PHYSFS_uint32 position; /* Current "virtual" position in file */
} LZMAentry; } LZMAentry;
@ -273,23 +287,30 @@ static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer,
allocTempImp.Alloc = SzAllocPhysicsFS; allocTempImp.Alloc = SzAllocPhysicsFS;
allocTempImp.Free = SzFreePhysicsFS; allocTempImp.Free = SzFreePhysicsFS;
if (lzma_err(SzExtract( /* Only decompress the folder if it is not allready cached */
&entry->archive->stream.InStream, /* compressed data */ if (entry->archive->folder[entry->folderIndex].cache == NULL)
&entry->archive->db, if (lzma_err(SzExtract(
entry->index, &entry->archive->stream.InStream, /* compressed data */
&entry->archive->blockIndex, /* Index of currently cached block, may be changed by SzExtract */ &entry->archive->db,
&entry->archive->block, /* Cache of current decompressed block, may be allocated/freed by SzExtract */ entry->fileIndex,
&entry->archive->blockSize, /* Size of current cache, may be changed by SzExtract */ /* Index of cached folder, will be changed by SzExtract */
&entry->offset, /* Offset of this file inside the cache block, set by SzExtract */ &entry->archive->folder[entry->folderIndex].index,
&fileSize, /* Size of this file */ /* Cache for decompressed folder, allocated/freed by SzExtract */
&allocImp, &entry->archive->folder[entry->folderIndex].cache,
&allocTempImp /* Size of cache, will be changed by SzExtract */
)) != SZ_OK) &entry->archive->folder[entry->folderIndex].size,
return -1; /* 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 */ /* Copy wanted bytes over from cache to outBuffer */
strncpy(outBuffer, strncpy(outBuffer,
(void*)(entry->archive->block + entry->offset + entry->position), (void*) (entry->archive->folder[entry->folderIndex].cache +
entry->offset + entry->position),
wantedSize); wantedSize);
entry->position += wantedSize; entry->position += wantedSize;
return objCount; return objCount;
@ -352,6 +373,13 @@ static int LZMA_fileClose(fvoid *opaque)
if (entry->next != NULL) if (entry->next != NULL)
entry->next->previous = entry->previous; 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); allocator.Free(entry);
entry = NULL; entry = NULL;
@ -384,17 +412,17 @@ static int LZMA_isArchive(const char *filename, int forWriting)
static void *LZMA_openArchive(const char *name, int forWriting) static void *LZMA_openArchive(const char *name, int forWriting)
{ {
PHYSFS_uint64 len;
LZMAarchive *archive = NULL; LZMAarchive *archive = NULL;
ISzAlloc allocImp; ISzAlloc allocImp;
ISzAlloc allocTempImp; ISzAlloc allocTempImp;
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL); 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)); archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL); BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);
archive->block = NULL;
archive->firstEntry = NULL; archive->firstEntry = NULL;
archive->lastEntry = NULL; archive->lastEntry = NULL;
@ -424,6 +452,16 @@ static void *LZMA_openArchive(const char *name, int forWriting)
return NULL; return NULL;
} /* if */ } /* 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); return(archive);
} /* LZMA_openArchive */ } /* LZMA_openArchive */
@ -529,20 +567,27 @@ static fvoid *LZMA_openRead(dvoid *opaque, const char *name, int *fileExists)
{ {
LZMAarchive *archive = (LZMAarchive *) opaque; LZMAarchive *archive = (LZMAarchive *) opaque;
LZMAentry *entry = NULL; 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); 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)); entry = (LZMAentry *) allocator.Malloc(sizeof (LZMAentry));
BAIL_IF_MACRO(entry == NULL, ERR_OUT_OF_MEMORY, NULL); BAIL_IF_MACRO(entry == NULL, ERR_OUT_OF_MEMORY, NULL);
entry->index = index; entry->fileIndex = fileIndex;
entry->folderIndex = folderIndex;
entry->archive = archive; 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->offset = 0; /* Offset will be set by LZMA_read() */
entry->position = 0; entry->position = 0;
archive->folder[folderIndex].references++;
entry->next = NULL; entry->next = NULL;
entry->previous = entry->archive->lastEntry; entry->previous = entry->archive->lastEntry;
if (entry->previous != NULL) if (entry->previous != NULL)
@ -584,7 +629,7 @@ static void LZMA_dirClose(dvoid *opaque)
__PHYSFS_platformClose(archive->stream.File); __PHYSFS_platformClose(archive->stream.File);
/* Free the cache which might have been allocated by LZMA_read() */ /* Free the cache which might have been allocated by LZMA_read() */
allocator.Free(archive->block); allocator.Free(archive->folder);
allocator.Free(archive); allocator.Free(archive);
} /* LZMA_dirClose */ } /* LZMA_dirClose */

View File

@ -92,4 +92,3 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the Common Public License You should have received a copy of the Common Public License
along with this library. along with this library.
k