Third-Party: Update LZMA SDK

This commit is contained in:
Vicki Pfau 2020-01-16 20:10:20 -08:00
parent dab12cf5c6
commit b2d406a411
73 changed files with 11359 additions and 3452 deletions

View File

@ -1,5 +1,5 @@
/* 7z.h -- 7z interface /* 7z.h -- 7z interface
2015-11-18 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_H #ifndef __7Z_H
#define __7Z_H #define __7Z_H
@ -98,7 +98,7 @@ UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
ILookInStream *stream, UInt64 startPos, ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, Byte *outBuffer, size_t outSize,
ISzAlloc *allocMain); ISzAllocPtr allocMain);
typedef struct typedef struct
{ {
@ -131,7 +131,7 @@ typedef struct
#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i]) #define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i])
void SzArEx_Init(CSzArEx *p); void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
@ -179,8 +179,8 @@ SRes SzArEx_Extract(
size_t *outBufferSize, /* buffer size for output buffer */ size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain, ISzAllocPtr allocMain,
ISzAlloc *allocTemp); ISzAllocPtr allocTemp);
/* /*
@ -195,7 +195,7 @@ SZ_ERROR_FAIL
*/ */
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
ISzAlloc *allocMain, ISzAlloc *allocTemp); ISzAllocPtr allocMain, ISzAllocPtr allocTemp);
EXTERN_C_END EXTERN_C_END

View File

@ -1,8 +1,10 @@
/* 7zAlloc.c -- Allocation functions /* 7zAlloc.c -- Allocation functions
2015-11-09 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <stdlib.h>
#include "7zAlloc.h" #include "7zAlloc.h"
/* #define _SZ_ALLOC_DEBUG */ /* #define _SZ_ALLOC_DEBUG */
@ -20,7 +22,7 @@ int g_allocCountTemp = 0;
#endif #endif
void *SzAlloc(void *p, size_t size) void *SzAlloc(ISzAllocPtr p, size_t size)
{ {
UNUSED_VAR(p); UNUSED_VAR(p);
if (size == 0) if (size == 0)
@ -32,7 +34,7 @@ void *SzAlloc(void *p, size_t size)
return malloc(size); return malloc(size);
} }
void SzFree(void *p, void *address) void SzFree(ISzAllocPtr p, void *address)
{ {
UNUSED_VAR(p); UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
@ -45,7 +47,7 @@ void SzFree(void *p, void *address)
free(address); free(address);
} }
void *SzAllocTemp(void *p, size_t size) void *SzAllocTemp(ISzAllocPtr p, size_t size)
{ {
UNUSED_VAR(p); UNUSED_VAR(p);
if (size == 0) if (size == 0)
@ -60,7 +62,7 @@ void *SzAllocTemp(void *p, size_t size)
return malloc(size); return malloc(size);
} }
void SzFreeTemp(void *p, void *address) void SzFreeTemp(ISzAllocPtr p, void *address)
{ {
UNUSED_VAR(p); UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG

View File

@ -1,23 +1,19 @@
/* 7zAlloc.h -- Allocation functions /* 7zAlloc.h -- Allocation functions
2013-03-25 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H #ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H #define __7Z_ALLOC_H
#include <stdlib.h> #include "7zTypes.h"
#ifdef __cplusplus EXTERN_C_BEGIN
extern "C" {
#endif
void *SzAlloc(void *p, size_t size); void *SzAlloc(ISzAllocPtr p, size_t size);
void SzFree(void *p, void *address); void SzFree(ISzAllocPtr p, void *address);
void *SzAllocTemp(void *p, size_t size); void *SzAllocTemp(ISzAllocPtr p, size_t size);
void SzFreeTemp(void *p, void *address); void SzFreeTemp(ISzAllocPtr p, void *address);
#ifdef __cplusplus EXTERN_C_END
}
#endif
#endif #endif

View File

@ -1,5 +1,5 @@
/* 7zArcIn.c -- 7z Input functions /* 7zArcIn.c -- 7z Input functions
2015-11-18 : Igor Pavlov : Public domain */ 2018-12-31 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -11,7 +11,7 @@
#include "CpuArch.h" #include "CpuArch.h"
#define MY_ALLOC(T, p, size, alloc) { \ #define MY_ALLOC(T, p, size, alloc) { \
if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; } if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; }
#define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) } #define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) }
@ -19,7 +19,7 @@
{ MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); } { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }
#define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \ #define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \
{ if ((size) == 0) p = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } } { if ((size) == 0) to = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } }
#define k7zMajorVersion 0 #define k7zMajorVersion 0
@ -60,7 +60,7 @@ const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
#define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } #define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc) static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc)
{ {
if (num == 0) if (num == 0)
{ {
@ -75,18 +75,18 @@ static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc)
return SZ_OK; return SZ_OK;
} }
void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc) void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc)
{ {
IAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
IAlloc_Free(alloc, p->Vals); p->Vals = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
} }
#define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } #define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc) void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc)
{ {
IAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
IAlloc_Free(alloc, p->Vals); p->Vals = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
} }
@ -107,18 +107,18 @@ static void SzAr_Init(CSzAr *p)
p->CodersData = NULL; p->CodersData = NULL;
} }
static void SzAr_Free(CSzAr *p, ISzAlloc *alloc) static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc)
{ {
IAlloc_Free(alloc, p->PackPositions); ISzAlloc_Free(alloc, p->PackPositions);
SzBitUi32s_Free(&p->FolderCRCs, alloc); SzBitUi32s_Free(&p->FolderCRCs, alloc);
IAlloc_Free(alloc, p->FoCodersOffsets); ISzAlloc_Free(alloc, p->FoCodersOffsets);
IAlloc_Free(alloc, p->FoStartPackStreamIndex); ISzAlloc_Free(alloc, p->FoStartPackStreamIndex);
IAlloc_Free(alloc, p->FoToCoderUnpackSizes); ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes);
IAlloc_Free(alloc, p->FoToMainUnpackSizeIndex); ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
IAlloc_Free(alloc, p->CoderUnpackSizes); ISzAlloc_Free(alloc, p->CoderUnpackSizes);
IAlloc_Free(alloc, p->CodersData); ISzAlloc_Free(alloc, p->CodersData);
SzAr_Init(p); SzAr_Init(p);
} }
@ -147,16 +147,16 @@ void SzArEx_Init(CSzArEx *p)
SzBitUi64s_Init(&p->CTime); SzBitUi64s_Init(&p->CTime);
} }
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc)
{ {
IAlloc_Free(alloc, p->UnpackPositions); ISzAlloc_Free(alloc, p->UnpackPositions);
IAlloc_Free(alloc, p->IsDirs); ISzAlloc_Free(alloc, p->IsDirs);
IAlloc_Free(alloc, p->FolderToFile); ISzAlloc_Free(alloc, p->FolderToFile);
IAlloc_Free(alloc, p->FileToFolder); ISzAlloc_Free(alloc, p->FileToFolder);
IAlloc_Free(alloc, p->FileNameOffsets); ISzAlloc_Free(alloc, p->FileNameOffsets);
IAlloc_Free(alloc, p->FileNames); ISzAlloc_Free(alloc, p->FileNames);
SzBitUi32s_Free(&p->CRCs, alloc); SzBitUi32s_Free(&p->CRCs, alloc);
SzBitUi32s_Free(&p->Attribs, alloc); SzBitUi32s_Free(&p->Attribs, alloc);
@ -305,7 +305,7 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
return sum; return sum;
} }
static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc) static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc)
{ {
Byte allAreDefined; Byte allAreDefined;
Byte *v2; Byte *v2;
@ -328,12 +328,12 @@ static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, I
{ {
unsigned numBits = (unsigned)numItems & 7; unsigned numBits = (unsigned)numItems & 7;
if (numBits != 0) if (numBits != 0)
v2[numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits)); v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));
} }
return SZ_OK; return SZ_OK;
} }
static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc) static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
{ {
UInt32 i; UInt32 i;
CSzData sd; CSzData sd;
@ -354,7 +354,7 @@ static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *c
return SZ_OK; return SZ_OK;
} }
static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc) static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
{ {
SzBitUi32s_Free(crcs, alloc); SzBitUi32s_Free(crcs, alloc);
RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)); RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc));
@ -380,7 +380,7 @@ static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems)
return SZ_OK; return SZ_OK;
} }
static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAlloc *alloc) static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc)
{ {
RINOK(SzReadNumber32(sd, &p->NumPackStreams)); RINOK(SzReadNumber32(sd, &p->NumPackStreams));
@ -635,7 +635,7 @@ static SRes ReadUnpackInfo(CSzAr *p,
CSzData *sd2, CSzData *sd2,
UInt32 numFoldersMax, UInt32 numFoldersMax,
const CBuf *tempBufs, UInt32 numTempBufs, const CBuf *tempBufs, UInt32 numTempBufs,
ISzAlloc *alloc) ISzAllocPtr alloc)
{ {
CSzData sd; CSzData sd;
@ -666,7 +666,7 @@ static SRes ReadUnpackInfo(CSzAr *p,
MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc); MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc);
MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc); MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc);
MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc); MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc);
MY_ALLOC(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc); MY_ALLOC_ZE(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc);
startBufPtr = sd.Data; startBufPtr = sd.Data;
@ -788,13 +788,9 @@ static SRes ReadUnpackInfo(CSzAr *p,
numCodersOutStreams += numCoders; numCodersOutStreams += numCoders;
if (numCodersOutStreams < numCoders) if (numCodersOutStreams < numCoders)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (numPackStreams > p->NumPackStreams - packStreamIndex)
packStreamIndex += numPackStreams;
if (packStreamIndex < numPackStreams)
return SZ_ERROR_UNSUPPORTED;
if (packStreamIndex > p->NumPackStreams)
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
packStreamIndex += numPackStreams;
} }
} }
@ -938,7 +934,7 @@ static SRes SzReadStreamsInfo(CSzAr *p,
UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,
UInt64 *dataOffset, UInt64 *dataOffset,
CSubStreamInfo *ssi, CSubStreamInfo *ssi,
ISzAlloc *alloc) ISzAllocPtr alloc)
{ {
UInt64 type; UInt64 type;
@ -980,7 +976,7 @@ static SRes SzReadAndDecodePackedStreams(
UInt32 numFoldersMax, UInt32 numFoldersMax,
UInt64 baseOffset, UInt64 baseOffset,
CSzAr *p, CSzAr *p,
ISzAlloc *allocTemp) ISzAllocPtr allocTemp)
{ {
UInt64 dataStartPos; UInt64 dataStartPos;
UInt32 fo; UInt32 fo;
@ -1047,7 +1043,7 @@ static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size
static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
CSzData *sd2, CSzData *sd2,
const CBuf *tempBufs, UInt32 numTempBufs, const CBuf *tempBufs, UInt32 numTempBufs,
ISzAlloc *alloc) ISzAllocPtr alloc)
{ {
CSzData sd; CSzData sd;
UInt32 i; UInt32 i;
@ -1100,16 +1096,14 @@ static SRes SzReadHeader2(
CSzData *sd, CSzData *sd,
ILookInStream *inStream, ILookInStream *inStream,
CBuf *tempBufs, UInt32 *numTempBufs, CBuf *tempBufs, UInt32 *numTempBufs,
ISzAlloc *allocMain, ISzAllocPtr allocMain,
ISzAlloc *allocTemp ISzAllocPtr allocTemp
) )
{ {
UInt64 type;
UInt32 numFiles = 0;
UInt32 numEmptyStreams = 0;
CSubStreamInfo ssi; CSubStreamInfo ssi;
const Byte *emptyStreams = NULL;
const Byte *emptyFiles = NULL; {
UInt64 type;
SzData_Clear(&ssi.sdSizes); SzData_Clear(&ssi.sdSizes);
SzData_Clear(&ssi.sdCRCs); SzData_Clear(&ssi.sdCRCs);
@ -1124,9 +1118,9 @@ static SRes SzReadHeader2(
{ {
for (;;) for (;;)
{ {
UInt64 type; UInt64 type2;
RINOK(ReadID(sd, &type)); RINOK(ReadID(sd, &type2));
if (type == k7zIdEnd) if (type2 == k7zIdEnd)
break; break;
RINOK(SkipData(sd)); RINOK(SkipData(sd));
} }
@ -1164,6 +1158,13 @@ static SRes SzReadHeader2(
if (type != k7zIdFilesInfo) if (type != k7zIdFilesInfo)
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
}
{
UInt32 numFiles = 0;
UInt32 numEmptyStreams = 0;
const Byte *emptyStreams = NULL;
const Byte *emptyFiles = NULL;
RINOK(SzReadNumber32(sd, &numFiles)); RINOK(SzReadNumber32(sd, &numFiles));
p->NumFiles = numFiles; p->NumFiles = numFiles;
@ -1462,7 +1463,7 @@ static SRes SzReadHeader2(
if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0) if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0)
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
} }
}
return SZ_OK; return SZ_OK;
} }
@ -1471,8 +1472,8 @@ static SRes SzReadHeader(
CSzArEx *p, CSzArEx *p,
CSzData *sd, CSzData *sd,
ILookInStream *inStream, ILookInStream *inStream,
ISzAlloc *allocMain, ISzAllocPtr allocMain,
ISzAlloc *allocTemp) ISzAllocPtr allocTemp)
{ {
UInt32 i; UInt32 i;
UInt32 numTempBufs = 0; UInt32 numTempBufs = 0;
@ -1500,8 +1501,8 @@ static SRes SzReadHeader(
static SRes SzArEx_Open2( static SRes SzArEx_Open2(
CSzArEx *p, CSzArEx *p,
ILookInStream *inStream, ILookInStream *inStream,
ISzAlloc *allocMain, ISzAllocPtr allocMain,
ISzAlloc *allocTemp) ISzAllocPtr allocTemp)
{ {
Byte header[k7zStartHeaderSize]; Byte header[k7zStartHeaderSize];
Int64 startArcPos; Int64 startArcPos;
@ -1512,7 +1513,7 @@ static SRes SzArEx_Open2(
SRes res; SRes res;
startArcPos = 0; startArcPos = 0;
RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR));
RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
@ -1541,7 +1542,7 @@ static SRes SzArEx_Open2(
{ {
Int64 pos = 0; Int64 pos = 0;
RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END));
if ((UInt64)pos < startArcPos + nextHeaderOffset || if ((UInt64)pos < startArcPos + nextHeaderOffset ||
(UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
(UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
@ -1622,7 +1623,7 @@ static SRes SzArEx_Open2(
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
ISzAlloc *allocMain, ISzAlloc *allocTemp) ISzAllocPtr allocMain, ISzAllocPtr allocTemp)
{ {
SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
if (res != SZ_OK) if (res != SZ_OK)
@ -1640,8 +1641,8 @@ SRes SzArEx_Extract(
size_t *outBufferSize, size_t *outBufferSize,
size_t *offset, size_t *offset,
size_t *outSizeProcessed, size_t *outSizeProcessed,
ISzAlloc *allocMain, ISzAllocPtr allocMain,
ISzAlloc *allocTemp) ISzAllocPtr allocTemp)
{ {
UInt32 folderIndex = p->FileToFolder[fileIndex]; UInt32 folderIndex = p->FileToFolder[fileIndex];
SRes res = SZ_OK; SRes res = SZ_OK;
@ -1651,7 +1652,7 @@ SRes SzArEx_Extract(
if (folderIndex == (UInt32)-1) if (folderIndex == (UInt32)-1)
{ {
IAlloc_Free(allocMain, *tempBuf); ISzAlloc_Free(allocMain, *tempBuf);
*blockIndex = folderIndex; *blockIndex = folderIndex;
*tempBuf = NULL; *tempBuf = NULL;
*outBufferSize = 0; *outBufferSize = 0;
@ -1663,7 +1664,7 @@ SRes SzArEx_Extract(
UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
/* /*
UInt64 unpackSizeSpec = UInt64 unpackSizeSpec =
p->UnpackPositions[p->FolderToFile[folderIndex + 1]] - p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] -
p->UnpackPositions[p->FolderToFile[folderIndex]]; p->UnpackPositions[p->FolderToFile[folderIndex]];
*/ */
size_t unpackSize = (size_t)unpackSizeSpec; size_t unpackSize = (size_t)unpackSizeSpec;
@ -1671,7 +1672,7 @@ SRes SzArEx_Extract(
if (unpackSize != unpackSizeSpec) if (unpackSize != unpackSizeSpec)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
*blockIndex = folderIndex; *blockIndex = folderIndex;
IAlloc_Free(allocMain, *tempBuf); ISzAlloc_Free(allocMain, *tempBuf);
*tempBuf = NULL; *tempBuf = NULL;
if (res == SZ_OK) if (res == SZ_OK)
@ -1679,7 +1680,7 @@ SRes SzArEx_Extract(
*outBufferSize = unpackSize; *outBufferSize = unpackSize;
if (unpackSize != 0) if (unpackSize != 0)
{ {
*tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize); *tempBuf = (Byte *)ISzAlloc_Alloc(allocMain, unpackSize);
if (*tempBuf == NULL) if (*tempBuf == NULL)
res = SZ_ERROR_MEM; res = SZ_ERROR_MEM;
} }
@ -1696,7 +1697,7 @@ SRes SzArEx_Extract(
{ {
UInt64 unpackPos = p->UnpackPositions[fileIndex]; UInt64 unpackPos = p->UnpackPositions[fileIndex];
*offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]); *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]);
*outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos); *outSizeProcessed = (size_t)(p->UnpackPositions[(size_t)fileIndex + 1] - unpackPos);
if (*offset + *outSizeProcessed > *outBufferSize) if (*offset + *outSizeProcessed > *outBufferSize)
return SZ_ERROR_FAIL; return SZ_ERROR_FAIL;
if (SzBitWithVals_Check(&p->CRCs, fileIndex)) if (SzBitWithVals_Check(&p->CRCs, fileIndex))
@ -1743,7 +1744,7 @@ size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest) UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
{ {
Bool needSlash; BoolInt needSlash;
if (!p->FileNameOffsets) if (!p->FileNameOffsets)
{ {
*(--dest) = 0; *(--dest) = 0;

View File

@ -1,5 +1,5 @@
/* 7zBuf.c -- Byte Buffer /* 7zBuf.c -- Byte Buffer
2013-01-21 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -11,7 +11,7 @@ void Buf_Init(CBuf *p)
p->size = 0; p->size = 0;
} }
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc)
{ {
p->size = 0; p->size = 0;
if (size == 0) if (size == 0)
@ -19,8 +19,8 @@ int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
p->data = 0; p->data = 0;
return 1; return 1;
} }
p->data = (Byte *)alloc->Alloc(alloc, size); p->data = (Byte *)ISzAlloc_Alloc(alloc, size);
if (p->data != 0) if (p->data)
{ {
p->size = size; p->size = size;
return 1; return 1;
@ -28,9 +28,9 @@ int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
return 0; return 0;
} }
void Buf_Free(CBuf *p, ISzAlloc *alloc) void Buf_Free(CBuf *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->data); ISzAlloc_Free(alloc, p->data);
p->data = 0; p->data = 0;
p->size = 0; p->size = 0;
} }

View File

@ -1,5 +1,5 @@
/* 7zBuf.h -- Byte Buffer /* 7zBuf.h -- Byte Buffer
2013-01-18 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_BUF_H #ifndef __7Z_BUF_H
#define __7Z_BUF_H #define __7Z_BUF_H
@ -15,8 +15,8 @@ typedef struct
} CBuf; } CBuf;
void Buf_Init(CBuf *p); void Buf_Init(CBuf *p);
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc);
void Buf_Free(CBuf *p, ISzAlloc *alloc); void Buf_Free(CBuf *p, ISzAllocPtr alloc);
typedef struct typedef struct
{ {
@ -27,8 +27,8 @@ typedef struct
void DynBuf_Construct(CDynBuf *p); void DynBuf_Construct(CDynBuf *p);
void DynBuf_SeekToBeg(CDynBuf *p); void DynBuf_SeekToBeg(CDynBuf *p);
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc);
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc);
EXTERN_C_END EXTERN_C_END

View File

@ -1,5 +1,5 @@
/* 7zBuf2.c -- Byte Buffer /* 7zBuf2.c -- Byte Buffer
2014-08-22 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -19,19 +19,20 @@ void DynBuf_SeekToBeg(CDynBuf *p)
p->pos = 0; p->pos = 0;
} }
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc) int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc)
{ {
if (size > p->size - p->pos) if (size > p->size - p->pos)
{ {
size_t newSize = p->pos + size; size_t newSize = p->pos + size;
Byte *data; Byte *data;
newSize += newSize / 4; newSize += newSize / 4;
data = (Byte *)alloc->Alloc(alloc, newSize); data = (Byte *)ISzAlloc_Alloc(alloc, newSize);
if (data == 0) if (!data)
return 0; return 0;
p->size = newSize; p->size = newSize;
memcpy(data, p->data, p->pos); if (p->pos != 0)
alloc->Free(alloc, p->data); memcpy(data, p->data, p->pos);
ISzAlloc_Free(alloc, p->data);
p->data = data; p->data = data;
} }
if (size != 0) if (size != 0)
@ -42,9 +43,9 @@ int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)
return 1; return 1;
} }
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->data); ISzAlloc_Free(alloc, p->data);
p->data = 0; p->data = 0;
p->size = 0; p->size = 0;
p->pos = 0; p->pos = 0;

View File

@ -1,5 +1,5 @@
/* 7zCrc.c -- CRC32 init /* 7zCrc.c -- CRC32 init
2015-03-10 : Igor Pavlov : Public domain */ 2017-06-06 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -61,12 +61,12 @@ void MY_FAST_CALL CrcGenerateTable()
UInt32 r = i; UInt32 r = i;
unsigned j; unsigned j;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
g_CrcTable[i] = r; g_CrcTable[i] = r;
} }
for (; i < 256 * CRC_NUM_TABLES; i++) for (i = 256; i < 256 * CRC_NUM_TABLES; i++)
{ {
UInt32 r = g_CrcTable[i - 256]; UInt32 r = g_CrcTable[(size_t)i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
} }
@ -86,8 +86,8 @@ void MY_FAST_CALL CrcGenerateTable()
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
if (!CPU_Is_InOrder()) if (!CPU_Is_InOrder())
g_CrcUpdate = CrcUpdateT8;
#endif #endif
g_CrcUpdate = CrcUpdateT8;
#endif #endif
#else #else
@ -101,7 +101,7 @@ void MY_FAST_CALL CrcGenerateTable()
g_CrcUpdate = CrcUpdateT4; g_CrcUpdate = CrcUpdateT4;
#if CRC_NUM_TABLES >= 8 #if CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT8; g_CrcUpdateT8 = CrcUpdateT8;
// g_CrcUpdate = CrcUpdateT8; g_CrcUpdate = CrcUpdateT8;
#endif #endif
} }
else if (p[0] != 1 || p[1] != 2) else if (p[0] != 1 || p[1] != 2)
@ -111,14 +111,14 @@ void MY_FAST_CALL CrcGenerateTable()
{ {
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
{ {
UInt32 x = g_CrcTable[i - 256]; UInt32 x = g_CrcTable[(size_t)i - 256];
g_CrcTable[i] = CRC_UINT32_SWAP(x); g_CrcTable[i] = CRC_UINT32_SWAP(x);
} }
g_CrcUpdateT4 = CrcUpdateT1_BeT4; g_CrcUpdateT4 = CrcUpdateT1_BeT4;
g_CrcUpdate = CrcUpdateT1_BeT4; g_CrcUpdate = CrcUpdateT1_BeT4;
#if CRC_NUM_TABLES >= 8 #if CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT1_BeT8; g_CrcUpdateT8 = CrcUpdateT1_BeT8;
// g_CrcUpdate = CrcUpdateT1_BeT8; g_CrcUpdate = CrcUpdateT1_BeT8;
#endif #endif
} }
} }

View File

@ -1,5 +1,5 @@
/* 7zCrcOpt.c -- CRC32 calculation /* 7zCrcOpt.c -- CRC32 calculation
2015-03-01 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -18,10 +18,10 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U
{ {
v ^= *(const UInt32 *)p; v ^= *(const UInt32 *)p;
v = v =
table[0x300 + ((v ) & 0xFF)] (table + 0x300)[((v ) & 0xFF)]
^ table[0x200 + ((v >> 8) & 0xFF)] ^ (table + 0x200)[((v >> 8) & 0xFF)]
^ table[0x100 + ((v >> 16) & 0xFF)] ^ (table + 0x100)[((v >> 16) & 0xFF)]
^ table[0x000 + ((v >> 24))]; ^ (table + 0x000)[((v >> 24))];
} }
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2(v, *p);
@ -38,16 +38,16 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U
UInt32 d; UInt32 d;
v ^= *(const UInt32 *)p; v ^= *(const UInt32 *)p;
v = v =
table[0x700 + ((v ) & 0xFF)] (table + 0x700)[((v ) & 0xFF)]
^ table[0x600 + ((v >> 8) & 0xFF)] ^ (table + 0x600)[((v >> 8) & 0xFF)]
^ table[0x500 + ((v >> 16) & 0xFF)] ^ (table + 0x500)[((v >> 16) & 0xFF)]
^ table[0x400 + ((v >> 24))]; ^ (table + 0x400)[((v >> 24))];
d = *((const UInt32 *)p + 1); d = *((const UInt32 *)p + 1);
v ^= v ^=
table[0x300 + ((d ) & 0xFF)] (table + 0x300)[((d ) & 0xFF)]
^ table[0x200 + ((d >> 8) & 0xFF)] ^ (table + 0x200)[((d >> 8) & 0xFF)]
^ table[0x100 + ((d >> 16) & 0xFF)] ^ (table + 0x100)[((d >> 16) & 0xFF)]
^ table[0x000 + ((d >> 24))]; ^ (table + 0x000)[((d >> 24))];
} }
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2(v, *p);
@ -74,10 +74,10 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, co
{ {
v ^= *(const UInt32 *)p; v ^= *(const UInt32 *)p;
v = v =
table[0x000 + ((v ) & 0xFF)] (table + 0x000)[((v ) & 0xFF)]
^ table[0x100 + ((v >> 8) & 0xFF)] ^ (table + 0x100)[((v >> 8) & 0xFF)]
^ table[0x200 + ((v >> 16) & 0xFF)] ^ (table + 0x200)[((v >> 16) & 0xFF)]
^ table[0x300 + ((v >> 24))]; ^ (table + 0x300)[((v >> 24))];
} }
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p); v = CRC_UPDATE_BYTE_2_BE(v, *p);
@ -96,16 +96,16 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, co
UInt32 d; UInt32 d;
v ^= *(const UInt32 *)p; v ^= *(const UInt32 *)p;
v = v =
table[0x400 + ((v ) & 0xFF)] (table + 0x400)[((v ) & 0xFF)]
^ table[0x500 + ((v >> 8) & 0xFF)] ^ (table + 0x500)[((v >> 8) & 0xFF)]
^ table[0x600 + ((v >> 16) & 0xFF)] ^ (table + 0x600)[((v >> 16) & 0xFF)]
^ table[0x700 + ((v >> 24))]; ^ (table + 0x700)[((v >> 24))];
d = *((const UInt32 *)p + 1); d = *((const UInt32 *)p + 1);
v ^= v ^=
table[0x000 + ((d ) & 0xFF)] (table + 0x000)[((d ) & 0xFF)]
^ table[0x100 + ((d >> 8) & 0xFF)] ^ (table + 0x100)[((d >> 8) & 0xFF)]
^ table[0x200 + ((d >> 16) & 0xFF)] ^ (table + 0x200)[((d >> 16) & 0xFF)]
^ table[0x300 + ((d >> 24))]; ^ (table + 0x300)[((d >> 24))];
} }
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p); v = CRC_UPDATE_BYTE_2_BE(v, *p);

View File

@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2015-11-18 : Igor Pavlov : Public domain */ 2019-02-02 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -39,28 +39,28 @@
typedef struct typedef struct
{ {
IByteIn p; IByteIn vt;
const Byte *cur; const Byte *cur;
const Byte *end; const Byte *end;
const Byte *begin; const Byte *begin;
UInt64 processed; UInt64 processed;
Bool extra; BoolInt extra;
SRes res; SRes res;
ILookInStream *inStream; const ILookInStream *inStream;
} CByteInToLook; } CByteInToLook;
static Byte ReadByte(void *pp) static Byte ReadByte(const IByteIn *pp)
{ {
CByteInToLook *p = (CByteInToLook *)pp; CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt);
if (p->cur != p->end) if (p->cur != p->end)
return *p->cur++; return *p->cur++;
if (p->res == SZ_OK) if (p->res == SZ_OK)
{ {
size_t size = p->cur - p->begin; size_t size = p->cur - p->begin;
p->processed += size; p->processed += size;
p->res = p->inStream->Skip(p->inStream, size); p->res = ILookInStream_Skip(p->inStream, size);
size = (1 << 25); size = (1 << 25);
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size);
p->cur = p->begin; p->cur = p->begin;
p->end = p->begin + size; p->end = p->begin + size;
if (size != 0) if (size != 0)
@ -70,14 +70,14 @@ static Byte ReadByte(void *pp)
return 0; return 0;
} }
static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
{ {
CPpmd7 ppmd; CPpmd7 ppmd;
CByteInToLook s; CByteInToLook s;
SRes res = SZ_OK; SRes res = SZ_OK;
s.p.Read = ReadByte; s.vt.Read = ReadByte;
s.inStream = inStream; s.inStream = inStream;
s.begin = s.end = s.cur = NULL; s.begin = s.end = s.cur = NULL;
s.extra = False; s.extra = False;
@ -103,7 +103,7 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, I
{ {
CPpmd7z_RangeDec rc; CPpmd7z_RangeDec rc;
Ppmd7z_RangeDec_CreateVTable(&rc); Ppmd7z_RangeDec_CreateVTable(&rc);
rc.Stream = &s.p; rc.Stream = &s.vt;
if (!Ppmd7z_RangeDec_Init(&rc)) if (!Ppmd7z_RangeDec_Init(&rc))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
else if (s.extra) else if (s.extra)
@ -113,7 +113,7 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, I
SizeT i; SizeT i;
for (i = 0; i < outSize; i++) for (i = 0; i < outSize; i++)
{ {
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt);
if (s.extra || sym < 0) if (s.extra || sym < 0)
break; break;
outBuffer[i] = (Byte)sym; outBuffer[i] = (Byte)sym;
@ -132,7 +132,7 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, I
static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
{ {
CLzmaDec state; CLzmaDec state;
SRes res = SZ_OK; SRes res = SZ_OK;
@ -149,14 +149,14 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
size_t lookahead = (1 << 18); size_t lookahead = (1 << 18);
if (lookahead > inSize) if (lookahead > inSize)
lookahead = (size_t)inSize; lookahead = (size_t)inSize;
res = inStream->Look(inStream, &inBuf, &lookahead); res = ILookInStream_Look(inStream, &inBuf, &lookahead);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
{ {
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
ELzmaStatus status; ELzmaStatus status;
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); res = LzmaDec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed; lookahead -= inProcessed;
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
@ -178,7 +178,7 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
break; break;
} }
res = inStream->Skip((void *)inStream, inProcessed); res = ILookInStream_Skip(inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
} }
@ -192,7 +192,7 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
#ifndef _7Z_NO_METHOD_LZMA2 #ifndef _7Z_NO_METHOD_LZMA2
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
{ {
CLzma2Dec state; CLzma2Dec state;
SRes res = SZ_OK; SRes res = SZ_OK;
@ -211,14 +211,14 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
size_t lookahead = (1 << 18); size_t lookahead = (1 << 18);
if (lookahead > inSize) if (lookahead > inSize)
lookahead = (size_t)inSize; lookahead = (size_t)inSize;
res = inStream->Look(inStream, &inBuf, &lookahead); res = ILookInStream_Look(inStream, &inBuf, &lookahead);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
{ {
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
ELzmaStatus status; ELzmaStatus status;
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); res = Lzma2Dec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed; lookahead -= inProcessed;
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
@ -237,7 +237,7 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
break; break;
} }
res = inStream->Skip((void *)inStream, inProcessed); res = ILookInStream_Skip(inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
} }
@ -258,18 +258,18 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
size_t curSize = (1 << 18); size_t curSize = (1 << 18);
if (curSize > inSize) if (curSize > inSize)
curSize = (size_t)inSize; curSize = (size_t)inSize;
RINOK(inStream->Look(inStream, &inBuf, &curSize)); RINOK(ILookInStream_Look(inStream, &inBuf, &curSize));
if (curSize == 0) if (curSize == 0)
return SZ_ERROR_INPUT_EOF; return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize); memcpy(outBuffer, inBuf, curSize);
outBuffer += curSize; outBuffer += curSize;
inSize -= curSize; inSize -= curSize;
RINOK(inStream->Skip((void *)inStream, curSize)); RINOK(ILookInStream_Skip(inStream, curSize));
} }
return SZ_OK; return SZ_OK;
} }
static Bool IS_MAIN_METHOD(UInt32 m) static BoolInt IS_MAIN_METHOD(UInt32 m)
{ {
switch (m) switch (m)
{ {
@ -286,7 +286,7 @@ static Bool IS_MAIN_METHOD(UInt32 m)
return False; return False;
} }
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c)
{ {
return return
c->NumStreams == 1 c->NumStreams == 1
@ -372,7 +372,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
const UInt64 *unpackSizes, const UInt64 *unpackSizes,
const UInt64 *packPositions, const UInt64 *packPositions,
ILookInStream *inStream, UInt64 startPos, ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain,
Byte *tempBuf[]) Byte *tempBuf[])
{ {
UInt32 ci; UInt32 ci;
@ -404,7 +404,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
outSizeCur = (SizeT)unpackSize; outSizeCur = (SizeT)unpackSize;
if (outSizeCur != unpackSize) if (outSizeCur != unpackSize)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur);
if (!temp && outSizeCur != 0) if (!temp && outSizeCur != 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
outBufCur = tempBuf[1 - ci] = temp; outBufCur = tempBuf[1 - ci] = temp;
@ -421,7 +421,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
offset = packPositions[si]; offset = packPositions[si];
inSize = packPositions[si + 1] - offset; inSize = packPositions[(size_t)si + 1] - offset;
RINOK(LookInStream_SeekTo(inStream, startPos + offset)); RINOK(LookInStream_SeekTo(inStream, startPos + offset));
if (coder->MethodID == k_Copy) if (coder->MethodID == k_Copy)
@ -460,7 +460,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
tempSizes[2] = (SizeT)s3Size; tempSizes[2] = (SizeT)s3Size;
if (tempSizes[2] != s3Size) if (tempSizes[2] != s3Size)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]);
if (!tempBuf[2] && tempSizes[2] != 0) if (!tempBuf[2] && tempSizes[2] != 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
@ -549,7 +549,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
ILookInStream *inStream, UInt64 startPos, ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize, Byte *outBuffer, size_t outSize,
ISzAlloc *allocMain) ISzAllocPtr allocMain)
{ {
SRes res; SRes res;
CSzFolder folder; CSzFolder folder;
@ -557,7 +557,7 @@ SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
sd.Data = data; sd.Data = data;
sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex]; sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex];
res = SzGetNextFolderItem(&folder, &sd); res = SzGetNextFolderItem(&folder, &sd);
@ -579,7 +579,7 @@ SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
outBuffer, (SizeT)outSize, allocMain, tempBuf); outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]); ISzAlloc_Free(allocMain, tempBuf[i]);
if (res == SZ_OK) if (res == SZ_OK)
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex)) if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))

View File

@ -1,5 +1,5 @@
/* 7zFile.c -- File IO /* 7zFile.c -- File IO
2009-11-24 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -238,49 +238,49 @@ WRes File_GetLength(CSzFile *p, UInt64 *length)
/* ---------- FileSeqInStream ---------- */ /* ---------- FileSeqInStream ---------- */
static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size)
{ {
CFileSeqInStream *p = (CFileSeqInStream *)pp; CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt);
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
} }
void FileSeqInStream_CreateVTable(CFileSeqInStream *p) void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
{ {
p->s.Read = FileSeqInStream_Read; p->vt.Read = FileSeqInStream_Read;
} }
/* ---------- FileInStream ---------- */ /* ---------- FileInStream ---------- */
static SRes FileInStream_Read(void *pp, void *buf, size_t *size) static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size)
{ {
CFileInStream *p = (CFileInStream *)pp; CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
} }
static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) static SRes FileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin)
{ {
CFileInStream *p = (CFileInStream *)pp; CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
return File_Seek(&p->file, pos, origin); return File_Seek(&p->file, pos, origin);
} }
void FileInStream_CreateVTable(CFileInStream *p) void FileInStream_CreateVTable(CFileInStream *p)
{ {
p->s.Read = FileInStream_Read; p->vt.Read = FileInStream_Read;
p->s.Seek = FileInStream_Seek; p->vt.Seek = FileInStream_Seek;
} }
/* ---------- FileOutStream ---------- */ /* ---------- FileOutStream ---------- */
static size_t FileOutStream_Write(void *pp, const void *data, size_t size) static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size)
{ {
CFileOutStream *p = (CFileOutStream *)pp; CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt);
File_Write(&p->file, data, &size); File_Write(&p->file, data, &size);
return size; return size;
} }
void FileOutStream_CreateVTable(CFileOutStream *p) void FileOutStream_CreateVTable(CFileOutStream *p)
{ {
p->s.Write = FileOutStream_Write; p->vt.Write = FileOutStream_Write;
} }

View File

