diff --git a/source/sz/7zDecode.c b/source/sz/7zDecode.c index 7b58319..55ca2a0 100644 --- a/source/sz/7zDecode.c +++ b/source/sz/7zDecode.c @@ -47,7 +47,7 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #else const Byte *inBuffer, #endif - Byte *outBuffer, size_t outSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain) { UInt32 si; @@ -109,7 +109,7 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, lzmaCallback.InCallback.Read = LzmaReadImp; #endif - if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, + if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; @@ -126,7 +126,7 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, if (state.Dictionary == 0) { allocMain->Free(state.Probs); - return SZE_OUTOFMEMORY; + return SZE_OUTOFMEMORYDIC; } } LzmaDecoderInit(&state); @@ -157,7 +157,7 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, // like SzDecode but uses less memory SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, ISzInStream *inStream, - Byte *outBuffer, size_t outSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain, size_t *fileOffset, size_t *fileSize) { @@ -220,7 +220,7 @@ SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, lzmaCallback.InCallback.Read = LzmaReadImp; #endif - if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, + if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; @@ -240,97 +240,51 @@ SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, } } LzmaDecoderInit(&state); - + // allocate memory for the temporary buffer Byte *tmpBuffer = (Byte *)allocMain->Alloc(_LZMA_TEMP_BUFFER_SIZE); - - // variables containing the number of the first and the last bytes of the buffer - size_t bufferStart, bufferEnd; - bufferStart = bufferEnd = 0; - - // integers contains the offset, the size and the already copied data which will be - // copied from the tmpBuffer to outBuffer - size_t copyOffset, copySize, copyDone; - copyOffset = copySize = copyDone = 0; - - UInt32 i = 0; - + // decompress data in _LZMA_TEMP_BUFFER_SIZE byte steps and copy the wanted file to outBuffer - do - { + size_t bytesLeft = *fileSize; // total bytes remaining to be read + size_t bytesToRead = 0; // bytes to read on this pass + size_t bytesRead = 0; // total bytes read + size_t offset = 0; // buffer offset + do + { + if(bytesLeft > _LZMA_TEMP_BUFFER_SIZE) + bytesToRead = _LZMA_TEMP_BUFFER_SIZE; + else + bytesToRead = bytesLeft; + + bytesLeft -= bytesToRead; + // decompress next bytes result = LzmaDecode(&state, - #ifdef _LZMA_IN_CB - &lzmaCallback.InCallback, - #else - //inBuffer, (SizeT)inSize, &inProcessed, //TODO! - #endif - tmpBuffer, _LZMA_TEMP_BUFFER_SIZE, &outSizeProcessedLoc - ); - - // check result + #ifdef _LZMA_IN_CB + &lzmaCallback.InCallback, + #else + //inBuffer, (SizeT)inSize, &inProcessed, //TODO! + #endif + tmpBuffer, bytesToRead, &outSizeProcessedLoc + ); + + // check result if(result == LZMA_RESULT_DATA_ERROR) - { return SZE_DATA_ERROR; - } - if(result != LZMA_RESULT_OK) - { + else if(result != LZMA_RESULT_OK) return SZE_FAIL; - } - + // normally this should never happen if(outSizeProcessedLoc > _LZMA_TEMP_BUFFER_SIZE) { return SZE_FAIL; } - - // update bufferStart and bufferEnd - bufferStart = _LZMA_TEMP_BUFFER_SIZE * i; - bufferEnd = bufferStart + outSizeProcessedLoc; - i++; - - // calculate copy offset and size - if(*fileOffset > bufferEnd) - { - // we haven't reached the start of the file yet - continue; - } - - // calculate offset - if(*fileOffset < bufferStart) - { - // the file has already started before this decompression step - copyOffset = 0; - } - else - { - // the file starts somewhere inside this buffer - copyDone = 0; - copyOffset = _LZMA_TEMP_BUFFER_SIZE - (bufferEnd - *fileOffset); - } - - // calculate size - if((*fileOffset + *fileSize) > bufferEnd) - { - // we'll need the whole buffer after copyOffset - copySize = _LZMA_TEMP_BUFFER_SIZE - copyOffset; - } - else - { - // we'll stop somewhere inside the buffer - copySize = (*fileOffset + *fileSize) - (bufferStart + copyOffset); - } - - // copy bytes to the real output buffer - if(copySize == 0) - { - continue; - } - // printf("memcpy(outBuffer + %d, tmpBuffer + %d, %d)\n", copyDone, copyOffset, copySize); - memcpy(outBuffer + copyDone, tmpBuffer + copyOffset, copySize); - copyDone += copySize; + + memcpy(outBuffer + offset, tmpBuffer, outSizeProcessedLoc); + bytesRead += bytesToRead; + offset += outSizeProcessedLoc; } - while((*fileOffset + *fileSize) > bufferEnd); + while(bytesLeft > 0); /* result = LzmaDecode(&state, #ifdef _LZMA_IN_CB @@ -340,7 +294,7 @@ SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, #endif outBuffer, (SizeT)outSize, &outSizeProcessedLoc);*/ //*outSizeProcessed = (size_t)outSizeProcessedLoc; - *outSizeProcessed = copyDone; + *outSizeProcessed = offset; allocMain->Free(tmpBuffer); // free the temporary buffer again allocMain->Free(state.Probs); allocMain->Free(state.Dictionary); diff --git a/source/sz/7zDecode.h b/source/sz/7zDecode.h index 9506e59..4f4d35d 100644 --- a/source/sz/7zDecode.h +++ b/source/sz/7zDecode.h @@ -19,17 +19,17 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #else const Byte *inBuffer, #endif - Byte *outBuffer, size_t outSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain); #ifdef _LZMA_OUT_READ #ifndef _LZMA_TEMP_BUFFER_SIZE -#define _LZMA_TEMP_BUFFER_SIZE (1 << 15) // size of the temporary buffer in bytes +#define _LZMA_TEMP_BUFFER_SIZE (1024) // size of the temporary buffer in bytes #endif SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, ISzInStream *stream, - Byte *outBuffer, size_t outSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain, size_t *fileOffset, size_t *fileSize); #endif // #ifdef _LZMA_OUT_READ diff --git a/source/sz/7zExtract.c b/source/sz/7zExtract.c index 9a82ea4..13ba62c 100644 --- a/source/sz/7zExtract.c +++ b/source/sz/7zExtract.c @@ -5,14 +5,14 @@ #include "7zCrc.h" SZ_RESULT SzExtract( - ISzInStream *inStream, + ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, - Byte **outBuffer, + Byte **outBuffer, size_t *outBufferSize, - size_t *offset, - size_t *outSizeProcessed, + size_t *offset, + size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { @@ -41,9 +41,9 @@ SZ_RESULT SzExtract( *blockIndex = folderIndex; allocMain->Free(*outBuffer); *outBuffer = 0; - + RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); - + #ifndef _LZMA_IN_CB if (packSize != 0) { @@ -67,12 +67,12 @@ SZ_RESULT SzExtract( if (res == SZ_OK) { size_t outRealSize; - res = SzDecode(db->Database.PackSizes + - db->FolderStartPackStreamIndex[folderIndex], folder, + res = SzDecode(db->Database.PackSizes + + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, #else - inBuffer, + inBuffer, #endif *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp); if (res == SZ_OK) @@ -96,7 +96,7 @@ SZ_RESULT SzExtract( } if (res == SZ_OK) { - UInt32 i; + UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) @@ -118,14 +118,14 @@ SZ_RESULT SzExtract( #ifdef _LZMA_OUT_READ // similar to SzExtract but needs less memory SZ_RESULT SzExtract2( - ISzInStream *inStream, + ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, - Byte **outBuffer, + Byte **outBuffer, size_t *outBufferSize, - size_t *offset, - size_t *outSizeProcessed, + size_t *offset, + size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { @@ -158,9 +158,9 @@ SZ_RESULT SzExtract2( allocMain->Free(*outBuffer); *outBuffer = 0; #endif - + RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); - + #ifndef _LZMA_IN_CB if (packSize != 0) { @@ -176,7 +176,7 @@ SZ_RESULT SzExtract2( { // calculate file offset and filesize CFileItem *fileItem = db->Database.Files + fileIndex; - UInt32 i; + UInt32 i; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; @@ -192,14 +192,14 @@ SZ_RESULT SzExtract2( } if (res == SZ_OK) { - + size_t outRealSize; - res = SzDecode2(db->Database.PackSizes + - db->FolderStartPackStreamIndex[folderIndex], folder, + res = SzDecode2(db->Database.PackSizes + + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, #else - inBuffer, + inBuffer, #endif *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp, offset, outSizeProcessed @@ -226,24 +226,24 @@ SZ_RESULT SzExtract2( } if (res == SZ_OK) { -/* UInt32 i; +/* UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size;*/ - CFileItem *fileItem = db->Database.Files + fileIndex; + //CFileItem *fileItem = db->Database.Files + fileIndex; if (/**offset +*/ *outSizeProcessed > *outBufferSize) return SZE_FAIL; { - if (fileItem->IsFileCRCDefined) - { - if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer/* + *offset*/, *outSizeProcessed)) - res = SZE_CRC_ERROR; // why does SzExtract return SZE_FAIL when we can return SZE_CRC_ERROR? - } + //if (fileItem->IsFileCRCDefined) + //{ + // if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer/* + *offset*/, *outSizeProcessed)) + // res = SZE_CRC_ERROR; // why does SzExtract return SZE_FAIL when we can return SZE_CRC_ERROR? + //} } } - + // change *offset to 0 because SzExtract normally decompresses the whole solid block // and sets *offset to the offset of the wanted file. // SzDecode2 does only copy the needed file to the output buffer and has to set *offset diff --git a/source/sz/7zTypes.h b/source/sz/7zTypes.h index d58904a..fa4c5c3 100644 --- a/source/sz/7zTypes.h +++ b/source/sz/7zTypes.h @@ -64,6 +64,8 @@ typedef UInt32 CFileSize; #define SZE_ARCHIVE_ERROR (6) +#define SZE_OUTOFMEMORYDIC (7) + #define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; } #endif