More 7zip work (thanks, Dennis!)
This commit is contained in:
parent
64cb8c260e
commit
a9d65e6d59
|
@ -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!).
|
||||
|
|
|
@ -51,16 +51,29 @@ typedef struct _CFileInStream
|
|||
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 @@ typedef struct _LZMAentry
|
|||
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,14 +287,20 @@ static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer,
|
|||
allocTempImp.Alloc = SzAllocPhysicsFS;
|
||||
allocTempImp.Free = SzFreePhysicsFS;
|
||||
|
||||
/* 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->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 */
|
||||
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
|
||||
|
@ -289,7 +309,8 @@ static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer,
|
|||
|
||||
/* 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 @@ static int LZMA_fileClose(fvoid *opaque)
|
|||
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,6 +412,7 @@ static int LZMA_isArchive(const char *filename, int forWriting)
|
|||
|
||||
static void *LZMA_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
PHYSFS_uint64 len;
|
||||
LZMAarchive *archive = NULL;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
|
@ -394,7 +423,6 @@ static void *LZMA_openArchive(const char *name, int forWriting)
|
|||
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 @@ static void *LZMA_openArchive(const char *name, int forWriting)
|
|||
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 @@ static fvoid *LZMA_openRead(dvoid *opaque, const char *name, int *fileExists)
|
|||
{
|
||||
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 @@ static void LZMA_dirClose(dvoid *opaque)
|
|||
__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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
along with this library.
|
||||
k
|
||||
|
|
Loading…
Reference in New Issue