@ -1,5 +1,5 @@
/* 7zFile.h -- File IO /* 7zFile.h -- File IO
2013-01-18 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_FILE_H #ifndef __7Z_FILE_H
#define __7Z_FILE_H #define __7Z_FILE_H
@ -54,7 +54,7 @@ WRes File_GetLength(CSzFile *p, UInt64 *length);
typedef struct typedef struct
{ {
ISeqInStream s; ISeqInStream vt;
CSzFile file; CSzFile file;
} CFileSeqInStream; } CFileSeqInStream;
@ -63,7 +63,7 @@ void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
typedef struct typedef struct
{ {
ISeekInStream s; ISeekInStream vt;
CSzFile file; CSzFile file;
} CFileInStream; } CFileInStream;
@ -72,7 +72,7 @@ void FileInStream_CreateVTable(CFileInStream *p);
typedef struct typedef struct
{ {
ISeqOutStream s; ISeqOutStream vt;
CSzFile file; CSzFile file;
} CFileOutStream; } CFileOutStream;

View File

@ -1,5 +1,5 @@
/* 7zStream.c -- 7z Stream functions /* 7zStream.c -- 7z Stream functions
2013-11-12 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -7,12 +7,12 @@
#include "7zTypes.h" #include "7zTypes.h"
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType)
{ {
while (size != 0) while (size != 0)
{ {
size_t processed = size; size_t processed = size;
RINOK(stream->Read(stream, buf, &processed)); RINOK(ISeqInStream_Read(stream, buf, &processed));
if (processed == 0) if (processed == 0)
return errorType; return errorType;
buf = (void *)((Byte *)buf + processed); buf = (void *)((Byte *)buf + processed);
@ -21,40 +21,42 @@ SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorT
return SZ_OK; return SZ_OK;
} }
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size)
{ {
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
} }
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf)
{ {
size_t processed = 1; size_t processed = 1;
RINOK(stream->Read(stream, buf, &processed)); RINOK(ISeqInStream_Read(stream, buf, &processed));
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
} }
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset)
{ {
Int64 t = offset; Int64 t = offset;
return stream->Seek(stream, &t, SZ_SEEK_SET); return ILookInStream_Seek(stream, &t, SZ_SEEK_SET);
} }
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size)
{ {
const void *lookBuf; const void *lookBuf;
if (*size == 0) if (*size == 0)
return SZ_OK; return SZ_OK;
RINOK(stream->Look(stream, &lookBuf, size)); RINOK(ILookInStream_Look(stream, &lookBuf, size));
memcpy(buf, lookBuf, *size); memcpy(buf, lookBuf, *size);
return stream->Skip(stream, *size); return ILookInStream_Skip(stream, *size);
} }
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType)
{ {
while (size != 0) while (size != 0)
{ {
size_t processed = size; size_t processed = size;
RINOK(stream->Read(stream, buf, &processed)); RINOK(ILookInStream_Read(stream, buf, &processed));
if (processed == 0) if (processed == 0)
return errorType; return errorType;
buf = (void *)((Byte *)buf + processed); buf = (void *)((Byte *)buf + processed);
@ -63,61 +65,67 @@ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes erro
return SZ_OK; return SZ_OK;
} }
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size)
{ {
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
} }
static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
#define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt);
static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
size_t size2 = p->size - p->pos; size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0) if (size2 == 0 && *size != 0)
{ {
p->pos = 0; p->pos = 0;
size2 = LookToRead_BUF_SIZE; p->size = 0;
res = p->realStream->Read(p->realStream, p->buf, &size2); size2 = p->bufSize;
res = ISeekInStream_Read(p->realStream, p->buf, &size2);
p->size = size2; p->size = size2;
} }
if (size2 < *size) if (*size > size2)
*size = size2; *size = size2;
*buf = p->buf + p->pos; *buf = p->buf + p->pos;
return res; return res;
} }
static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size) static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
size_t size2 = p->size - p->pos; size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0) if (size2 == 0 && *size != 0)
{ {
p->pos = 0; p->pos = 0;
if (*size > LookToRead_BUF_SIZE) p->size = 0;
*size = LookToRead_BUF_SIZE; if (*size > p->bufSize)
res = p->realStream->Read(p->realStream, p->buf, size); *size = p->bufSize;
res = ISeekInStream_Read(p->realStream, p->buf, size);
size2 = p->size = *size; size2 = p->size = *size;
} }
if (size2 < *size) if (*size > size2)
*size = size2; *size = size2;
*buf = p->buf + p->pos; *buf = p->buf + p->pos;
return res; return res;
} }
static SRes LookToRead_Skip(void *pp, size_t offset) static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset)
{ {
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
p->pos += offset; p->pos += offset;
return SZ_OK; return SZ_OK;
} }
static SRes LookToRead_Read(void *pp, void *buf, size_t *size) static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size)
{ {
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
size_t rem = p->size - p->pos; size_t rem = p->size - p->pos;
if (rem == 0) if (rem == 0)
return p->realStream->Read(p->realStream, buf, size); return ISeekInStream_Read(p->realStream, buf, size);
if (rem > *size) if (rem > *size)
rem = *size; rem = *size;
memcpy(buf, p->buf + p->pos, rem); memcpy(buf, p->buf + p->pos, rem);
@ -126,46 +134,43 @@ static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
return SZ_OK; return SZ_OK;
} }
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) static SRes LookToRead2_Seek(const ILookInStream *pp, Int64 *pos, ESzSeek origin)
{ {
CLookToRead *p = (CLookToRead *)pp; GET_LookToRead2
p->pos = p->size = 0; p->pos = p->size = 0;
return p->realStream->Seek(p->realStream, pos, origin); return ISeekInStream_Seek(p->realStream, pos, origin);
} }
void LookToRead_CreateVTable(CLookToRead *p, int lookahead) void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead)
{ {
p->s.Look = lookahead ? p->vt.Look = lookahead ?
LookToRead_Look_Lookahead : LookToRead2_Look_Lookahead :
LookToRead_Look_Exact; LookToRead2_Look_Exact;
p->s.Skip = LookToRead_Skip; p->vt.Skip = LookToRead2_Skip;
p->s.Read = LookToRead_Read; p->vt.Read = LookToRead2_Read;
p->s.Seek = LookToRead_Seek; p->vt.Seek = LookToRead2_Seek;
} }
void LookToRead_Init(CLookToRead *p)
{
p->pos = p->size = 0;
}
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size)
{ {
CSecToLook *p = (CSecToLook *)pp; CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt);
return LookInStream_LookRead(p->realStream, buf, size); return LookInStream_LookRead(p->realStream, buf, size);
} }
void SecToLook_CreateVTable(CSecToLook *p) void SecToLook_CreateVTable(CSecToLook *p)
{ {
p->s.Read = SecToLook_Read; p->vt.Read = SecToLook_Read;
} }
static SRes SecToRead_Read(void *pp, void *buf, size_t *size) static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size)
{ {
CSecToRead *p = (CSecToRead *)pp; CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt);
return p->realStream->Read(p->realStream, buf, size); return ILookInStream_Read(p->realStream, buf, size);
} }
void SecToRead_CreateVTable(CSecToRead *p) void SecToRead_CreateVTable(CSecToRead *p)
{ {
p->s.Read = SecToRead_Read; p->vt.Read = SecToRead_Read;
} }

View File

@ -1,5 +1,5 @@
/* 7zTypes.h -- Basic types /* 7zTypes.h -- Basic types
2013-11-12 : Igor Pavlov : Public domain */ 2018-08-04 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H #ifndef __7Z_TYPES_H
#define __7Z_TYPES_H #define __7Z_TYPES_H
@ -42,13 +42,23 @@ EXTERN_C_BEGIN
typedef int SRes; typedef int SRes;
#ifdef _WIN32 #ifdef _WIN32
/* typedef DWORD WRes; */ /* typedef DWORD WRes; */
typedef unsigned WRes; typedef unsigned WRes;
#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
#else #else
typedef int WRes; typedef int WRes;
#define MY__FACILITY_WIN32 7
#define MY__FACILITY__WRes MY__FACILITY_WIN32
#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
#endif #endif
#ifndef RINOK #ifndef RINOK
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
#endif #endif
@ -93,7 +103,8 @@ typedef UInt32 SizeT;
typedef size_t SizeT; typedef size_t SizeT;
#endif #endif
typedef int Bool; typedef int BoolInt;
/* typedef BoolInt Bool; */
#define True 1 #define True 1
#define False 0 #define False 0
@ -112,48 +123,72 @@ typedef int Bool;
#define MY_NO_INLINE #define MY_NO_INLINE
#endif #endif
#define MY_FORCE_INLINE __forceinline
#define MY_CDECL __cdecl #define MY_CDECL __cdecl
#define MY_FAST_CALL __fastcall #define MY_FAST_CALL __fastcall
#else #else
#define MY_NO_INLINE #define MY_NO_INLINE
#define MY_FORCE_INLINE
#define MY_CDECL #define MY_CDECL
#define MY_FAST_CALL #define MY_FAST_CALL
/* inline keyword : for C++ / C99 */
/* GCC, clang: */
/*
#if defined (__GNUC__) && (__GNUC__ >= 4)
#define MY_FORCE_INLINE __attribute__((always_inline))
#define MY_NO_INLINE __attribute__((noinline))
#endif
*/
#endif #endif
/* The following interfaces use first parameter as pointer to structure */ /* The following interfaces use first parameter as pointer to structure */
typedef struct typedef struct IByteIn IByteIn;
struct IByteIn
{ {
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */
} IByteIn; };
#define IByteIn_Read(p) (p)->Read(p)
typedef struct
{
void (*Write)(void *p, Byte b);
} IByteOut;
typedef struct typedef struct IByteOut IByteOut;
struct IByteOut
{ {
SRes (*Read)(void *p, void *buf, size_t *size); void (*Write)(const IByteOut *p, Byte b);
};
#define IByteOut_Write(p, b) (p)->Write(p, b)
typedef struct ISeqInStream ISeqInStream;
struct ISeqInStream
{
SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */ (output(*size) < input(*size)) is allowed */
} ISeqInStream; };
#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
/* it can return SZ_ERROR_INPUT_EOF */ /* it can return SZ_ERROR_INPUT_EOF */
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size);
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType);
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf);
typedef struct
typedef struct ISeqOutStream ISeqOutStream;
struct ISeqOutStream
{ {
size_t (*Write)(void *p, const void *buf, size_t size); size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes. /* Returns: result - the number of actually written bytes.
(result < size) means error */ (result < size) means error */
} ISeqOutStream; };
#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
typedef enum typedef enum
{ {
@ -162,78 +197,162 @@ typedef enum
SZ_SEEK_END = 2 SZ_SEEK_END = 2
} ESzSeek; } ESzSeek;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ISeekInStream;
typedef struct typedef struct ISeekInStream ISeekInStream;
struct ISeekInStream
{ {
SRes (*Look)(void *p, const void **buf, size_t *size); SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin);
};
#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size)
#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
typedef struct ILookInStream ILookInStream;
struct ILookInStream
{
SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed (output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */ (output(*size) < input(*size)) is allowed */
SRes (*Skip)(void *p, size_t offset); SRes (*Skip)(const ILookInStream *p, size_t offset);
/* offset must be <= output(*size) of Look */ /* offset must be <= output(*size) of Look */
SRes (*Read)(void *p, void *buf, size_t *size); SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */ /* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin);
} ILookInStream; };
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); #define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size)
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); #define ILookInStream_Skip(p, offset) (p)->Skip(p, offset)
#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size)
#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size);
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset);
/* reads via ILookInStream::Read */ /* reads via ILookInStream::Read */
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType);
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size);
#define LookToRead_BUF_SIZE (1 << 14)
typedef struct typedef struct
{ {
ILookInStream s; ILookInStream vt;
ISeekInStream *realStream; const ISeekInStream *realStream;
size_t pos; size_t pos;
size_t size; size_t size; /* it's data size */
Byte buf[LookToRead_BUF_SIZE];
} CLookToRead; /* the following variables must be set outside */
Byte *buf;
size_t bufSize;
} CLookToRead2;
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);
#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; }
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
void LookToRead_Init(CLookToRead *p);
typedef struct typedef struct
{ {
ISeqInStream s; ISeqInStream vt;
ILookInStream *realStream; const ILookInStream *realStream;
} CSecToLook; } CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p); void SecToLook_CreateVTable(CSecToLook *p);
typedef struct typedef struct
{ {
ISeqInStream s; ISeqInStream vt;
ILookInStream *realStream; const ILookInStream *realStream;
} CSecToRead; } CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p); void SecToRead_CreateVTable(CSecToRead *p);
typedef struct
typedef struct ICompressProgress ICompressProgress;
struct ICompressProgress
{ {
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break. /* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */ Value (UInt64)(Int64)-1 for size means unknown value. */
} ICompressProgress; };
#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
typedef struct
typedef struct ISzAlloc ISzAlloc;
typedef const ISzAlloc * ISzAllocPtr;
struct ISzAlloc
{ {
void *(*Alloc)(void *p, size_t size); void *(*Alloc)(ISzAllocPtr p, size_t size);
void (*Free)(void *p, void *address); /* address can be 0 */ void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
} ISzAlloc; };
#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)
#define ISzAlloc_Free(p, a) (p)->Free(p, a)
/* deprecated */
#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)
#define IAlloc_Free(p, a) ISzAlloc_Free(p, a)
#ifndef MY_offsetof
#ifdef offsetof
#define MY_offsetof(type, m) offsetof(type, m)
/*
#define MY_offsetof(type, m) FIELD_OFFSET(type, m)
*/
#else
#define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))
#endif
#endif
#ifndef MY_container_of
/*
#define MY_container_of(ptr, type, m) container_of(ptr, type, m)
#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)
#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))
#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))
*/
/*
GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly"
GCC 3.4.4 : classes with constructor
GCC 4.8.1 : classes with non-public variable members"
*/
#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
#endif
#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr))
/*
#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
*/
#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m)
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
/*
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m)
*/
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef _WIN32 #ifdef _WIN32

View File

@ -1,14 +1,21 @@
#define MY_VER_MAJOR 15 #define MY_VER_MAJOR 19
#define MY_VER_MINOR 14 #define MY_VER_MINOR 00
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "15.14" #define MY_VERSION_NUMBERS "19.00"
#define MY_VERSION "15.14" #define MY_VERSION MY_VERSION_NUMBERS
#define MY_DATE "2015-12-31"
#ifdef MY_CPU_NAME
#define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")"
#else
#define MY_VERSION_CPU MY_VERSION
#endif
#define MY_DATE "2019-02-21"
#undef MY_COPYRIGHT #undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE #undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov" #define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov" #define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR #ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR #define MY_COPYRIGHT MY_COPYRIGHT_CR
@ -16,4 +23,5 @@
#define MY_COPYRIGHT MY_COPYRIGHT_PD #define MY_COPYRIGHT MY_COPYRIGHT_PD
#endif #endif
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " : " MY_COPYRIGHT " : " MY_DATE #define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE

View File

@ -1,5 +1,5 @@
/* Aes.c -- AES encryption / decryption /* Aes.c -- AES encryption / decryption
2015-02-23 : Igor Pavlov : Public domain */ 2017-01-24 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -49,7 +49,13 @@ static const Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0
#define gb0(x) ( (x) & 0xFF) #define gb0(x) ( (x) & 0xFF)
#define gb1(x) (((x) >> ( 8)) & 0xFF) #define gb1(x) (((x) >> ( 8)) & 0xFF)
#define gb2(x) (((x) >> (16)) & 0xFF) #define gb2(x) (((x) >> (16)) & 0xFF)
#define gb3(x) (((x) >> (24)) & 0xFF) #define gb3(x) (((x) >> (24)))
#define gb(n, x) gb ## n(x)
#define TT(x) (T + (x << 8))
#define DD(x) (D + (x << 8))
void AesGenTables(void) void AesGenTables(void)
{ {
@ -63,10 +69,10 @@ void AesGenTables(void)
UInt32 a1 = Sbox[i]; UInt32 a1 = Sbox[i];
UInt32 a2 = xtime(a1); UInt32 a2 = xtime(a1);
UInt32 a3 = a2 ^ a1; UInt32 a3 = a2 ^ a1;
T[ i] = Ui32(a2, a1, a1, a3); TT(0)[i] = Ui32(a2, a1, a1, a3);
T[0x100 + i] = Ui32(a3, a2, a1, a1); TT(1)[i] = Ui32(a3, a2, a1, a1);
T[0x200 + i] = Ui32(a1, a3, a2, a1); TT(2)[i] = Ui32(a1, a3, a2, a1);
T[0x300 + i] = Ui32(a1, a1, a3, a2); TT(3)[i] = Ui32(a1, a1, a3, a2);
} }
{ {
UInt32 a1 = InvS[i]; UInt32 a1 = InvS[i];
@ -77,10 +83,10 @@ void AesGenTables(void)
UInt32 aB = a8 ^ a2 ^ a1; UInt32 aB = a8 ^ a2 ^ a1;
UInt32 aD = a8 ^ a4 ^ a1; UInt32 aD = a8 ^ a4 ^ a1;
UInt32 aE = a8 ^ a4 ^ a2; UInt32 aE = a8 ^ a4 ^ a2;
D[ i] = Ui32(aE, a9, aD, aB); DD(0)[i] = Ui32(aE, a9, aD, aB);
D[0x100 + i] = Ui32(aB, aE, a9, aD); DD(1)[i] = Ui32(aB, aE, a9, aD);
D[0x200 + i] = Ui32(aD, aB, aE, a9); DD(2)[i] = Ui32(aD, aB, aE, a9);
D[0x300 + i] = Ui32(a9, aD, aB, aE); DD(3)[i] = Ui32(a9, aD, aB, aE);
} }
} }
@ -99,7 +105,7 @@ void AesGenTables(void)
} }
#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])] #define HT(i, x, s) TT(x)[gb(x, s[(i + x) & 3])]
#define HT4(m, i, s, p) m[i] = \ #define HT4(m, i, s, p) m[i] = \
HT(i, 0, s) ^ \ HT(i, 0, s) ^ \
@ -113,11 +119,11 @@ void AesGenTables(void)
HT4(m, 2, s, p); \ HT4(m, 2, s, p); \
HT4(m, 3, s, p); \ HT4(m, 3, s, p); \
#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])] #define FT(i, x) Sbox[gb(x, m[(i + x) & 3])]
#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i]; #define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];
#define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])] #define HD(i, x, s) DD(x)[gb(x, s[(i - x) & 3])]
#define HD4(m, i, s, p) m[i] = \ #define HD4(m, i, s, p) m[i] = \
HD(i, 0, s) ^ \ HD(i, 0, s) ^ \
@ -131,7 +137,7 @@ void AesGenTables(void)
HD4(m, 2, s, p); \ HD4(m, 2, s, p); \
HD4(m, 3, s, p); \ HD4(m, 3, s, p); \
#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])] #define FD(i, x) InvS[gb(x, m[(i - x) & 3])]
#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i]; #define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];
void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize) void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)
@ -147,7 +153,7 @@ void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)
for (; i < wSize; i++) for (; i < wSize; i++)
{ {
UInt32 t = w[i - 1]; UInt32 t = w[(size_t)i - 1];
unsigned rem = i % keySize; unsigned rem = i % keySize;
if (rem == 0) if (rem == 0)
t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]); t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]);
@ -167,10 +173,10 @@ void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)
{ {
UInt32 r = w[i]; UInt32 r = w[i];
w[i] = w[i] =
D[ Sbox[gb0(r)]] ^ DD(0)[Sbox[gb0(r)]] ^
D[0x100 + Sbox[gb1(r)]] ^ DD(1)[Sbox[gb1(r)]] ^
D[0x200 + Sbox[gb2(r)]] ^ DD(2)[Sbox[gb2(r)]] ^
D[0x300 + Sbox[gb3(r)]]; DD(3)[Sbox[gb3(r)]];
} }
} }
@ -276,20 +282,25 @@ void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)
for (; numBlocks != 0; numBlocks--) for (; numBlocks != 0; numBlocks--)
{ {
UInt32 temp[4]; UInt32 temp[4];
Byte buf[16]; unsigned i;
int i;
if (++p[0] == 0) if (++p[0] == 0)
p[1]++; p[1]++;
Aes_Encode(p + 4, temp, p); Aes_Encode(p + 4, temp, p);
SetUi32(buf, temp[0]); for (i = 0; i < 4; i++, data += 4)
SetUi32(buf + 4, temp[1]); {
SetUi32(buf + 8, temp[2]); UInt32 t = temp[i];
SetUi32(buf + 12, temp[3]);
for (i = 0; i < 16; i++) #ifdef MY_CPU_LE_UNALIGN
*data++ ^= buf[i]; *((UInt32 *)data) ^= t;
#else
data[0] ^= (t & 0xFF);
data[1] ^= ((t >> 8) & 0xFF);
data[2] ^= ((t >> 16) & 0xFF);
data[3] ^= ((t >> 24));
#endif
}
} }
} }

View File

@ -1,12 +1,12 @@
/* AesOpt.c -- Intel's AES /* AesOpt.c -- Intel's AES
2013-11-12 : Igor Pavlov : Public domain */ 2017-06-08 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "CpuArch.h" #include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
#if _MSC_VER >= 1500 #if (_MSC_VER > 1500) || (_MSC_FULL_VER >= 150030729)
#define USE_INTEL_AES #define USE_INTEL_AES
#endif #endif
#endif #endif

View File

@ -1,8 +1,10 @@
/* Alloc.c -- Memory allocation functions /* Alloc.c -- Memory allocation functions
2015-02-21 : Igor Pavlov : Public domain */ 2018-04-27 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <stdio.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#endif #endif
@ -14,20 +16,127 @@
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
#include <stdio.h> #include <stdio.h>
int g_allocCount = 0; int g_allocCount = 0;
int g_allocCountMid = 0; int g_allocCountMid = 0;
int g_allocCountBig = 0; int g_allocCountBig = 0;
#define CONVERT_INT_TO_STR(charType, tempSize) \
unsigned char temp[tempSize]; unsigned i = 0; \
while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \
*s++ = (charType)('0' + (unsigned)val); \
while (i != 0) { i--; *s++ = temp[i]; } \
*s = 0;
static void ConvertUInt64ToString(UInt64 val, char *s)
{
CONVERT_INT_TO_STR(char, 24);
}
#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
static void ConvertUInt64ToHex(UInt64 val, char *s)
{
UInt64 v = val;
unsigned i;
for (i = 1;; i++)
{
v >>= 4;
if (v == 0)
break;
}
s[i] = 0;
do
{
unsigned t = (unsigned)(val & 0xF);
val >>= 4;
s[--i] = GET_HEX_CHAR(t);
}
while (i);
}
#define DEBUG_OUT_STREAM stderr
static void Print(const char *s)
{
fputs(s, DEBUG_OUT_STREAM);
}
static void PrintAligned(const char *s, size_t align)
{
size_t len = strlen(s);
for(;;)
{
fputc(' ', DEBUG_OUT_STREAM);
if (len >= align)
break;
++len;
}
Print(s);
}
static void PrintLn()
{
Print("\n");
}
static void PrintHex(UInt64 v, size_t align)
{
char s[32];
ConvertUInt64ToHex(v, s);
PrintAligned(s, align);
}
static void PrintDec(UInt64 v, size_t align)
{
char s[32];
ConvertUInt64ToString(v, s);
PrintAligned(s, align);
}
static void PrintAddr(void *p)
{
PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12);
}
#define PRINT_ALLOC(name, cnt, size, ptr) \
Print(name " "); \
PrintDec(cnt++, 10); \
PrintHex(size, 10); \
PrintAddr(ptr); \
PrintLn();
#define PRINT_FREE(name, cnt, ptr) if (ptr) { \
Print(name " "); \
PrintDec(--cnt, 10); \
PrintAddr(ptr); \
PrintLn(); }
#else
#define PRINT_ALLOC(name, cnt, size, ptr)
#define PRINT_FREE(name, cnt, ptr)
#define Print(s)
#define PrintLn()
#define PrintHex(v, align)
#define PrintDec(v, align)
#define PrintAddr(p)
#endif #endif
void *MyAlloc(size_t size) void *MyAlloc(size_t size)
{ {
if (size == 0) if (size == 0)
return 0; return NULL;
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
{ {
void *p = malloc(size); void *p = malloc(size);
fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); PRINT_ALLOC("Alloc ", g_allocCount, size, p);
return p; return p;
} }
#else #else
@ -37,10 +146,8 @@ void *MyAlloc(size_t size)
void MyFree(void *address) void MyFree(void *address)
{ {
#ifdef _SZ_ALLOC_DEBUG PRINT_FREE("Free ", g_allocCount, address);
if (address != 0)
fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address);
#endif
free(address); free(address);
} }
@ -49,20 +156,18 @@ void MyFree(void *address)
void *MidAlloc(size_t size) void *MidAlloc(size_t size)
{ {
if (size == 0) if (size == 0)
return 0; return NULL;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL);
#endif
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
} }
void MidFree(void *address) void MidFree(void *address)
{ {
#ifdef _SZ_ALLOC_DEBUG PRINT_FREE("Free-Mid", g_allocCountMid, address);
if (address != 0)
fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); if (!address)
#endif
if (address == 0)
return; return;
VirtualFree(address, 0, MEM_RELEASE); VirtualFree(address, 0, MEM_RELEASE);
} }
@ -79,10 +184,10 @@ typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
void SetLargePageSize() void SetLargePageSize()
{ {
#ifdef _7ZIP_LARGE_PAGES #ifdef _7ZIP_LARGE_PAGES
SIZE_T size = 0; SIZE_T size;
GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
if (largePageMinimum == 0) if (!largePageMinimum)
return; return;
size = largePageMinimum(); size = largePageMinimum();
if (size == 0 || (size & (size - 1)) != 0) if (size == 0 || (size & (size - 1)) != 0)
@ -95,31 +200,36 @@ void SetLargePageSize()
void *BigAlloc(size_t size) void *BigAlloc(size_t size)
{ {
if (size == 0) if (size == 0)
return 0; return NULL;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL);
#endif
#ifdef _7ZIP_LARGE_PAGES #ifdef _7ZIP_LARGE_PAGES
if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
{ {
void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), SIZE_T ps = g_LargePageSize;
MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (ps != 0 && ps <= (1 << 30) && size > (ps / 2))
if (res != 0) {
return res; size_t size2;
ps--;
size2 = (size + ps) & ~ps;
if (size2 >= size)
{
void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
if (res)
return res;
}
}
} }
#endif #endif
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
} }
void BigFree(void *address) void BigFree(void *address)
{ {
#ifdef _SZ_ALLOC_DEBUG PRINT_FREE("Free-Big", g_allocCountBig, address);
if (address != 0)
fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
#endif
if (address == 0) if (!address)
return; return;
VirtualFree(address, 0, MEM_RELEASE); VirtualFree(address, 0, MEM_RELEASE);
} }
@ -127,10 +237,219 @@ void BigFree(void *address)
#endif #endif
static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); } static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
static void SzFree(void *p, void *address) { UNUSED_VAR(p); MyFree(address); } static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); }
ISzAlloc g_Alloc = { SzAlloc, SzFree }; const ISzAlloc g_Alloc = { SzAlloc, SzFree };
static void *SzBigAlloc(void *p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); } static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); }
static void SzBigFree(void *p, void *address) { UNUSED_VAR(p); BigFree(address); } static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); }
ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }
static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); }
const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
/*
uintptr_t : <stdint.h> C99 (optional)
: unsupported in VS6
*/
#ifdef _WIN32
typedef UINT_PTR UIntPtr;
#else
/*
typedef uintptr_t UIntPtr;
*/
typedef ptrdiff_t UIntPtr;
#endif
#define ADJUST_ALLOC_SIZE 0
/*
#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1)
*/
/*
Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if
MyAlloc() can return address that is NOT multiple of sizeof(void *).
*/
/*
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1))))
*/
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1))))
#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align)
#if (_POSIX_C_SOURCE >= 200112L) && !defined(_WIN32)
#define USE_posix_memalign
#endif
/*
This posix_memalign() is for test purposes only.
We also need special Free() function instead of free(),
if this posix_memalign() is used.
*/
/*
static int posix_memalign(void **ptr, size_t align, size_t size)
{
size_t newSize = size + align;
void *p;
void *pAligned;
*ptr = NULL;
if (newSize < size)
return 12; // ENOMEM
p = MyAlloc(newSize);
if (!p)
return 12; // ENOMEM
pAligned = MY_ALIGN_PTR_UP_PLUS(p, align);
((void **)pAligned)[-1] = p;
*ptr = pAligned;
return 0;
}
*/
/*
ALLOC_ALIGN_SIZE >= sizeof(void *)
ALLOC_ALIGN_SIZE >= cache_line_size
*/
#define ALLOC_ALIGN_SIZE ((size_t)1 << 7)
static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
{
#ifndef USE_posix_memalign
void *p;
void *pAligned;
size_t newSize;
UNUSED_VAR(pp);
/* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
block to prevent cache line sharing with another allocated blocks */
newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE;
if (newSize < size)
return NULL;
p = MyAlloc(newSize);
if (!p)
return NULL;
pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE);
Print(" size="); PrintHex(size, 8);
Print(" a_size="); PrintHex(newSize, 8);
Print(" ptr="); PrintAddr(p);
Print(" a_ptr="); PrintAddr(pAligned);
PrintLn();
((void **)pAligned)[-1] = p;
return pAligned;
#else
void *p;
UNUSED_VAR(pp);
if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size))
return NULL;
Print(" posix_memalign="); PrintAddr(p);
PrintLn();
return p;
#endif
}
static void SzAlignedFree(ISzAllocPtr pp, void *address)
{
UNUSED_VAR(pp);
#ifndef USE_posix_memalign
if (address)
MyFree(((void **)address)[-1]);
#else
free(address);
#endif
}
const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };
#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *))
/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */
#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1]
/*
#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1]
*/
static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
{
CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);
void *adr;
void *pAligned;
size_t newSize;
size_t extra;
size_t alignSize = (size_t)1 << p->numAlignBits;
if (alignSize < sizeof(void *))
alignSize = sizeof(void *);
if (p->offset >= alignSize)
return NULL;
/* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
block to prevent cache line sharing with another allocated blocks */
extra = p->offset & (sizeof(void *) - 1);
newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE;
if (newSize < size)
return NULL;
adr = ISzAlloc_Alloc(p->baseAlloc, newSize);
if (!adr)
return NULL;
pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr +
alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset;
PrintLn();
Print("- Aligned: ");
Print(" size="); PrintHex(size, 8);
Print(" a_size="); PrintHex(newSize, 8);
Print(" ptr="); PrintAddr(adr);
Print(" a_ptr="); PrintAddr(pAligned);
PrintLn();
REAL_BLOCK_PTR_VAR(pAligned) = adr;
return pAligned;
}
static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)
{
if (address)
{
CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);
PrintLn();
Print("- Aligned Free: ");
PrintLn();
ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address));
}
}
void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p)
{
p->vt.Alloc = AlignOffsetAlloc_Alloc;
p->vt.Free = AlignOffsetAlloc_Free;
}

View File

@ -1,5 +1,5 @@
/* Alloc.h -- Memory allocation functions /* Alloc.h -- Memory allocation functions
2015-02-21 : Igor Pavlov : Public domain */ 2018-02-19 : Igor Pavlov : Public domain */
#ifndef __COMMON_ALLOC_H #ifndef __COMMON_ALLOC_H
#define __COMMON_ALLOC_H #define __COMMON_ALLOC_H
@ -29,8 +29,22 @@ void BigFree(void *address);
#endif #endif
extern ISzAlloc g_Alloc; extern const ISzAlloc g_Alloc;
extern ISzAlloc g_BigAlloc; extern const ISzAlloc g_BigAlloc;
extern const ISzAlloc g_MidAlloc;
extern const ISzAlloc g_AlignedAlloc;
typedef struct
{
ISzAlloc vt;
ISzAllocPtr baseAlloc;
unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */
size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */
} CAlignOffsetAlloc;
void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p);
EXTERN_C_END EXTERN_C_END

View File

@ -1,5 +1,5 @@
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
2015-08-01 : Igor Pavlov : Public domain */ 2018-04-28 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -61,7 +61,8 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
Byte *dest = p->dest; Byte *dest = p->dest;
if (dest == p->destLim) if (dest == p->destLim)
return SZ_OK; return SZ_OK;
*dest = p->temp[p->state++ - BCJ2_DEC_STATE_ORIG_0]; *dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];
p->state++;
p->dest = dest + 1; p->dest = dest + 1;
} }
} }
@ -231,10 +232,10 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
if (rem < 4) if (rem < 4)
{ {
SizeT i; p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8;
SetUi32(p->temp, val); p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8;
for (i = 0; i < rem; i++) p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8;
dest[i] = p->temp[i]; p->temp[3] = (Byte)val;
p->dest = dest + rem; p->dest = dest + rem;
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
break; break;

View File

@ -1,5 +1,5 @@
/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code) /* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)
2014-11-10 : Igor Pavlov : Public domain */ 2019-02-02 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -12,7 +12,6 @@
#define PRF(x) #define PRF(x)
#endif #endif
#include <windows.h>
#include <string.h> #include <string.h>
#include "Bcj2.h" #include "Bcj2.h"
@ -53,7 +52,7 @@ void Bcj2Enc_Init(CBcj2Enc *p)
p->probs[i] = kBitModelTotal >> 1; p->probs[i] = kBitModelTotal >> 1;
} }
static Bool MY_FAST_CALL RangeEnc_ShiftLow(CBcj2Enc *p) static BoolInt MY_FAST_CALL RangeEnc_ShiftLow(CBcj2Enc *p)
{ {
if ((UInt32)p->low < (UInt32)0xFF000000 || (UInt32)(p->low >> 32) != 0) if ((UInt32)p->low < (UInt32)0xFF000000 || (UInt32)(p->low >> 32) != 0)
{ {
@ -166,7 +165,7 @@ static void Bcj2Enc_Encode_2(CBcj2Enc *p)
{ {
Byte context = (Byte)(num == 0 ? p->prevByte : src[-1]); Byte context = (Byte)(num == 0 ? p->prevByte : src[-1]);
Bool needConvert; BoolInt needConvert;
p->bufs[BCJ2_STREAM_MAIN] = dest + 1; p->bufs[BCJ2_STREAM_MAIN] = dest + 1;
p->ip += (UInt32)num + 1; p->ip += (UInt32)num + 1;
@ -254,7 +253,7 @@ void Bcj2Enc_Encode(CBcj2Enc *p)
{ {
const Byte *src = p->src; const Byte *src = p->src;
const Byte *srcLim = p->srcLim; const Byte *srcLim = p->srcLim;
unsigned finishMode = p->finishMode; EBcj2Enc_FinishMode finishMode = p->finishMode;
p->src = p->temp; p->src = p->temp;
p->srcLim = p->temp + p->tempPos; p->srcLim = p->temp + p->tempPos;
@ -271,7 +270,7 @@ void Bcj2Enc_Encode(CBcj2Enc *p)
unsigned i; unsigned i;
p->tempPos = tempPos; p->tempPos = tempPos;
for (i = 0; i < tempPos; i++) for (i = 0; i < tempPos; i++)
p->temp[i] = p->temp[i + num]; p->temp[i] = p->temp[(size_t)i + num];
p->src = src; p->src = src;
p->srcLim = srcLim; p->srcLim = srcLim;

View File

@ -1,135 +1,230 @@
/* Bra.c -- Converters for RISC code /* Bra.c -- Converters for RISC code
2010-04-16 : Igor Pavlov : Public domain */ 2017-04-04 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "CpuArch.h"
#include "Bra.h" #include "Bra.h"
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; Byte *p;
if (size < 4) const Byte *lim;
return 0; size &= ~(size_t)3;
size -= 4; ip += 4;
ip += 8; p = data;
for (i = 0; i <= size; i += 4) lim = data + size;
if (encoding)
for (;;)
{ {
if (data[i + 3] == 0xEB) for (;;)
{ {
UInt32 dest; if (p >= lim)
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); return p - data;
src <<= 2; p += 4;
if (encoding) if (p[-1] == 0xEB)
dest = ip + (UInt32)i + src; break;
else }
dest = src - (ip + (UInt32)i); {
dest >>= 2; UInt32 v = GetUi32(p - 4);
data[i + 2] = (Byte)(dest >> 16); v <<= 2;
data[i + 1] = (Byte)(dest >> 8); v += ip + (UInt32)(p - data);
data[i + 0] = (Byte)dest; v >>= 2;
v &= 0x00FFFFFF;
v |= 0xEB000000;
SetUi32(p - 4, v);
}
}
for (;;)
{
for (;;)
{
if (p >= lim)
return p - data;
p += 4;
if (p[-1] == 0xEB)
break;
}
{
UInt32 v = GetUi32(p - 4);
v <<= 2;
v -= ip + (UInt32)(p - data);
v >>= 2;
v &= 0x00FFFFFF;
v |= 0xEB000000;
SetUi32(p - 4, v);
} }
} }
return i;
} }
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; Byte *p;
if (size < 4) const Byte *lim;
return 0; size &= ~(size_t)1;
size -= 4; p = data;
ip += 4; lim = data + size - 4;
for (i = 0; i <= size; i += 2)
if (encoding)
for (;;)
{ {
if ((data[i + 1] & 0xF8) == 0xF0 && UInt32 b1;
(data[i + 3] & 0xF8) == 0xF8) for (;;)
{ {
UInt32 dest; UInt32 b3;
UInt32 src = if (p > lim)
(((UInt32)data[i + 1] & 0x7) << 19) | return p - data;
((UInt32)data[i + 0] << 11) | b1 = p[1];
(((UInt32)data[i + 3] & 0x7) << 8) | b3 = p[3];
(data[i + 2]); p += 2;
b1 ^= 8;
if ((b3 & b1) >= 0xF8)
break;
}
{
UInt32 v =
((UInt32)b1 << 19)
+ (((UInt32)p[1] & 0x7) << 8)
+ (((UInt32)p[-2] << 11))
+ (p[0]);
src <<= 1; p += 2;
if (encoding) {
dest = ip + (UInt32)i + src; UInt32 cur = (ip + (UInt32)(p - data)) >> 1;
else v += cur;
dest = src - (ip + (UInt32)i); }
dest >>= 1;
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); p[-4] = (Byte)(v >> 11);
data[i + 0] = (Byte)(dest >> 11); p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); p[-2] = (Byte)v;
data[i + 2] = (Byte)dest; p[-1] = (Byte)(0xF8 | (v >> 8));
i += 2; }
}
for (;;)
{
UInt32 b1;
for (;;)
{
UInt32 b3;
if (p > lim)
return p - data;
b1 = p[1];
b3 = p[3];
p += 2;
b1 ^= 8;
if ((b3 & b1) >= 0xF8)
break;
}
{
UInt32 v =
((UInt32)b1 << 19)
+ (((UInt32)p[1] & 0x7) << 8)
+ (((UInt32)p[-2] << 11))
+ (p[0]);
p += 2;
{
UInt32 cur = (ip + (UInt32)(p - data)) >> 1;
v -= cur;
}
/*
SetUi16(p - 4, (UInt16)(((v >> 11) & 0x7FF) | 0xF000));
SetUi16(p - 2, (UInt16)(v | 0xF800));
*/
p[-4] = (Byte)(v >> 11);
p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
p[-2] = (Byte)v;
p[-1] = (Byte)(0xF8 | (v >> 8));
} }
} }
return i;
} }
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; Byte *p;
if (size < 4) const Byte *lim;
return 0; size &= ~(size_t)3;
size -= 4; ip -= 4;
for (i = 0; i <= size; i += 4) p = data;
{ lim = data + size;
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
{
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |
((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3] & (~3));
UInt32 dest; for (;;)
{
for (;;)
{
if (p >= lim)
return p - data;
p += 4;
/* if ((v & 0xFC000003) == 0x48000001) */
if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1)
break;
}
{
UInt32 v = GetBe32(p - 4);
if (encoding) if (encoding)
dest = ip + (UInt32)i + src; v += ip + (UInt32)(p - data);
else else
dest = src - (ip + (UInt32)i); v -= ip + (UInt32)(p - data);
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); v &= 0x03FFFFFF;
data[i + 1] = (Byte)(dest >> 16); v |= 0x48000000;
data[i + 2] = (Byte)(dest >> 8); SetBe32(p - 4, v);
data[i + 3] &= 0x3;
data[i + 3] |= dest;
} }
} }
return i;
} }
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
UInt32 i; Byte *p;
if (size < 4) const Byte *lim;
return 0; size &= ~(size_t)3;
size -= 4; ip -= 4;
for (i = 0; i <= size; i += 4) p = data;
lim = data + size;
for (;;)
{ {
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) || for (;;)
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
{ {
UInt32 src = if (p >= lim)
((UInt32)data[i + 0] << 24) | return p - data;
((UInt32)data[i + 1] << 16) | /*
((UInt32)data[i + 2] << 8) | v = GetBe32(p);
((UInt32)data[i + 3]); p += 4;
UInt32 dest; m = v + ((UInt32)5 << 29);
m ^= (UInt32)7 << 29;
src <<= 2; m += (UInt32)1 << 22;
if ((m & ((UInt32)0x1FF << 23)) == 0)
break;
*/
p += 4;
if ((p[-4] == 0x40 && (p[-3] & 0xC0) == 0) ||
(p[-4] == 0x7F && (p[-3] >= 0xC0)))
break;
}
{
UInt32 v = GetBe32(p - 4);
v <<= 2;
if (encoding) if (encoding)
dest = ip + i + src; v += ip + (UInt32)(p - data);
else else
dest = src - (ip + i); v -= ip + (UInt32)(p - data);
dest >>= 2;
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; v &= 0x01FFFFFF;
v -= (UInt32)1 << 24;
data[i + 0] = (Byte)(dest >> 24); v ^= 0xFF000000;
data[i + 1] = (Byte)(dest >> 16); v >>= 2;
data[i + 2] = (Byte)(dest >> 8); v |= 0x40000000;
data[i + 3] = (Byte)dest; SetBe32(p - 4, v);
} }
} }
return i;
} }

View File

@ -1,5 +1,5 @@
/* Bra86.c -- Converter for x86 code (BCJ) /* Bra86.c -- Converter for x86 code (BCJ)
2013-11-12 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -37,7 +37,7 @@ SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding
else else
{ {
mask >>= (unsigned)d; mask >>= (unsigned)d;
if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1]))) if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1])))
{ {
mask = (mask >> 1) | 4; mask = (mask >> 1) | 4;
pos++; pos++;

View File

@ -1,69 +1,53 @@
/* BraIA64.c -- Converter for IA-64 code /* BraIA64.c -- Converter for IA-64 code
2013-11-12 : Igor Pavlov : Public domain */ 2017-01-26 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "CpuArch.h"
#include "Bra.h" #include "Bra.h"
static const Byte kBranchTable[32] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
4, 4, 6, 6, 0, 0, 7, 7,
4, 4, 0, 0, 4, 4, 0, 0
};
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{ {
SizeT i; SizeT i;
if (size < 16) if (size < 16)
return 0; return 0;
size -= 16; size -= 16;
for (i = 0; i <= size; i += 16) i = 0;
do
{ {
UInt32 instrTemplate = data[i] & 0x1F; unsigned m = ((UInt32)0x334B0000 >> (data[i] & 0x1E)) & 3;
UInt32 mask = kBranchTable[instrTemplate]; if (m)
UInt32 bitPos = 5;
int slot;
for (slot = 0; slot < 3; slot++, bitPos += 41)
{ {
UInt32 bytePos, bitRes; m++;
UInt64 instruction, instNorm; do
int j;
if (((mask >> slot) & 1) == 0)
continue;
bytePos = (bitPos >> 3);
bitRes = bitPos & 0x7;
instruction = 0;
for (j = 0; j < 6; j++)
instruction += (UInt64)data[i + j + bytePos] << (8 * j);
instNorm = instruction >> bitRes;
if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0)
{ {
UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); Byte *p = data + (i + (size_t)m * 5 - 8);
UInt32 dest; if (((p[3] >> m) & 15) == 5
src |= ((UInt32)(instNorm >> 36) & 1) << 20; && (((p[-1] | ((UInt32)p[0] << 8)) >> m) & 0x70) == 0)
{
unsigned raw = GetUi32(p);
unsigned v = raw >> m;
v = (v & 0xFFFFF) | ((v & (1 << 23)) >> 3);
src <<= 4; v <<= 4;
if (encoding)
v += ip + (UInt32)i;
else
v -= ip + (UInt32)i;
v >>= 4;
if (encoding) v &= 0x1FFFFF;
dest = ip + (UInt32)i + src; v += 0x700000;
else v &= 0x8FFFFF;
dest = src - (ip + (UInt32)i); raw &= ~((UInt32)0x8FFFFF << m);
raw |= (v << m);
dest >>= 4; SetUi32(p, raw);
}
instNorm &= ~((UInt64)(0x8FFFFF) << 13);
instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);
instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));
instruction &= (1 << bitRes) - 1;
instruction |= (instNorm << bitRes);
for (j = 0; j < 6; j++)
data[i + j + bytePos] = (Byte)(instruction >> (8 * j));
} }
while (++m <= 4);
} }
i += 16;
} }
while (i <= size);
return i; return i;
} }

View File

@ -1,5 +1,5 @@
/* Compiler.h /* Compiler.h
2015-08-02 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_COMPILER_H #ifndef __7Z_COMPILER_H
#define __7Z_COMPILER_H #define __7Z_COMPILER_H
@ -21,6 +21,7 @@
#pragma warning(disable : 4514) // unreferenced inline function has been removed #pragma warning(disable : 4514) // unreferenced inline function has been removed
#pragma warning(disable : 4702) // unreachable code #pragma warning(disable : 4702) // unreachable code
#pragma warning(disable : 4710) // not inlined #pragma warning(disable : 4710) // not inlined
#pragma warning(disable : 4714) // function marked as __forceinline not inlined
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
#endif #endif

View File

@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code /* CpuArch.c -- CPU specific code
2015-03-25: Igor Pavlov : Public domain */ 2018-02-18: Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -45,7 +45,8 @@ static UInt32 CheckFlag(UInt32 flag)
"push %%EDX\n\t" "push %%EDX\n\t"
"popf\n\t" "popf\n\t"
"andl %%EAX, %0\n\t": "andl %%EAX, %0\n\t":
"=c" (flag) : "c" (flag)); "=c" (flag) : "c" (flag) :
"%eax", "%edx");
#endif #endif
return flag; return flag;
} }
@ -79,7 +80,13 @@ void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
#else #else
__asm__ __volatile__ ( __asm__ __volatile__ (
#if defined(MY_CPU_X86) && defined(__PIC__) #if defined(MY_CPU_AMD64) && defined(__PIC__)
"mov %%rbx, %%rdi;"
"cpuid;"
"xchg %%rbx, %%rdi;"
: "=a" (*a) ,
"=D" (*b) ,
#elif defined(MY_CPU_X86) && defined(__PIC__)
"mov %%ebx, %%edi;" "mov %%ebx, %%edi;"
"cpuid;" "cpuid;"
"xchgl %%ebx, %%edi;" "xchgl %%ebx, %%edi;"
@ -108,7 +115,7 @@ void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
#endif #endif
} }
Bool x86cpuid_CheckAndRead(Cx86cpuid *p) BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p)
{ {
CHECK_CPUID_IS_SUPPORTED CHECK_CPUID_IS_SUPPORTED
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
@ -137,7 +144,7 @@ int x86cpuid_GetFirm(const Cx86cpuid *p)
return -1; return -1;
} }
Bool CPU_Is_InOrder() BoolInt CPU_Is_InOrder()
{ {
Cx86cpuid p; Cx86cpuid p;
int firm; int firm;
@ -168,7 +175,7 @@ Bool CPU_Is_InOrder()
#if !defined(MY_CPU_AMD64) && defined(_WIN32) #if !defined(MY_CPU_AMD64) && defined(_WIN32)
#include <windows.h> #include <windows.h>
static Bool CPU_Sys_Is_SSE_Supported() static BoolInt CPU_Sys_Is_SSE_Supported()
{ {
OSVERSIONINFO vi; OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi); vi.dwOSVersionInfoSize = sizeof(vi);
@ -181,7 +188,7 @@ static Bool CPU_Sys_Is_SSE_Supported()
#define CHECK_SYS_SSE_SUPPORT #define CHECK_SYS_SSE_SUPPORT
#endif #endif
Bool CPU_Is_Aes_Supported() BoolInt CPU_Is_Aes_Supported()
{ {
Cx86cpuid p; Cx86cpuid p;
CHECK_SYS_SSE_SUPPORT CHECK_SYS_SSE_SUPPORT
@ -190,4 +197,22 @@ Bool CPU_Is_Aes_Supported()
return (p.c >> 25) & 1; return (p.c >> 25) & 1;
} }
BoolInt CPU_IsSupported_PageGB()
{
Cx86cpuid cpuid;
if (!x86cpuid_CheckAndRead(&cpuid))
return False;
{
UInt32 d[4] = { 0 };
MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]);
if (d[0] < 0x80000001)
return False;
}
{
UInt32 d[4] = { 0 };
MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]);
return (d[3] >> 26) & 1;
}
}
#endif #endif

View File

@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code /* CpuArch.h -- CPU specific code
2015-12-01: Igor Pavlov : Public domain */ 2018-02-18 : Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H #ifndef __CPU_ARCH_H
#define __CPU_ARCH_H #define __CPU_ARCH_H
@ -16,48 +16,122 @@ If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of pl
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
*/ */
#if defined(_M_X64) \ #if defined(_M_X64) \
|| defined(_M_AMD64) \ || defined(_M_AMD64) \
|| defined(__x86_64__) \ || defined(__x86_64__) \
|| defined(__AMD64__) \ || defined(__AMD64__) \
|| defined(__amd64__) || defined(__amd64__)
#define MY_CPU_AMD64 #define MY_CPU_AMD64
#endif #ifdef __ILP32__
#define MY_CPU_NAME "x32"
#if defined(MY_CPU_AMD64) \ #else
|| defined(_M_IA64) \ #define MY_CPU_NAME "x64"
|| defined(__AARCH64EL__) \ #endif
|| defined(__AARCH64EB__)
#define MY_CPU_64BIT #define MY_CPU_64BIT
#endif #endif
#if defined(_M_IX86) || defined(__i386__)
#define MY_CPU_X86 #if defined(_M_IX86) \
|| defined(__i386__)
#define MY_CPU_X86
#define MY_CPU_NAME "x86"
#define MY_CPU_32BIT
#endif #endif
#if defined(_M_ARM64) \
|| defined(__AARCH64EL__) \
|| defined(__AARCH64EB__) \
|| defined(__aarch64__)
#define MY_CPU_ARM64
#define MY_CPU_NAME "arm64"
#define MY_CPU_64BIT
#endif
#if defined(_M_ARM) \
|| defined(_M_ARM_NT) \
|| defined(_M_ARMT) \
|| defined(__arm__) \
|| defined(__thumb__) \
|| defined(__ARMEL__) \
|| defined(__ARMEB__) \
|| defined(__THUMBEL__) \
|| defined(__THUMBEB__)
#define MY_CPU_ARM
#define MY_CPU_NAME "arm"
#define MY_CPU_32BIT
#endif
#if defined(_M_IA64) \
|| defined(__ia64__)
#define MY_CPU_IA64
#define MY_CPU_NAME "ia64"
#define MY_CPU_64BIT
#endif
#if defined(__mips64) \
|| defined(__mips64__) \
|| (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3))
#define MY_CPU_NAME "mips64"
#define MY_CPU_64BIT
#elif defined(__mips__)
#define MY_CPU_NAME "mips"
/* #define MY_CPU_32BIT */
#endif
#if defined(__ppc64__) \
|| defined(__powerpc64__)
#ifdef __ILP32__
#define MY_CPU_NAME "ppc64-32"
#else
#define MY_CPU_NAME "ppc64"
#endif
#define MY_CPU_64BIT
#elif defined(__ppc__) \
|| defined(__powerpc__)
#define MY_CPU_NAME "ppc"
#define MY_CPU_32BIT
#endif
#if defined(__sparc64__)
#define MY_CPU_NAME "sparc64"
#define MY_CPU_64BIT
#elif defined(__sparc__)
#define MY_CPU_NAME "sparc"
/* #define MY_CPU_32BIT */
#endif
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) #if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
#define MY_CPU_X86_OR_AMD64 #define MY_CPU_X86_OR_AMD64
#endif #endif
#if defined(MY_CPU_X86) \
|| defined(_M_ARM) \ #ifdef _WIN32
|| defined(__ARMEL__) \
|| defined(__THUMBEL__) \ #ifdef MY_CPU_ARM
|| defined(__ARMEB__) \ #define MY_CPU_ARM_LE
|| defined(__THUMBEB__) #endif
#define MY_CPU_32BIT
#ifdef MY_CPU_ARM64
#define MY_CPU_ARM64_LE
#endif
#ifdef _M_IA64
#define MY_CPU_IA64_LE
#endif
#endif #endif
#if defined(_WIN32) && defined(_M_ARM)
#define MY_CPU_ARM_LE
#endif
#if defined(_WIN32) && defined(_M_IA64)
#define MY_CPU_IA64_LE
#endif
#if defined(MY_CPU_X86_OR_AMD64) \ #if defined(MY_CPU_X86_OR_AMD64) \
|| defined(MY_CPU_ARM_LE) \ || defined(MY_CPU_ARM_LE) \
|| defined(MY_CPU_ARM64_LE) \
|| defined(MY_CPU_IA64_LE) \ || defined(MY_CPU_IA64_LE) \
|| defined(__LITTLE_ENDIAN__) \ || defined(__LITTLE_ENDIAN__) \
|| defined(__ARMEL__) \ || defined(__ARMEL__) \
@ -66,6 +140,7 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|| defined(__MIPSEL__) \ || defined(__MIPSEL__) \
|| defined(__MIPSEL) \ || defined(__MIPSEL) \
|| defined(_MIPSEL) \ || defined(_MIPSEL) \
|| defined(__BFIN__) \
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
#define MY_CPU_LE #define MY_CPU_LE
#endif #endif
@ -85,14 +160,37 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
#define MY_CPU_BE #define MY_CPU_BE
#endif #endif
#if defined(MY_CPU_LE) && defined(MY_CPU_BE) #if defined(MY_CPU_LE) && defined(MY_CPU_BE)
Stop_Compiling_Bad_Endian #error Stop_Compiling_Bad_Endian
#endif #endif
#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT)
#error Stop_Compiling_Bad_32_64_BIT
#endif
#ifndef MY_CPU_NAME
#ifdef MY_CPU_LE
#define MY_CPU_NAME "LE"
#elif defined(MY_CPU_BE)
#define MY_CPU_NAME "BE"
#else
/*
#define MY_CPU_NAME ""
*/
#endif
#endif
#ifdef MY_CPU_LE #ifdef MY_CPU_LE
#if defined(MY_CPU_X86_OR_AMD64) \ #if defined(MY_CPU_X86_OR_AMD64) \
/* || defined(__AARCH64EL__) */ || defined(MY_CPU_ARM64) \
|| defined(__ARM_FEATURE_UNALIGNED)
#define MY_CPU_LE_UNALIGN #define MY_CPU_LE_UNALIGN
#endif #endif
#endif #endif
@ -138,6 +236,11 @@ Stop_Compiling_Bad_Endian
#endif #endif
#ifdef __has_builtin
#define MY__has_builtin(x) __has_builtin(x)
#else
#define MY__has_builtin(x) 0
#endif
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300) #if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
@ -145,15 +248,21 @@ Stop_Compiling_Bad_Endian
#include <stdlib.h> #include <stdlib.h>
#pragma intrinsic(_byteswap_ushort)
#pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_ulong)
#pragma intrinsic(_byteswap_uint64) #pragma intrinsic(_byteswap_uint64)
/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
#elif defined(MY_CPU_LE_UNALIGN) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) #elif defined(MY_CPU_LE_UNALIGN) && ( \
(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
|| (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) )
/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */
#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p)) #define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p)) #define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
@ -178,10 +287,14 @@ Stop_Compiling_Bad_Endian
#endif #endif
#ifndef GetBe16
#define GetBe16(p) ( (UInt16) ( \ #define GetBe16(p) ( (UInt16) ( \
((UInt16)((const Byte *)(p))[0] << 8) | \ ((UInt16)((const Byte *)(p))[0] << 8) | \
((const Byte *)(p))[1] )) ((const Byte *)(p))[1] ))
#endif
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
@ -205,15 +318,16 @@ enum
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d); void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
Bool x86cpuid_CheckAndRead(Cx86cpuid *p); BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p); int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF)) #define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF)) #define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
#define x86cpuid_GetStepping(ver) (ver & 0xF) #define x86cpuid_GetStepping(ver) (ver & 0xF)
Bool CPU_Is_InOrder(); BoolInt CPU_Is_InOrder();
Bool CPU_Is_Aes_Supported(); BoolInt CPU_Is_Aes_Supported();
BoolInt CPU_IsSupported_PageGB();
#endif #endif

108
src/third-party/lzma/DllSecur.c vendored Normal file
View File

@ -0,0 +1,108 @@
/* DllSecur.c -- DLL loading security
2018-02-21 : Igor Pavlov : Public domain */
#include "Precomp.h"
#ifdef _WIN32
#include <windows.h>
#include "DllSecur.h"
#ifndef UNDER_CE
typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags);
#define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400
#define MY_LOAD_LIBRARY_SEARCH_SYSTEM32 0x800
static const char * const g_Dlls =
#ifndef _CONSOLE
"UXTHEME\0"
#endif
"USERENV\0"
"SETUPAPI\0"
"APPHELP\0"
"PROPSYS\0"
"DWMAPI\0"
"CRYPTBASE\0"
"OLEACC\0"
"CLBCATQ\0"
"VERSION\0"
;
#endif
void My_SetDefaultDllDirectories()
{
#ifndef UNDER_CE
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
GetVersionEx(&vi);
if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0)
{
Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories)
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories");
if (setDllDirs)
if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS))
return;
}
#endif
}
void LoadSecurityDlls()
{
#ifndef UNDER_CE
wchar_t buf[MAX_PATH + 100];
{
// at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ???
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0)
{
Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories)
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories");
if (setDllDirs)
if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS))
return;
}
}
{
unsigned len = GetSystemDirectoryW(buf, MAX_PATH + 2);
if (len == 0 || len > MAX_PATH)
return;
}
{
const char *dll;
unsigned pos = (unsigned)lstrlenW(buf);
if (buf[pos - 1] != '\\')
buf[pos++] = '\\';
for (dll = g_Dlls; dll[0] != 0;)
{
unsigned k = 0;
for (;;)
{
char c = *dll++;
buf[pos + k] = (Byte)c;
k++;
if (c == 0)
break;
}
lstrcatW(buf, L".dll");
LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
}
#endif
}
#endif

20
src/third-party/lzma/DllSecur.h vendored Normal file
View File

@ -0,0 +1,20 @@
/* DllSecur.h -- DLL loading for security
2018-02-19 : Igor Pavlov : Public domain */
#ifndef __DLL_SECUR_H
#define __DLL_SECUR_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#ifdef _WIN32
void My_SetDefaultDllDirectories();
void LoadSecurityDlls();
#endif
EXTERN_C_END
#endif

View File

@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms /* LzFind.c -- Match finder for LZ algorithms
2015-10-15 : Igor Pavlov : Public domain */ 2018-07-08 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -16,18 +16,18 @@
#define kStartMaxLen 3 #define kStartMaxLen 3
static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)
{ {
if (!p->directInput) if (!p->directInput)
{ {
alloc->Free(alloc, p->bufferBase); ISzAlloc_Free(alloc, p->bufferBase);
p->bufferBase = NULL; p->bufferBase = NULL;
} }
} }
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc)
{ {
UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
if (p->directInput) if (p->directInput)
@ -39,7 +39,7 @@ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *a
{ {
LzInWindow_Free(p, alloc); LzInWindow_Free(p, alloc);
p->blockSize = blockSize; p->blockSize = blockSize;
p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize);
} }
return (p->bufferBase != NULL); return (p->bufferBase != NULL);
} }
@ -81,7 +81,7 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
if (size == 0) if (size == 0)
return; return;
p->result = p->stream->Read(p->stream, dest, &size); p->result = ISeqInStream_Read(p->stream, dest, &size);
if (p->result != SZ_OK) if (p->result != SZ_OK)
return; return;
if (size == 0) if (size == 0)
@ -138,45 +138,46 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
void MatchFinder_Construct(CMatchFinder *p) void MatchFinder_Construct(CMatchFinder *p)
{ {
UInt32 i; unsigned i;
p->bufferBase = NULL; p->bufferBase = NULL;
p->directInput = 0; p->directInput = 0;
p->hash = NULL; p->hash = NULL;
p->expectedDataSize = (UInt64)(Int64)-1;
MatchFinder_SetDefaultSettings(p); MatchFinder_SetDefaultSettings(p);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
UInt32 r = i; UInt32 r = (UInt32)i;
unsigned j; unsigned j;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
p->crc[i] = r; p->crc[i] = r;
} }
} }
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->hash); ISzAlloc_Free(alloc, p->hash);
p->hash = NULL; p->hash = NULL;
} }
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)
{ {
MatchFinder_FreeThisClassMemory(p, alloc); MatchFinder_FreeThisClassMemory(p, alloc);
LzInWindow_Free(p, alloc); LzInWindow_Free(p, alloc);
} }
static CLzRef* AllocRefs(size_t num, ISzAlloc *alloc) static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)
{ {
size_t sizeInBytes = (size_t)num * sizeof(CLzRef); size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
if (sizeInBytes / sizeof(CLzRef) != num) if (sizeInBytes / sizeof(CLzRef) != num)
return NULL; return NULL;
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes);
} }
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc) ISzAllocPtr alloc)
{ {
UInt32 sizeReserv; UInt32 sizeReserv;
@ -208,7 +209,11 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
hs = (1 << 16) - 1; hs = (1 << 16) - 1;
else else
{ {
hs = historySize - 1; hs = historySize;
if (hs > p->expectedDataSize)
hs = (UInt32)p->expectedDataSize;
if (hs != 0)
hs--;
hs |= (hs >> 1); hs |= (hs >> 1);
hs |= (hs >> 2); hs |= (hs >> 2);
hs |= (hs >> 4); hs |= (hs >> 4);
@ -292,17 +297,33 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
p->posLimit = p->pos + limit; p->posLimit = p->pos + limit;
} }
void MatchFinder_Init_2(CMatchFinder *p, int readData)
{
UInt32 i;
UInt32 *hash = p->hash;
UInt32 num = p->hashSizeSum;
for (i = 0; i < num; i++)
hash[i] = kEmptyHashValue;
void MatchFinder_Init_LowHash(CMatchFinder *p)
{
size_t i;
CLzRef *items = p->hash;
size_t numItems = p->fixedHashSize;
for (i = 0; i < numItems; i++)
items[i] = kEmptyHashValue;
}
void MatchFinder_Init_HighHash(CMatchFinder *p)
{
size_t i;
CLzRef *items = p->hash + p->fixedHashSize;
size_t numItems = (size_t)p->hashMask + 1;
for (i = 0; i < numItems; i++)
items[i] = kEmptyHashValue;
}
void MatchFinder_Init_3(CMatchFinder *p, int readData)
{
p->cyclicBufferPos = 0; p->cyclicBufferPos = 0;
p->buffer = p->bufferBase; p->buffer = p->bufferBase;
p->pos = p->streamPos = p->cyclicBufferSize; p->pos =
p->streamPos = p->cyclicBufferSize;
p->result = SZ_OK; p->result = SZ_OK;
p->streamEndWasReached = 0; p->streamEndWasReached = 0;
@ -312,11 +333,15 @@ void MatchFinder_Init_2(CMatchFinder *p, int readData)
MatchFinder_SetLimits(p); MatchFinder_SetLimits(p);
} }
void MatchFinder_Init(CMatchFinder *p) void MatchFinder_Init(CMatchFinder *p)
{ {
MatchFinder_Init_2(p, True); MatchFinder_Init_HighHash(p);
MatchFinder_Init_LowHash(p);
MatchFinder_Init_3(p, True);
} }
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
{ {
return (p->pos - p->historySize - 1) & kNormalizeMask; return (p->pos - p->historySize - 1) & kNormalizeMask;
@ -343,6 +368,8 @@ static void MatchFinder_Normalize(CMatchFinder *p)
MatchFinder_ReduceOffsets(p, subValue); MatchFinder_ReduceOffsets(p, subValue);
} }
MY_NO_INLINE
static void MatchFinder_CheckLimits(CMatchFinder *p) static void MatchFinder_CheckLimits(CMatchFinder *p)
{ {
if (p->pos == kMaxValForNormalize) if (p->pos == kMaxValForNormalize)
@ -354,10 +381,16 @@ static void MatchFinder_CheckLimits(CMatchFinder *p)
MatchFinder_SetLimits(p); MatchFinder_SetLimits(p);
} }
static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
/*
(lenLimit > maxLen)
*/
MY_FORCE_INLINE
static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen) UInt32 *distances, unsigned maxLen)
{ {
/*
son[_cyclicBufferPos] = curMatch; son[_cyclicBufferPos] = curMatch;
for (;;) for (;;)
{ {
@ -375,7 +408,8 @@ static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos,
break; break;
if (maxLen < len) if (maxLen < len)
{ {
*distances++ = maxLen = len; maxLen = len;
*distances++ = len;
*distances++ = delta - 1; *distances++ = delta - 1;
if (len == lenLimit) if (len == lenLimit)
return distances; return distances;
@ -383,15 +417,58 @@ static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos,
} }
} }
} }
*/
const Byte *lim = cur + lenLimit;
son[_cyclicBufferPos] = curMatch;
do
{
UInt32 delta = pos - curMatch;
if (delta >= _cyclicBufferSize)
break;
{
ptrdiff_t diff;
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
diff = (ptrdiff_t)0 - delta;
if (cur[maxLen] == cur[maxLen + diff])
{
const Byte *c = cur;
while (*c == c[diff])
{
if (++c == lim)
{
distances[0] = (UInt32)(lim - cur);
distances[1] = delta - 1;
return distances + 2;
}
}
{
unsigned len = (unsigned)(c - cur);
if (maxLen < len)
{
maxLen = len;
distances[0] = (UInt32)len;
distances[1] = delta - 1;
distances += 2;
}
}
}
}
}
while (--cutValue);
return distances;
} }
MY_FORCE_INLINE
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen) UInt32 *distances, UInt32 maxLen)
{ {
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1); CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0; unsigned len0 = 0, len1 = 0;
for (;;) for (;;)
{ {
UInt32 delta = pos - curMatch; UInt32 delta = pos - curMatch;
@ -401,9 +478,10 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
return distances; return distances;
} }
{ {
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta; const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1); unsigned len = (len0 < len1 ? len0 : len1);
UInt32 pair0 = pair[0];
if (pb[len] == cur[len]) if (pb[len] == cur[len])
{ {
if (++len != lenLimit && pb[len] == cur[len]) if (++len != lenLimit && pb[len] == cur[len])
@ -412,11 +490,12 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
break; break;
if (maxLen < len) if (maxLen < len)
{ {
*distances++ = maxLen = len; maxLen = (UInt32)len;
*distances++ = (UInt32)len;
*distances++ = delta - 1; *distances++ = delta - 1;
if (len == lenLimit) if (len == lenLimit)
{ {
*ptr1 = pair[0]; *ptr1 = pair0;
*ptr0 = pair[1]; *ptr0 = pair[1];
return distances; return distances;
} }
@ -443,9 +522,9 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
{ {
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1); CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0; unsigned len0 = 0, len1 = 0;
for (;;) for (;;)
{ {
UInt32 delta = pos - curMatch; UInt32 delta = pos - curMatch;
@ -455,9 +534,9 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
return; return;
} }
{ {
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta; const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1); unsigned len = (len0 < len1 ? len0 : len1);
if (pb[len] == cur[len]) if (pb[len] == cur[len])
{ {
while (++len != lenLimit) while (++len != lenLimit)
@ -495,13 +574,13 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
p->buffer++; \ p->buffer++; \
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
#define MOVE_POS_RET MOVE_POS return offset; #define MOVE_POS_RET MOVE_POS return (UInt32)offset;
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define GET_MATCHES_HEADER2(minLen, ret_op) \ #define GET_MATCHES_HEADER2(minLen, ret_op) \
UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \ unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
cur = p->buffer; cur = p->buffer;
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
@ -510,22 +589,22 @@ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
#define GET_MATCHES_FOOTER(offset, maxLen) \ #define GET_MATCHES_FOOTER(offset, maxLen) \
offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
distances + offset, maxLen) - distances); MOVE_POS_RET; distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
#define SKIP_FOOTER \ #define SKIP_FOOTER \
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
#define UPDATE_maxLen { \ #define UPDATE_maxLen { \
ptrdiff_t diff = (ptrdiff_t)0 - d2; \ ptrdiff_t diff = (ptrdiff_t)0 - d2; \
const Byte *c = cur + maxLen; \ const Byte *c = cur + maxLen; \
const Byte *lim = cur + lenLimit; \ const Byte *lim = cur + lenLimit; \
for (; c != lim; c++) if (*(c + diff) != *c) break; \ for (; c != lim; c++) if (*(c + diff) != *c) break; \
maxLen = (UInt32)(c - cur); } maxLen = (unsigned)(c - cur); }
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 offset; unsigned offset;
GET_MATCHES_HEADER(2) GET_MATCHES_HEADER(2)
HASH2_CALC; HASH2_CALC;
curMatch = p->hash[hv]; curMatch = p->hash[hv];
@ -536,7 +615,7 @@ static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 offset; unsigned offset;
GET_MATCHES_HEADER(3) GET_MATCHES_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hv]; curMatch = p->hash[hv];
@ -547,7 +626,8 @@ UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 h2, d2, maxLen, offset, pos; UInt32 h2, d2, pos;
unsigned maxLen, offset;
UInt32 *hash; UInt32 *hash;
GET_MATCHES_HEADER(3) GET_MATCHES_HEADER(3)
@ -558,10 +638,10 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
d2 = pos - hash[h2]; d2 = pos - hash[h2];
curMatch = hash[kFix3HashSize + hv]; curMatch = (hash + kFix3HashSize)[hv];
hash[h2] = pos; hash[h2] = pos;
hash[kFix3HashSize + hv] = pos; (hash + kFix3HashSize)[hv] = pos;
maxLen = 2; maxLen = 2;
offset = 0; offset = 0;
@ -569,12 +649,12 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{ {
UPDATE_maxLen UPDATE_maxLen
distances[0] = maxLen; distances[0] = (UInt32)maxLen;
distances[1] = d2 - 1; distances[1] = d2 - 1;
offset = 2; offset = 2;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET; MOVE_POS_RET;
} }
} }
@ -584,7 +664,8 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 h2, h3, d2, d3, maxLen, offset, pos; UInt32 h2, h3, d2, d3, pos;
unsigned maxLen, offset;
UInt32 *hash; UInt32 *hash;
GET_MATCHES_HEADER(4) GET_MATCHES_HEADER(4)
@ -593,21 +674,22 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash; hash = p->hash;
pos = p->pos; pos = p->pos;
d2 = pos - hash[ h2]; d2 = pos - hash [h2];
d3 = pos - hash[kFix3HashSize + h3]; d3 = pos - (hash + kFix3HashSize)[h3];
curMatch = hash[kFix4HashSize + hv]; curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] = pos; hash [h2] = pos;
hash[kFix3HashSize + h3] = pos; (hash + kFix3HashSize)[h3] = pos;
hash[kFix4HashSize + hv] = pos; (hash + kFix4HashSize)[hv] = pos;
maxLen = 0; maxLen = 0;
offset = 0; offset = 0;
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{ {
distances[0] = maxLen = 2; maxLen = 2;
distances[0] = 2;
distances[1] = d2 - 1; distances[1] = d2 - 1;
offset = 2; offset = 2;
} }
@ -615,7 +697,7 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{ {
maxLen = 3; maxLen = 3;
distances[offset + 1] = d3 - 1; distances[(size_t)offset + 1] = d3 - 1;
offset += 2; offset += 2;
d2 = d3; d2 = d3;
} }
@ -623,10 +705,10 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0) if (offset != 0)
{ {
UPDATE_maxLen UPDATE_maxLen
distances[offset - 2] = maxLen; distances[(size_t)offset - 2] = (UInt32)maxLen;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET; MOVE_POS_RET;
} }
} }
@ -649,16 +731,16 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash; hash = p->hash;
pos = p->pos; pos = p->pos;
d2 = pos - hash[ h2]; d2 = pos - hash [h2];
d3 = pos - hash[kFix3HashSize + h3]; d3 = pos - (hash + kFix3HashSize)[h3];
d4 = pos - hash[kFix4HashSize + h4]; d4 = pos - (hash + kFix4HashSize)[h4];
curMatch = hash[kFix5HashSize + hv]; curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] = pos; hash [h2] = pos;
hash[kFix3HashSize + h3] = pos; (hash + kFix3HashSize)[h3] = pos;
hash[kFix4HashSize + h4] = pos; (hash + kFix4HashSize)[h4] = pos;
hash[kFix5HashSize + hv] = pos; (hash + kFix5HashSize)[hv] = pos;
maxLen = 0; maxLen = 0;
offset = 0; offset = 0;
@ -691,7 +773,7 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
&& *(cur - d4 + 3) == *(cur + 3)) && *(cur - d4 + 3) == *(cur + 3))
{ {
maxLen = 4; maxLen = 4;
distances[offset + 1] = d4 - 1; distances[(size_t)offset + 1] = d4 - 1;
offset += 2; offset += 2;
d2 = d4; d2 = d4;
} }
@ -699,7 +781,7 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0) if (offset != 0)
{ {
UPDATE_maxLen UPDATE_maxLen
distances[offset - 2] = maxLen; distances[(size_t)offset - 2] = maxLen;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
@ -716,7 +798,8 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 h2, h3, d2, d3, maxLen, offset, pos; UInt32 h2, h3, d2, d3, pos;
unsigned maxLen, offset;
UInt32 *hash; UInt32 *hash;
GET_MATCHES_HEADER(4) GET_MATCHES_HEADER(4)
@ -725,21 +808,21 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash; hash = p->hash;
pos = p->pos; pos = p->pos;
d2 = pos - hash[ h2]; d2 = pos - hash [h2];
d3 = pos - hash[kFix3HashSize + h3]; d3 = pos - (hash + kFix3HashSize)[h3];
curMatch = (hash + kFix4HashSize)[hv];
curMatch = hash[kFix4HashSize + hv]; hash [h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
hash[ h2] = pos; (hash + kFix4HashSize)[hv] = pos;
hash[kFix3HashSize + h3] = pos;
hash[kFix4HashSize + hv] = pos;
maxLen = 0; maxLen = 0;
offset = 0; offset = 0;
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{ {
distances[0] = maxLen = 2; maxLen = 2;
distances[0] = 2;
distances[1] = d2 - 1; distances[1] = d2 - 1;
offset = 2; offset = 2;
} }
@ -747,7 +830,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{ {
maxLen = 3; maxLen = 3;
distances[offset + 1] = d3 - 1; distances[(size_t)offset + 1] = d3 - 1;
offset += 2; offset += 2;
d2 = d3; d2 = d3;
} }
@ -755,7 +838,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0) if (offset != 0)
{ {
UPDATE_maxLen UPDATE_maxLen
distances[offset - 2] = maxLen; distances[(size_t)offset - 2] = (UInt32)maxLen;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
@ -766,7 +849,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (maxLen < 3) if (maxLen < 3)
maxLen = 3; maxLen = 3;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances + offset, maxLen) - (distances)); distances + offset, maxLen) - (distances));
MOVE_POS_RET MOVE_POS_RET
} }
@ -783,16 +866,16 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash; hash = p->hash;
pos = p->pos; pos = p->pos;
d2 = pos - hash[ h2]; d2 = pos - hash [h2];
d3 = pos - hash[kFix3HashSize + h3]; d3 = pos - (hash + kFix3HashSize)[h3];
d4 = pos - hash[kFix4HashSize + h4]; d4 = pos - (hash + kFix4HashSize)[h4];
curMatch = hash[kFix5HashSize + hv]; curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] = pos; hash [h2] = pos;
hash[kFix3HashSize + h3] = pos; (hash + kFix3HashSize)[h3] = pos;
hash[kFix4HashSize + h4] = pos; (hash + kFix4HashSize)[h4] = pos;
hash[kFix5HashSize + hv] = pos; (hash + kFix5HashSize)[hv] = pos;
maxLen = 0; maxLen = 0;
offset = 0; offset = 0;
@ -825,7 +908,7 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
&& *(cur - d4 + 3) == *(cur + 3)) && *(cur - d4 + 3) == *(cur + 3))
{ {
maxLen = 4; maxLen = 4;
distances[offset + 1] = d4 - 1; distances[(size_t)offset + 1] = d4 - 1;
offset += 2; offset += 2;
d2 = d4; d2 = d4;
} }
@ -833,7 +916,7 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0) if (offset != 0)
{ {
UPDATE_maxLen UPDATE_maxLen
distances[offset - 2] = maxLen; distances[(size_t)offset - 2] = maxLen;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
@ -852,12 +935,12 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 offset; unsigned offset;
GET_MATCHES_HEADER(3) GET_MATCHES_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hv]; curMatch = p->hash[hv];
p->hash[hv] = p->pos; p->hash[hv] = p->pos;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances, 2) - (distances)); distances, 2) - (distances));
MOVE_POS_RET MOVE_POS_RET
} }
@ -897,9 +980,9 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(3) SKIP_HEADER(3)
HASH3_CALC; HASH3_CALC;
hash = p->hash; hash = p->hash;
curMatch = hash[kFix3HashSize + hv]; curMatch = (hash + kFix3HashSize)[hv];
hash[h2] = hash[h2] =
hash[kFix3HashSize + hv] = p->pos; (hash + kFix3HashSize)[hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
@ -914,10 +997,10 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(4) SKIP_HEADER(4)
HASH4_CALC; HASH4_CALC;
hash = p->hash; hash = p->hash;
curMatch = hash[kFix4HashSize + hv]; curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] = hash [h2] =
hash[kFix3HashSize + h3] = (hash + kFix3HashSize)[h3] =
hash[kFix4HashSize + hv] = p->pos; (hash + kFix4HashSize)[hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
@ -933,11 +1016,11 @@ static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(5) SKIP_HEADER(5)
HASH5_CALC; HASH5_CALC;
hash = p->hash; hash = p->hash;
curMatch = hash[kFix5HashSize + hv]; curMatch = (hash + kFix5HashSize)[hv];
hash[ h2] = hash [h2] =
hash[kFix3HashSize + h3] = (hash + kFix3HashSize)[h3] =
hash[kFix4HashSize + h4] = (hash + kFix4HashSize)[h4] =
hash[kFix5HashSize + hv] = p->pos; (hash + kFix5HashSize)[hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
@ -953,10 +1036,10 @@ static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(4) SKIP_HEADER(4)
HASH4_CALC; HASH4_CALC;
hash = p->hash; hash = p->hash;
curMatch = hash[kFix4HashSize + hv]; curMatch = (hash + kFix4HashSize)[hv];
hash[ h2] = hash [h2] =
hash[kFix3HashSize + h3] = (hash + kFix3HashSize)[h3] =
hash[kFix4HashSize + hv] = p->pos; (hash + kFix4HashSize)[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS MOVE_POS
} }
@ -973,11 +1056,11 @@ static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_HEADER(5) SKIP_HEADER(5)
HASH5_CALC; HASH5_CALC;
hash = p->hash; hash = p->hash;
curMatch = p->hash[kFix5HashSize + hv]; curMatch = hash + kFix5HashSize)[hv];
hash[ h2] = hash [h2] =
hash[kFix3HashSize + h3] = (hash + kFix3HashSize)[h3] =
hash[kFix4HashSize + h4] = (hash + kFix4HashSize)[h4] =
hash[kFix5HashSize + hv] = p->pos; (hash + kFix5HashSize)[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS MOVE_POS
} }

View File

@ -1,5 +1,5 @@
/* LzFind.h -- Match finder for LZ algorithms /* LzFind.h -- Match finder for LZ algorithms
2015-10-15 : Igor Pavlov : Public domain */ 2017-06-10 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_H #ifndef __LZ_FIND_H
#define __LZ_FIND_H #define __LZ_FIND_H
@ -47,6 +47,8 @@ typedef struct _CMatchFinder
SRes result; SRes result;
UInt32 crc[256]; UInt32 crc[256];
size_t numRefs; size_t numRefs;
UInt64 expectedDataSize;
} CMatchFinder; } CMatchFinder;
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
@ -71,8 +73,8 @@ void MatchFinder_Construct(CMatchFinder *p);
*/ */
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc); ISzAllocPtr alloc);
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
@ -103,7 +105,9 @@ typedef struct _IMatchFinder
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
void MatchFinder_Init_2(CMatchFinder *p, int readData); void MatchFinder_Init_LowHash(CMatchFinder *p);
void MatchFinder_Init_HighHash(CMatchFinder *p);
void MatchFinder_Init_3(CMatchFinder *p, int readData);
void MatchFinder_Init(CMatchFinder *p); void MatchFinder_Init(CMatchFinder *p);
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);

View File

@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms /* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2015-10-15 : Igor Pavlov : Public domain */ 2018-12-29 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -33,6 +33,8 @@ static void MtSync_GetNextBlock(CMtSync *p)
Event_Set(&p->canStart); Event_Set(&p->canStart);
Event_Wait(&p->wasStarted); Event_Wait(&p->wasStarted);
// if (mt) MatchFinder_Init_LowHash(mt->MatchFinder);
} }
else else
{ {
@ -155,6 +157,9 @@ static void HashThreadFunc(CMatchFinderMt *mt)
UInt32 numProcessedBlocks = 0; UInt32 numProcessedBlocks = 0;
Event_Wait(&p->canStart); Event_Wait(&p->canStart);
Event_Set(&p->wasStarted); Event_Set(&p->wasStarted);
MatchFinder_Init_HighHash(mt->MatchFinder);
for (;;) for (;;)
{ {
if (p->exit) if (p->exit)
@ -205,7 +210,7 @@ static void HashThreadFunc(CMatchFinderMt *mt)
if (num > kMtHashBlockSize - 2) if (num > kMtHashBlockSize - 2)
num = kMtHashBlockSize - 2; num = kMtHashBlockSize - 2;
mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);
heads[0] += num; heads[0] = 2 + num;
} }
mf->pos += num; mf->pos += num;
mf->buffer += num; mf->buffer += num;
@ -227,38 +232,57 @@ static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
#define kEmptyHashValue 0 #define kEmptyHashValue 0
/* #define MFMT_GM_INLINE */ #define MFMT_GM_INLINE
#ifdef MFMT_GM_INLINE #ifdef MFMT_GM_INLINE
#define NO_INLINE MY_FAST_CALL /*
we use size_t for _cyclicBufferPos instead of UInt32
to eliminate "movsx" BUG in old MSVC x64 compiler.
*/
static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, MY_NO_INLINE
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, static UInt32 *GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *distances, UInt32 _maxLen, const UInt32 *hash, const UInt32 *limit, UInt32 size, UInt32 *posRes)
{ {
do do
{ {
UInt32 *distances = _distances + 1; UInt32 *_distances = ++distances;
UInt32 curMatch = pos - *hash++; UInt32 delta = *hash++;
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1); CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0; unsigned len0 = 0, len1 = 0;
UInt32 cutValue = _cutValue; UInt32 cutValue = _cutValue;
UInt32 maxLen = _maxLen; unsigned maxLen = (unsigned)_maxLen;
for (;;)
/*
if (size > 1)
{ {
UInt32 delta = pos - curMatch; UInt32 delta = *hash;
if (cutValue-- == 0 || delta >= _cyclicBufferSize) if (delta < _cyclicBufferSize)
{ {
*ptr0 = *ptr1 = kEmptyHashValue; UInt32 cyc1 = _cyclicBufferPos + 1;
break; CLzRef *pair = son + ((size_t)(cyc1 - delta + ((delta > cyc1) ? _cyclicBufferSize : 0)) << 1);
Byte b = *(cur + 1 - delta);
_distances[0] = pair[0];
_distances[1] = b;
} }
}
*/
if (cutValue == 0 || delta >= _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
}
else
for(;;)
{
{ {
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((_cyclicBufferPos < delta) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta; const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1); unsigned len = (len0 < len1 ? len0 : len1);
UInt32 pair0 = *pair;
if (pb[len] == cur[len]) if (pb[len] == cur[len])
{ {
if (++len != lenLimit && pb[len] == cur[len]) if (++len != lenLimit && pb[len] == cur[len])
@ -267,54 +291,66 @@ static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *
break; break;
if (maxLen < len) if (maxLen < len)
{ {
*distances++ = maxLen = len; maxLen = len;
*distances++ = (UInt32)len;
*distances++ = delta - 1; *distances++ = delta - 1;
if (len == lenLimit) if (len == lenLimit)
{ {
*ptr1 = pair[0]; UInt32 pair1 = pair[1];
*ptr0 = pair[1]; *ptr1 = pair0;
*ptr0 = pair1;
break; break;
} }
} }
} }
if (pb[len] < cur[len])
{ {
*ptr1 = curMatch; UInt32 curMatch = pos - delta;
ptr1 = pair + 1; // delta = pos - *pair;
curMatch = *ptr1; // delta = pos - pair[((UInt32)pb[len] - (UInt32)cur[len]) >> 31];
len1 = len; if (pb[len] < cur[len])
} {
else delta = pos - pair[1];
{ *ptr1 = curMatch;
*ptr0 = curMatch; ptr1 = pair + 1;
ptr0 = pair; len1 = len;
curMatch = *ptr0; }
len0 = len; else
{
delta = pos - *pair;
*ptr0 = curMatch;
ptr0 = pair;
len0 = len;
}
} }
} }
if (--cutValue == 0 || delta >= _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
break;
}
} }
pos++; pos++;
_cyclicBufferPos++; _cyclicBufferPos++;
cur++; cur++;
{ {
UInt32 num = (UInt32)(distances - _distances); UInt32 num = (UInt32)(distances - _distances);
*_distances = num - 1; _distances[-1] = num;
_distances += num;
limit -= num;
} }
} }
while (limit > 0 && --size != 0); while (distances < limit && --size != 0);
*posRes = pos; *posRes = pos;
return limit; return distances;
} }
#endif #endif
static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
{ {
UInt32 numProcessed = 0; UInt32 numProcessed = 0;
UInt32 curPos = 2; UInt32 curPos = 2;
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); // * 2
distances[1] = p->hashNumAvail; distances[1] = p->hashNumAvail;
@ -364,8 +400,10 @@ static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
#else #else
{ {
UInt32 posRes; UInt32 posRes;
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, curPos = (UInt32)(GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos), size, &posRes); distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos,
distances + limit,
size, &posRes) - distances);
p->hashBufPos += posRes - pos; p->hashBufPos += posRes - pos;
cyclicBufferPos += posRes - pos; cyclicBufferPos += posRes - pos;
p->buffer += posRes - pos; p->buffer += posRes - pos;
@ -443,13 +481,13 @@ void MatchFinderMt_Construct(CMatchFinderMt *p)
MtSync_Construct(&p->btSync); MtSync_Construct(&p->btSync);
} }
static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->hashBuf); ISzAlloc_Free(alloc, p->hashBuf);
p->hashBuf = NULL; p->hashBuf = NULL;
} }
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc)
{ {
MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->hashSync);
MtSync_Destruct(&p->btSync); MtSync_Destruct(&p->btSync);
@ -472,7 +510,7 @@ static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)
} }
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc)
{ {
CMatchFinder *mf = p->MatchFinder; CMatchFinder *mf = p->MatchFinder;
p->historySize = historySize; p->historySize = historySize;
@ -480,7 +518,7 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
return SZ_ERROR_PARAM; return SZ_ERROR_PARAM;
if (!p->hashBuf) if (!p->hashBuf)
{ {
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
if (!p->hashBuf) if (!p->hashBuf)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
p->btBuf = p->hashBuf + kHashBufferSize; p->btBuf = p->hashBuf + kHashBufferSize;
@ -496,14 +534,18 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
} }
/* Call it after ReleaseStream / SetStream */ /* Call it after ReleaseStream / SetStream */
void MatchFinderMt_Init(CMatchFinderMt *p) static void MatchFinderMt_Init(CMatchFinderMt *p)
{ {
CMatchFinder *mf = p->MatchFinder; CMatchFinder *mf = p->MatchFinder;
p->btBufPos = p->btBufPosLimit = 0;
p->hashBufPos = p->hashBufPosLimit = 0; p->btBufPos =
p->btBufPosLimit = 0;
p->hashBufPos =
p->hashBufPosLimit = 0;
/* Init without data reading. We don't want to read data in this thread */ /* Init without data reading. We don't want to read data in this thread */
MatchFinder_Init_2(mf, False); MatchFinder_Init_3(mf, False);
MatchFinder_Init_LowHash(mf);
p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf); p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);
p->btNumAvailBytes = 0; p->btNumAvailBytes = 0;
@ -591,10 +633,10 @@ static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *dista
MT_HASH3_CALC MT_HASH3_CALC
curMatch2 = hash[ h2]; curMatch2 = hash[ h2];
curMatch3 = hash[kFix3HashSize + h3]; curMatch3 = (hash + kFix3HashSize)[h3];
hash[ h2] = lzPos; hash[ h2] = lzPos;
hash[kFix3HashSize + h3] = lzPos; (hash + kFix3HashSize)[h3] = lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{ {
@ -627,12 +669,12 @@ static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distan
MT_HASH4_CALC MT_HASH4_CALC
curMatch2 = hash[ h2]; curMatch2 = hash[ h2];
curMatch3 = hash[kFix3HashSize + h3]; curMatch3 = (hash + kFix3HashSize)[h3];
curMatch4 = hash[kFix4HashSize + h4]; curMatch4 = (hash + kFix4HashSize)[h4];
hash[ h2] = lzPos; hash[ h2] = lzPos;
hash[kFix3HashSize + h3] = lzPos; (hash + kFix3HashSize)[h3] = lzPos;
hash[kFix4HashSize + h4] = lzPos; (hash + kFix4HashSize)[h4] = lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{ {
@ -684,8 +726,12 @@ static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
UInt32 i; UInt32 i;
for (i = 0; i < len; i += 2) for (i = 0; i < len; i += 2)
{ {
*distances++ = *btBuf++; UInt32 v0 = btBuf[0];
*distances++ = *btBuf++; UInt32 v1 = btBuf[1];
btBuf += 2;
distances[0] = v0;
distances[1] = v1;
distances += 2;
} }
} }
INCREASE_LZ_POS INCREASE_LZ_POS
@ -712,8 +758,12 @@ static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
do do
{ {
*distances2++ = *btBuf++; UInt32 v0 = btBuf[0];
*distances2++ = *btBuf++; UInt32 v1 = btBuf[1];
btBuf += 2;
distances2[0] = v0;
distances2[1] = v1;
distances2 += 2;
} }
while ((len -= 2) != 0); while ((len -= 2) != 0);
len = (UInt32)(distances2 - (distances)); len = (UInt32)(distances2 - (distances));
@ -746,7 +796,7 @@ static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
SKIP_HEADER_MT(3) SKIP_HEADER_MT(3)
UInt32 h2, h3; UInt32 h2, h3;
MT_HASH3_CALC MT_HASH3_CALC
hash[kFix3HashSize + h3] = (hash + kFix3HashSize)[h3] =
hash[ h2] = hash[ h2] =
p->lzPos; p->lzPos;
SKIP_FOOTER_MT SKIP_FOOTER_MT
@ -758,8 +808,8 @@ static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
SKIP_HEADER_MT(4) SKIP_HEADER_MT(4)
UInt32 h2, h3, h4; UInt32 h2, h3, h4;
MT_HASH4_CALC MT_HASH4_CALC
hash[kFix4HashSize + h4] = (hash + kFix4HashSize)[h4] =
hash[kFix3HashSize + h3] = (hash + kFix3HashSize)[h3] =
hash[ h2] = hash[ h2] =
p->lzPos; p->lzPos;
SKIP_FOOTER_MT SKIP_FOOTER_MT
@ -777,7 +827,7 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
{ {
case 2: case 2:
p->GetHeadsFunc = GetHeads2; p->GetHeadsFunc = GetHeads2;
p->MixMatchesFunc = (Mf_Mix_Matches)0; p->MixMatchesFunc = (Mf_Mix_Matches)NULL;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
break; break;

View File

@ -1,5 +1,5 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms /* LzFindMt.h -- multithreaded Match finder for LZ algorithms
2015-05-03 : Igor Pavlov : Public domain */ 2018-07-04 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_MT_H #ifndef __LZ_FIND_MT_H
#define __LZ_FIND_MT_H #define __LZ_FIND_MT_H
@ -19,10 +19,10 @@ EXTERN_C_BEGIN
typedef struct _CMtSync typedef struct _CMtSync
{ {
Bool wasCreated; BoolInt wasCreated;
Bool needStart; BoolInt needStart;
Bool exit; BoolInt exit;
Bool stopWriting; BoolInt stopWriting;
CThread thread; CThread thread;
CAutoResetEvent canStart; CAutoResetEvent canStart;
@ -30,8 +30,8 @@ typedef struct _CMtSync
CAutoResetEvent wasStopped; CAutoResetEvent wasStopped;
CSemaphore freeSemaphore; CSemaphore freeSemaphore;
CSemaphore filledSemaphore; CSemaphore filledSemaphore;
Bool csWasInitialized; BoolInt csWasInitialized;
Bool csWasEntered; BoolInt csWasEntered;
CCriticalSection cs; CCriticalSection cs;
UInt32 numProcessedBlocks; UInt32 numProcessedBlocks;
} CMtSync; } CMtSync;
@ -90,9 +90,9 @@ typedef struct _CMatchFinderMt
} CMatchFinderMt; } CMatchFinderMt;
void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Construct(CMatchFinderMt *p);
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc);
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc);
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);

View File

@ -1,5 +1,5 @@
/* Lzma2Dec.c -- LZMA2 Decoder /* Lzma2Dec.c -- LZMA2 Decoder
2015-11-09 : Igor Pavlov : Public domain */ 2019-02-02 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */ /* #define SHOW_DEBUG_INFO */
@ -14,28 +14,22 @@
#include "Lzma2Dec.h" #include "Lzma2Dec.h"
/* /*
00000000 - EOS 00000000 - End of data
00000001 U U - Uncompressed Reset Dic 00000001 U U - Uncompressed, reset dic, need reset state and set new prop
00000010 U U - Uncompressed No Reset 00000010 U U - Uncompressed, no reset
100uuuuu U U P P - LZMA no reset 100uuuuu U U P P - LZMA, no reset
101uuuuu U U P P - LZMA reset state 101uuuuu U U P P - LZMA, reset state
110uuuuu U U P P S - LZMA reset state + new prop 110uuuuu U U P P S - LZMA, reset state + set new prop
111uuuuu U U P P S - LZMA reset state + new prop + reset dic 111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
u, U - Unpack Size u, U - Unpack Size
P - Pack Size P - Pack Size
S - Props S - Props
*/ */
#define LZMA2_CONTROL_LZMA (1 << 7)
#define LZMA2_CONTROL_COPY_NO_RESET 2
#define LZMA2_CONTROL_COPY_RESET_DIC 1 #define LZMA2_CONTROL_COPY_RESET_DIC 1
#define LZMA2_CONTROL_EOF 0
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0) #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
#define LZMA2_LCLP_MAX 4 #define LZMA2_LCLP_MAX 4
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
@ -74,14 +68,14 @@ static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
return SZ_OK; return SZ_OK;
} }
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
{ {
Byte props[LZMA_PROPS_SIZE]; Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props)); RINOK(Lzma2Dec_GetOldProps(prop, props));
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
} }
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
{ {
Byte props[LZMA_PROPS_SIZE]; Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props)); RINOK(Lzma2Dec_GetOldProps(prop, props));
@ -91,9 +85,11 @@ SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
void Lzma2Dec_Init(CLzma2Dec *p) void Lzma2Dec_Init(CLzma2Dec *p)
{ {
p->state = LZMA2_STATE_CONTROL; p->state = LZMA2_STATE_CONTROL;
p->needInitDic = True; p->needInitLevel = 0xE0;
p->needInitState = True; p->isExtraMode = False;
p->needInitProp = True; p->unpackSize = 0;
// p->decoder.dicPos = 0; // we can use it instead of full init
LzmaDec_Init(&p->decoder); LzmaDec_Init(&p->decoder);
} }
@ -102,19 +98,26 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
switch (p->state) switch (p->state)
{ {
case LZMA2_STATE_CONTROL: case LZMA2_STATE_CONTROL:
p->isExtraMode = False;
p->control = b; p->control = b;
PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos)); PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
PRF(printf(" %2X", (unsigned)b)); PRF(printf(" %02X", (unsigned)b));
if (p->control == 0) if (b == 0)
return LZMA2_STATE_FINISHED; return LZMA2_STATE_FINISHED;
if (LZMA2_IS_UNCOMPRESSED_STATE(p)) if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{ {
if ((p->control & 0x7F) > 2) if (b == LZMA2_CONTROL_COPY_RESET_DIC)
p->needInitLevel = 0xC0;
else if (b > 2 || p->needInitLevel == 0xE0)
return LZMA2_STATE_ERROR; return LZMA2_STATE_ERROR;
p->unpackSize = 0;
} }
else else
p->unpackSize = (UInt32)(p->control & 0x1F) << 16; {
if (b < p->needInitLevel)
return LZMA2_STATE_ERROR;
p->needInitLevel = 0;
p->unpackSize = (UInt32)(b & 0x1F) << 16;
}
return LZMA2_STATE_UNPACK0; return LZMA2_STATE_UNPACK0;
case LZMA2_STATE_UNPACK0: case LZMA2_STATE_UNPACK0:
@ -124,8 +127,8 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
case LZMA2_STATE_UNPACK1: case LZMA2_STATE_UNPACK1:
p->unpackSize |= (UInt32)b; p->unpackSize |= (UInt32)b;
p->unpackSize++; p->unpackSize++;
PRF(printf(" %8u", (unsigned)p->unpackSize)); PRF(printf(" %7u", (unsigned)p->unpackSize));
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
case LZMA2_STATE_PACK0: case LZMA2_STATE_PACK0:
p->packSize = (UInt32)b << 8; p->packSize = (UInt32)b << 8;
@ -134,9 +137,9 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
case LZMA2_STATE_PACK1: case LZMA2_STATE_PACK1:
p->packSize |= (UInt32)b; p->packSize |= (UInt32)b;
p->packSize++; p->packSize++;
PRF(printf(" %8u", (unsigned)p->packSize)); // if (p->packSize < 5) return LZMA2_STATE_ERROR;
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: PRF(printf(" %5u", (unsigned)p->packSize));
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
case LZMA2_STATE_PROP: case LZMA2_STATE_PROP:
{ {
@ -145,13 +148,12 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
return LZMA2_STATE_ERROR; return LZMA2_STATE_ERROR;
lc = b % 9; lc = b % 9;
b /= 9; b /= 9;
p->decoder.prop.pb = b / 5; p->decoder.prop.pb = (Byte)(b / 5);
lp = b % 5; lp = b % 5;
if (lc + lp > LZMA2_LCLP_MAX) if (lc + lp > LZMA2_LCLP_MAX)
return LZMA2_STATE_ERROR; return LZMA2_STATE_ERROR;
p->decoder.prop.lc = lc; p->decoder.prop.lc = (Byte)lc;
p->decoder.prop.lp = lp; p->decoder.prop.lp = (Byte)lp;
p->needInitProp = False;
return LZMA2_STATE_DATA; return LZMA2_STATE_DATA;
} }
} }
@ -167,7 +169,8 @@ static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT s
p->processedPos += (UInt32)size; p->processedPos += (UInt32)size;
} }
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState); void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
@ -176,12 +179,17 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
*srcLen = 0; *srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED; *status = LZMA_STATUS_NOT_SPECIFIED;
while (p->state != LZMA2_STATE_FINISHED) while (p->state != LZMA2_STATE_ERROR)
{ {
SizeT dicPos = p->decoder.dicPos; SizeT dicPos;
if (p->state == LZMA2_STATE_ERROR) if (p->state == LZMA2_STATE_FINISHED)
return SZ_ERROR_DATA; {
*status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
}
dicPos = p->decoder.dicPos;
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
{ {
@ -198,29 +206,25 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
} }
(*srcLen)++; (*srcLen)++;
p->state = Lzma2Dec_UpdateState(p, *src++); p->state = Lzma2Dec_UpdateState(p, *src++);
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED) if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
{ break;
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
}
continue; continue;
} }
{ {
SizeT destSizeCur = dicLimit - dicPos; SizeT inCur = inSize - *srcLen;
SizeT srcSizeCur = inSize - *srcLen; SizeT outCur = dicLimit - dicPos;
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
if (p->unpackSize <= destSizeCur) if (outCur >= p->unpackSize)
{ {
destSizeCur = (SizeT)p->unpackSize; outCur = (SizeT)p->unpackSize;
curFinishMode = LZMA_FINISH_END; curFinishMode = LZMA_FINISH_END;
} }
if (LZMA2_IS_UNCOMPRESSED_STATE(p)) if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{ {
if (*srcLen == inSize) if (inCur == 0)
{ {
*status = LZMA_STATUS_NEEDS_MORE_INPUT; *status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK; return SZ_OK;
@ -228,135 +232,241 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (p->state == LZMA2_STATE_DATA) if (p->state == LZMA2_STATE_DATA)
{ {
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
if (initDic)
p->needInitProp = p->needInitState = True;
else if (p->needInitDic)
{
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
}
p->needInitDic = False;
LzmaDec_InitDicAndState(&p->decoder, initDic, False); LzmaDec_InitDicAndState(&p->decoder, initDic, False);
} }
if (srcSizeCur > destSizeCur) if (inCur > outCur)
srcSizeCur = destSizeCur; inCur = outCur;
if (inCur == 0)
break;
if (srcSizeCur == 0) LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
{
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
}
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); src += inCur;
*srcLen += inCur;
src += srcSizeCur; p->unpackSize -= (UInt32)inCur;
*srcLen += srcSizeCur;
p->unpackSize -= (UInt32)srcSizeCur;
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
} }
else else
{ {
SizeT outSizeProcessed;
SRes res; SRes res;
if (p->state == LZMA2_STATE_DATA) if (p->state == LZMA2_STATE_DATA)
{ {
unsigned mode = LZMA2_GET_LZMA_MODE(p); BoolInt initDic = (p->control >= 0xE0);
Bool initDic = (mode == 3); BoolInt initState = (p->control >= 0xA0);
Bool initState = (mode != 0);
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
{
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
}
LzmaDec_InitDicAndState(&p->decoder, initDic, initState); LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
p->needInitDic = False;
p->needInitState = False;
p->state = LZMA2_STATE_DATA_CONT; p->state = LZMA2_STATE_DATA_CONT;
} }
if (srcSizeCur > p->packSize) if (inCur > p->packSize)
srcSizeCur = (SizeT)p->packSize; inCur = (SizeT)p->packSize;
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
src += srcSizeCur; src += inCur;
*srcLen += srcSizeCur; *srcLen += inCur;
p->packSize -= (UInt32)srcSizeCur; p->packSize -= (UInt32)inCur;
outCur = p->decoder.dicPos - dicPos;
p->unpackSize -= (UInt32)outCur;
outSizeProcessed = p->decoder.dicPos - dicPos; if (res != 0)
p->unpackSize -= (UInt32)outSizeProcessed; break;
RINOK(res);
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
return res; {
if (p->packSize == 0)
break;
return SZ_OK;
}
if (srcSizeCur == 0 && outSizeProcessed == 0) if (inCur == 0 && outCur == 0)
{ {
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|| p->unpackSize != 0 || p->unpackSize != 0
|| p->packSize != 0) || p->packSize != 0)
{ break;
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
}
p->state = LZMA2_STATE_CONTROL; p->state = LZMA2_STATE_CONTROL;
} }
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) *status = LZMA_STATUS_NOT_SPECIFIED;
*status = LZMA_STATUS_NOT_FINISHED;
} }
} }
} }
*status = LZMA_STATUS_FINISHED_WITH_MARK; *status = LZMA_STATUS_NOT_SPECIFIED;
return SZ_OK; p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
} }
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
SizeT outSize,
const Byte *src, SizeT *srcLen,
int checkFinishBlock)
{
SizeT inSize = *srcLen;
*srcLen = 0;
while (p->state != LZMA2_STATE_ERROR)
{
if (p->state == LZMA2_STATE_FINISHED)
return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
if (outSize == 0 && !checkFinishBlock)
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{
if (*srcLen == inSize)
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
(*srcLen)++;
p->state = Lzma2Dec_UpdateState(p, *src++);
if (p->state == LZMA2_STATE_UNPACK0)
{
// if (p->decoder.dicPos != 0)
if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
return LZMA2_PARSE_STATUS_NEW_BLOCK;
// if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
}
// The following code can be commented.
// It's not big problem, if we read additional input bytes.
// It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
{
// checkFinishBlock is true. So we expect that block must be finished,
// We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
// break;
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
}
if (p->state == LZMA2_STATE_DATA)
return LZMA2_PARSE_STATUS_NEW_CHUNK;
continue;
}
if (outSize == 0)
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
{
SizeT inCur = inSize - *srcLen;
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if (inCur == 0)
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
if (inCur > p->unpackSize)
inCur = p->unpackSize;
if (inCur > outSize)
inCur = outSize;
p->decoder.dicPos += inCur;
src += inCur;
*srcLen += inCur;
outSize -= inCur;
p->unpackSize -= (UInt32)inCur;
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
}
else
{
p->isExtraMode = True;
if (inCur == 0)
{
if (p->packSize != 0)
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
}
else if (p->state == LZMA2_STATE_DATA)
{
p->state = LZMA2_STATE_DATA_CONT;
if (*src != 0)
{
// first byte of lzma chunk must be Zero
*srcLen += 1;
p->packSize--;
break;
}
}
if (inCur > p->packSize)
inCur = (SizeT)p->packSize;
src += inCur;
*srcLen += inCur;
p->packSize -= (UInt32)inCur;
if (p->packSize == 0)
{
SizeT rem = outSize;
if (rem > p->unpackSize)
rem = p->unpackSize;
p->decoder.dicPos += rem;
p->unpackSize -= (UInt32)rem;
outSize -= rem;
if (p->unpackSize == 0)
p->state = LZMA2_STATE_CONTROL;
}
}
}
}
p->state = LZMA2_STATE_ERROR;
return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
}
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{ {
SizeT outSize = *destLen, inSize = *srcLen; SizeT outSize = *destLen, inSize = *srcLen;
*srcLen = *destLen = 0; *srcLen = *destLen = 0;
for (;;) for (;;)
{ {
SizeT srcSizeCur = inSize, outSizeCur, dicPos; SizeT inCur = inSize, outCur, dicPos;
ELzmaFinishMode curFinishMode; ELzmaFinishMode curFinishMode;
SRes res; SRes res;
if (p->decoder.dicPos == p->decoder.dicBufSize) if (p->decoder.dicPos == p->decoder.dicBufSize)
p->decoder.dicPos = 0; p->decoder.dicPos = 0;
dicPos = p->decoder.dicPos; dicPos = p->decoder.dicPos;
if (outSize > p->decoder.dicBufSize - dicPos) curFinishMode = LZMA_FINISH_ANY;
outCur = p->decoder.dicBufSize - dicPos;
if (outCur >= outSize)
{ {
outSizeCur = p->decoder.dicBufSize; outCur = outSize;
curFinishMode = LZMA_FINISH_ANY;
}
else
{
outSizeCur = dicPos + outSize;
curFinishMode = finishMode; curFinishMode = finishMode;
} }
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status); res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
src += srcSizeCur;
inSize -= srcSizeCur; src += inCur;
*srcLen += srcSizeCur; inSize -= inCur;
outSizeCur = p->decoder.dicPos - dicPos; *srcLen += inCur;
memcpy(dest, p->decoder.dic + dicPos, outSizeCur); outCur = p->decoder.dicPos - dicPos;
dest += outSizeCur; memcpy(dest, p->decoder.dic + dicPos, outCur);
outSize -= outSizeCur; dest += outCur;
*destLen += outSizeCur; outSize -= outCur;
*destLen += outCur;
if (res != 0) if (res != 0)
return res; return res;
if (outSizeCur == 0 || outSize == 0) if (outCur == 0 || outSize == 0)
return SZ_OK; return SZ_OK;
} }
} }
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
{ {
CLzma2Dec p; CLzma2Dec p;
SRes res; SRes res;

View File

@ -1,5 +1,5 @@
/* Lzma2Dec.h -- LZMA2 Decoder /* Lzma2Dec.h -- LZMA2 Decoder
2015-05-13 : Igor Pavlov : Public domain */ 2018-02-19 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H #ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H #define __LZMA2_DEC_H
@ -12,25 +12,24 @@ EXTERN_C_BEGIN
typedef struct typedef struct
{ {
CLzmaDec decoder;
UInt32 packSize;
UInt32 unpackSize;
unsigned state; unsigned state;
Byte control; Byte control;
Bool needInitDic; Byte needInitLevel;
Bool needInitState; Byte isExtraMode;
Bool needInitProp; Byte _pad_;
UInt32 packSize;
UInt32 unpackSize;
CLzmaDec decoder;
} CLzma2Dec; } CLzma2Dec;
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) #define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc); #define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc)
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc); #define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc)
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
void Lzma2Dec_Init(CLzma2Dec *p); void Lzma2Dec_Init(CLzma2Dec *p);
/* /*
finishMode: finishMode:
It has meaning only if the decoding reaches output limit (*destLen or dicLimit). It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
@ -53,6 +52,47 @@ SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- LZMA2 block and chunk parsing ---------- */
/*
Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.
It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:
- LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.
- LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.
CLzma2Dec::unpackSize contains unpack size of that chunk
*/
typedef enum
{
/*
LZMA_STATUS_NOT_SPECIFIED // data error
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED //
LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused
*/
LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,
LZMA2_PARSE_STATUS_NEW_CHUNK
} ELzma2ParseStatus;
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
SizeT outSize, // output size
const Byte *src, SizeT *srcLen,
int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position.
);
/*
LZMA2 parser doesn't decode LZMA chunks, so we must read
full input LZMA chunk to decode some part of LZMA chunk.
Lzma2Dec_GetUnpackExtra() returns the value that shows
max possible number of output bytes that can be output by decoder
at current input positon.
*/
#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0);
/* ---------- One Call Interface ---------- */ /* ---------- One Call Interface ---------- */
/* /*
@ -73,7 +113,7 @@ Returns:
*/ */
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);
EXTERN_C_END EXTERN_C_END

1082
src/third-party/lzma/Lzma2DecMt.c vendored Normal file

File diff suppressed because it is too large Load Diff

79
src/third-party/lzma/Lzma2DecMt.h vendored Normal file
View File

@ -0,0 +1,79 @@
/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread
2018-02-17 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_MT_H
#define __LZMA2_DEC_MT_H
#include "7zTypes.h"
EXTERN_C_BEGIN
typedef struct
{
size_t inBufSize_ST;
size_t outStep_ST;
#ifndef _7ZIP_ST
unsigned numThreads;
size_t inBufSize_MT;
size_t outBlockMax;
size_t inBlockMax;
#endif
} CLzma2DecMtProps;
/* init to single-thread mode */
void Lzma2DecMtProps_Init(CLzma2DecMtProps *p);
/* ---------- CLzma2DecMtHandle Interface ---------- */
/* Lzma2DecMt_ * functions can return the following exit codes:
SRes:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - ISeqOutStream write callback error
// SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
*/
typedef void * CLzma2DecMtHandle;
CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);
void Lzma2DecMt_Destroy(CLzma2DecMtHandle p);
SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p,
Byte prop,
const CLzma2DecMtProps *props,
ISeqOutStream *outStream,
const UInt64 *outDataSize, // NULL means undefined
int finishMode, // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished
// Byte *outBuf, size_t *outBufSize,
ISeqInStream *inStream,
// const Byte *inData, size_t inDataSize,
// out variables:
UInt64 *inProcessed,
int *isMT, /* out: (*isMT == 0), if single thread decoding was used */
// UInt64 *outProcessed,
ICompressProgress *progress);
/* ---------- Read from CLzma2DecMtHandle Interface ---------- */
SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
Byte prop,
const CLzma2DecMtProps *props,
const UInt64 *outDataSize, int finishMode,
ISeqInStream *inStream);
SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
Byte *data, size_t *outSize,
UInt64 *inStreamProcessed);
EXTERN_C_END
#endif

View File

@ -1,9 +1,8 @@
/* Lzma2Enc.c -- LZMA2 Encoder /* Lzma2Enc.c -- LZMA2 Encoder
2015-10-04 : Igor Pavlov : Public domain */ 2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
/* #include <stdio.h> */
#include <string.h> #include <string.h>
/* #define _7ZIP_ST */ /* #define _7ZIP_ST */
@ -13,7 +12,7 @@
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
#include "MtCoder.h" #include "MtCoder.h"
#else #else
#define NUM_MT_CODER_THREADS_MAX 1 #define MTCODER__THREADS_MAX 1
#endif #endif
#define LZMA2_CONTROL_LZMA (1 << 7) #define LZMA2_CONTROL_LZMA (1 << 7)
@ -35,41 +34,97 @@
#define PRF(x) /* x */ #define PRF(x) /* x */
/* ---------- CLimitedSeqInStream ---------- */
typedef struct
{
ISeqInStream vt;
ISeqInStream *realStream;
UInt64 limit;
UInt64 processed;
int finished;
} CLimitedSeqInStream;
static void LimitedSeqInStream_Init(CLimitedSeqInStream *p)
{
p->limit = (UInt64)(Int64)-1;
p->processed = 0;
p->finished = 0;
}
static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size)
{
CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt);
size_t size2 = *size;
SRes res = SZ_OK;
if (p->limit != (UInt64)(Int64)-1)
{
UInt64 rem = p->limit - p->processed;
if (size2 > rem)
size2 = (size_t)rem;
}
if (size2 != 0)
{
res = ISeqInStream_Read(p->realStream, data, &size2);
p->finished = (size2 == 0 ? 1 : 0);
p->processed += size2;
}
*size = size2;
return res;
}
/* ---------- CLzma2EncInt ---------- */ /* ---------- CLzma2EncInt ---------- */
typedef struct typedef struct
{ {
CLzmaEncHandle enc; CLzmaEncHandle enc;
Byte propsAreSet;
Byte propsByte;
Byte needInitState;
Byte needInitProp;
UInt64 srcPos; UInt64 srcPos;
Byte props;
Bool needInitState;
Bool needInitProp;
} CLzma2EncInt; } CLzma2EncInt;
static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)
static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props)
{ {
Byte propsEncoded[LZMA_PROPS_SIZE]; if (!p->propsAreSet)
SizeT propsSize = LZMA_PROPS_SIZE; {
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps)); SizeT propsSize = LZMA_PROPS_SIZE;
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize)); Byte propsEncoded[LZMA_PROPS_SIZE];
p->srcPos = 0; RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
p->props = propsEncoded[0]; RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
p->needInitState = True; p->propsByte = propsEncoded[0];
p->needInitProp = True; p->propsAreSet = True;
}
return SZ_OK; return SZ_OK;
} }
static void Lzma2EncInt_InitBlock(CLzma2EncInt *p)
{
p->srcPos = 0;
p->needInitState = True;
p->needInitProp = True;
}
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
ISzAlloc *alloc, ISzAlloc *allocBig); ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig); UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp); const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
void LzmaEnc_Finish(CLzmaEncHandle pp); void LzmaEnc_Finish(CLzmaEncHandle pp);
void LzmaEnc_SaveState(CLzmaEncHandle pp); void LzmaEnc_SaveState(CLzmaEncHandle pp);
void LzmaEnc_RestoreState(CLzmaEncHandle pp); void LzmaEnc_RestoreState(CLzmaEncHandle pp);
/*
UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp);
*/
static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
size_t *packSizeRes, ISeqOutStream *outStream) size_t *packSizeRes, ISeqOutStream *outStream)
@ -78,7 +133,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
size_t packSize = packSizeLimit; size_t packSize = packSizeLimit;
UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX; UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0); unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
Bool useCopyBlock; BoolInt useCopyBlock;
SRes res; SRes res;
*packSizeRes = 0; *packSizeRes = 0;
@ -126,7 +181,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
if (outStream) if (outStream)
{ {
*packSizeRes += destPos; *packSizeRes += destPos;
if (outStream->Write(outStream, outBuf, destPos) != destPos) if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE; return SZ_ERROR_WRITE;
destPos = 0; destPos = 0;
} }
@ -154,7 +209,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
outBuf[destPos++] = (Byte)pm; outBuf[destPos++] = (Byte)pm;
if (p->needInitProp) if (p->needInitProp)
outBuf[destPos++] = p->props; outBuf[destPos++] = p->propsByte;
p->needInitProp = False; p->needInitProp = False;
p->needInitState = False; p->needInitState = False;
@ -162,7 +217,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
p->srcPos += unpackSize; p->srcPos += unpackSize;
if (outStream) if (outStream)
if (outStream->Write(outStream, outBuf, destPos) != destPos) if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE; return SZ_ERROR_WRITE;
*packSizeRes = destPos; *packSizeRes = destPos;
@ -176,14 +231,16 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
void Lzma2EncProps_Init(CLzma2EncProps *p) void Lzma2EncProps_Init(CLzma2EncProps *p)
{ {
LzmaEncProps_Init(&p->lzmaProps); LzmaEncProps_Init(&p->lzmaProps);
p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO;
p->numBlockThreads_Reduced = -1;
p->numBlockThreads_Max = -1;
p->numTotalThreads = -1; p->numTotalThreads = -1;
p->numBlockThreads = -1;
p->blockSize = 0;
} }
void Lzma2EncProps_Normalize(CLzma2EncProps *p) void Lzma2EncProps_Normalize(CLzma2EncProps *p)
{ {
int t1, t1n, t2, t3; UInt64 fileSize;
int t1, t1n, t2, t2r, t3;
{ {
CLzmaEncProps lzmaProps = p->lzmaProps; CLzmaEncProps lzmaProps = p->lzmaProps;
LzmaEncProps_Normalize(&lzmaProps); LzmaEncProps_Normalize(&lzmaProps);
@ -191,11 +248,11 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
} }
t1 = p->lzmaProps.numThreads; t1 = p->lzmaProps.numThreads;
t2 = p->numBlockThreads; t2 = p->numBlockThreads_Max;
t3 = p->numTotalThreads; t3 = p->numTotalThreads;
if (t2 > NUM_MT_CODER_THREADS_MAX) if (t2 > MTCODER__THREADS_MAX)
t2 = NUM_MT_CODER_THREADS_MAX; t2 = MTCODER__THREADS_MAX;
if (t3 <= 0) if (t3 <= 0)
{ {
@ -211,8 +268,8 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
t1 = 1; t1 = 1;
t2 = t3; t2 = t3;
} }
if (t2 > NUM_MT_CODER_THREADS_MAX) if (t2 > MTCODER__THREADS_MAX)
t2 = NUM_MT_CODER_THREADS_MAX; t2 = MTCODER__THREADS_MAX;
} }
else if (t1 <= 0) else if (t1 <= 0)
{ {
@ -225,46 +282,71 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
p->lzmaProps.numThreads = t1; p->lzmaProps.numThreads = t1;
t2r = t2;
fileSize = p->lzmaProps.reduceSize;
if ( p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
&& p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO
&& (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))
p->lzmaProps.reduceSize = p->blockSize;
LzmaEncProps_Normalize(&p->lzmaProps); LzmaEncProps_Normalize(&p->lzmaProps);
p->lzmaProps.reduceSize = fileSize;
t1 = p->lzmaProps.numThreads; t1 = p->lzmaProps.numThreads;
if (p->blockSize == 0) if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID)
{ {
UInt32 dictSize = p->lzmaProps.dictSize; t2r = t2 = 1;
UInt64 blockSize = (UInt64)dictSize << 2; t3 = t1;
const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
if (blockSize < kMinSize) blockSize = kMinSize;
if (blockSize > kMaxSize) blockSize = kMaxSize;
if (blockSize < dictSize) blockSize = dictSize;
p->blockSize = (size_t)blockSize;
} }
else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1)
if (t2 > 1 && p->lzmaProps.reduceSize != (UInt64)(Int64)-1)
{ {
UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1; /* if there is no block multi-threading, we use SOLID block */
if (temp > p->lzmaProps.reduceSize) p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;
}
else
{
if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO)
{ {
UInt64 numBlocks = temp / p->blockSize; const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
const UInt32 dictSize = p->lzmaProps.dictSize;
UInt64 blockSize = (UInt64)dictSize << 2;
if (blockSize < kMinSize) blockSize = kMinSize;
if (blockSize > kMaxSize) blockSize = kMaxSize;
if (blockSize < dictSize) blockSize = dictSize;
blockSize += (kMinSize - 1);
blockSize &= ~(UInt64)(kMinSize - 1);
p->blockSize = blockSize;
}
if (t2 > 1 && fileSize != (UInt64)(Int64)-1)
{
UInt64 numBlocks = fileSize / p->blockSize;
if (numBlocks * p->blockSize != fileSize)
numBlocks++;
if (numBlocks < (unsigned)t2) if (numBlocks < (unsigned)t2)
{ {
t2 = (unsigned)numBlocks; t2r = (unsigned)numBlocks;
if (t2 == 0) if (t2r == 0)
t2 = 1; t2r = 1;
t3 = t1 * t2; t3 = t1 * t2r;
} }
} }
} }
p->numBlockThreads = t2; p->numBlockThreads_Max = t2;
p->numBlockThreads_Reduced = t2r;
p->numTotalThreads = t3; p->numTotalThreads = t3;
} }
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{ {
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
} }
@ -274,180 +356,112 @@ typedef struct
{ {
Byte propEncoded; Byte propEncoded;
CLzma2EncProps props; CLzma2EncProps props;
UInt64 expectedDataSize;
Byte *outBuf; Byte *tempBufLzma;
ISzAlloc *alloc; ISzAllocPtr alloc;
ISzAlloc *allocBig; ISzAllocPtr allocBig;
CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX]; CLzma2EncInt coders[MTCODER__THREADS_MAX];
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
ISeqOutStream *outStream;
Byte *outBuf;
size_t outBuf_Rem; /* remainder in outBuf */
size_t outBufSize; /* size of allocated outBufs[i] */
size_t outBufsDataSizes[MTCODER__BLOCKS_MAX];
BoolInt mtCoder_WasConstructed;
CMtCoder mtCoder; CMtCoder mtCoder;
Byte *outBufs[MTCODER__BLOCKS_MAX];
#endif #endif
} CLzma2Enc; } CLzma2Enc;
/* ---------- Lzma2EncThread ---------- */
static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder, CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
{ {
UInt64 packTotal = 0; CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));
SRes res = SZ_OK;
if (!mainEncoder->outBuf)
{
mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
if (!mainEncoder->outBuf)
return SZ_ERROR_MEM;
}
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
mainEncoder->alloc, mainEncoder->allocBig));
for (;;)
{
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);
if (res != SZ_OK)
break;
packTotal += packSize;
res = Progress(progress, p->srcPos, packTotal);
if (res != SZ_OK)
break;
if (packSize == 0)
break;
}
LzmaEnc_Finish(p->enc);
if (res == SZ_OK)
{
Byte b = 0;
if (outStream->Write(outStream, &b, 1) != 1)
return SZ_ERROR_WRITE;
}
return res;
}
#ifndef _7ZIP_ST
typedef struct
{
IMtCoderCallback funcTable;
CLzma2Enc *lzma2Enc;
} CMtCallbackImp;
static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,
const Byte *src, size_t srcSize, int finished)
{
CMtCallbackImp *imp = (CMtCallbackImp *)pp;
CLzma2Enc *mainEncoder = imp->lzma2Enc;
CLzma2EncInt *p = &mainEncoder->coders[index];
SRes res = SZ_OK;
{
size_t destLim = *destSize;
*destSize = 0;
if (srcSize != 0)
{
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,
mainEncoder->alloc, mainEncoder->allocBig));
while (p->srcPos < srcSize)
{
size_t packSize = destLim - *destSize;
res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);
if (res != SZ_OK)
break;
*destSize += packSize;
if (packSize == 0)
{
res = SZ_ERROR_FAIL;
break;
}
if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)
{
res = SZ_ERROR_PROGRESS;
break;
}
}
LzmaEnc_Finish(p->enc);
if (res != SZ_OK)
return res;
}
if (finished)
{
if (*destSize == destLim)
return SZ_ERROR_OUTPUT_EOF;
dest[(*destSize)++] = 0;
}
}
return res;
}
#endif
/* ---------- Lzma2Enc ---------- */
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
{
CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
if (!p) if (!p)
return NULL; return NULL;
Lzma2EncProps_Init(&p->props); Lzma2EncProps_Init(&p->props);
Lzma2EncProps_Normalize(&p->props); Lzma2EncProps_Normalize(&p->props);
p->outBuf = 0; p->expectedDataSize = (UInt64)(Int64)-1;
p->tempBufLzma = NULL;
p->alloc = alloc; p->alloc = alloc;
p->allocBig = allocBig; p->allocBig = allocBig;
{ {
unsigned i; unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) for (i = 0; i < MTCODER__THREADS_MAX; i++)
p->coders[i].enc = 0; p->coders[i].enc = NULL;
} }
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
MtCoder_Construct(&p->mtCoder); p->mtCoder_WasConstructed = False;
{
unsigned i;
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
p->outBufs[i] = NULL;
p->outBufSize = 0;
}
#endif #endif
return p; return p;
} }
#ifndef _7ZIP_ST
static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)
{
unsigned i;
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
if (p->outBufs[i])
{
ISzAlloc_Free(p->alloc, p->outBufs[i]);
p->outBufs[i] = NULL;
}
p->outBufSize = 0;
}
#endif
void Lzma2Enc_Destroy(CLzma2EncHandle pp) void Lzma2Enc_Destroy(CLzma2EncHandle pp)
{ {
CLzma2Enc *p = (CLzma2Enc *)pp; CLzma2Enc *p = (CLzma2Enc *)pp;
unsigned i; unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) for (i = 0; i < MTCODER__THREADS_MAX; i++)
{ {
CLzma2EncInt *t = &p->coders[i]; CLzma2EncInt *t = &p->coders[i];
if (t->enc) if (t->enc)
{ {
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig); LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
t->enc = 0; t->enc = NULL;
} }
} }
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
MtCoder_Destruct(&p->mtCoder); if (p->mtCoder_WasConstructed)
{
MtCoder_Destruct(&p->mtCoder);
p->mtCoder_WasConstructed = False;
}
Lzma2Enc_FreeOutBufs(p);
#endif #endif
IAlloc_Free(p->alloc, p->outBuf); ISzAlloc_Free(p->alloc, p->tempBufLzma);
IAlloc_Free(p->alloc, pp); p->tempBufLzma = NULL;
ISzAlloc_Free(p->alloc, pp);
} }
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props) SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
{ {
CLzma2Enc *p = (CLzma2Enc *)pp; CLzma2Enc *p = (CLzma2Enc *)pp;
@ -460,6 +474,14 @@ SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
return SZ_OK; return SZ_OK;
} }
void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
p->expectedDataSize = expectedDataSiize;
}
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp) Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
{ {
CLzma2Enc *p = (CLzma2Enc *)pp; CLzma2Enc *p = (CLzma2Enc *)pp;
@ -471,50 +493,311 @@ Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
return (Byte)i; return (Byte)i;
} }
SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
int i;
for (i = 0; i < p->props.numBlockThreads; i++) static SRes Lzma2Enc_EncodeMt1(
CLzma2Enc *me,
CLzma2EncInt *p,
ISeqOutStream *outStream,
Byte *outBuf, size_t *outBufSize,
ISeqInStream *inStream,
const Byte *inData, size_t inDataSize,
int finished,
ICompressProgress *progress)
{
UInt64 unpackTotal = 0;
UInt64 packTotal = 0;
size_t outLim = 0;
CLimitedSeqInStream limitedInStream;
if (outBuf)
{ {
CLzma2EncInt *t = &p->coders[(unsigned)i]; outLim = *outBufSize;
if (!t->enc) *outBufSize = 0;
}
if (!p->enc)
{
p->propsAreSet = False;
p->enc = LzmaEnc_Create(me->alloc);
if (!p->enc)
return SZ_ERROR_MEM;
}
limitedInStream.realStream = inStream;
if (inStream)
{
limitedInStream.vt.Read = LimitedSeqInStream_Read;
}
if (!outBuf)
{
// outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma
if (!me->tempBufLzma)
{ {
t->enc = LzmaEnc_Create(p->alloc); me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
if (!t->enc) if (!me->tempBufLzma)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
} }
} }
#ifndef _7ZIP_ST RINOK(Lzma2EncInt_InitStream(p, &me->props));
if (p->props.numBlockThreads > 1)
for (;;)
{ {
CMtCallbackImp mtCallback; SRes res = SZ_OK;
size_t inSizeCur = 0;
mtCallback.funcTable.Code = MtCallbackImp_Code; Lzma2EncInt_InitBlock(p);
mtCallback.lzma2Enc = p;
LimitedSeqInStream_Init(&limitedInStream);
limitedInStream.limit = me->props.blockSize;
if (inStream)
{
UInt64 expected = (UInt64)(Int64)-1;
// inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize
if (me->expectedDataSize != (UInt64)(Int64)-1
&& me->expectedDataSize >= unpackTotal)
expected = me->expectedDataSize - unpackTotal;
if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
&& expected > me->props.blockSize)
expected = (size_t)me->props.blockSize;
LzmaEnc_SetDataSize(p->enc, expected);
RINOK(LzmaEnc_PrepareForLzma2(p->enc,
&limitedInStream.vt,
LZMA2_KEEP_WINDOW_SIZE,
me->alloc,
me->allocBig));
}
else
{
inSizeCur = inDataSize - (size_t)unpackTotal;
if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
&& inSizeCur > me->props.blockSize)
inSizeCur = (size_t)me->props.blockSize;
// LzmaEnc_SetDataSize(p->enc, inSizeCur);
RINOK(LzmaEnc_MemPrepare(p->enc,
inData + (size_t)unpackTotal, inSizeCur,
LZMA2_KEEP_WINDOW_SIZE,
me->alloc,
me->allocBig));
}
for (;;)
{
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
if (outBuf)
packSize = outLim - (size_t)packTotal;
res = Lzma2EncInt_EncodeSubblock(p,
outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,
outBuf ? NULL : outStream);
if (res != SZ_OK)
break;
packTotal += packSize;
if (outBuf)
*outBufSize = (size_t)packTotal;
res = Progress(progress, unpackTotal + p->srcPos, packTotal);
if (res != SZ_OK)
break;
/*
if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)
break;
*/
if (packSize == 0)
break;
}
LzmaEnc_Finish(p->enc);
unpackTotal += p->srcPos;
RINOK(res);
if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))
return SZ_ERROR_FAIL;
if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))
{
if (finished)
{
if (outBuf)
{
size_t destPos = *outBufSize;
if (destPos >= outLim)
return SZ_ERROR_OUTPUT_EOF;
outBuf[destPos] = 0;
*outBufSize = destPos + 1;
}
else
{
Byte b = 0;
if (ISeqOutStream_Write(outStream, &b, 1) != 1)
return SZ_ERROR_WRITE;
}
}
return SZ_OK;
}
}
}
#ifndef _7ZIP_ST
static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex,
const Byte *src, size_t srcSize, int finished)
{
CLzma2Enc *me = (CLzma2Enc *)pp;
size_t destSize = me->outBufSize;
SRes res;
CMtProgressThunk progressThunk;
Byte *dest = me->outBufs[outBufIndex];
me->outBufsDataSizes[outBufIndex] = 0;
if (!dest)
{
dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
if (!dest)
return SZ_ERROR_MEM;
me->outBufs[outBufIndex] = dest;
}
MtProgressThunk_CreateVTable(&progressThunk);
progressThunk.mtProgress = &me->mtCoder.mtProgress;
progressThunk.inSize = 0;
progressThunk.outSize = 0;
res = Lzma2Enc_EncodeMt1(me,
&me->coders[coderIndex],
NULL, dest, &destSize,
NULL, src, srcSize,
finished,
&progressThunk.vt);
me->outBufsDataSizes[outBufIndex] = destSize;
return res;
}
static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex)
{
CLzma2Enc *me = (CLzma2Enc *)pp;
size_t size = me->outBufsDataSizes[outBufIndex];
const Byte *data = me->outBufs[outBufIndex];
if (me->outStream)
return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE;
if (size > me->outBuf_Rem)
return SZ_ERROR_OUTPUT_EOF;
memcpy(me->outBuf, data, size);
me->outBuf_Rem -= size;
me->outBuf += size;
return SZ_OK;
}
#endif
SRes Lzma2Enc_Encode2(CLzma2EncHandle pp,
ISeqOutStream *outStream,
Byte *outBuf, size_t *outBufSize,
ISeqInStream *inStream,
const Byte *inData, size_t inDataSize,
ICompressProgress *progress)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
if (inStream && inData)
return SZ_ERROR_PARAM;
if (outStream && outBuf)
return SZ_ERROR_PARAM;
{
unsigned i;
for (i = 0; i < MTCODER__THREADS_MAX; i++)
p->coders[i].propsAreSet = False;
}
#ifndef _7ZIP_ST
if (p->props.numBlockThreads_Reduced > 1)
{
IMtCoderCallback2 vt;
if (!p->mtCoder_WasConstructed)
{
p->mtCoder_WasConstructed = True;
MtCoder_Construct(&p->mtCoder);
}
vt.Code = Lzma2Enc_MtCallback_Code;
vt.Write = Lzma2Enc_MtCallback_Write;
p->outStream = outStream;
p->outBuf = NULL;
p->outBuf_Rem = 0;
if (!outStream)
{
p->outBuf = outBuf;
p->outBuf_Rem = *outBufSize;
*outBufSize = 0;
}
p->mtCoder.allocBig = p->allocBig;
p->mtCoder.progress = progress; p->mtCoder.progress = progress;
p->mtCoder.inStream = inStream; p->mtCoder.inStream = inStream;
p->mtCoder.outStream = outStream; p->mtCoder.inData = inData;
p->mtCoder.alloc = p->alloc; p->mtCoder.inDataSize = inDataSize;
p->mtCoder.mtCallback = &mtCallback.funcTable; p->mtCoder.mtCallback = &vt;
p->mtCoder.mtCallbackObject = p;
p->mtCoder.blockSize = (size_t)p->props.blockSize;
if (p->mtCoder.blockSize != p->props.blockSize)
return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */
p->mtCoder.blockSize = p->props.blockSize;
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
if (p->mtCoder.destBlockSize < p->props.blockSize)
{ {
p->mtCoder.destBlockSize = (size_t)0 - 1; size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16;
if (p->mtCoder.destBlockSize < p->props.blockSize) if (destBlockSize < p->mtCoder.blockSize)
return SZ_ERROR_FAIL; return SZ_ERROR_PARAM;
if (p->outBufSize != destBlockSize)
Lzma2Enc_FreeOutBufs(p);
p->outBufSize = destBlockSize;
} }
p->mtCoder.numThreads = p->props.numBlockThreads;
return MtCoder_Code(&p->mtCoder); p->mtCoder.numThreadsMax = p->props.numBlockThreads_Max;
p->mtCoder.expectedDataSize = p->expectedDataSize;
{
SRes res = MtCoder_Code(&p->mtCoder);
if (!outStream)
*outBufSize = p->outBuf - outBuf;
return res;
}
} }
#endif #endif
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
return Lzma2Enc_EncodeMt1(p,
&p->coders[0],
outStream, outBuf, outBufSize,
inStream, inData, inDataSize,
True, /* finished */
progress);
} }

View File

@ -1,5 +1,5 @@
/* Lzma2Enc.h -- LZMA2 Encoder /* Lzma2Enc.h -- LZMA2 Encoder
2013-01-18 : Igor Pavlov : Public domain */ 2017-07-27 : Igor Pavlov : Public domain */
#ifndef __LZMA2_ENC_H #ifndef __LZMA2_ENC_H
#define __LZMA2_ENC_H #define __LZMA2_ENC_H
@ -8,11 +8,15 @@
EXTERN_C_BEGIN EXTERN_C_BEGIN
#define LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO 0
#define LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID ((UInt64)(Int64)-1)
typedef struct typedef struct
{ {
CLzmaEncProps lzmaProps; CLzmaEncProps lzmaProps;
size_t blockSize; UInt64 blockSize;
int numBlockThreads; int numBlockThreads_Reduced;
int numBlockThreads_Max;
int numTotalThreads; int numTotalThreads;
} CLzma2EncProps; } CLzma2EncProps;
@ -22,40 +26,29 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p);
/* ---------- CLzmaEnc2Handle Interface ---------- */ /* ---------- CLzmaEnc2Handle Interface ---------- */
/* Lzma2Enc_* functions can return the following exit codes: /* Lzma2Enc_* functions can return the following exit codes:
Returns: SRes:
SZ_OK - OK SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - Write callback error SZ_ERROR_WRITE - ISeqOutStream write callback error
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
*/ */
typedef void * CLzma2EncHandle; typedef void * CLzma2EncHandle;
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig); CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);
void Lzma2Enc_Destroy(CLzma2EncHandle p); void Lzma2Enc_Destroy(CLzma2EncHandle p);
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props); SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize);
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p); Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
SRes Lzma2Enc_Encode(CLzma2EncHandle p, SRes Lzma2Enc_Encode2(CLzma2EncHandle p,
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress); ISeqOutStream *outStream,
Byte *outBuf, size_t *outBufSize,
/* ---------- One Call Interface ---------- */ ISeqInStream *inStream,
const Byte *inData, size_t inDataSize,
/* Lzma2Encode ICompressProgress *progress);
Return code:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
/*
SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
*/
EXTERN_C_END EXTERN_C_END

View File

@ -1,5 +1,5 @@
/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder
2015-11-08 : Igor Pavlov : Public domain */ 2016-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -9,9 +9,6 @@
#include "Bra.h" #include "Bra.h"
#include "LzmaDec.h" #include "LzmaDec.h"
static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
static void SzFree(void *p, void *address) { UNUSED_VAR(p); MyFree(address); }
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
{ {
unsigned i; unsigned i;
@ -25,7 +22,6 @@ SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)
{ {
ISzAlloc g_Alloc = { SzAlloc, SzFree };
SRes res; SRes res;
int useFilter; int useFilter;
SizeT inSizePure; SizeT inSizePure;

View File

@ -1,5 +1,5 @@
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
2015-11-08 : Igor Pavlov : Public domain */ 2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -13,16 +13,12 @@
#define SZE_OUT_OVERFLOW SZE_DATA_ERROR #define SZE_OUT_OVERFLOW SZE_DATA_ERROR
static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
static void SzFree(void *p, void *address) { UNUSED_VAR(p); MyFree(address); }
int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode) int level, UInt32 dictSize, int filterMode)
{ {
ISzAlloc g_Alloc = { SzAlloc, SzFree };
size_t outSize2 = *destLen; size_t outSize2 = *destLen;
Byte *filteredStream; Byte *filteredStream;
Bool useFilter; BoolInt useFilter;
int mainResult = SZ_ERROR_OUTPUT_EOF; int mainResult = SZ_ERROR_OUTPUT_EOF;
CLzmaEncProps props; CLzmaEncProps props;
LzmaEncProps_Init(&props); LzmaEncProps_Init(&props);
@ -60,7 +56,7 @@ int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
{ {
size_t minSize = 0; size_t minSize = 0;
Bool bestIsFiltered = False; BoolInt bestIsFiltered = False;
/* passes for SZ_FILTER_AUTO: /* passes for SZ_FILTER_AUTO:
0 - BCJ + LZMA 0 - BCJ + LZMA
@ -75,7 +71,7 @@ int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
size_t outPropsSize = 5; size_t outPropsSize = 5;
SRes curRes; SRes curRes;
Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); BoolInt curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
if (curModeIsFiltered && !bestIsFiltered) if (curModeIsFiltered && !bestIsFiltered)
break; break;
if (useFilter && i == 0) if (useFilter && i == 0)

View File

@ -1,12 +1,13 @@
/* LzmaDec.c -- LZMA Decoder /* LzmaDec.c -- LZMA Decoder
2015-06-23 : Igor Pavlov : Public domain */ 2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "LzmaDec.h"
#include <string.h> #include <string.h>
/* #include "CpuArch.h" */
#include "LzmaDec.h"
#define kNumTopBits 24 #define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits) #define kTopValue ((UInt32)1 << kNumTopBits)
@ -18,15 +19,22 @@
#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
{ UPDATE_0(p); i = (i + i); A0; } else \ { UPDATE_0(p); i = (i + i); A0; } else \
{ UPDATE_1(p); i = (i + i) + 1; A1; } { UPDATE_1(p); i = (i + i) + 1; A1; }
#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } #define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); }
#define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \
{ UPDATE_0(p + i); A0; } else \
{ UPDATE_1(p + i); A1; }
#define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; )
#define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; )
#define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; )
#define TREE_DECODE(probs, limit, i) \ #define TREE_DECODE(probs, limit, i) \
{ i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
@ -46,16 +54,19 @@
i -= 0x40; } i -= 0x40; }
#endif #endif
#define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol) #define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol)
#define MATCHED_LITER_DEC \ #define MATCHED_LITER_DEC \
matchByte <<= 1; \ matchByte += matchByte; \
bit = (matchByte & offs); \ bit = offs; \
probLit = prob + offs + bit + symbol; \ offs &= matchByte; \
GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) probLit = prob + (offs + bit + symbol); \
GET_BIT2(probLit, symbol, offs ^= bit; , ;)
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
#define UPDATE_0_CHECK range = bound; #define UPDATE_0_CHECK range = bound;
#define UPDATE_1_CHECK range -= bound; code -= bound; #define UPDATE_1_CHECK range -= bound; code -= bound;
#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
@ -66,25 +77,28 @@
{ i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
#define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \
{ UPDATE_0_CHECK; i += m; m += m; } else \
{ UPDATE_1_CHECK; m += m; i += m; }
#define kNumPosBitsMax 4 #define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax) #define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3 #define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8 #define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits) #define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0 #define LenLow 0
#define LenChoice2 (LenChoice + 1) #define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits))
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols) #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define LenChoice LenLow
#define LenChoice2 (LenLow + (1 << kLenNumLowBits))
#define kNumStates 12 #define kNumStates 12
#define kNumStates2 16
#define kNumLitStates 7 #define kNumLitStates 7
#define kStartPosModelIndex 4 #define kStartPosModelIndex 4
@ -98,54 +112,117 @@
#define kAlignTableSize (1 << kNumAlignBits) #define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2 #define kMatchMinLen 2
#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols)
#define IsMatch 0 /* External ASM code needs same CLzmaProb array layout. So don't change it. */
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
/* (probs_1664) is faster and better for code size at some platforms */
/*
#ifdef MY_CPU_X86_OR_AMD64
*/
#define kStartOffset 1664
#define GET_PROBS p->probs_1664
/*
#define GET_PROBS p->probs + kStartOffset
#else
#define kStartOffset 0
#define GET_PROBS p->probs
#endif
*/
#define SpecPos (-kStartOffset)
#define IsRep0Long (SpecPos + kNumFullDistances)
#define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax))
#define LenCoder (RepLenCoder + kNumLenProbs)
#define IsMatch (LenCoder + kNumLenProbs)
#define Align (IsMatch + (kNumStates2 << kNumPosBitsMax))
#define IsRep (Align + kAlignTableSize)
#define IsRepG0 (IsRep + kNumStates) #define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates) #define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates) #define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates) #define PosSlot (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) #define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) #define NUM_BASE_PROBS (Literal + kStartOffset)
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#define LZMA_BASE_SIZE 1846 #if Align != 0 && kStartOffset != 0
#define LZMA_LIT_SIZE 0x300 #error Stop_Compiling_Bad_LZMA_kAlign
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif #endif
#define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) #if NUM_BASE_PROBS != 1984
#error Stop_Compiling_Bad_LZMA_PROBS
#endif
#define LZMA_LIT_SIZE 0x300
#define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
#define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4)
#define COMBINED_PS_STATE (posState + state)
#define GET_LEN_STATE (posState)
#define LZMA_DIC_MIN (1 << 12) #define LZMA_DIC_MIN (1 << 12)
/* First LZMA-symbol is always decoded. /*
And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization p->remainLen : shows status of LZMA decoder:
< kMatchSpecLenStart : normal remain
= kMatchSpecLenStart : finished
= kMatchSpecLenStart + 1 : need init range coder
= kMatchSpecLenStart + 2 : need init range coder and state
*/
/* ---------- LZMA_DECODE_REAL ---------- */
/*
LzmaDec_DecodeReal_3() can be implemented in external ASM file.
3 - is the code compatibility version of that function for check at link time.
*/
#define LZMA_DECODE_REAL LzmaDec_DecodeReal_3
/*
LZMA_DECODE_REAL()
In:
RangeCoder is normalized
if (p->dicPos == limit)
{
LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases.
So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol
is not END_OF_PAYALOAD_MARKER, then function returns error code.
}
Processing:
first LZMA symbol will be decoded in any case
All checks for limits are at the end of main loop,
It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit),
RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked.
Out: Out:
RangeCoder is normalized
Result: Result:
SZ_OK - OK SZ_OK - OK
SZ_ERROR_DATA - Error SZ_ERROR_DATA - Error
p->remainLen: p->remainLen:
< kMatchSpecLenStart : normal remain < kMatchSpecLenStart : normal remain
= kMatchSpecLenStart : finished = kMatchSpecLenStart : finished
= kMatchSpecLenStart + 1 : Flush marker (unused now)
= kMatchSpecLenStart + 2 : State Init Marker (unused now)
*/ */
static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
{
CLzmaProb *probs = p->probs;
unsigned state = p->state; #ifdef _LZMA_DEC_OPT
int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit);
#else
static
int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
{
CLzmaProb *probs = GET_PROBS;
unsigned state = (unsigned)p->state;
UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
unsigned lc = p->prop.lc; unsigned lc = p->prop.lc;
unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc);
Byte *dic = p->dic; Byte *dic = p->dic;
SizeT dicBufSize = p->dicBufSize; SizeT dicBufSize = p->dicBufSize;
@ -164,17 +241,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
CLzmaProb *prob; CLzmaProb *prob;
UInt32 bound; UInt32 bound;
unsigned ttt; unsigned ttt;
unsigned posState = processedPos & pbMask; unsigned posState = CALC_POS_STATE(processedPos, pbMask);
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; prob = probs + IsMatch + COMBINED_PS_STATE;
IF_BIT_0(prob) IF_BIT_0(prob)
{ {
unsigned symbol; unsigned symbol;
UPDATE_0(prob); UPDATE_0(prob);
prob = probs + Literal; prob = probs + Literal;
if (processedPos != 0 || checkDicSize != 0) if (processedPos != 0 || checkDicSize != 0)
prob += ((UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc);
(dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
processedPos++; processedPos++;
if (state < kNumLitStates) if (state < kNumLitStates)
@ -240,13 +316,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
else else
{ {
UPDATE_1(prob); UPDATE_1(prob);
/*
// that case was checked before with kBadRepCode
if (checkDicSize == 0 && processedPos == 0) if (checkDicSize == 0 && processedPos == 0)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
*/
prob = probs + IsRepG0 + state; prob = probs + IsRepG0 + state;
IF_BIT_0(prob) IF_BIT_0(prob)
{ {
UPDATE_0(prob); UPDATE_0(prob);
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; prob = probs + IsRep0Long + COMBINED_PS_STATE;
IF_BIT_0(prob) IF_BIT_0(prob)
{ {
UPDATE_0(prob); UPDATE_0(prob);
@ -294,14 +373,14 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
#ifdef _LZMA_SIZE_OPT #ifdef _LZMA_SIZE_OPT
{ {
unsigned limit, offset; unsigned lim, offset;
CLzmaProb *probLen = prob + LenChoice; CLzmaProb *probLen = prob + LenChoice;
IF_BIT_0(probLen) IF_BIT_0(probLen)
{ {
UPDATE_0(probLen); UPDATE_0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits); probLen = prob + LenLow + GET_LEN_STATE;
offset = 0; offset = 0;
limit = (1 << kLenNumLowBits); lim = (1 << kLenNumLowBits);
} }
else else
{ {
@ -310,19 +389,19 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
IF_BIT_0(probLen) IF_BIT_0(probLen)
{ {
UPDATE_0(probLen); UPDATE_0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits); probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
offset = kLenNumLowSymbols; offset = kLenNumLowSymbols;
limit = (1 << kLenNumMidBits); lim = (1 << kLenNumLowBits);
} }
else else
{ {
UPDATE_1(probLen); UPDATE_1(probLen);
probLen = prob + LenHigh; probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols; offset = kLenNumLowSymbols * 2;
limit = (1 << kLenNumHighBits); lim = (1 << kLenNumHighBits);
} }
} }
TREE_DECODE(probLen, limit, len); TREE_DECODE(probLen, lim, len);
len += offset; len += offset;
} }
#else #else
@ -331,7 +410,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
IF_BIT_0(probLen) IF_BIT_0(probLen)
{ {
UPDATE_0(probLen); UPDATE_0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits); probLen = prob + LenLow + GET_LEN_STATE;
len = 1; len = 1;
TREE_GET_BIT(probLen, len); TREE_GET_BIT(probLen, len);
TREE_GET_BIT(probLen, len); TREE_GET_BIT(probLen, len);
@ -345,7 +424,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
IF_BIT_0(probLen) IF_BIT_0(probLen)
{ {
UPDATE_0(probLen); UPDATE_0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits); probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
len = 1; len = 1;
TREE_GET_BIT(probLen, len); TREE_GET_BIT(probLen, len);
TREE_GET_BIT(probLen, len); TREE_GET_BIT(probLen, len);
@ -356,7 +435,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
UPDATE_1(probLen); UPDATE_1(probLen);
probLen = prob + LenHigh; probLen = prob + LenHigh;
TREE_DECODE(probLen, (1 << kLenNumHighBits), len); TREE_DECODE(probLen, (1 << kLenNumHighBits), len);
len += kLenNumLowSymbols + kLenNumMidSymbols; len += kLenNumLowSymbols * 2;
} }
} }
} }
@ -376,16 +455,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
if (posSlot < kEndPosModelIndex) if (posSlot < kEndPosModelIndex)
{ {
distance <<= numDirectBits; distance <<= numDirectBits;
prob = probs + SpecPos + distance - posSlot - 1; prob = probs + SpecPos;
{ {
UInt32 mask = 1; UInt32 m = 1;
unsigned i = 1; distance++;
do do
{ {
GET_BIT2(prob + i, i, ; , distance |= mask); REV_BIT_VAR(prob, distance, m);
mask <<= 1;
} }
while (--numDirectBits != 0); while (--numDirectBits);
distance -= m;
} }
} }
else else
@ -412,19 +491,20 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
} }
*/ */
} }
while (--numDirectBits != 0); while (--numDirectBits);
prob = probs + Align; prob = probs + Align;
distance <<= kNumAlignBits; distance <<= kNumAlignBits;
{ {
unsigned i = 1; unsigned i = 1;
GET_BIT2(prob + i, i, ; , distance |= 1); REV_BIT_CONST(prob, i, 1);
GET_BIT2(prob + i, i, ; , distance |= 2); REV_BIT_CONST(prob, i, 2);
GET_BIT2(prob + i, i, ; , distance |= 4); REV_BIT_CONST(prob, i, 4);
GET_BIT2(prob + i, i, ; , distance |= 8); REV_BIT_LAST (prob, i, 8);
distance |= i;
} }
if (distance == (UInt32)0xFFFFFFFF) if (distance == (UInt32)0xFFFFFFFF)
{ {
len += kMatchSpecLenStart; len = kMatchSpecLenStart;
state -= kNumStates; state -= kNumStates;
break; break;
} }
@ -435,20 +515,12 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
rep2 = rep1; rep2 = rep1;
rep1 = rep0; rep1 = rep0;
rep0 = distance + 1; rep0 = distance + 1;
if (checkDicSize == 0) state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
{ if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize))
if (distance >= processedPos)
{
p->dicPos = dicPos;
return SZ_ERROR_DATA;
}
}
else if (distance >= checkDicSize)
{ {
p->dicPos = dicPos; p->dicPos = dicPos;
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
} }
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
} }
len += kMatchMinLen; len += kMatchMinLen;
@ -467,7 +539,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
curLen = ((rem < len) ? (unsigned)rem : len); curLen = ((rem < len) ? (unsigned)rem : len);
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
processedPos += curLen; processedPos += (UInt32)curLen;
len -= curLen; len -= curLen;
if (curLen <= dicBufSize - pos) if (curLen <= dicBufSize - pos)
@ -475,7 +547,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
Byte *dest = dic + dicPos; Byte *dest = dic + dicPos;
ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
const Byte *lim = dest + curLen; const Byte *lim = dest + curLen;
dicPos += curLen; dicPos += (SizeT)curLen;
do do
*(dest) = (Byte)*(dest + src); *(dest) = (Byte)*(dest + src);
while (++dest != lim); while (++dest != lim);
@ -500,17 +572,18 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
p->buf = buf; p->buf = buf;
p->range = range; p->range = range;
p->code = code; p->code = code;
p->remainLen = len; p->remainLen = (UInt32)len;
p->dicPos = dicPos; p->dicPos = dicPos;
p->processedPos = processedPos; p->processedPos = processedPos;
p->reps[0] = rep0; p->reps[0] = rep0;
p->reps[1] = rep1; p->reps[1] = rep1;
p->reps[2] = rep2; p->reps[2] = rep2;
p->reps[3] = rep3; p->reps[3] = rep3;
p->state = state; p->state = (UInt32)state;
return SZ_OK; return SZ_OK;
} }
#endif
static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
{ {
@ -519,7 +592,7 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
Byte *dic = p->dic; Byte *dic = p->dic;
SizeT dicPos = p->dicPos; SizeT dicPos = p->dicPos;
SizeT dicBufSize = p->dicBufSize; SizeT dicBufSize = p->dicBufSize;
unsigned len = p->remainLen; unsigned len = (unsigned)p->remainLen;
SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */ SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
SizeT rem = limit - dicPos; SizeT rem = limit - dicPos;
if (rem < len) if (rem < len)
@ -528,8 +601,8 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
p->checkDicSize = p->prop.dicSize; p->checkDicSize = p->prop.dicSize;
p->processedPos += len; p->processedPos += (UInt32)len;
p->remainLen -= len; p->remainLen -= (UInt32)len;
while (len != 0) while (len != 0)
{ {
len--; len--;
@ -540,6 +613,14 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
} }
} }
#define kRange0 0xFFFFFFFF
#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))
#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)))
#if kBadRepCode != (0xC0000000 - 0x400)
#error Stop_Compiling_Bad_LZMA_Check
#endif
static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
{ {
do do
@ -550,9 +631,13 @@ static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte
UInt32 rem = p->prop.dicSize - p->processedPos; UInt32 rem = p->prop.dicSize - p->processedPos;
if (limit - p->dicPos > rem) if (limit - p->dicPos > rem)
limit2 = p->dicPos + rem; limit2 = p->dicPos + rem;
if (p->processedPos == 0)
if (p->code >= kBadRepCode)
return SZ_ERROR_DATA;
} }
RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit));
if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize) if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
p->checkDicSize = p->prop.dicSize; p->checkDicSize = p->prop.dicSize;
@ -561,9 +646,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte
} }
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
if (p->remainLen > kMatchSpecLenStart)
p->remainLen = kMatchSpecLenStart;
return 0; return 0;
} }
@ -580,17 +662,17 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
UInt32 range = p->range; UInt32 range = p->range;
UInt32 code = p->code; UInt32 code = p->code;
const Byte *bufLimit = buf + inSize; const Byte *bufLimit = buf + inSize;
const CLzmaProb *probs = p->probs; const CLzmaProb *probs = GET_PROBS;
unsigned state = p->state; unsigned state = (unsigned)p->state;
ELzmaDummy res; ELzmaDummy res;
{ {
const CLzmaProb *prob; const CLzmaProb *prob;
UInt32 bound; UInt32 bound;
unsigned ttt; unsigned ttt;
unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1);
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; prob = probs + IsMatch + COMBINED_PS_STATE;
IF_BIT_0_CHECK(prob) IF_BIT_0_CHECK(prob)
{ {
UPDATE_0_CHECK UPDATE_0_CHECK
@ -618,10 +700,11 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
{ {
unsigned bit; unsigned bit;
const CLzmaProb *probLit; const CLzmaProb *probLit;
matchByte <<= 1; matchByte += matchByte;
bit = (matchByte & offs); bit = offs;
probLit = prob + offs + bit + symbol; offs &= matchByte;
GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) probLit = prob + (offs + bit + symbol);
GET_BIT2_CHECK(probLit, symbol, offs ^= bit; , ; )
} }
while (symbol < 0x100); while (symbol < 0x100);
} }
@ -648,7 +731,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
IF_BIT_0_CHECK(prob) IF_BIT_0_CHECK(prob)
{ {
UPDATE_0_CHECK; UPDATE_0_CHECK;
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; prob = probs + IsRep0Long + COMBINED_PS_STATE;
IF_BIT_0_CHECK(prob) IF_BIT_0_CHECK(prob)
{ {
UPDATE_0_CHECK; UPDATE_0_CHECK;
@ -691,7 +774,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
IF_BIT_0_CHECK(probLen) IF_BIT_0_CHECK(probLen)
{ {
UPDATE_0_CHECK; UPDATE_0_CHECK;
probLen = prob + LenLow + (posState << kLenNumLowBits); probLen = prob + LenLow + GET_LEN_STATE;
offset = 0; offset = 0;
limit = 1 << kLenNumLowBits; limit = 1 << kLenNumLowBits;
} }
@ -702,15 +785,15 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
IF_BIT_0_CHECK(probLen) IF_BIT_0_CHECK(probLen)
{ {
UPDATE_0_CHECK; UPDATE_0_CHECK;
probLen = prob + LenMid + (posState << kLenNumMidBits); probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
offset = kLenNumLowSymbols; offset = kLenNumLowSymbols;
limit = 1 << kLenNumMidBits; limit = 1 << kLenNumLowBits;
} }
else else
{ {
UPDATE_1_CHECK; UPDATE_1_CHECK;
probLen = prob + LenHigh; probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols; offset = kLenNumLowSymbols * 2;
limit = 1 << kLenNumHighBits; limit = 1 << kLenNumHighBits;
} }
} }
@ -722,7 +805,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
{ {
unsigned posSlot; unsigned posSlot;
prob = probs + PosSlot + prob = probs + PosSlot +
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) <<
kNumPosSlotBits); kNumPosSlotBits);
TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex) if (posSlot >= kStartPosModelIndex)
@ -733,7 +816,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
if (posSlot < kEndPosModelIndex) if (posSlot < kEndPosModelIndex)
{ {
prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits);
} }
else else
{ {
@ -745,17 +828,18 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
code -= range & (((code - range) >> 31) - 1); code -= range & (((code - range) >> 31) - 1);
/* if (code >= range) code -= range; */ /* if (code >= range) code -= range; */
} }
while (--numDirectBits != 0); while (--numDirectBits);
prob = probs + Align; prob = probs + Align;
numDirectBits = kNumAlignBits; numDirectBits = kNumAlignBits;
} }
{ {
unsigned i = 1; unsigned i = 1;
unsigned m = 1;
do do
{ {
GET_BIT_CHECK(prob + i, i); REV_BIT_CHECK(prob, i, m);
} }
while (--numDirectBits != 0); while (--numDirectBits);
} }
} }
} }
@ -766,20 +850,19 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
} }
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState)
{ {
p->needFlush = 1; p->remainLen = kMatchSpecLenStart + 1;
p->remainLen = 0;
p->tempBufSize = 0; p->tempBufSize = 0;
if (initDic) if (initDic)
{ {
p->processedPos = 0; p->processedPos = 0;
p->checkDicSize = 0; p->checkDicSize = 0;
p->needInitState = 1; p->remainLen = kMatchSpecLenStart + 2;
} }
if (initState) if (initState)
p->needInitState = 1; p->remainLen = kMatchSpecLenStart + 2;
} }
void LzmaDec_Init(CLzmaDec *p) void LzmaDec_Init(CLzmaDec *p)
@ -788,53 +871,54 @@ void LzmaDec_Init(CLzmaDec *p)
LzmaDec_InitDicAndState(p, True, True); LzmaDec_InitDicAndState(p, True, True);
} }
static void LzmaDec_InitStateReal(CLzmaDec *p)
{
SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
SizeT i;
CLzmaProb *probs = p->probs;
for (i = 0; i < numProbs; i++)
probs[i] = kBitModelTotal >> 1;
p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
p->state = 0;
p->needInitState = 0;
}
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
ELzmaFinishMode finishMode, ELzmaStatus *status) ELzmaFinishMode finishMode, ELzmaStatus *status)
{ {
SizeT inSize = *srcLen; SizeT inSize = *srcLen;
(*srcLen) = 0; (*srcLen) = 0;
LzmaDec_WriteRem(p, dicLimit);
*status = LZMA_STATUS_NOT_SPECIFIED; *status = LZMA_STATUS_NOT_SPECIFIED;
if (p->remainLen > kMatchSpecLenStart)
{
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
p->tempBuf[p->tempBufSize++] = *src++;
if (p->tempBufSize != 0 && p->tempBuf[0] != 0)
return SZ_ERROR_DATA;
if (p->tempBufSize < RC_INIT_SIZE)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
p->code =
((UInt32)p->tempBuf[1] << 24)
| ((UInt32)p->tempBuf[2] << 16)
| ((UInt32)p->tempBuf[3] << 8)
| ((UInt32)p->tempBuf[4]);
p->range = 0xFFFFFFFF;
p->tempBufSize = 0;
if (p->remainLen > kMatchSpecLenStart + 1)
{
SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
SizeT i;
CLzmaProb *probs = p->probs;
for (i = 0; i < numProbs; i++)
probs[i] = kBitModelTotal >> 1;
p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
p->state = 0;
}
p->remainLen = 0;
}
LzmaDec_WriteRem(p, dicLimit);
while (p->remainLen != kMatchSpecLenStart) while (p->remainLen != kMatchSpecLenStart)
{ {
int checkEndMarkNow; int checkEndMarkNow = 0;
if (p->needFlush)
{
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
p->tempBuf[p->tempBufSize++] = *src++;
if (p->tempBufSize < RC_INIT_SIZE)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
if (p->tempBuf[0] != 0)
return SZ_ERROR_DATA;
p->code =
((UInt32)p->tempBuf[1] << 24)
| ((UInt32)p->tempBuf[2] << 16)
| ((UInt32)p->tempBuf[3] << 8)
| ((UInt32)p->tempBuf[4]);
p->range = 0xFFFFFFFF;
p->needFlush = 0;
p->tempBufSize = 0;
}
checkEndMarkNow = 0;
if (p->dicPos >= dicLimit) if (p->dicPos >= dicLimit)
{ {
if (p->remainLen == 0 && p->code == 0) if (p->remainLen == 0 && p->code == 0)
@ -855,9 +939,6 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
checkEndMarkNow = 1; checkEndMarkNow = 1;
} }
if (p->needInitState)
LzmaDec_InitStateReal(p);
if (p->tempBufSize == 0) if (p->tempBufSize == 0)
{ {
SizeT processed; SizeT processed;
@ -898,10 +979,10 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
p->tempBufSize = rem; p->tempBufSize = rem;
if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
{ {
int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT)rem);
if (dummyRes == DUMMY_ERROR) if (dummyRes == DUMMY_ERROR)
{ {
(*srcLen) += lookAhead; (*srcLen) += (SizeT)lookAhead;
*status = LZMA_STATUS_NEEDS_MORE_INPUT; *status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK; return SZ_OK;
} }
@ -924,17 +1005,20 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
return SZ_ERROR_FAIL; /* some internal error */ return SZ_ERROR_FAIL; /* some internal error */
lookAhead -= rem; lookAhead -= rem;
} }
(*srcLen) += lookAhead; (*srcLen) += (SizeT)lookAhead;
src += lookAhead; src += lookAhead;
inSize -= lookAhead; inSize -= (SizeT)lookAhead;
p->tempBufSize = 0; p->tempBufSize = 0;
} }
} }
if (p->code == 0)
*status = LZMA_STATUS_FINISHED_WITH_MARK; if (p->code != 0)
return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; return SZ_ERROR_DATA;
*status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
} }
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{ {
SizeT outSize = *destLen; SizeT outSize = *destLen;
@ -975,19 +1059,19 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *sr
} }
} }
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->probs); ISzAlloc_Free(alloc, p->probs);
p->probs = NULL; p->probs = NULL;
} }
static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) static void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->dic); ISzAlloc_Free(alloc, p->dic);
p->dic = NULL; p->dic = NULL;
} }
void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc)
{ {
LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeProbs(p, alloc);
LzmaDec_FreeDict(p, alloc); LzmaDec_FreeDict(p, alloc);
@ -1011,29 +1095,30 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
if (d >= (9 * 5 * 5)) if (d >= (9 * 5 * 5))
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
p->lc = d % 9; p->lc = (Byte)(d % 9);
d /= 9; d /= 9;
p->pb = d / 5; p->pb = (Byte)(d / 5);
p->lp = d % 5; p->lp = (Byte)(d % 5);
return SZ_OK; return SZ_OK;
} }
static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc)
{ {
UInt32 numProbs = LzmaProps_GetNumProbs(propNew); UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
if (!p->probs || numProbs != p->numProbs) if (!p->probs || numProbs != p->numProbs)
{ {
LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeProbs(p, alloc);
p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); p->probs = (CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb));
p->numProbs = numProbs;
if (!p->probs) if (!p->probs)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
p->probs_1664 = p->probs + 1664;
p->numProbs = numProbs;
} }
return SZ_OK; return SZ_OK;
} }
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)
{ {
CLzmaProps propNew; CLzmaProps propNew;
RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaProps_Decode(&propNew, props, propsSize));
@ -1042,7 +1127,7 @@ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, I
return SZ_OK; return SZ_OK;
} }
SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)
{ {
CLzmaProps propNew; CLzmaProps propNew;
SizeT dicBufSize; SizeT dicBufSize;
@ -1062,7 +1147,7 @@ SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAll
if (!p->dic || dicBufSize != p->dicBufSize) if (!p->dic || dicBufSize != p->dicBufSize)
{ {
LzmaDec_FreeDict(p, alloc); LzmaDec_FreeDict(p, alloc);
p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); p->dic = (Byte *)ISzAlloc_Alloc(alloc, dicBufSize);
if (!p->dic) if (!p->dic)
{ {
LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeProbs(p, alloc);
@ -1076,7 +1161,7 @@ SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAll
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc) ELzmaStatus *status, ISzAllocPtr alloc)
{ {
CLzmaDec p; CLzmaDec p;
SRes res; SRes res;

View File

@ -1,5 +1,5 @@
/* LzmaDec.h -- LZMA Decoder /* LzmaDec.h -- LZMA Decoder
2013-01-18 : Igor Pavlov : Public domain */ 2018-04-21 : Igor Pavlov : Public domain */
#ifndef __LZMA_DEC_H #ifndef __LZMA_DEC_H
#define __LZMA_DEC_H #define __LZMA_DEC_H
@ -12,11 +12,13 @@ EXTERN_C_BEGIN
/* _LZMA_PROB32 can increase the speed on some CPUs, /* _LZMA_PROB32 can increase the speed on some CPUs,
but memory usage for CLzmaDec::probs will be doubled in that case */ but memory usage for CLzmaDec::probs will be doubled in that case */
typedef
#ifdef _LZMA_PROB32 #ifdef _LZMA_PROB32
#define CLzmaProb UInt32 UInt32
#else #else
#define CLzmaProb UInt16 UInt16
#endif #endif
CLzmaProb;
/* ---------- LZMA Properties ---------- */ /* ---------- LZMA Properties ---------- */
@ -25,7 +27,10 @@ EXTERN_C_BEGIN
typedef struct _CLzmaProps typedef struct _CLzmaProps
{ {
unsigned lc, lp, pb; Byte lc;
Byte lp;
Byte pb;
Byte _pad_;
UInt32 dicSize; UInt32 dicSize;
} CLzmaProps; } CLzmaProps;
@ -47,32 +52,34 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
typedef struct typedef struct
{ {
/* Don't change this structure. ASM code can use it. */
CLzmaProps prop; CLzmaProps prop;
CLzmaProb *probs; CLzmaProb *probs;
CLzmaProb *probs_1664;
Byte *dic; Byte *dic;
const Byte *buf;
UInt32 range, code;
SizeT dicPos;
SizeT dicBufSize; SizeT dicBufSize;
SizeT dicPos;
const Byte *buf;
UInt32 range;
UInt32 code;
UInt32 processedPos; UInt32 processedPos;
UInt32 checkDicSize; UInt32 checkDicSize;
unsigned state;
UInt32 reps[4]; UInt32 reps[4];
unsigned remainLen; UInt32 state;
int needFlush; UInt32 remainLen;
int needInitState;
UInt32 numProbs; UInt32 numProbs;
unsigned tempBufSize; unsigned tempBufSize;
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
} CLzmaDec; } CLzmaDec;
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } #define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
void LzmaDec_Init(CLzmaDec *p); void LzmaDec_Init(CLzmaDec *p);
/* There are two types of LZMA streams: /* There are two types of LZMA streams:
0) Stream with end mark. That end mark adds about 6 bytes to compressed size. - Stream with end mark. That end mark adds about 6 bytes to compressed size.
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ - Stream without end mark. You must know exact uncompressed size to decompress such stream. */
typedef enum typedef enum
{ {
@ -129,11 +136,11 @@ LzmaDec_Allocate* can return:
SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_UNSUPPORTED - Unsupported properties
*/ */
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
/* ---------- Dictionary Interface ---------- */ /* ---------- Dictionary Interface ---------- */
@ -142,7 +149,7 @@ void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
You must work with CLzmaDec variables directly in this interface. You must work with CLzmaDec variables directly in this interface.
STEPS: STEPS:
LzmaDec_Constr() LzmaDec_Construct()
LzmaDec_Allocate() LzmaDec_Allocate()
for (each new stream) for (each new stream)
{ {
@ -220,7 +227,7 @@ Returns:
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc); ELzmaStatus *status, ISzAllocPtr alloc);
EXTERN_C_END EXTERN_C_END

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* LzmaEnc.h -- LZMA Encoder /* LzmaEnc.h -- LZMA Encoder
2013-01-18 : Igor Pavlov : Public domain */ 2017-07-27 : Igor Pavlov : Public domain */
#ifndef __LZMA_ENC_H #ifndef __LZMA_ENC_H
#define __LZMA_ENC_H #define __LZMA_ENC_H
@ -12,12 +12,10 @@ EXTERN_C_BEGIN
typedef struct _CLzmaEncProps typedef struct _CLzmaEncProps
{ {
int level; /* 0 <= level <= 9 */ int level; /* 0 <= level <= 9 */
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version (1 << 12) <= dictSize <= (3 << 29) for 64-bit version
default = (1 << 24) */ default = (1 << 24) */
UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.
Encoder uses this value to reduce dictionary size */
int lc; /* 0 <= lc <= 8, default = 3 */ int lc; /* 0 <= lc <= 8, default = 3 */
int lp; /* 0 <= lp <= 4, default = 0 */ int lp; /* 0 <= lp <= 4, default = 0 */
int pb; /* 0 <= pb <= 4, default = 2 */ int pb; /* 0 <= pb <= 4, default = 2 */
@ -25,9 +23,12 @@ typedef struct _CLzmaEncProps
int fb; /* 5 <= fb <= 273, default = 32 */ int fb; /* 5 <= fb <= 273, default = 32 */
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
int numHashBytes; /* 2, 3 or 4, default = 4 */ int numHashBytes; /* 2, 3 or 4, default = 4 */
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
int numThreads; /* 1 or 2, default = 2 */ int numThreads; /* 1 or 2, default = 2 */
UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.
Encoder uses this value to reduce dictionary size */
} CLzmaEncProps; } CLzmaEncProps;
void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Init(CLzmaEncProps *p);
@ -37,41 +38,38 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
/* ---------- CLzmaEncHandle Interface ---------- */ /* ---------- CLzmaEncHandle Interface ---------- */
/* LzmaEnc_* functions can return the following exit codes: /* LzmaEnc* functions can return the following exit codes:
Returns: SRes:
SZ_OK - OK SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - Write callback error. SZ_ERROR_WRITE - ISeqOutStream write callback error
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
*/ */
typedef void * CLzmaEncHandle; typedef void * CLzmaEncHandle;
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc);
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize);
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p);
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
/* ---------- One Call Interface ---------- */ /* ---------- One Call Interface ---------- */
/* LzmaEncode
Return code:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
EXTERN_C_END EXTERN_C_END

View File

@ -1,168 +1,89 @@
/* MtCoder.c -- Multi-thread Coder /* MtCoder.c -- Multi-thread Coder
2015-10-13 : Igor Pavlov : Public domain */ 2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "MtCoder.h" #include "MtCoder.h"
void LoopThread_Construct(CLoopThread *p) #ifndef _7ZIP_ST
{
Thread_Construct(&p->thread);
Event_Construct(&p->startEvent);
Event_Construct(&p->finishedEvent);
}
void LoopThread_Close(CLoopThread *p) SRes MtProgressThunk_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize)
{ {
Thread_Close(&p->thread); CMtProgressThunk *thunk = CONTAINER_FROM_VTBL(pp, CMtProgressThunk, vt);
Event_Close(&p->startEvent); UInt64 inSize2 = 0;
Event_Close(&p->finishedEvent); UInt64 outSize2 = 0;
} if (inSize != (UInt64)(Int64)-1)
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
{
CLoopThread *p = (CLoopThread *)pp;
for (;;)
{ {
if (Event_Wait(&p->startEvent) != 0) inSize2 = inSize - thunk->inSize;
return SZ_ERROR_THREAD; thunk->inSize = inSize;
if (p->stop)
return 0;
p->res = p->func(p->param);
if (Event_Set(&p->finishedEvent) != 0)
return SZ_ERROR_THREAD;
} }
if (outSize != (UInt64)(Int64)-1)
{
outSize2 = outSize - thunk->outSize;
thunk->outSize = outSize;
}
return MtProgress_ProgressAdd(thunk->mtProgress, inSize2, outSize2);
} }
WRes LoopThread_Create(CLoopThread *p)
void MtProgressThunk_CreateVTable(CMtProgressThunk *p)
{ {
p->stop = 0; p->vt.Progress = MtProgressThunk_Progress;
RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));
RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));
return Thread_Create(&p->thread, LoopThreadFunc, p);
} }
WRes LoopThread_StopAndWait(CLoopThread *p)
{
p->stop = 1;
if (Event_Set(&p->startEvent) != 0)
return SZ_ERROR_THREAD;
return Thread_Wait(&p->thread);
}
WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }
WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
}
static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
{
unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
p->inSizes[i] = p->outSizes[i] = 0;
p->totalInSize = p->totalOutSize = 0;
p->progress = progress;
p->res = SZ_OK;
}
static void MtProgress_Reinit(CMtProgress *p, unsigned index)
{
p->inSizes[index] = 0;
p->outSizes[index] = 0;
}
#define UPDATE_PROGRESS(size, prev, total) \
if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)
{
SRes res;
CriticalSection_Enter(&p->cs);
UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)
UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)
if (p->res == SZ_OK)
p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);
res = p->res;
CriticalSection_Leave(&p->cs);
return res;
}
static void MtProgress_SetError(CMtProgress *p, SRes res)
{
CriticalSection_Enter(&p->cs);
if (p->res == SZ_OK)
p->res = res;
CriticalSection_Leave(&p->cs);
}
static void MtCoder_SetError(CMtCoder* p, SRes res)
{
CriticalSection_Enter(&p->cs);
if (p->res == SZ_OK)
p->res = res;
CriticalSection_Leave(&p->cs);
}
/* ---------- MtThread ---------- */
void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
{
p->mtCoder = mtCoder;
p->outBuf = 0;
p->inBuf = 0;
Event_Construct(&p->canRead);
Event_Construct(&p->canWrite);
LoopThread_Construct(&p->thread);
}
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
static void CMtThread_CloseEvents(CMtThread *p)
static WRes ArEvent_OptCreate_And_Reset(CEvent *p)
{ {
Event_Close(&p->canRead); if (Event_IsCreated(p))
Event_Close(&p->canWrite); return Event_Reset(p);
return AutoResetEvent_CreateNotSignaled(p);
} }
static void CMtThread_Destruct(CMtThread *p)
{
CMtThread_CloseEvents(p);
if (Thread_WasCreated(&p->thread.thread)) static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp);
static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t)
{
WRes wres = ArEvent_OptCreate_And_Reset(&t->startEvent);
if (wres == 0)
{ {
LoopThread_StopAndWait(&p->thread); t->stop = False;
LoopThread_Close(&p->thread); if (!Thread_WasCreated(&t->thread))
wres = Thread_Create(&t->thread, ThreadFunc, t);
if (wres == 0)
wres = Event_Set(&t->startEvent);
}
if (wres == 0)
return SZ_OK;
return MY_SRes_HRESULT_FROM_WRes(wres);
}
static void MtCoderThread_Destruct(CMtCoderThread *t)
{
if (Thread_WasCreated(&t->thread))
{
t->stop = 1;
Event_Set(&t->startEvent);
Thread_Wait(&t->thread);
Thread_Close(&t->thread);
} }
if (p->mtCoder->alloc) Event_Close(&t->startEvent);
IAlloc_Free(p->mtCoder->alloc, p->outBuf);
p->outBuf = 0;
if (p->mtCoder->alloc) if (t->inBuf)
IAlloc_Free(p->mtCoder->alloc, p->inBuf); {
p->inBuf = 0; ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf);
t->inBuf = NULL;
}
} }
#define MY_BUF_ALLOC(buf, size, newSize) \
if (buf == 0 || size != newSize) \
{ IAlloc_Free(p->mtCoder->alloc, buf); \
size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \
if (buf == 0) return SZ_ERROR_MEM; }
static SRes CMtThread_Prepare(CMtThread *p)
{
MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)
MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)
p->stopReading = False;
p->stopWriting = False;
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));
return SZ_OK;
}
static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize) static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
{ {
@ -170,158 +91,511 @@ static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
*processedSize = 0; *processedSize = 0;
while (size != 0) while (size != 0)
{ {
size_t curSize = size; size_t cur = size;
SRes res = stream->Read(stream, data, &curSize); SRes res = ISeqInStream_Read(stream, data, &cur);
*processedSize += curSize; *processedSize += cur;
data += curSize; data += cur;
size -= curSize; size -= cur;
RINOK(res); RINOK(res);
if (curSize == 0) if (cur == 0)
return SZ_OK; return SZ_OK;
} }
return SZ_OK; return SZ_OK;
} }
#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads - 1 ? 0 : p->index + 1]
static SRes MtThread_Process(CMtThread *p, Bool *stop) /*
ThreadFunc2() returns:
SZ_OK - in all normal cases (even for stream error or memory allocation error)
SZ_ERROR_THREAD - in case of failure in system synch function
*/
static SRes ThreadFunc2(CMtCoderThread *t)
{ {
CMtThread *next; CMtCoder *mtc = t->mtCoder;
*stop = True;
if (Event_Wait(&p->canRead) != 0)
return SZ_ERROR_THREAD;
next = GET_NEXT_THREAD(p);
if (p->stopReading)
{
next->stopReading = True;
return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;
}
{
size_t size = p->mtCoder->blockSize;
size_t destSize = p->outBufSize;
RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));
next->stopReading = *stop = (size != p->mtCoder->blockSize);
if (Event_Set(&next->canRead) != 0)
return SZ_ERROR_THREAD;
RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,
p->outBuf, &destSize, p->inBuf, size, *stop));
MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);
if (Event_Wait(&p->canWrite) != 0)
return SZ_ERROR_THREAD;
if (p->stopWriting)
return SZ_ERROR_FAIL;
if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)
return SZ_ERROR_WRITE;
return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;
}
}
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
{
CMtThread *p = (CMtThread *)pp;
for (;;) for (;;)
{ {
Bool stop; unsigned bi;
CMtThread *next = GET_NEXT_THREAD(p); SRes res;
SRes res = MtThread_Process(p, &stop); SRes res2;
if (res != SZ_OK) BoolInt finished;
unsigned bufIndex;
size_t size;
const Byte *inData;
UInt64 readProcessed = 0;
RINOK_THREAD(Event_Wait(&mtc->readEvent))
/* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */
if (mtc->stopReading)
{ {
MtCoder_SetError(p->mtCoder, res); return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD;
MtProgress_SetError(&p->mtCoder->mtProgress, res);
next->stopReading = True;
next->stopWriting = True;
Event_Set(&next->canRead);
Event_Set(&next->canWrite);
return res;
} }
if (stop)
res = MtProgress_GetError(&mtc->mtProgress);
size = 0;
inData = NULL;
finished = True;
if (res == SZ_OK)
{
size = mtc->blockSize;
if (mtc->inStream)
{
if (!t->inBuf)
{
t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize);
if (!t->inBuf)
res = SZ_ERROR_MEM;
}
if (res == SZ_OK)
{
res = FullRead(mtc->inStream, t->inBuf, &size);
readProcessed = mtc->readProcessed + size;
mtc->readProcessed = readProcessed;
}
if (res != SZ_OK)
{
mtc->readRes = res;
/* after reading error - we can stop encoding of previous blocks */
MtProgress_SetError(&mtc->mtProgress, res);
}
else
finished = (size != mtc->blockSize);
}
else
{
size_t rem;
readProcessed = mtc->readProcessed;
rem = mtc->inDataSize - (size_t)readProcessed;
if (size > rem)
size = rem;
inData = mtc->inData + (size_t)readProcessed;
readProcessed += size;
mtc->readProcessed = readProcessed;
finished = (mtc->inDataSize == (size_t)readProcessed);
}
}
/* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */
res2 = SZ_OK;
if (Semaphore_Wait(&mtc->blocksSemaphore) != 0)
{
res2 = SZ_ERROR_THREAD;
if (res == SZ_OK)
{
res = res2;
// MtProgress_SetError(&mtc->mtProgress, res);
}
}
bi = mtc->blockIndex;
if (++mtc->blockIndex >= mtc->numBlocksMax)
mtc->blockIndex = 0;
bufIndex = (unsigned)(int)-1;
if (res == SZ_OK)
res = MtProgress_GetError(&mtc->mtProgress);
if (res != SZ_OK)
finished = True;
if (!finished)
{
if (mtc->numStartedThreads < mtc->numStartedThreadsLimit
&& mtc->expectedDataSize != readProcessed)
{
res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]);
if (res == SZ_OK)
mtc->numStartedThreads++;
else
{
MtProgress_SetError(&mtc->mtProgress, res);
finished = True;
}
}
}
if (finished)
mtc->stopReading = True;
RINOK_THREAD(Event_Set(&mtc->readEvent))
if (res2 != SZ_OK)
return res2;
if (res == SZ_OK)
{
CriticalSection_Enter(&mtc->cs);
bufIndex = mtc->freeBlockHead;
mtc->freeBlockHead = mtc->freeBlockList[bufIndex];
CriticalSection_Leave(&mtc->cs);
res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex,
mtc->inStream ? t->inBuf : inData, size, finished);
// MtProgress_Reinit(&mtc->mtProgress, t->index);
if (res != SZ_OK)
MtProgress_SetError(&mtc->mtProgress, res);
}
{
CMtCoderBlock *block = &mtc->blocks[bi];
block->res = res;
block->bufIndex = bufIndex;
block->finished = finished;
}
#ifdef MTCODER__USE_WRITE_THREAD
RINOK_THREAD(Event_Set(&mtc->writeEvents[bi]))
#else
{
unsigned wi;
{
CriticalSection_Enter(&mtc->cs);
wi = mtc->writeIndex;
if (wi == bi)
mtc->writeIndex = (unsigned)(int)-1;
else
mtc->ReadyBlocks[bi] = True;
CriticalSection_Leave(&mtc->cs);
}
if (wi != bi)
{
if (res != SZ_OK || finished)
return 0;
continue;
}
if (mtc->writeRes != SZ_OK)
res = mtc->writeRes;
for (;;)
{
if (res == SZ_OK && bufIndex != (unsigned)(int)-1)
{
res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex);
if (res != SZ_OK)
{
mtc->writeRes = res;
MtProgress_SetError(&mtc->mtProgress, res);
}
}
if (++wi >= mtc->numBlocksMax)
wi = 0;
{
BoolInt isReady;
CriticalSection_Enter(&mtc->cs);
if (bufIndex != (unsigned)(int)-1)
{
mtc->freeBlockList[bufIndex] = mtc->freeBlockHead;
mtc->freeBlockHead = bufIndex;
}
isReady = mtc->ReadyBlocks[wi];
if (isReady)
mtc->ReadyBlocks[wi] = False;
else
mtc->writeIndex = wi;
CriticalSection_Leave(&mtc->cs);
RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore))
if (!isReady)
break;
}
{
CMtCoderBlock *block = &mtc->blocks[wi];
if (res == SZ_OK && block->res != SZ_OK)
res = block->res;
bufIndex = block->bufIndex;
finished = block->finished;
}
}
}
#endif
if (finished || res != SZ_OK)
return 0; return 0;
} }
} }
void MtCoder_Construct(CMtCoder* p)
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
{
CMtCoderThread *t = (CMtCoderThread *)pp;
for (;;)
{
if (Event_Wait(&t->startEvent) != 0)
return SZ_ERROR_THREAD;
if (t->stop)
return 0;
{
SRes res = ThreadFunc2(t);
CMtCoder *mtc = t->mtCoder;
if (res != SZ_OK)
{
MtProgress_SetError(&mtc->mtProgress, res);
}
#ifndef MTCODER__USE_WRITE_THREAD
{
unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads);
if (numFinished == mtc->numStartedThreads)
if (Event_Set(&mtc->finishedEvent) != 0)
return SZ_ERROR_THREAD;
}
#endif
}
}
}
void MtCoder_Construct(CMtCoder *p)
{ {
unsigned i; unsigned i;
p->alloc = 0;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) p->blockSize = 0;
p->numThreadsMax = 0;
p->expectedDataSize = (UInt64)(Int64)-1;
p->inStream = NULL;
p->inData = NULL;
p->inDataSize = 0;
p->progress = NULL;
p->allocBig = NULL;
p->mtCallback = NULL;
p->mtCallbackObject = NULL;
p->allocatedBufsSize = 0;
Event_Construct(&p->readEvent);
Semaphore_Construct(&p->blocksSemaphore);
for (i = 0; i < MTCODER__THREADS_MAX; i++)
{ {
CMtThread *t = &p->threads[i]; CMtCoderThread *t = &p->threads[i];
t->mtCoder = p;
t->index = i; t->index = i;
CMtThread_Construct(t, p); t->inBuf = NULL;
t->stop = False;
Event_Construct(&t->startEvent);
Thread_Construct(&t->thread);
} }
#ifdef MTCODER__USE_WRITE_THREAD
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
Event_Construct(&p->writeEvents[i]);
#else
Event_Construct(&p->finishedEvent);
#endif
CriticalSection_Init(&p->cs); CriticalSection_Init(&p->cs);
CriticalSection_Init(&p->mtProgress.cs); CriticalSection_Init(&p->mtProgress.cs);
} }
void MtCoder_Destruct(CMtCoder* p)
static void MtCoder_Free(CMtCoder *p)
{ {
unsigned i; unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
CMtThread_Destruct(&p->threads[i]); /*
p->stopReading = True;
if (Event_IsCreated(&p->readEvent))
Event_Set(&p->readEvent);
*/
for (i = 0; i < MTCODER__THREADS_MAX; i++)
MtCoderThread_Destruct(&p->threads[i]);
Event_Close(&p->readEvent);
Semaphore_Close(&p->blocksSemaphore);
#ifdef MTCODER__USE_WRITE_THREAD
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
Event_Close(&p->writeEvents[i]);
#else
Event_Close(&p->finishedEvent);
#endif
}
void MtCoder_Destruct(CMtCoder *p)
{
MtCoder_Free(p);
CriticalSection_Delete(&p->cs); CriticalSection_Delete(&p->cs);
CriticalSection_Delete(&p->mtProgress.cs); CriticalSection_Delete(&p->mtProgress.cs);
} }
SRes MtCoder_Code(CMtCoder *p) SRes MtCoder_Code(CMtCoder *p)
{ {
unsigned i, numThreads = p->numThreads; unsigned numThreads = p->numThreadsMax;
unsigned numBlocksMax;
unsigned i;
SRes res = SZ_OK; SRes res = SZ_OK;
p->res = SZ_OK;
if (numThreads > MTCODER__THREADS_MAX)
numThreads = MTCODER__THREADS_MAX;
numBlocksMax = MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads);
if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++;
if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++;
if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++;
if (numBlocksMax > MTCODER__BLOCKS_MAX)
numBlocksMax = MTCODER__BLOCKS_MAX;
if (p->blockSize != p->allocatedBufsSize)
{
for (i = 0; i < MTCODER__THREADS_MAX; i++)
{
CMtCoderThread *t = &p->threads[i];
if (t->inBuf)
{
ISzAlloc_Free(p->allocBig, t->inBuf);
t->inBuf = NULL;
}
}
p->allocatedBufsSize = p->blockSize;
}
p->readRes = SZ_OK;
MtProgress_Init(&p->mtProgress, p->progress); MtProgress_Init(&p->mtProgress, p->progress);
for (i = 0; i < numThreads; i++) #ifdef MTCODER__USE_WRITE_THREAD
for (i = 0; i < numBlocksMax; i++)
{
RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->writeEvents[i]));
}
#else
RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->finishedEvent));
#endif
{ {
RINOK(CMtThread_Prepare(&p->threads[i])); RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->readEvent));
if (Semaphore_IsCreated(&p->blocksSemaphore))
{
RINOK_THREAD(Semaphore_Close(&p->blocksSemaphore));
}
RINOK_THREAD(Semaphore_Create(&p->blocksSemaphore, numBlocksMax, numBlocksMax));
} }
for (i = 0; i < numThreads; i++) for (i = 0; i < MTCODER__BLOCKS_MAX - 1; i++)
p->freeBlockList[i] = i + 1;
p->freeBlockList[MTCODER__BLOCKS_MAX - 1] = (unsigned)(int)-1;
p->freeBlockHead = 0;
p->readProcessed = 0;
p->blockIndex = 0;
p->numBlocksMax = numBlocksMax;
p->stopReading = False;
#ifndef MTCODER__USE_WRITE_THREAD
p->writeIndex = 0;
p->writeRes = SZ_OK;
for (i = 0; i < MTCODER__BLOCKS_MAX; i++)
p->ReadyBlocks[i] = False;
p->numFinishedThreads = 0;
#endif
p->numStartedThreadsLimit = numThreads;
p->numStartedThreads = 0;
// for (i = 0; i < numThreads; i++)
{ {
CMtThread *t = &p->threads[i]; CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++];
CLoopThread *lt = &t->thread; RINOK(MtCoderThread_CreateAndStart(nextThread));
}
if (!Thread_WasCreated(&lt->thread)) RINOK_THREAD(Event_Set(&p->readEvent))
#ifdef MTCODER__USE_WRITE_THREAD
{
unsigned bi = 0;
for (;; bi++)
{ {
lt->func = ThreadFunc; if (bi >= numBlocksMax)
lt->param = t; bi = 0;
RINOK_THREAD(Event_Wait(&p->writeEvents[bi]))
if (LoopThread_Create(lt) != SZ_OK)
{ {
res = SZ_ERROR_THREAD; const CMtCoderBlock *block = &p->blocks[bi];
break; unsigned bufIndex = block->bufIndex;
BoolInt finished = block->finished;
if (res == SZ_OK && block->res != SZ_OK)
res = block->res;
if (bufIndex != (unsigned)(int)-1)
{
if (res == SZ_OK)
{
res = p->mtCallback->Write(p->mtCallbackObject, bufIndex);
if (res != SZ_OK)
MtProgress_SetError(&p->mtProgress, res);
}
CriticalSection_Enter(&p->cs);
{
p->freeBlockList[bufIndex] = p->freeBlockHead;
p->freeBlockHead = bufIndex;
}
CriticalSection_Leave(&p->cs);
}
RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore))
if (finished)
break;
} }
} }
} }
#else
{
WRes wres = Event_Wait(&p->finishedEvent);
res = MY_SRes_HRESULT_FROM_WRes(wres);
}
#endif
if (res == SZ_OK) if (res == SZ_OK)
{ res = p->readRes;
unsigned j;
for (i = 0; i < numThreads; i++)
{
CMtThread *t = &p->threads[i];
if (LoopThread_StartSubThread(&t->thread) != SZ_OK)
{
res = SZ_ERROR_THREAD;
p->threads[0].stopReading = True;
break;
}
}
Event_Set(&p->threads[0].canWrite); if (res == SZ_OK)
Event_Set(&p->threads[0].canRead); res = p->mtProgress.res;
for (j = 0; j < i; j++) #ifndef MTCODER__USE_WRITE_THREAD
LoopThread_WaitSubThread(&p->threads[j].thread); if (res == SZ_OK)
} res = p->writeRes;
#endif
for (i = 0; i < numThreads; i++) if (res != SZ_OK)
CMtThread_CloseEvents(&p->threads[i]); MtCoder_Free(p);
return (res == SZ_OK) ? p->res : res; return res;
} }
#endif

View File

@ -1,98 +1,141 @@
/* MtCoder.h -- Multi-thread Coder /* MtCoder.h -- Multi-thread Coder
2009-11-19 : Igor Pavlov : Public domain */ 2018-07-04 : Igor Pavlov : Public domain */
#ifndef __MT_CODER_H #ifndef __MT_CODER_H
#define __MT_CODER_H #define __MT_CODER_H
#include "Threads.h" #include "MtDec.h"
EXTERN_C_BEGIN EXTERN_C_BEGIN
typedef struct /*
{ if ( defined MTCODER__USE_WRITE_THREAD) : main thread writes all data blocks to output stream
CThread thread; if (not defined MTCODER__USE_WRITE_THREAD) : any coder thread can write data blocks to output stream
CAutoResetEvent startEvent; */
CAutoResetEvent finishedEvent; /* #define MTCODER__USE_WRITE_THREAD */
int stop;
THREAD_FUNC_TYPE func;
LPVOID param;
THREAD_FUNC_RET_TYPE res;
} CLoopThread;
void LoopThread_Construct(CLoopThread *p);
void LoopThread_Close(CLoopThread *p);
WRes LoopThread_Create(CLoopThread *p);
WRes LoopThread_StopAndWait(CLoopThread *p);
WRes LoopThread_StartSubThread(CLoopThread *p);
WRes LoopThread_WaitSubThread(CLoopThread *p);
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
#define NUM_MT_CODER_THREADS_MAX 32 #define MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1)
#define MTCODER__THREADS_MAX 64
#define MTCODER__BLOCKS_MAX (MTCODER__GET_NUM_BLOCKS_FROM_THREADS(MTCODER__THREADS_MAX) + 3)
#else #else
#define NUM_MT_CODER_THREADS_MAX 1 #define MTCODER__THREADS_MAX 1
#define MTCODER__BLOCKS_MAX 1
#endif #endif
#ifndef _7ZIP_ST
typedef struct typedef struct
{ {
UInt64 totalInSize; ICompressProgress vt;
UInt64 totalOutSize; CMtProgress *mtProgress;
ICompressProgress *progress; UInt64 inSize;
SRes res; UInt64 outSize;
CCriticalSection cs; } CMtProgressThunk;
UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];
UInt64 outSizes[NUM_MT_CODER_THREADS_MAX]; void MtProgressThunk_CreateVTable(CMtProgressThunk *p);
} CMtProgress;
#define MtProgressThunk_Init(p) { (p)->inSize = 0; (p)->outSize = 0; }
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);
struct _CMtCoder; struct _CMtCoder;
typedef struct typedef struct
{ {
struct _CMtCoder *mtCoder; struct _CMtCoder *mtCoder;
Byte *outBuf;
size_t outBufSize;
Byte *inBuf;
size_t inBufSize;
unsigned index; unsigned index;
CLoopThread thread; int stop;
Byte *inBuf;
CAutoResetEvent startEvent;
CThread thread;
} CMtCoderThread;
Bool stopReading;
Bool stopWriting;
CAutoResetEvent canRead;
CAutoResetEvent canWrite;
} CMtThread;
typedef struct typedef struct
{ {
SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize, SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex,
const Byte *src, size_t srcSize, int finished); const Byte *src, size_t srcSize, int finished);
} IMtCoderCallback; SRes (*Write)(void *p, unsigned outBufIndex);
} IMtCoderCallback2;
typedef struct
{
SRes res;
unsigned bufIndex;
BoolInt finished;
} CMtCoderBlock;
typedef struct _CMtCoder typedef struct _CMtCoder
{ {
size_t blockSize; /* input variables */
size_t destBlockSize;
unsigned numThreads; size_t blockSize; /* size of input block */
unsigned numThreadsMax;
UInt64 expectedDataSize;
ISeqInStream *inStream; ISeqInStream *inStream;
ISeqOutStream *outStream; const Byte *inData;
ICompressProgress *progress; size_t inDataSize;
ISzAlloc *alloc;
ICompressProgress *progress;
ISzAllocPtr allocBig;
IMtCoderCallback2 *mtCallback;
void *mtCallbackObject;
/* internal variables */
size_t allocatedBufsSize;
CAutoResetEvent readEvent;
CSemaphore blocksSemaphore;
BoolInt stopReading;
SRes readRes;
#ifdef MTCODER__USE_WRITE_THREAD
CAutoResetEvent writeEvents[MTCODER__BLOCKS_MAX];
#else
CAutoResetEvent finishedEvent;
SRes writeRes;
unsigned writeIndex;
Byte ReadyBlocks[MTCODER__BLOCKS_MAX];
LONG numFinishedThreads;
#endif
unsigned numStartedThreadsLimit;
unsigned numStartedThreads;
unsigned numBlocksMax;
unsigned blockIndex;
UInt64 readProcessed;
IMtCoderCallback *mtCallback;
CCriticalSection cs; CCriticalSection cs;
SRes res;
unsigned freeBlockHead;
unsigned freeBlockList[MTCODER__BLOCKS_MAX];
CMtProgress mtProgress; CMtProgress mtProgress;
CMtThread threads[NUM_MT_CODER_THREADS_MAX]; CMtCoderBlock blocks[MTCODER__BLOCKS_MAX];
CMtCoderThread threads[MTCODER__THREADS_MAX];
} CMtCoder; } CMtCoder;
void MtCoder_Construct(CMtCoder* p);
void MtCoder_Destruct(CMtCoder* p); void MtCoder_Construct(CMtCoder *p);
void MtCoder_Destruct(CMtCoder *p);
SRes MtCoder_Code(CMtCoder *p); SRes MtCoder_Code(CMtCoder *p);
#endif
EXTERN_C_END EXTERN_C_END
#endif #endif

1138
src/third-party/lzma/MtDec.c vendored Normal file

File diff suppressed because it is too large Load Diff

201
src/third-party/lzma/MtDec.h vendored Normal file
View File

@ -0,0 +1,201 @@
/* MtDec.h -- Multi-thread Decoder
2018-07-04 : Igor Pavlov : Public domain */
#ifndef __MT_DEC_H
#define __MT_DEC_H
#include "7zTypes.h"
#ifndef _7ZIP_ST
#include "Threads.h"
#endif
EXTERN_C_BEGIN
#ifndef _7ZIP_ST
#ifndef _7ZIP_ST
#define MTDEC__THREADS_MAX 32
#else
#define MTDEC__THREADS_MAX 1
#endif
typedef struct
{
ICompressProgress *progress;
SRes res;
UInt64 totalInSize;
UInt64 totalOutSize;
CCriticalSection cs;
} CMtProgress;
void MtProgress_Init(CMtProgress *p, ICompressProgress *progress);
SRes MtProgress_Progress_ST(CMtProgress *p);
SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize);
SRes MtProgress_GetError(CMtProgress *p);
void MtProgress_SetError(CMtProgress *p, SRes res);
struct _CMtDec;
typedef struct
{
struct _CMtDec *mtDec;
unsigned index;
void *inBuf;
size_t inDataSize_Start; // size of input data in start block
UInt64 inDataSize; // total size of input data in all blocks
CThread thread;
CAutoResetEvent canRead;
CAutoResetEvent canWrite;
void *allocaPtr;
} CMtDecThread;
void MtDecThread_FreeInBufs(CMtDecThread *t);
typedef enum
{
MTDEC_PARSE_CONTINUE, // continue this block with more input data
MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread
MTDEC_PARSE_NEW, // new block
MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue)
} EMtDecParseState;
typedef struct
{
// in
int startCall;
const Byte *src;
size_t srcSize;
// in : (srcSize == 0) is allowed
// out : it's allowed to return less that actually was used ?
int srcFinished;
// out
EMtDecParseState state;
BoolInt canCreateNewThread;
UInt64 outPos; // check it (size_t)
} CMtDecCallbackInfo;
typedef struct
{
void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci);
// PreCode() and Code():
// (SRes_return_result != SZ_OK) means stop decoding, no need another blocks
SRes (*PreCode)(void *p, unsigned coderIndex);
SRes (*Code)(void *p, unsigned coderIndex,
const Byte *src, size_t srcSize, int srcFinished,
UInt64 *inCodePos, UInt64 *outCodePos, int *stop);
// stop - means stop another Code calls
/* Write() must be called, if Parse() was called
set (needWrite) if
{
&& (was not interrupted by progress)
&& (was not interrupted in previous block)
}
out:
if (*needContinue), decoder still need to continue decoding with new iteration,
even after MTDEC_PARSE_END
if (*canRecode), we didn't flush current block data, so we still can decode current block later.
*/
SRes (*Write)(void *p, unsigned coderIndex,
BoolInt needWriteToStream,
const Byte *src, size_t srcSize,
// int srcFinished,
BoolInt *needContinue,
BoolInt *canRecode);
} IMtDecCallback;
typedef struct _CMtDec
{
/* input variables */
size_t inBufSize; /* size of input block */
unsigned numThreadsMax;
// size_t inBlockMax;
unsigned numThreadsMax_2;
ISeqInStream *inStream;
// const Byte *inData;
// size_t inDataSize;
ICompressProgress *progress;
ISzAllocPtr alloc;
IMtDecCallback *mtCallback;
void *mtCallbackObject;
/* internal variables */
size_t allocatedBufsSize;
BoolInt exitThread;
WRes exitThreadWRes;
UInt64 blockIndex;
BoolInt isAllocError;
BoolInt overflow;
SRes threadingErrorSRes;
BoolInt needContinue;
// CAutoResetEvent finishedEvent;
SRes readRes;
SRes codeRes;
BoolInt wasInterrupted;
unsigned numStartedThreads_Limit;
unsigned numStartedThreads;
Byte *crossBlock;
size_t crossStart;
size_t crossEnd;
UInt64 readProcessed;
BoolInt readWasFinished;
UInt64 inProcessed;
unsigned filledThreadStart;
unsigned numFilledThreads;
#ifndef _7ZIP_ST
BoolInt needInterrupt;
UInt64 interruptIndex;
CMtProgress mtProgress;
CMtDecThread threads[MTDEC__THREADS_MAX];
#endif
} CMtDec;
void MtDec_Construct(CMtDec *p);
void MtDec_Destruct(CMtDec *p);
/*
MtDec_Code() returns:
SZ_OK - in most cases
MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function
*/
SRes MtDec_Code(CMtDec *p);
Byte *MtDec_GetCrossBuff(CMtDec *p);
int MtDec_PrepareRead(CMtDec *p);
const Byte *MtDec_Read(CMtDec *p, size_t *inLim);
#endif
EXTERN_C_END
#endif

View File

@ -1,5 +1,5 @@
/* Ppmd.h -- PPMD codec common code /* Ppmd.h -- PPMD codec common code
2013-01-18 : Igor Pavlov : Public domain 2017-04-03 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#ifndef __PPMD_H #ifndef __PPMD_H
@ -77,8 +77,8 @@ typedef
CPpmd_Byte_Ref; CPpmd_Byte_Ref;
#define PPMD_SetAllBitsIn256Bytes(p) \ #define PPMD_SetAllBitsIn256Bytes(p) \
{ unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \ { size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \
p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }} p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }}
EXTERN_C_END EXTERN_C_END

View File

@ -1,5 +1,5 @@
/* Ppmd7.c -- PPMdH codec /* Ppmd7.c -- PPMdH codec
2015-09-28 : Igor Pavlov : Public domain 2018-07-04 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -15,7 +15,7 @@ static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x
#define UNIT_SIZE 12 #define UNIT_SIZE 12
#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
#define U2I(nu) (p->Units2Indx[(nu) - 1]) #define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1])
#define I2U(indx) (p->Indx2Units[indx]) #define I2U(indx) (p->Indx2Units[indx])
#ifdef PPMD_32BIT #ifdef PPMD_32BIT
@ -88,29 +88,31 @@ void Ppmd7_Construct(CPpmd7 *p)
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40); memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
} }
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc) void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->Base); ISzAlloc_Free(alloc, p->Base);
p->Size = 0; p->Size = 0;
p->Base = 0; p->Base = 0;
} }
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc) BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc)
{ {
if (p->Base == 0 || p->Size != size) if (!p->Base || p->Size != size)
{ {
size_t size2;
Ppmd7_Free(p, alloc); Ppmd7_Free(p, alloc);
size2 = 0
#ifndef PPMD_32BIT
+ UNIT_SIZE
#endif
;
p->AlignOffset = p->AlignOffset =
#ifdef PPMD_32BIT #ifdef PPMD_32BIT
(4 - size) & 3; (4 - size) & 3;
#else #else
4 - (size & 3); 4 - (size & 3);
#endif #endif
if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size + size2)) == 0)
#ifndef PPMD_32BIT
+ UNIT_SIZE
#endif
)) == 0)
return False; return False;
p->Size = size; p->Size = size;
} }
@ -340,7 +342,7 @@ void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
p->DummySee.Count = 64; /* unused */ p->DummySee.Count = 64; /* unused */
} }
static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip) static CTX_PTR CreateSuccessors(CPpmd7 *p, BoolInt skip)
{ {
CPpmd_State upState; CPpmd_State upState;
CTX_PTR c = p->MinContext; CTX_PTR c = p->MinContext;
@ -513,7 +515,7 @@ static void UpdateModel(CPpmd7 *p)
/* Expand for one UNIT */ /* Expand for one UNIT */
unsigned oldNU = ns1 >> 1; unsigned oldNU = ns1 >> 1;
unsigned i = U2I(oldNU); unsigned i = U2I(oldNU);
if (i != U2I(oldNU + 1)) if (i != U2I((size_t)oldNU + 1))
{ {
void *ptr = AllocUnits(p, i + 1); void *ptr = AllocUnits(p, i + 1);
void *oldPtr; void *oldPtr;
@ -639,10 +641,10 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
unsigned nonMasked = p->MinContext->NumStats - numMasked; unsigned nonMasked = p->MinContext->NumStats - numMasked;
if (p->MinContext->NumStats != 256) if (p->MinContext->NumStats != 256)
{ {
see = p->See[p->NS2Indx[nonMasked - 1]] + see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] +
(nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + 2 * (unsigned)(p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
4 * (numMasked > nonMasked) + 4 * (unsigned)(numMasked > nonMasked) +
p->HiBitsFlag; p->HiBitsFlag;
{ {
unsigned r = (see->Summ >> see->Shift); unsigned r = (see->Summ >> see->Shift);

View File

@ -1,5 +1,5 @@
/* Ppmd7.h -- PPMdH compression codec /* Ppmd7.h -- PPMdH compression codec
2010-03-12 : Igor Pavlov : Public domain 2018-07-04 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
/* This code supports virtual RangeDecoder and includes the implementation /* This code supports virtual RangeDecoder and includes the implementation
@ -60,8 +60,8 @@ typedef struct
} CPpmd7; } CPpmd7;
void Ppmd7_Construct(CPpmd7 *p); void Ppmd7_Construct(CPpmd7 *p);
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc); BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc);
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc); void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc);
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder); void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL) #define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
@ -86,10 +86,10 @@ void Ppmd7_Update2(CPpmd7 *p);
void Ppmd7_UpdateBin(CPpmd7 *p); void Ppmd7_UpdateBin(CPpmd7 *p);
#define Ppmd7_GetBinSumm(p) \ #define Ppmd7_GetBinSumm(p) \
&p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \ 2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \
((p->RunLength >> 26) & 0x20)] ((p->RunLength >> 26) & 0x20)]
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
@ -97,26 +97,28 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
/* ---------- Decode ---------- */ /* ---------- Decode ---------- */
typedef struct typedef struct IPpmd7_RangeDec IPpmd7_RangeDec;
struct IPpmd7_RangeDec
{ {
UInt32 (*GetThreshold)(void *p, UInt32 total); UInt32 (*GetThreshold)(const IPpmd7_RangeDec *p, UInt32 total);
void (*Decode)(void *p, UInt32 start, UInt32 size); void (*Decode)(const IPpmd7_RangeDec *p, UInt32 start, UInt32 size);
UInt32 (*DecodeBit)(void *p, UInt32 size0); UInt32 (*DecodeBit)(const IPpmd7_RangeDec *p, UInt32 size0);
} IPpmd7_RangeDec; };
typedef struct typedef struct
{ {
IPpmd7_RangeDec p; IPpmd7_RangeDec vt;
UInt32 Range; UInt32 Range;
UInt32 Code; UInt32 Code;
IByteIn *Stream; IByteIn *Stream;
} CPpmd7z_RangeDec; } CPpmd7z_RangeDec;
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p); void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p); BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0) #define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc); int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc);
/* ---------- Encode ---------- */ /* ---------- Encode ---------- */

View File

@ -1,5 +1,5 @@
/* Ppmd7Dec.c -- PPMdH Decoder /* Ppmd7Dec.c -- PPMdH Decoder
2010-03-12 : Igor Pavlov : Public domain 2018-07-04 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -8,49 +8,51 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#define kTopValue (1 << 24) #define kTopValue (1 << 24)
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
{ {
unsigned i; unsigned i;
p->Code = 0; p->Code = 0;
p->Range = 0xFFFFFFFF; p->Range = 0xFFFFFFFF;
if (p->Stream->Read((void *)p->Stream) != 0) if (IByteIn_Read(p->Stream) != 0)
return False; return False;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
return (p->Code < 0xFFFFFFFF); return (p->Code < 0xFFFFFFFF);
} }
static UInt32 Range_GetThreshold(void *pp, UInt32 total) #define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt);
static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total)
{ {
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; GET_Ppmd7z_RangeDec
return (p->Code) / (p->Range /= total); return p->Code / (p->Range /= total);
} }
static void Range_Normalize(CPpmd7z_RangeDec *p) static void Range_Normalize(CPpmd7z_RangeDec *p)
{ {
if (p->Range < kTopValue) if (p->Range < kTopValue)
{ {
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
p->Range <<= 8; p->Range <<= 8;
if (p->Range < kTopValue) if (p->Range < kTopValue)
{ {
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
p->Range <<= 8; p->Range <<= 8;
} }
} }
} }
static void Range_Decode(void *pp, UInt32 start, UInt32 size) static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size)
{ {
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; GET_Ppmd7z_RangeDec
p->Code -= start * p->Range; p->Code -= start * p->Range;
p->Range *= size; p->Range *= size;
Range_Normalize(p); Range_Normalize(p);
} }
static UInt32 Range_DecodeBit(void *pp, UInt32 size0) static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0)
{ {
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; GET_Ppmd7z_RangeDec
UInt32 newBound = (p->Range >> 14) * size0; UInt32 newBound = (p->Range >> 14) * size0;
UInt32 symbol; UInt32 symbol;
if (p->Code < newBound) if (p->Code < newBound)
@ -70,15 +72,15 @@ static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
{ {
p->p.GetThreshold = Range_GetThreshold; p->vt.GetThreshold = Range_GetThreshold;
p->p.Decode = Range_Decode; p->vt.Decode = Range_Decode;
p->p.DecodeBit = Range_DecodeBit; p->vt.DecodeBit = Range_DecodeBit;
} }
#define MASK(sym) ((signed char *)charMask)[sym] #define MASK(sym) ((signed char *)charMask)[sym]
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc) int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc)
{ {
size_t charMask[256 / sizeof(size_t)]; size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 1) if (p->MinContext->NumStats != 1)

View File

@ -1,5 +1,5 @@
/* Ppmd7Enc.c -- PPMdH Encoder /* Ppmd7Enc.c -- PPMdH Encoder
2015-09-28 : Igor Pavlov : Public domain 2017-04-03 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -23,7 +23,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
Byte temp = p->Cache; Byte temp = p->Cache;
do do
{ {
p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32))); IByteOut_Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
temp = 0xFF; temp = 0xFF;
} }
while (--p->CacheSize != 0); while (--p->CacheSize != 0);

View File

@ -1,5 +1,5 @@
/* Crypto/Sha256.c -- SHA-256 Hash /* Crypto/Sha256.c -- SHA-256 Hash
2015-11-14 : Igor Pavlov : Public domain 2017-04-03 : Igor Pavlov : Public domain
This code is based on public domain code from Wei Dai's Crypto++ library. */ This code is based on public domain code from Wei Dai's Crypto++ library. */
#include "Precomp.h" #include "Precomp.h"
@ -45,7 +45,7 @@ void Sha256_Init(CSha256 *p)
#ifdef _SHA256_UNROLL2 #ifdef _SHA256_UNROLL2
#define R(a,b,c,d,e,f,g,h, i) \ #define R(a,b,c,d,e,f,g,h, i) \
h += S1(e) + Ch(e,f,g) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \ h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + (j ? blk2(i) : blk0(i)); \
d += h; \ d += h; \
h += S0(a) + Maj(a, b, c) h += S0(a) + Maj(a, b, c)
@ -73,7 +73,7 @@ void Sha256_Init(CSha256 *p)
#define h(i) T[(7-(i))&7] #define h(i) T[(7-(i))&7]
#define R(i) \ #define R(i) \
h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \ h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+(size_t)(j)] + (j ? blk2(i) : blk0(i)); \
d(i) += h(i); \ d(i) += h(i); \
h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) \ h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) \

View File

@ -1,5 +1,5 @@
/* Threads.c -- multithreading library /* Threads.c -- multithreading library
2014-09-21 : Igor Pavlov : Public domain */ 2017-06-26 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -12,18 +12,20 @@
static WRes GetError() static WRes GetError()
{ {
DWORD res = GetLastError(); DWORD res = GetLastError();
return (res) ? (WRes)(res) : 1; return res ? (WRes)res : 1;
} }
WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } static WRes HandleToWRes(HANDLE h) { return (h != NULL) ? 0 : GetError(); }
WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } static WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
WRes HandlePtr_Close(HANDLE *p) WRes HandlePtr_Close(HANDLE *p)
{ {
if (*p != NULL) if (*p != NULL)
{
if (!CloseHandle(*p)) if (!CloseHandle(*p))
return GetError(); return GetError();
*p = NULL; *p = NULL;
}
return 0; return 0;
} }
@ -49,7 +51,7 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
return HandleToWRes(*p); return HandleToWRes(*p);
} }
WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
{ {
*p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
return HandleToWRes(*p); return HandleToWRes(*p);

View File

@ -1,5 +1,5 @@
/* Threads.h -- multithreading library /* Threads.h -- multithreading library
2013-11-12 : Igor Pavlov : Public domain */ 2017-06-18 : Igor Pavlov : Public domain */
#ifndef __7Z_THREADS_H #ifndef __7Z_THREADS_H
#define __7Z_THREADS_H #define __7Z_THREADS_H
@ -49,7 +49,8 @@ WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
typedef HANDLE CSemaphore; typedef HANDLE CSemaphore;
#define Semaphore_Construct(p) (*p) = NULL #define Semaphore_Construct(p) *(p) = NULL
#define Semaphore_IsCreated(p) (*(p) != NULL)
#define Semaphore_Close(p) HandlePtr_Close(p) #define Semaphore_Close(p) HandlePtr_Close(p)
#define Semaphore_Wait(p) Handle_WaitObject(*(p)) #define Semaphore_Wait(p) Handle_WaitObject(*(p))
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);

View File

@ -1,11 +1,13 @@
/* 7zMain.c - Test application for 7z Decoder /* 7zMain.c - Test application for 7z Decoder
2015-08-02 : Igor Pavlov : Public domain */ 2019-02-02 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../../CpuArch.h"
#include "../../7z.h" #include "../../7z.h"
#include "../../7zAlloc.h" #include "../../7zAlloc.h"
#include "../../7zBuf.h" #include "../../7zBuf.h"
@ -23,7 +25,17 @@
#endif #endif
#endif #endif
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
#define kInputBufSize ((size_t)1 << 18)
static const ISzAlloc g_Alloc = { SzAlloc, SzFree };
static void Print(const char *s)
{
fputs(s, stdout);
}
static int Buf_EnsureSize(CBuf *dest, size_t size) static int Buf_EnsureSize(CBuf *dest, size_t size)
{ {
@ -164,7 +176,7 @@ static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s
char defaultChar = '_'; char defaultChar = '_';
BOOL defUsed; BOOL defUsed;
unsigned numChars = 0; unsigned numChars = 0;
numChars = WideCharToMultiByte(codePage, 0, s, len, (char *)buf->data, size, &defaultChar, &defUsed); numChars = WideCharToMultiByte(codePage, 0, (LPCWSTR)s, len, (char *)buf->data, size, &defaultChar, &defUsed);
if (numChars == 0 || numChars >= size) if (numChars == 0 || numChars >= size)
return SZ_ERROR_FAIL; return SZ_ERROR_FAIL;
buf->data[numChars] = 0; buf->data[numChars] = 0;
@ -190,7 +202,7 @@ static WRes MyCreateDir(const UInt16 *name)
{ {
#ifdef USE_WINDOWS_FILE #ifdef USE_WINDOWS_FILE
return CreateDirectoryW(name, NULL) ? 0 : GetLastError(); return CreateDirectoryW((LPCWSTR)name, NULL) ? 0 : GetLastError();
#else #else
@ -215,7 +227,7 @@ static WRes MyCreateDir(const UInt16 *name)
static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name) static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)
{ {
#ifdef USE_WINDOWS_FILE #ifdef USE_WINDOWS_FILE
return OutFile_OpenW(p, name); return OutFile_OpenW(p, (LPCWSTR)name);
#else #else
CBuf buf; CBuf buf;
WRes res; WRes res;
@ -227,6 +239,7 @@ static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)
#endif #endif
} }
static SRes PrintString(const UInt16 *s) static SRes PrintString(const UInt16 *s)
{ {
CBuf buf; CBuf buf;
@ -238,12 +251,12 @@ static SRes PrintString(const UInt16 *s)
#endif #endif
); );
if (res == SZ_OK) if (res == SZ_OK)
fputs((const char *)buf.data, stdout); Print((const char *)buf.data);
Buf_Free(&buf, &g_Alloc); Buf_Free(&buf, &g_Alloc);
return res; return res;
} }
static void UInt64ToStr(UInt64 value, char *s) static void UInt64ToStr(UInt64 value, char *s, int numDigits)
{ {
char temp[32]; char temp[32];
int pos = 0; int pos = 0;
@ -253,6 +266,10 @@ static void UInt64ToStr(UInt64 value, char *s)
value /= 10; value /= 10;
} }
while (value != 0); while (value != 0);
for (numDigits -= pos; numDigits > 0; numDigits--)
*s++ = ' ';
do do
*s++ = temp[--pos]; *s++ = temp[--pos];
while (pos); while (pos);
@ -266,8 +283,10 @@ static char *UIntToStr(char *s, unsigned value, int numDigits)
do do
temp[pos++] = (char)('0' + (value % 10)); temp[pos++] = (char)('0' + (value % 10));
while (value /= 10); while (value /= 10);
for (numDigits -= pos; numDigits > 0; numDigits--) for (numDigits -= pos; numDigits > 0; numDigits--)
*s++ = '0'; *s++ = '0';
do do
*s++ = temp[--pos]; *s++ = temp[--pos];
while (pos); while (pos);
@ -310,10 +329,10 @@ static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s)
ms[1] = 29; ms[1] = 29;
for (mon = 0;; mon++) for (mon = 0;; mon++)
{ {
unsigned s = ms[mon]; unsigned d = ms[mon];
if (v < s) if (v < d)
break; break;
v -= s; v -= d;
} }
s = UIntToStr(s, year, 4); *s++ = '-'; s = UIntToStr(s, year, 4); *s++ = '-';
UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3; UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3;
@ -323,12 +342,19 @@ static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s)
UIntToStr_2(s, sec); s[2] = 0; UIntToStr_2(s, sec); s[2] = 0;
} }
void PrintError(char *sz) static void PrintLF()
{ {
printf("\nERROR: %s\n", sz); Print("\n");
} }
static void GetAttribString(UInt32 wa, Bool isDir, char *s) static void PrintError(char *s)
{
Print("\nERROR: ");
Print(s);
PrintLF();
}
static void GetAttribString(UInt32 wa, BoolInt isDir, char *s)
{ {
#ifdef USE_WINDOWS_FILE #ifdef USE_WINDOWS_FILE
s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.'); s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');
@ -343,25 +369,27 @@ static void GetAttribString(UInt32 wa, Bool isDir, char *s)
#endif #endif
} }
// #define NUM_PARENTS_MAX 128 // #define NUM_PARENTS_MAX 128
int MY_CDECL main(int numargs, char *args[]) int MY_CDECL main(int numargs, char *args[])
{ {
CFileInStream archiveStream;
CLookToRead lookStream;
CSzArEx db;
SRes res;
ISzAlloc allocImp; ISzAlloc allocImp;
ISzAlloc allocTempImp; ISzAlloc allocTempImp;
CFileInStream archiveStream;
CLookToRead2 lookStream;
CSzArEx db;
SRes res;
UInt16 *temp = NULL; UInt16 *temp = NULL;
size_t tempSize = 0; size_t tempSize = 0;
// UInt32 parents[NUM_PARENTS_MAX]; // UInt32 parents[NUM_PARENTS_MAX];
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n"); Print("\n7z Decoder " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n");
if (numargs == 1) if (numargs == 1)
{ {
printf( Print(
"Usage: 7zDec <command> <archive_name>\n\n" "Usage: 7zDec <command> <archive_name>\n\n"
"<Commands>\n" "<Commands>\n"
" e: Extract files from archive (without using directory names)\n" " e: Extract files from archive (without using directory names)\n"
@ -381,11 +409,9 @@ int MY_CDECL main(int numargs, char *args[])
g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
#endif #endif
allocImp.Alloc = SzAlloc;
allocImp.Free = SzFree;
allocTempImp.Alloc = SzAllocTemp; allocImp = g_Alloc;
allocTempImp.Free = SzFreeTemp; allocTempImp = g_Alloc;
#ifdef UNDER_CE #ifdef UNDER_CE
if (InFile_OpenW(&archiveStream.file, L"\test.7z")) if (InFile_OpenW(&archiveStream.file, L"\test.7z"))
@ -398,16 +424,31 @@ int MY_CDECL main(int numargs, char *args[])
} }
FileInStream_CreateVTable(&archiveStream); FileInStream_CreateVTable(&archiveStream);
LookToRead_CreateVTable(&lookStream, False); LookToRead2_CreateVTable(&lookStream, False);
lookStream.buf = NULL;
lookStream.realStream = &archiveStream.s; res = SZ_OK;
LookToRead_Init(&lookStream);
{
lookStream.buf = (Byte *)ISzAlloc_Alloc(&allocImp, kInputBufSize);
if (!lookStream.buf)
res = SZ_ERROR_MEM;
else
{
lookStream.bufSize = kInputBufSize;
lookStream.realStream = &archiveStream.vt;
LookToRead2_Init(&lookStream);
}
}
CrcGenerateTable(); CrcGenerateTable();
SzArEx_Init(&db); SzArEx_Init(&db);
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if (res == SZ_OK)
{
res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp);
}
if (res == SZ_OK) if (res == SZ_OK)
{ {
@ -477,7 +518,7 @@ int MY_CDECL main(int numargs, char *args[])
GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr); GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr);
fileSize = SzArEx_GetFileSize(&db, i); fileSize = SzArEx_GetFileSize(&db, i);
UInt64ToStr(fileSize, s); UInt64ToStr(fileSize, s, 10);
if (SzBitWithVals_Check(&db.MTime, i)) if (SzBitWithVals_Check(&db.MTime, i))
ConvertFileTimeToString(&db.MTime.Vals[i], t); ConvertFileTimeToString(&db.MTime.Vals[i], t);
@ -489,29 +530,33 @@ int MY_CDECL main(int numargs, char *args[])
t[j] = '\0'; t[j] = '\0';
} }
printf("%s %s %10s ", t, attr, s); Print(t);
Print(" ");
Print(attr);
Print(" ");
Print(s);
Print(" ");
res = PrintString(temp); res = PrintString(temp);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (isDir) if (isDir)
printf("/"); Print("/");
printf("\n"); PrintLF();
continue; continue;
} }
fputs(testCommand ? Print(testCommand ?
"Testing ": "Testing ":
"Extracting ", "Extracting ");
stdout);
res = PrintString(temp); res = PrintString(temp);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (isDir) if (isDir)
printf("/"); Print("/");
else else
{ {
res = SzArEx_Extract(&db, &lookStream.s, i, res = SzArEx_Extract(&db, &lookStream.vt, i,
&blockIndex, &outBuffer, &outBufferSize, &blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed, &offset, &outSizeProcessed,
&allocImp, &allocTempImp); &allocImp, &allocTempImp);
@ -543,7 +588,7 @@ int MY_CDECL main(int numargs, char *args[])
if (isDir) if (isDir)
{ {
MyCreateDir(destPath); MyCreateDir(destPath);
printf("\n"); PrintLF();
continue; continue;
} }
else if (OutFile_OpenUtf16(&outFile, destPath)) else if (OutFile_OpenUtf16(&outFile, destPath))
@ -562,6 +607,31 @@ int MY_CDECL main(int numargs, char *args[])
break; break;
} }
#ifdef USE_WINDOWS_FILE
{
FILETIME mtime, ctime;
FILETIME *mtimePtr = NULL;
FILETIME *ctimePtr = NULL;
if (SzBitWithVals_Check(&db.MTime, i))
{
const CNtfsFileTime *t = &db.MTime.Vals[i];
mtime.dwLowDateTime = (DWORD)(t->Low);
mtime.dwHighDateTime = (DWORD)(t->High);
mtimePtr = &mtime;
}
if (SzBitWithVals_Check(&db.CTime, i))
{
const CNtfsFileTime *t = &db.CTime.Vals[i];
ctime.dwLowDateTime = (DWORD)(t->Low);
ctime.dwHighDateTime = (DWORD)(t->High);
ctimePtr = &ctime;
}
if (mtimePtr || ctimePtr)
SetFileTime(outFile.handle, ctimePtr, NULL, mtimePtr);
}
#endif
if (File_Close(&outFile)) if (File_Close(&outFile))
{ {
PrintError("can not close output file"); PrintError("can not close output file");
@ -571,23 +641,31 @@ int MY_CDECL main(int numargs, char *args[])
#ifdef USE_WINDOWS_FILE #ifdef USE_WINDOWS_FILE
if (SzBitWithVals_Check(&db.Attribs, i)) if (SzBitWithVals_Check(&db.Attribs, i))
SetFileAttributesW(destPath, db.Attribs.Vals[i]); {
UInt32 attrib = db.Attribs.Vals[i];
/* p7zip stores posix attributes in high 16 bits and adds 0x8000 as marker.
We remove posix bits, if we detect posix mode field */
if ((attrib & 0xF0000000) != 0)
attrib &= 0x7FFF;
SetFileAttributesW((LPCWSTR)destPath, attrib);
}
#endif #endif
} }
printf("\n"); PrintLF();
} }
IAlloc_Free(&allocImp, outBuffer); ISzAlloc_Free(&allocImp, outBuffer);
} }
} }
SzArEx_Free(&db, &allocImp);
SzFree(NULL, temp); SzFree(NULL, temp);
SzArEx_Free(&db, &allocImp);
ISzAlloc_Free(&allocImp, lookStream.buf);
File_Close(&archiveStream.file); File_Close(&archiveStream.file);
if (res == SZ_OK) if (res == SZ_OK)
{ {
printf("\nEverything is Ok\n"); Print("\nEverything is Ok\n");
return 0; return 0;
} }
@ -598,7 +676,11 @@ int MY_CDECL main(int numargs, char *args[])
else if (res == SZ_ERROR_CRC) else if (res == SZ_ERROR_CRC)
PrintError("CRC error"); PrintError("CRC error");
else else
printf("\nERROR #%d\n", res); {
char s[32];
UInt64ToStr(res, s, 0);
PrintError(s);
}
return 1; return 1;
} }

View File

@ -1,5 +1,5 @@
/* LzmaUtil.c -- Test application for LZMA compression /* LzmaUtil.c -- Test application for LZMA compression
2015-11-08 : Igor Pavlov : Public domain */ 2018-07-04 : Igor Pavlov : Public domain */
#include "../../Precomp.h" #include "../../Precomp.h"
@ -7,26 +7,29 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../../CpuArch.h"
#include "../../Alloc.h" #include "../../Alloc.h"
#include "../../7zFile.h" #include "../../7zFile.h"
#include "../../7zVersion.h" #include "../../7zVersion.h"
#include "../../LzmaDec.h" #include "../../LzmaDec.h"
#include "../../LzmaEnc.h" #include "../../LzmaEnc.h"
const char *kCantReadMessage = "Can not read input file"; static const char * const kCantReadMessage = "Can not read input file";
const char *kCantWriteMessage = "Can not write output file"; static const char * const kCantWriteMessage = "Can not write output file";
const char *kCantAllocateMessage = "Can not allocate memory"; static const char * const kCantAllocateMessage = "Can not allocate memory";
const char *kDataErrorMessage = "Data error"; static const char * const kDataErrorMessage = "Data error";
void PrintHelp(char *buffer) static void PrintHelp(char *buffer)
{ {
strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" strcat(buffer,
"\nUsage: lzma <e|d> inputFile outputFile\n" "\nLZMA-C " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
" e: encode file\n" "Usage: lzma <e|d> inputFile outputFile\n"
" d: decode file\n"); " e: encode file\n"
" d: decode file\n");
} }
int PrintError(char *buffer, const char *message) static int PrintError(char *buffer, const char *message)
{ {
strcat(buffer, "\nError: "); strcat(buffer, "\nError: ");
strcat(buffer, message); strcat(buffer, message);
@ -34,20 +37,22 @@ int PrintError(char *buffer, const char *message)
return 1; return 1;
} }
int PrintErrorNumber(char *buffer, SRes val) static int PrintErrorNumber(char *buffer, SRes val)
{ {
sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
return 1; return 1;
} }
int PrintUserError(char *buffer) static int PrintUserError(char *buffer)
{ {
return PrintError(buffer, "Incorrect command"); return PrintError(buffer, "Incorrect command");
} }
#define IN_BUF_SIZE (1 << 16) #define IN_BUF_SIZE (1 << 16)
#define OUT_BUF_SIZE (1 << 16) #define OUT_BUF_SIZE (1 << 16)
static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
UInt64 unpackSize) UInt64 unpackSize)
{ {
@ -101,6 +106,7 @@ static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inS
} }
} }
static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
{ {
UInt64 unpackSize; UInt64 unpackSize;
@ -163,14 +169,15 @@ static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 file
return res; return res;
} }
int main2(int numArgs, const char *args[], char *rs)
static int main2(int numArgs, const char *args[], char *rs)
{ {
CFileSeqInStream inStream; CFileSeqInStream inStream;
CFileOutStream outStream; CFileOutStream outStream;
char c; char c;
int res; int res;
int encodeMode; int encodeMode;
Bool useOutFile = False; BoolInt useOutFile = False;
FileSeqInStream_CreateVTable(&inStream); FileSeqInStream_CreateVTable(&inStream);
File_Construct(&inStream.file); File_Construct(&inStream.file);
@ -215,11 +222,11 @@ int main2(int numArgs, const char *args[], char *rs)
{ {
UInt64 fileSize; UInt64 fileSize;
File_GetLength(&inStream.file, &fileSize); File_GetLength(&inStream.file, &fileSize);
res = Encode(&outStream.s, &inStream.s, fileSize, rs); res = Encode(&outStream.vt, &inStream.vt, fileSize, rs);
} }
else else
{ {
res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL); res = Decode(&outStream.vt, useOutFile ? &inStream.vt : NULL);
} }
if (useOutFile) if (useOutFile)
@ -241,6 +248,7 @@ int main2(int numArgs, const char *args[], char *rs)
return 0; return 0;
} }
int MY_CDECL main(int numArgs, const char *args[]) int MY_CDECL main(int numArgs, const char *args[])
{ {
char rs[800] = { 0 }; char rs[800] = { 0 };

View File

@ -98,6 +98,10 @@ SOURCE=..\..\7zStream.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\7zTypes.h
# End Source File
# Begin Source File
SOURCE=..\..\7zVersion.h SOURCE=..\..\7zVersion.h
# End Source File # End Source File
# Begin Source File # Begin Source File
@ -160,9 +164,5 @@ SOURCE=..\..\Threads.c
SOURCE=..\..\Threads.h SOURCE=..\..\Threads.h
# End Source File # End Source File
# Begin Source File
SOURCE=..\..\Types.h
# End Source File
# End Target # End Target
# End Project # End Project

View File

@ -1,5 +1,5 @@
/* SfxSetup.c - 7z SFX Setup /* SfxSetup.c - 7z SFX Setup
2015-11-08 : Igor Pavlov : Public domain */ 2019-02-02 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -20,9 +20,12 @@
#include "../../7zCrc.h" #include "../../7zCrc.h"
#include "../../7zFile.h" #include "../../7zFile.h"
#include "../../CpuArch.h" #include "../../CpuArch.h"
#include "../../DllSecur.h"
#define k_EXE_ExtIndex 2 #define k_EXE_ExtIndex 2
#define kInputBufSize ((size_t)1 << 18)
static const char * const kExts[] = static const char * const kExts[] =
{ {
"bat" "bat"
@ -124,7 +127,7 @@ static WRes MyCreateDir(const WCHAR *name)
#define kSignatureSearchLimit (1 << 22) #define kSignatureSearchLimit (1 << 22)
static Bool FindSignature(CSzFile *stream, UInt64 *resPos) static BoolInt FindSignature(CSzFile *stream, UInt64 *resPos)
{ {
Byte buf[kBufferSize]; Byte buf[kBufferSize];
size_t numPrevBytes = 0; size_t numPrevBytes = 0;
@ -160,7 +163,7 @@ static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
} }
} }
static Bool DoesFileOrDirExist(const WCHAR *path) static BoolInt DoesFileOrDirExist(const WCHAR *path)
{ {
WIN32_FIND_DATAW fd; WIN32_FIND_DATAW fd;
HANDLE handle; HANDLE handle;
@ -237,7 +240,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
#endif #endif
{ {
CFileInStream archiveStream; CFileInStream archiveStream;
CLookToRead lookStream; CLookToRead2 lookStream;
CSzArEx db; CSzArEx db;
SRes res = SZ_OK; SRes res = SZ_OK;
ISzAlloc allocImp; ISzAlloc allocImp;
@ -251,9 +254,11 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
DWORD winRes; DWORD winRes;
const wchar_t *cmdLineParams; const wchar_t *cmdLineParams;
const char *errorMessage = NULL; const char *errorMessage = NULL;
Bool useShellExecute = True; BoolInt useShellExecute = True;
DWORD exitCode = 0; DWORD exitCode = 0;
LoadSecurityDlls();
#ifdef _CONSOLE #ifdef _CONSOLE
SetConsoleCtrlHandler(HandlerRoutine, TRUE); SetConsoleCtrlHandler(HandlerRoutine, TRUE);
#else #else
@ -272,7 +277,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
allocTempImp.Free = SzFreeTemp; allocTempImp.Free = SzFreeTemp;
FileInStream_CreateVTable(&archiveStream); FileInStream_CreateVTable(&archiveStream);
LookToRead_CreateVTable(&lookStream, False); LookToRead2_CreateVTable(&lookStream, False);
lookStream.buf = NULL;
winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH); winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH);
if (winRes == 0 || winRes > MAX_PATH) if (winRes == 0 || winRes > MAX_PATH)
@ -281,7 +287,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
cmdLineParams = GetCommandLineW(); cmdLineParams = GetCommandLineW();
#ifndef UNDER_CE #ifndef UNDER_CE
{ {
Bool quoteMode = False; BoolInt quoteMode = False;
for (;; cmdLineParams++) for (;; cmdLineParams++)
{ {
wchar_t c = *cmdLineParams; wchar_t c = *cmdLineParams;
@ -373,14 +379,22 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
if (res == SZ_OK) if (res == SZ_OK)
{ {
lookStream.realStream = &archiveStream.s; lookStream.buf = (Byte *)ISzAlloc_Alloc(&allocImp, kInputBufSize);
LookToRead_Init(&lookStream); if (!lookStream.buf)
res = SZ_ERROR_MEM;
else
{
lookStream.bufSize = kInputBufSize;
lookStream.realStream = &archiveStream.vt;
LookToRead2_Init(&lookStream);
}
} }
SzArEx_Init(&db); SzArEx_Init(&db);
if (res == SZ_OK) if (res == SZ_OK)
{ {
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp);
} }
if (res == SZ_OK) if (res == SZ_OK)
@ -396,11 +410,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
{ {
size_t offset = 0; size_t offset = 0;
size_t outSizeProcessed = 0; size_t outSizeProcessed = 0;
size_t len;
WCHAR *temp; WCHAR *temp;
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
if (len >= MAX_PATH) if (SzArEx_GetFileNameUtf16(&db, i, NULL) >= MAX_PATH)
{ {
res = SZ_ERROR_FAIL; res = SZ_ERROR_FAIL;
break; break;
@ -408,9 +420,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
temp = path + pathLen; temp = path + pathLen;
SzArEx_GetFileNameUtf16(&db, i, temp); SzArEx_GetFileNameUtf16(&db, i, (UInt16 *)temp);
{ {
res = SzArEx_Extract(&db, &lookStream.s, i, res = SzArEx_Extract(&db, &lookStream.vt, i,
&blockIndex, &outBuffer, &outBufferSize, &blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed, &offset, &outSizeProcessed,
&allocImp, &allocTempImp); &allocImp, &allocTempImp);
@ -515,16 +527,19 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
{ {
WCHAR *temp = path + pathLen; WCHAR *temp = path + pathLen;
UInt32 j; UInt32 j;
SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp); SzArEx_GetFileNameUtf16(&db, executeFileIndex, (UInt16 *)temp);
for (j = 0; temp[j] != 0; j++) for (j = 0; temp[j] != 0; j++)
if (temp[j] == '/') if (temp[j] == '/')
temp[j] = CHAR_PATH_SEPARATOR; temp[j] = CHAR_PATH_SEPARATOR;
} }
} }
IAlloc_Free(&allocImp, outBuffer); ISzAlloc_Free(&allocImp, outBuffer);
} }
SzArEx_Free(&db, &allocImp); SzArEx_Free(&db, &allocImp);
ISzAlloc_Free(&allocImp, lookStream.buf);
File_Close(&archiveStream.file); File_Close(&archiveStream.file);
if (res == SZ_OK) if (res == SZ_OK)

View File

@ -187,6 +187,14 @@ SOURCE=..\..\Delta.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\DllSecur.c
# End Source File
# Begin Source File
SOURCE=..\..\DllSecur.h
# End Source File
# Begin Source File
SOURCE=..\..\Lzma2Dec.c SOURCE=..\..\Lzma2Dec.c
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@ -1,4 +1,5 @@
PROG = 7zS2.sfx PROG = 7zS2.sfx
MY_FIXED = 1
C_OBJS = \ C_OBJS = \
$O\7zAlloc.obj \ $O\7zAlloc.obj \
@ -16,6 +17,7 @@ C_OBJS = \
$O\BraIA64.obj \ $O\BraIA64.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Delta.obj \ $O\Delta.obj \
$O\DllSecur.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \

View File

@ -1,4 +1,5 @@
PROG = 7zS2con.sfx PROG = 7zS2con.sfx
MY_FIXED = 1
CFLAGS = $(CFLAGS) -D_CONSOLE CFLAGS = $(CFLAGS) -D_CONSOLE
C_OBJS = \ C_OBJS = \
@ -17,6 +18,7 @@ C_OBJS = \
$O\BraIA64.obj \ $O\BraIA64.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Delta.obj \ $O\Delta.obj \
$O\DllSecur.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \

View File

@ -1,5 +1,5 @@
/* Xz.c - Xz /* Xz.c - Xz
2015-05-01 : Igor Pavlov : Public domain */ 2017-05-12 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -9,7 +9,7 @@
#include "XzCrc64.h" #include "XzCrc64.h"
const Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 }; const Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };
const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' }; /* const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' }; */
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v) unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)
{ {
@ -20,22 +20,22 @@ unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)
v >>= 7; v >>= 7;
} }
while (v != 0); while (v != 0);
buf[i - 1] &= 0x7F; buf[(size_t)i - 1] &= 0x7F;
return i; return i;
} }
void Xz_Construct(CXzStream *p) void Xz_Construct(CXzStream *p)
{ {
p->numBlocks = p->numBlocksAllocated = 0; p->numBlocks = 0;
p->blocks = 0; p->blocks = NULL;
p->flags = 0; p->flags = 0;
} }
void Xz_Free(CXzStream *p, ISzAlloc *alloc) void Xz_Free(CXzStream *p, ISzAllocPtr alloc)
{ {
alloc->Free(alloc, p->blocks); ISzAlloc_Free(alloc, p->blocks);
p->numBlocks = p->numBlocksAllocated = 0; p->numBlocks = 0;
p->blocks = 0; p->blocks = NULL;
} }
unsigned XzFlags_GetCheckSize(CXzStreamFlags f) unsigned XzFlags_GetCheckSize(CXzStreamFlags f)

View File

@ -1,5 +1,5 @@
/* Xz.h - Xz interface /* Xz.h - Xz interface
2015-05-01 : Igor Pavlov : Public domain */ 2018-07-04 : Igor Pavlov : Public domain */
#ifndef __XZ_H #ifndef __XZ_H
#define __XZ_H #define __XZ_H
@ -50,9 +50,10 @@ typedef struct
#define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1) #define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)
#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0) #define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0)
#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0) #define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)
#define XzBlock_HasUnsupportedFlags(p) (((p)->flags & ~(XZ_BF_NUM_FILTERS_MASK | XZ_BF_PACK_SIZE | XZ_BF_UNPACK_SIZE)) != 0)
SRes XzBlock_Parse(CXzBlock *p, const Byte *header); SRes XzBlock_Parse(CXzBlock *p, const Byte *header);
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes); SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, BoolInt *isIndex, UInt32 *headerSizeRes);
/* ---------- xz stream ---------- */ /* ---------- xz stream ---------- */
@ -60,7 +61,13 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt
#define XZ_FOOTER_SIG_SIZE 2 #define XZ_FOOTER_SIG_SIZE 2
extern const Byte XZ_SIG[XZ_SIG_SIZE]; extern const Byte XZ_SIG[XZ_SIG_SIZE];
/*
extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE]; extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
*/
#define XZ_FOOTER_SIG_0 'Y'
#define XZ_FOOTER_SIG_1 'Z'
#define XZ_STREAM_FLAGS_SIZE 2 #define XZ_STREAM_FLAGS_SIZE 2
#define XZ_STREAM_CRC_SIZE 4 #define XZ_STREAM_CRC_SIZE 4
@ -106,13 +113,12 @@ typedef struct
{ {
CXzStreamFlags flags; CXzStreamFlags flags;
size_t numBlocks; size_t numBlocks;
size_t numBlocksAllocated;
CXzBlockSizes *blocks; CXzBlockSizes *blocks;
UInt64 startOffset; UInt64 startOffset;
} CXzStream; } CXzStream;
void Xz_Construct(CXzStream *p); void Xz_Construct(CXzStream *p);
void Xz_Free(CXzStream *p, ISzAlloc *alloc); void Xz_Free(CXzStream *p, ISzAllocPtr alloc);
#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1) #define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)
@ -127,12 +133,15 @@ typedef struct
} CXzs; } CXzs;
void Xzs_Construct(CXzs *p); void Xzs_Construct(CXzs *p);
void Xzs_Free(CXzs *p, ISzAlloc *alloc); void Xzs_Free(CXzs *p, ISzAllocPtr alloc);
SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc); SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAllocPtr alloc);
UInt64 Xzs_GetNumBlocks(const CXzs *p); UInt64 Xzs_GetNumBlocks(const CXzs *p);
UInt64 Xzs_GetUnpackSize(const CXzs *p); UInt64 Xzs_GetUnpackSize(const CXzs *p);
// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
typedef enum typedef enum
{ {
CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */ CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */
@ -141,43 +150,55 @@ typedef enum
CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */ CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */
} ECoderStatus; } ECoderStatus;
// ECoderFinishMode values are identical to ELzmaFinishMode
typedef enum typedef enum
{ {
CODER_FINISH_ANY, /* finish at any point */ CODER_FINISH_ANY, /* finish at any point */
CODER_FINISH_END /* block must be finished at the end */ CODER_FINISH_END /* block must be finished at the end */
} ECoderFinishMode; } ECoderFinishMode;
typedef struct _IStateCoder typedef struct _IStateCoder
{ {
void *p; void *p;
void (*Free)(void *p, ISzAlloc *alloc); void (*Free)(void *p, ISzAllocPtr alloc);
SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc); SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAllocPtr alloc);
void (*Init)(void *p); void (*Init)(void *p);
SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, SRes (*Code2)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished); int srcWasFinished, ECoderFinishMode finishMode,
// int *wasFinished,
ECoderStatus *status);
SizeT (*Filter)(void *p, Byte *data, SizeT size);
} IStateCoder; } IStateCoder;
#define MIXCODER_NUM_FILTERS_MAX 4 #define MIXCODER_NUM_FILTERS_MAX 4
typedef struct typedef struct
{ {
ISzAlloc *alloc; ISzAllocPtr alloc;
Byte *buf; Byte *buf;
unsigned numCoders; unsigned numCoders;
Byte *outBuf;
size_t outBufSize;
size_t outWritten; // is equal to lzmaDecoder.dicPos (in outBuf mode)
BoolInt wasFinished;
SRes res;
ECoderStatus status;
// BoolInt SingleBufMode;
int finished[MIXCODER_NUM_FILTERS_MAX - 1]; int finished[MIXCODER_NUM_FILTERS_MAX - 1];
size_t pos[MIXCODER_NUM_FILTERS_MAX - 1]; size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];
size_t size[MIXCODER_NUM_FILTERS_MAX - 1]; size_t size[MIXCODER_NUM_FILTERS_MAX - 1];
UInt64 ids[MIXCODER_NUM_FILTERS_MAX]; UInt64 ids[MIXCODER_NUM_FILTERS_MAX];
SRes results[MIXCODER_NUM_FILTERS_MAX];
IStateCoder coders[MIXCODER_NUM_FILTERS_MAX]; IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];
} CMixCoder; } CMixCoder;
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);
void MixCoder_Free(CMixCoder *p);
void MixCoder_Init(CMixCoder *p);
SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId);
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int srcWasFinished,
ECoderFinishMode finishMode, ECoderStatus *status);
typedef enum typedef enum
{ {
@ -191,6 +212,7 @@ typedef enum
XZ_STATE_BLOCK_FOOTER XZ_STATE_BLOCK_FOOTER
} EXzState; } EXzState;
typedef struct typedef struct
{ {
EXzState state; EXzState state;
@ -204,7 +226,7 @@ typedef struct
UInt64 packSize; UInt64 packSize;
UInt64 unpackSize; UInt64 unpackSize;
UInt64 numBlocks; UInt64 numBlocks; // number of finished blocks in current stream
UInt64 indexSize; UInt64 indexSize;
UInt64 indexPos; UInt64 indexPos;
UInt64 padSize; UInt64 padSize;
@ -218,14 +240,65 @@ typedef struct
CXzBlock block; CXzBlock block;
CXzCheck check; CXzCheck check;
CSha256 sha; CSha256 sha;
BoolInt parseMode;
BoolInt headerParsedOk;
BoolInt decodeToStreamSignature;
unsigned decodeOnlyOneBlock;
Byte *outBuf;
size_t outBufSize;
size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked
Byte shaDigest[SHA256_DIGEST_SIZE]; Byte shaDigest[SHA256_DIGEST_SIZE];
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
} CXzUnpacker; } CXzUnpacker;
void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc); /* alloc : aligned for cache line allocation is better */
void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc);
void XzUnpacker_Init(CXzUnpacker *p); void XzUnpacker_Init(CXzUnpacker *p);
void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize);
void XzUnpacker_Free(CXzUnpacker *p); void XzUnpacker_Free(CXzUnpacker *p);
/*
XzUnpacker
The sequence for decoding functions:
{
XzUnpacker_Construct()
[Decoding_Calls]
XzUnpacker_Free()
}
[Decoding_Calls]
There are 3 types of interfaces for [Decoding_Calls] calls:
Interface-1 : Partial output buffers:
{
XzUnpacker_Init()
for()
XzUnpacker_Code();
}
Interface-2 : Direct output buffer:
Use it, if you know exact size of decoded data, and you need
whole xz unpacked data in one output buffer.
xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode.
{
XzUnpacker_Init()
XzUnpacker_SetOutBufMode(); // to set output buffer and size
for()
XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code()
}
Interface-3 : Direct output buffer : One call full decoding
It unpacks whole input buffer to output buffer in one call.
It uses Interface-2 internally.
{
XzUnpacker_CodeFull()
}
*/
/* /*
finishMode: finishMode:
It has meaning only if the decoding reaches output limit (*destLen). It has meaning only if the decoding reaches output limit (*destLen).
@ -255,20 +328,132 @@ Returns:
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, const Byte *src, SizeT *srcLen, int srcFinished,
ECoderStatus *status); ECoderFinishMode finishMode, ECoderStatus *status);
Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p); SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen,
ECoderFinishMode finishMode, ECoderStatus *status);
BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p);
/* /*
Call XzUnpacker_GetExtraSize after XzUnpacker_Code function to detect real size of XzUnpacker_GetExtraSize() returns then number of uncofirmed bytes,
xz stream in two cases: if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state.
XzUnpacker_Code() returns: These bytes can be some bytes after xz archive, or
it can be start of new xz stream.
Call XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of
xz stream in two cases, if XzUnpacker_Code() returns:
res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT
res == SZ_ERROR_NO_ARCHIVE res == SZ_ERROR_NO_ARCHIVE
*/ */
UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p); UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p);
/*
for random block decoding:
XzUnpacker_Init();
set CXzUnpacker::streamFlags
XzUnpacker_PrepareToRandomBlockDecoding()
loop
{
XzUnpacker_Code()
XzUnpacker_IsBlockFinished()
}
*/
void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p);
BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p);
#define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags))
/* ---------- Multi Threading Decoding ---------- */
typedef struct
{
size_t inBufSize_ST;
size_t outStep_ST;
BoolInt ignoreErrors;
#ifndef _7ZIP_ST
unsigned numThreads;
size_t inBufSize_MT;
size_t memUseMax;
#endif
} CXzDecMtProps;
void XzDecMtProps_Init(CXzDecMtProps *p);
typedef void * CXzDecMtHandle;
/*
alloc : XzDecMt uses CAlignOffsetAlloc for addresses allocated by (alloc).
allocMid : for big allocations, aligned allocation is better
*/
CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);
void XzDecMt_Destroy(CXzDecMtHandle p);
typedef struct
{
Byte UnpackSize_Defined;
Byte NumStreams_Defined;
Byte NumBlocks_Defined;
Byte DataAfterEnd;
Byte DecodingTruncated; // Decoding was Truncated, we need only partial output data
UInt64 InSize; // pack size processed
UInt64 OutSize;
UInt64 NumStreams;
UInt64 NumBlocks;
SRes DecodeRes;
SRes ReadRes;
SRes ProgressRes;
SRes CombinedRes;
SRes CombinedRes_Type;
} CXzStatInfo;
void XzStatInfo_Clear(CXzStatInfo *p);
/*
XzDecMt_Decode()
SRes:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_NO_ARCHIVE - is not xz archive
SZ_ERROR_ARCHIVE - Headers error
SZ_ERROR_DATA - Data Error
SZ_ERROR_CRC - CRC Error
SZ_ERROR_INPUT_EOF - it needs more input data
SZ_ERROR_WRITE - ISeqOutStream error
(SZ_ERROR_READ) - ISeqInStream errors
(SZ_ERROR_PROGRESS) - ICompressProgress errors
// SZ_ERROR_THREAD - error in multi-threading functions
MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function
*/
SRes XzDecMt_Decode(CXzDecMtHandle p,
const CXzDecMtProps *props,
const UInt64 *outDataSize, // NULL means undefined
int finishMode, // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished
ISeqOutStream *outStream,
// Byte *outBuf, size_t *outBufSize,
ISeqInStream *inStream,
// const Byte *inData, size_t inDataSize,
CXzStatInfo *stat,
int *isMT, // 0 means that ST (Single-Thread) version was used
ICompressProgress *progress);
EXTERN_C_END EXTERN_C_END

View File

@ -1,5 +1,5 @@
/* XzCrc64.c -- CRC64 calculation /* XzCrc64.c -- CRC64 calculation
2015-03-01 : Igor Pavlov : Public domain */ 2017-05-23 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -9,9 +9,9 @@
#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) #define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)
#ifdef MY_CPU_LE #ifdef MY_CPU_LE
#define CRC_NUM_TABLES 4 #define CRC64_NUM_TABLES 4
#else #else
#define CRC_NUM_TABLES 5 #define CRC64_NUM_TABLES 5
#define CRC_UINT64_SWAP(v) \ #define CRC_UINT64_SWAP(v) \
((v >> 56) \ ((v >> 56) \
| ((v >> 40) & ((UInt64)0xFF << 8)) \ | ((v >> 40) & ((UInt64)0xFF << 8)) \
@ -29,10 +29,10 @@
UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table);
#endif #endif
typedef UInt64 (MY_FAST_CALL *CRC_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table); typedef UInt64 (MY_FAST_CALL *CRC64_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table);
static CRC_FUNC g_Crc64Update; static CRC64_FUNC g_Crc64Update;
UInt64 g_Crc64Table[256 * CRC_NUM_TABLES]; UInt64 g_Crc64Table[256 * CRC64_NUM_TABLES];
UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size) UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size)
{ {
@ -52,12 +52,12 @@ void MY_FAST_CALL Crc64GenerateTable()
UInt64 r = i; UInt64 r = i;
unsigned j; unsigned j;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrc64Poly & ~((r & 1) - 1)); r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1)));
g_Crc64Table[i] = r; g_Crc64Table[i] = r;
} }
for (; i < 256 * CRC_NUM_TABLES; i++) for (i = 256; i < 256 * CRC64_NUM_TABLES; i++)
{ {
UInt64 r = g_Crc64Table[i - 256]; UInt64 r = g_Crc64Table[(size_t)i - 256];
g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8); g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8);
} }
@ -74,9 +74,9 @@ void MY_FAST_CALL Crc64GenerateTable()
else else
#endif #endif
{ {
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) for (i = 256 * CRC64_NUM_TABLES - 1; i >= 256; i--)
{ {
UInt64 x = g_Crc64Table[i - 256]; UInt64 x = g_Crc64Table[(size_t)i - 256];
g_Crc64Table[i] = CRC_UINT64_SWAP(x); g_Crc64Table[i] = CRC_UINT64_SWAP(x);
} }
g_Crc64Update = XzCrc64UpdateT1_BeT4; g_Crc64Update = XzCrc64UpdateT1_BeT4;

View File

@ -1,5 +1,5 @@
/* XzCrc64Opt.c -- CRC64 calculation /* XzCrc64Opt.c -- CRC64 calculation
2015-03-01 : Igor Pavlov : Public domain */ 2017-06-30 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -7,24 +7,24 @@
#ifndef MY_CPU_BE #ifndef MY_CPU_BE
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table) UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC64_UPDATE_BYTE_2(v, *p);
for (; size >= 4; size -= 4, p += 4) for (; size >= 4; size -= 4, p += 4)
{ {
UInt32 d = (UInt32)v ^ *(const UInt32 *)p; UInt32 d = (UInt32)v ^ *(const UInt32 *)p;
v = (v >> 32) v = (v >> 32)
^ table[0x300 + ((d ) & 0xFF)] ^ (table + 0x300)[((d ) & 0xFF)]
^ table[0x200 + ((d >> 8) & 0xFF)] ^ (table + 0x200)[((d >> 8) & 0xFF)]
^ table[0x100 + ((d >> 16) & 0xFF)] ^ (table + 0x100)[((d >> 16) & 0xFF)]
^ table[0x000 + ((d >> 24))]; ^ (table + 0x000)[((d >> 24))];
} }
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC64_UPDATE_BYTE_2(v, *p);
return v; return v;
} }
@ -43,7 +43,7 @@ UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, con
| ((v << 40) & ((UInt64)0xFF << 48)) \ | ((v << 40) & ((UInt64)0xFF << 48)) \
| ((v << 56))) | ((v << 56)))
#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8)) #define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8))
UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table) UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table)
{ {
@ -51,18 +51,18 @@ UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size
table += 0x100; table += 0x100;
v = CRC_UINT64_SWAP(v); v = CRC_UINT64_SWAP(v);
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p); v = CRC64_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 4; size -= 4, p += 4) for (; size >= 4; size -= 4, p += 4)
{ {
UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)p; UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)p;
v = (v << 32) v = (v << 32)
^ table[0x000 + ((d ) & 0xFF)] ^ (table + 0x000)[((d ) & 0xFF)]
^ table[0x100 + ((d >> 8) & 0xFF)] ^ (table + 0x100)[((d >> 8) & 0xFF)]
^ table[0x200 + ((d >> 16) & 0xFF)] ^ (table + 0x200)[((d >> 16) & 0xFF)]
^ table[0x300 + ((d >> 24))]; ^ (table + 0x300)[((d >> 24))];
} }
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p); v = CRC64_UPDATE_BYTE_2_BE(v, *p);
return CRC_UINT64_SWAP(v); return CRC_UINT64_SWAP(v);
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* XzEnc.h -- Xz Encode /* XzEnc.h -- Xz Encode
2011-02-07 : Igor Pavlov : Public domain */ 2017-06-27 : Igor Pavlov : Public domain */
#ifndef __XZ_ENC_H #ifndef __XZ_ENC_H
#define __XZ_ENC_H #define __XZ_ENC_H
@ -10,6 +10,11 @@
EXTERN_C_BEGIN EXTERN_C_BEGIN
#define XZ_PROPS__BLOCK_SIZE__AUTO LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO
#define XZ_PROPS__BLOCK_SIZE__SOLID LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID
typedef struct typedef struct
{ {
UInt32 id; UInt32 id;
@ -20,15 +25,31 @@ typedef struct
void XzFilterProps_Init(CXzFilterProps *p); void XzFilterProps_Init(CXzFilterProps *p);
typedef struct typedef struct
{ {
const CLzma2EncProps *lzma2Props; CLzma2EncProps lzma2Props;
const CXzFilterProps *filterProps; CXzFilterProps filterProps;
unsigned checkId; unsigned checkId;
UInt64 blockSize;
int numBlockThreads_Reduced;
int numBlockThreads_Max;
int numTotalThreads;
int forceWriteSizesInHeader;
UInt64 reduceSize;
} CXzProps; } CXzProps;
void XzProps_Init(CXzProps *p); void XzProps_Init(CXzProps *p);
typedef void * CXzEncHandle;
CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);
void XzEnc_Destroy(CXzEncHandle p);
SRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props);
void XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize);
SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
const CXzProps *props, ICompressProgress *progress); const CXzProps *props, ICompressProgress *progress);

View File

@ -1,5 +1,5 @@
/* XzIn.c - Xz input /* XzIn.c - Xz input
2015-11-08 : Igor Pavlov : Public domain */ 2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -9,6 +9,12 @@
#include "CpuArch.h" #include "CpuArch.h"
#include "Xz.h" #include "Xz.h"
/*
#define XZ_FOOTER_SIG_CHECK(p) (memcmp((p), XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0)
*/
#define XZ_FOOTER_SIG_CHECK(p) ((p)[0] == XZ_FOOTER_SIG_0 && (p)[1] == XZ_FOOTER_SIG_1)
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream) SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream)
{ {
Byte sig[XZ_STREAM_HEADER_SIZE]; Byte sig[XZ_STREAM_HEADER_SIZE];
@ -22,13 +28,13 @@ SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream)
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; } if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes) SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, BoolInt *isIndex, UInt32 *headerSizeRes)
{ {
Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
unsigned headerSize; unsigned headerSize;
*headerSizeRes = 0; *headerSizeRes = 0;
RINOK(SeqInStream_ReadByte(inStream, &header[0])); RINOK(SeqInStream_ReadByte(inStream, &header[0]));
headerSize = ((unsigned)header[0] << 2) + 4; headerSize = (unsigned)header[0];
if (headerSize == 0) if (headerSize == 0)
{ {
*headerSizeRes = 1; *headerSizeRes = 1;
@ -37,12 +43,13 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt
} }
*isIndex = False; *isIndex = False;
headerSize = (headerSize << 2) + 4;
*headerSizeRes = headerSize; *headerSizeRes = headerSize;
RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1)); RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1));
return XzBlock_Parse(p, header); return XzBlock_Parse(p, header);
} }
#define ADD_SIZE_CHECH(size, val) \ #define ADD_SIZE_CHECK(size, val) \
{ UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; } { UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; }
UInt64 Xz_GetUnpackSize(const CXzStream *p) UInt64 Xz_GetUnpackSize(const CXzStream *p)
@ -50,7 +57,7 @@ UInt64 Xz_GetUnpackSize(const CXzStream *p)
UInt64 size = 0; UInt64 size = 0;
size_t i; size_t i;
for (i = 0; i < p->numBlocks; i++) for (i = 0; i < p->numBlocks; i++)
ADD_SIZE_CHECH(size, p->blocks[i].unpackSize); ADD_SIZE_CHECK(size, p->blocks[i].unpackSize);
return size; return size;
} }
@ -59,7 +66,7 @@ UInt64 Xz_GetPackSize(const CXzStream *p)
UInt64 size = 0; UInt64 size = 0;
size_t i; size_t i;
for (i = 0; i < p->numBlocks; i++) for (i = 0; i < p->numBlocks; i++)
ADD_SIZE_CHECH(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3); ADD_SIZE_CHECK(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3);
return size; return size;
} }
@ -70,7 +77,7 @@ SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream)
} }
*/ */
static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc) static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc)
{ {
size_t numBlocks, pos = 1; size_t numBlocks, pos = 1;
UInt32 crc; UInt32 crc;
@ -96,9 +103,8 @@ static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *
{ {
size_t i; size_t i;
p->numBlocks = numBlocks; p->numBlocks = numBlocks;
p->numBlocksAllocated = numBlocks; p->blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); if (!p->blocks)
if (p->blocks == 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
for (i = 0; i < numBlocks; i++) for (i = 0; i < numBlocks; i++)
{ {
@ -115,7 +121,7 @@ static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *
return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
} }
static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAlloc *alloc) static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAllocPtr alloc)
{ {
SRes res; SRes res;
size_t size; size_t size;
@ -125,13 +131,13 @@ static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize,
size = (size_t)indexSize; size = (size_t)indexSize;
if (size != indexSize) if (size != indexSize)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
buf = alloc->Alloc(alloc, size); buf = (Byte *)ISzAlloc_Alloc(alloc, size);
if (buf == 0) if (!buf)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);
if (res == SZ_OK) if (res == SZ_OK)
res = Xz_ReadIndex2(p, buf, size, alloc); res = Xz_ReadIndex2(p, buf, size, alloc);
alloc->Free(alloc, buf); ISzAlloc_Free(alloc, buf);
return res; return res;
} }
@ -142,7 +148,7 @@ static SRes LookInStream_SeekRead_ForArc(ILookInStream *stream, UInt64 offset, v
/* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */ /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */
} }
static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc) static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAllocPtr alloc)
{ {
UInt64 indexSize; UInt64 indexSize;
Byte buf[XZ_STREAM_FOOTER_SIZE]; Byte buf[XZ_STREAM_FOOTER_SIZE];
@ -154,7 +160,7 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
pos -= XZ_STREAM_FOOTER_SIZE; pos -= XZ_STREAM_FOOTER_SIZE;
RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)); RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE));
if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) if (!XZ_FOOTER_SIG_CHECK(buf + 10))
{ {
UInt32 total = 0; UInt32 total = 0;
pos += XZ_STREAM_FOOTER_SIZE; pos += XZ_STREAM_FOOTER_SIZE;
@ -187,7 +193,7 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
return SZ_ERROR_NO_ARCHIVE; return SZ_ERROR_NO_ARCHIVE;
pos -= XZ_STREAM_FOOTER_SIZE; pos -= XZ_STREAM_FOOTER_SIZE;
RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)); RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE));
if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) if (!XZ_FOOTER_SIG_CHECK(buf + 10))
return SZ_ERROR_NO_ARCHIVE; return SZ_ERROR_NO_ARCHIVE;
} }
@ -224,7 +230,7 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
SecToRead_CreateVTable(&secToRead); SecToRead_CreateVTable(&secToRead);
secToRead.realStream = stream; secToRead.realStream = stream;
RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s)); RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt));
return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE;
} }
} }
@ -238,12 +244,12 @@ void Xzs_Construct(CXzs *p)
p->streams = 0; p->streams = 0;
} }
void Xzs_Free(CXzs *p, ISzAlloc *alloc) void Xzs_Free(CXzs *p, ISzAllocPtr alloc)
{ {
size_t i; size_t i;
for (i = 0; i < p->num; i++) for (i = 0; i < p->num; i++)
Xz_Free(&p->streams[i], alloc); Xz_Free(&p->streams[i], alloc);
alloc->Free(alloc, p->streams); ISzAlloc_Free(alloc, p->streams);
p->num = p->numAllocated = 0; p->num = p->numAllocated = 0;
p->streams = 0; p->streams = 0;
} }
@ -262,7 +268,7 @@ UInt64 Xzs_GetUnpackSize(const CXzs *p)
UInt64 size = 0; UInt64 size = 0;
size_t i; size_t i;
for (i = 0; i < p->num; i++) for (i = 0; i < p->num; i++)
ADD_SIZE_CHECH(size, Xz_GetUnpackSize(&p->streams[i])); ADD_SIZE_CHECK(size, Xz_GetUnpackSize(&p->streams[i]));
return size; return size;
} }
@ -272,15 +278,15 @@ UInt64 Xzs_GetPackSize(const CXzs *p)
UInt64 size = 0; UInt64 size = 0;
size_t i; size_t i;
for (i = 0; i < p->num; i++) for (i = 0; i < p->num; i++)
ADD_SIZE_CHECH(size, Xz_GetTotalSize(&p->streams[i])); ADD_SIZE_CHECK(size, Xz_GetTotalSize(&p->streams[i]));
return size; return size;
} }
*/ */
SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc) SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAllocPtr alloc)
{ {
Int64 endOffset = 0; Int64 endOffset = 0;
RINOK(stream->Seek(stream, &endOffset, SZ_SEEK_END)); RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END));
*startOffset = endOffset; *startOffset = endOffset;
for (;;) for (;;)
{ {
@ -293,20 +299,20 @@ SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompr
if (p->num == p->numAllocated) if (p->num == p->numAllocated)
{ {
size_t newNum = p->num + p->num / 4 + 1; size_t newNum = p->num + p->num / 4 + 1;
Byte *data = (Byte *)alloc->Alloc(alloc, newNum * sizeof(CXzStream)); Byte *data = (Byte *)ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream));
if (data == 0) if (!data)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
p->numAllocated = newNum; p->numAllocated = newNum;
if (p->num != 0) if (p->num != 0)
memcpy(data, p->streams, p->num * sizeof(CXzStream)); memcpy(data, p->streams, p->num * sizeof(CXzStream));
alloc->Free(alloc, p->streams); ISzAlloc_Free(alloc, p->streams);
p->streams = (CXzStream *)data; p->streams = (CXzStream *)data;
} }
p->streams[p->num++] = st; p->streams[p->num++] = st;
if (*startOffset == 0) if (*startOffset == 0)
break; break;
RINOK(LookInStream_SeekTo(stream, *startOffset)); RINOK(LookInStream_SeekTo(stream, *startOffset));
if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK) if (progress && ICompressProgress_Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)
return SZ_ERROR_PROGRESS; return SZ_ERROR_PROGRESS;
} }
return SZ_OK; return SZ_OK;

View File

@ -16,6 +16,8 @@
#include "third-party/lzma/7zFile.h" #include "third-party/lzma/7zFile.h"
#include "third-party/lzma/7zVersion.h" #include "third-party/lzma/7zVersion.h"
#define BUFFER_SIZE 0x2000
struct VDirEntry7z { struct VDirEntry7z {
struct VDirEntry d; struct VDirEntry d;
@ -30,7 +32,7 @@ struct VDir7z {
// What is all this garbage? // What is all this garbage?
CFileInStream archiveStream; CFileInStream archiveStream;
CLookToRead lookStream; CLookToRead2 lookStream;
CSzArEx db; CSzArEx db;
ISzAlloc allocImp; ISzAlloc allocImp;
ISzAlloc allocTempImp; ISzAlloc allocTempImp;
@ -88,15 +90,18 @@ struct VDir* VDirOpen7z(const char* path, int flags) {
vd->allocTempImp.Free = SzFreeTemp; vd->allocTempImp.Free = SzFreeTemp;
FileInStream_CreateVTable(&vd->archiveStream); FileInStream_CreateVTable(&vd->archiveStream);
LookToRead_CreateVTable(&vd->lookStream, False); LookToRead2_CreateVTable(&vd->lookStream, False);
vd->lookStream.realStream = &vd->archiveStream.s; vd->lookStream.realStream = &vd->archiveStream.vt;
LookToRead_Init(&vd->lookStream); vd->lookStream.buf = malloc(BUFFER_SIZE);
vd->lookStream.bufSize = BUFFER_SIZE;
LookToRead2_Init(&vd->lookStream);
CrcGenerateTable(); CrcGenerateTable();
SzArEx_Init(&vd->db); SzArEx_Init(&vd->db);
SRes res = SzArEx_Open(&vd->db, &vd->lookStream.s, &vd->allocImp, &vd->allocTempImp); SRes res = SzArEx_Open(&vd->db, &vd->lookStream.vt, &vd->allocImp, &vd->allocTempImp);
if (res != SZ_OK) { if (res != SZ_OK) {
SzArEx_Free(&vd->db, &vd->allocImp); SzArEx_Free(&vd->db, &vd->allocImp);
File_Close(&vd->archiveStream.file); File_Close(&vd->archiveStream.file);
@ -211,6 +216,7 @@ bool _vd7zClose(struct VDir* vd) {
SzArEx_Free(&vd7z->db, &vd7z->allocImp); SzArEx_Free(&vd7z->db, &vd7z->allocImp);
File_Close(&vd7z->archiveStream.file); File_Close(&vd7z->archiveStream.file);
free(vd7z->lookStream.buf);
free(vd7z->dirent.utf8); free(vd7z->dirent.utf8);
vd7z->dirent.utf8 = 0; vd7z->dirent.utf8 = 0;
@ -281,7 +287,7 @@ struct VFile* _vd7zOpenFile(struct VDir* vd, const char* path, int mode) {
UInt32 blockIndex; UInt32 blockIndex;
vf->outBuffer = 0; vf->outBuffer = 0;
SRes res = SzArEx_Extract(&vd7z->db, &vd7z->lookStream.s, i, &blockIndex, SRes res = SzArEx_Extract(&vd7z->db, &vd7z->lookStream.vt, i, &blockIndex,
&vf->outBuffer, &outBufferSize, &vf->outBuffer, &outBufferSize,
&vf->bufferOffset, &vf->size, &vf->bufferOffset, &vf->size,
&vd7z->allocImp, &vd7z->allocTempImp); &vd7z->allocImp, &vd7z->allocTempImp);