Compare commits

...

12 Commits
9.35 ... 15.14

Author SHA1 Message Date
Igor Pavlov
c20d013055 15.14 2016-05-28 00:16:58 +01:00
Igor Pavlov
9608215ad8 15.13 2016-05-28 00:16:58 +01:00
Igor Pavlov
5de23c1deb 15.12 2016-05-28 00:16:58 +01:00
Igor Pavlov
e24f7fba53 15.11 2016-05-28 00:16:57 +01:00
Igor Pavlov
7c8a265a15 15.10 2016-05-28 00:16:57 +01:00
Igor Pavlov
a663a6deb7 15.09 2016-05-28 00:16:56 +01:00
Igor Pavlov
6543c28020 15.08 2016-05-28 00:16:56 +01:00
Igor Pavlov
f6444c3256 15.07 2016-05-28 00:16:55 +01:00
Igor Pavlov
cba375916f 15.06 2016-05-28 00:16:55 +01:00
Igor Pavlov
54490d51d5 15.05 2016-05-28 00:16:54 +01:00
Igor Pavlov
0713a3ab80 9.38 2016-05-28 00:16:53 +01:00
Igor Pavlov
7e021179cd 9.36 2016-05-28 00:16:53 +01:00
767 changed files with 58130 additions and 23288 deletions

98
C/7z.h
View File

@@ -1,5 +1,5 @@
/* 7z.h -- 7z interface /* 7z.h -- 7z interface
2013-01-18 : Igor Pavlov : Public domain */ 2015-11-18 : Igor Pavlov : Public domain */
#ifndef __7Z_H #ifndef __7Z_H
#define __7Z_H #define __7Z_H
@@ -11,7 +11,7 @@ EXTERN_C_BEGIN
#define k7zStartHeaderSize 0x20 #define k7zStartHeaderSize 0x20
#define k7zSignatureSize 6 #define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize]; extern const Byte k7zSignature[k7zSignatureSize];
typedef struct typedef struct
{ {
@@ -25,8 +25,7 @@ typedef struct
{ {
size_t PropsOffset; size_t PropsOffset;
UInt32 MethodID; UInt32 MethodID;
Byte NumInStreams; Byte NumStreams;
Byte NumOutStreams;
Byte PropsSize; Byte PropsSize;
} CSzCoderInfo; } CSzCoderInfo;
@@ -34,37 +33,25 @@ typedef struct
{ {
UInt32 InIndex; UInt32 InIndex;
UInt32 OutIndex; UInt32 OutIndex;
} CSzBindPair; } CSzBond;
#define SZ_NUM_CODERS_IN_FOLDER_MAX 4 #define SZ_NUM_CODERS_IN_FOLDER_MAX 4
#define SZ_NUM_BINDS_IN_FOLDER_MAX 3 #define SZ_NUM_BONDS_IN_FOLDER_MAX 3
#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4 #define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4
#define SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX 4
typedef struct typedef struct
{ {
UInt32 NumCoders; UInt32 NumCoders;
UInt32 NumBindPairs; UInt32 NumBonds;
UInt32 NumPackStreams; UInt32 NumPackStreams;
UInt32 MainOutStream; UInt32 UnpackStream;
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
CSzBindPair BindPairs[SZ_NUM_BINDS_IN_FOLDER_MAX]; CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
UInt64 CodersUnpackSizes[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX];
} CSzFolder; } CSzFolder;
/*
typedef struct
{
size_t CodersDataOffset;
size_t UnpackSizeDataOffset;
// UInt32 StartCoderUnpackSizesIndex;
UInt32 StartPackStreamIndex;
// UInt32 IndexOfMainOutStream;
} CSzFolder2;
*/
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes); SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
typedef struct typedef struct
{ {
@@ -94,47 +81,25 @@ typedef struct
UInt32 NumPackStreams; UInt32 NumPackStreams;
UInt32 NumFolders; UInt32 NumFolders;
UInt64 *PackPositions; // NumPackStreams + 1 UInt64 *PackPositions; // NumPackStreams + 1
CSzBitUi32s FolderCRCs; CSzBitUi32s FolderCRCs; // NumFolders
size_t *FoCodersOffsets; size_t *FoCodersOffsets; // NumFolders + 1
size_t *FoSizesOffsets; UInt32 *FoStartPackStreamIndex; // NumFolders + 1
// UInt32 StartCoderUnpackSizesIndex; UInt32 *FoToCoderUnpackSizes; // NumFolders + 1
UInt32 *FoStartPackStreamIndex; Byte *FoToMainUnpackSizeIndex; // NumFolders
UInt64 *CoderUnpackSizes; // for all coders in all folders
// CSzFolder2 *Folders; // +1 item for sum values
Byte *CodersData; Byte *CodersData;
Byte *UnpackSizesData;
size_t UnpackSizesDataSize;
// UInt64 *CoderUnpackSizes;
} CSzAr; } CSzAr;
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); ISzAlloc *allocMain);
/*
SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
typedef struct typedef struct
{ {
CSzAr db; CSzAr db;
@@ -144,7 +109,7 @@ typedef struct
UInt32 NumFiles; UInt32 NumFiles;
UInt64 *UnpackPositions; UInt64 *UnpackPositions; // NumFiles + 1
// Byte *IsEmptyFiles; // Byte *IsEmptyFiles;
Byte *IsDirs; Byte *IsDirs;
CSzBitUi32s CRCs; CSzBitUi32s CRCs;
@@ -154,9 +119,8 @@ typedef struct
CSzBitUi64s MTime; CSzBitUi64s MTime;
CSzBitUi64s CTime; CSzBitUi64s CTime;
// UInt32 *FolderStartPackStreamIndex; UInt32 *FolderToFile; // NumFolders + 1
UInt32 *FolderStartFileIndex; // + 1 UInt32 *FileToFolder; // NumFiles
UInt32 *FileIndexToFolderIndexMap;
size_t *FileNameOffsets; /* in 2-byte steps */ size_t *FileNameOffsets; /* in 2-byte steps */
Byte *FileNames; /* UTF-16-LE */ Byte *FileNames; /* UTF-16-LE */
@@ -184,6 +148,28 @@ 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);
*/ */
/*
SzArEx_Extract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
SRes SzArEx_Extract( SRes SzArEx_Extract(
const CSzArEx *db, const CSzArEx *db,
ILookInStream *inStream, ILookInStream *inStream,

View File

@@ -1,5 +1,5 @@
/* 7zAlloc.c -- Allocation functions /* 7zAlloc.c -- Allocation functions
2010-10-29 : Igor Pavlov : Public domain */ 2015-11-09 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -22,11 +22,11 @@ int g_allocCountTemp = 0;
void *SzAlloc(void *p, size_t size) void *SzAlloc(void *p, size_t size)
{ {
p = p; UNUSED_VAR(p);
if (size == 0) if (size == 0)
return 0; return 0;
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); fprintf(stderr, "\nAlloc %10u bytes; count = %10d", (unsigned)size, g_allocCount);
g_allocCount++; g_allocCount++;
#endif #endif
return malloc(size); return malloc(size);
@@ -34,7 +34,7 @@ void *SzAlloc(void *p, size_t size)
void SzFree(void *p, void *address) void SzFree(void *p, void *address)
{ {
p = p; UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
if (address != 0) if (address != 0)
{ {
@@ -47,11 +47,11 @@ void SzFree(void *p, void *address)
void *SzAllocTemp(void *p, size_t size) void *SzAllocTemp(void *p, size_t size)
{ {
p = p; UNUSED_VAR(p);
if (size == 0) if (size == 0)
return 0; return 0;
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); fprintf(stderr, "\nAlloc_temp %10u bytes; count = %10d", (unsigned)size, g_allocCountTemp);
g_allocCountTemp++; g_allocCountTemp++;
#ifdef _WIN32 #ifdef _WIN32
return HeapAlloc(GetProcessHeap(), 0, size); return HeapAlloc(GetProcessHeap(), 0, size);
@@ -62,7 +62,7 @@ void *SzAllocTemp(void *p, size_t size)
void SzFreeTemp(void *p, void *address) void SzFreeTemp(void *p, void *address)
{ {
p = p; UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG #ifdef _SZ_ALLOC_DEBUG
if (address != 0) if (address != 0)
{ {

View File

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

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/* 7zBuf2.c -- Byte Buffer /* 7zBuf2.c -- Byte Buffer
2013-11-12 : Igor Pavlov : Public domain */ 2014-08-22 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -34,8 +34,11 @@ int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)
alloc->Free(alloc, p->data); alloc->Free(alloc, p->data);
p->data = data; p->data = data;
} }
memcpy(p->data + p->pos, buf, size); if (size != 0)
p->pos += size; {
memcpy(p->data + p->pos, buf, size);
p->pos += size;
}
return 1; return 1;
} }

View File

@@ -1,5 +1,5 @@
/* 7zCrc.c -- CRC32 init /* 7zCrc.c -- CRC32 init
2013-11-12 : Igor Pavlov : Public domain */ 2015-03-10 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -8,24 +8,28 @@
#define kCrcPoly 0xEDB88320 #define kCrcPoly 0xEDB88320
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_LE
#define CRC_NUM_TABLES 8 #define CRC_NUM_TABLES 8
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#elif defined(MY_CPU_LE)
#define CRC_NUM_TABLES 4
#else #else
#define CRC_NUM_TABLES 5 #define CRC_NUM_TABLES 9
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif #endif
#ifndef MY_CPU_BE #ifndef MY_CPU_BE
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif #endif
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
CRC_FUNC g_CrcUpdateT4;
CRC_FUNC g_CrcUpdateT8;
CRC_FUNC g_CrcUpdate; CRC_FUNC g_CrcUpdate;
UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
@@ -38,6 +42,17 @@ UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
} }
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
const Byte *pEnd = p + size;
for (; p != pEnd; p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
void MY_FAST_CALL CrcGenerateTable() void MY_FAST_CALL CrcGenerateTable()
{ {
UInt32 i; UInt32 i;
@@ -54,22 +69,43 @@ void MY_FAST_CALL CrcGenerateTable()
UInt32 r = g_CrcTable[i - 256]; UInt32 r = g_CrcTable[i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
} }
#if CRC_NUM_TABLES < 4
g_CrcUpdate = CrcUpdateT1;
#else
#ifdef MY_CPU_LE #ifdef MY_CPU_LE
g_CrcUpdate = CrcUpdateT4; g_CrcUpdateT4 = CrcUpdateT4;
g_CrcUpdate = CrcUpdateT4;
#if CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT8;
#if CRC_NUM_TABLES == 8 #ifdef MY_CPU_X86_OR_AMD64
if (!CPU_Is_InOrder()) if (!CPU_Is_InOrder())
g_CrcUpdate = CrcUpdateT8; g_CrcUpdate = CrcUpdateT8;
#endif #endif
#endif
#else #else
{ {
#ifndef MY_CPU_BE #ifndef MY_CPU_BE
UInt32 k = 1; UInt32 k = 0x01020304;
if (*(const Byte *)&k == 1) const Byte *p = (const Byte *)&k;
if (p[0] == 4 && p[1] == 3)
{
g_CrcUpdateT4 = CrcUpdateT4;
g_CrcUpdate = CrcUpdateT4; g_CrcUpdate = CrcUpdateT4;
#if CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT8;
// g_CrcUpdate = CrcUpdateT8;
#endif
}
else if (p[0] != 1 || p[1] != 2)
g_CrcUpdate = CrcUpdateT1;
else else
#endif #endif
{ {
@@ -78,8 +114,15 @@ void MY_FAST_CALL CrcGenerateTable()
UInt32 x = g_CrcTable[i - 256]; UInt32 x = g_CrcTable[i - 256];
g_CrcTable[i] = CRC_UINT32_SWAP(x); g_CrcTable[i] = CRC_UINT32_SWAP(x);
} }
g_CrcUpdateT4 = CrcUpdateT1_BeT4;
g_CrcUpdate = CrcUpdateT1_BeT4; g_CrcUpdate = CrcUpdateT1_BeT4;
#if CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT1_BeT8;
// g_CrcUpdate = CrcUpdateT1_BeT8;
#endif
} }
} }
#endif #endif
#endif
} }

View File

@@ -1,14 +1,14 @@
/* 7zCrcOpt.c -- CRC32 calculation /* 7zCrcOpt.c -- CRC32 calculation
2013-11-12 : Igor Pavlov : Public domain */ 2015-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "CpuArch.h" #include "CpuArch.h"
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
#ifndef MY_CPU_BE #ifndef MY_CPU_BE
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
@@ -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);
@@ -30,7 +30,28 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
{ {
return CrcUpdateT4(v, data, size, table); const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
for (; size >= 8; size -= 8, p += 8)
{
UInt32 d;
v ^= *(const UInt32 *)p;
v =
table[0x700 + ((v ) & 0xFF)]
^ table[0x600 + ((v >> 8) & 0xFF)]
^ table[0x500 + ((v >> 16) & 0xFF)]
^ table[0x400 + ((v >> 24))];
d = *((const UInt32 *)p + 1);
v ^=
table[0x300 + ((d ) & 0xFF)]
^ table[0x200 + ((d >> 8) & 0xFF)]
^ table[0x100 + ((d >> 16) & 0xFF)]
^ table[0x000 + ((d >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
} }
#endif #endif
@@ -40,27 +61,55 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8))
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
v = CRC_UINT32_SWAP(v);
table += 0x100; table += 0x100;
v = CRC_UINT32_SWAP(v);
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 4; size -= 4, p += 4) for (; size >= 4; size -= 4, p += 4)
{ {
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))];
} }
table -= 0x100;
v = CRC_UINT32_SWAP(v);
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2_BE(v, *p);
return v; return CRC_UINT32_SWAP(v);
}
UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
table += 0x100;
v = CRC_UINT32_SWAP(v);
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 8; size -= 8, p += 8)
{
UInt32 d;
v ^= *(const UInt32 *)p;
v =
table[0x400 + ((v ) & 0xFF)]
^ table[0x500 + ((v >> 8) & 0xFF)]
^ table[0x600 + ((v >> 16) & 0xFF)]
^ table[0x700 + ((v >> 24))];
d = *((const UInt32 *)p + 1);
v ^=
table[0x000 + ((d ) & 0xFF)]
^ table[0x100 + ((d >> 8) & 0xFF)]
^ table[0x200 + ((d >> 16) & 0xFF)]
^ table[0x300 + ((d >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p);
return CRC_UINT32_SWAP(v);
} }
#endif #endif

272
C/7zDec.c
View File

@@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2014-06-16 : Igor Pavlov : Public domain */ 2015-11-18 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -8,10 +8,12 @@
/* #define _7ZIP_PPMD_SUPPPORT */ /* #define _7ZIP_PPMD_SUPPPORT */
#include "7z.h" #include "7z.h"
#include "7zCrc.h"
#include "Bcj2.h" #include "Bcj2.h"
#include "Bra.h" #include "Bra.h"
#include "CpuArch.h" #include "CpuArch.h"
#include "Delta.h"
#include "LzmaDec.h" #include "LzmaDec.h"
#include "Lzma2Dec.h" #include "Lzma2Dec.h"
#ifdef _7ZIP_PPMD_SUPPPORT #ifdef _7ZIP_PPMD_SUPPPORT
@@ -19,14 +21,17 @@
#endif #endif
#define k_Copy 0 #define k_Copy 0
#define k_Delta 3
#define k_LZMA2 0x21 #define k_LZMA2 0x21
#define k_LZMA 0x30101 #define k_LZMA 0x30101
#define k_BCJ 0x03030103 #define k_BCJ 0x3030103
#define k_PPC 0x03030205 #define k_BCJ2 0x303011B
#define k_ARM 0x03030501 #define k_PPC 0x3030205
#define k_ARMT 0x03030701 #define k_IA64 0x3030401
#define k_SPARC 0x03030805 #define k_ARM 0x3030501
#define k_BCJ2 0x0303011B #define k_ARMT 0x3030701
#define k_SPARC 0x3030805
#ifdef _7ZIP_PPMD_SUPPPORT #ifdef _7ZIP_PPMD_SUPPPORT
@@ -140,11 +145,11 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
for (;;) for (;;)
{ {
Byte *inBuf = NULL; const void *inBuf = NULL;
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((void *)inStream, (const void **)&inBuf, &lookahead); res = inStream->Look(inStream, &inBuf, &lookahead);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -156,14 +161,23 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
{ {
if (state.dicBufSize != outSize || lookahead != 0 || if (outSize != state.dicPos || inSize != 0)
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
break; break;
} }
if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
break;
if (inProcessed == 0 && dicPos == state.dicPos)
{
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed); res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -174,6 +188,9 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
return res; return res;
} }
#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, ISzAlloc *allocMain)
{ {
@@ -190,11 +207,11 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
for (;;) for (;;)
{ {
Byte *inBuf = NULL; const void *inBuf = NULL;
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((void *)inStream, (const void **)&inBuf, &lookahead); res = inStream->Look(inStream, &inBuf, &lookahead);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -206,13 +223,20 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
inSize -= inProcessed; inSize -= inProcessed;
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
{ {
if (state.decoder.dicBufSize != outSize || lookahead != 0 || if (outSize != state.decoder.dicPos || inSize != 0)
(status != LZMA_STATUS_FINISHED_WITH_MARK))
res = SZ_ERROR_DATA; res = SZ_ERROR_DATA;
break; break;
} }
if (inProcessed == 0 && dicPos == state.decoder.dicPos)
{
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed); res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@@ -223,15 +247,18 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
return res; return res;
} }
#endif
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
{ {
while (inSize > 0) while (inSize > 0)
{ {
void *inBuf; const void *inBuf;
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((void *)inStream, (const void **)&inBuf, &curSize)); RINOK(inStream->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);
@@ -248,7 +275,9 @@ static Bool IS_MAIN_METHOD(UInt32 m)
{ {
case k_Copy: case k_Copy:
case k_LZMA: case k_LZMA:
#ifndef _7Z_NO_METHOD_LZMA2
case k_LZMA2: case k_LZMA2:
#endif
#ifdef _7ZIP_PPMD_SUPPPORT #ifdef _7ZIP_PPMD_SUPPPORT
case k_PPMD: case k_PPMD:
#endif #endif
@@ -260,13 +289,12 @@ static Bool IS_MAIN_METHOD(UInt32 m)
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
{ {
return return
c->NumInStreams == 1 && c->NumStreams == 1
c->NumOutStreams == 1 && /* && c->MethodID <= (UInt32)0xFFFFFFFF */
/* c->MethodID <= (UInt32)0xFFFFFFFF && */ && IS_MAIN_METHOD((UInt32)c->MethodID);
IS_MAIN_METHOD((UInt32)c->MethodID);
} }
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
static SRes CheckSupportedFolder(const CSzFolder *f) static SRes CheckSupportedFolder(const CSzFolder *f)
{ {
@@ -276,51 +304,64 @@ static SRes CheckSupportedFolder(const CSzFolder *f)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (f->NumCoders == 1) if (f->NumCoders == 1)
{ {
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
return SZ_OK; return SZ_OK;
} }
#ifndef _7Z_NO_METHODS_FILTERS
if (f->NumCoders == 2) if (f->NumCoders == 2)
{ {
const CSzCoderInfo *c = &f->Coders[1]; const CSzCoderInfo *c = &f->Coders[1];
if ( if (
/* c->MethodID > (UInt32)0xFFFFFFFF || */ /* c->MethodID > (UInt32)0xFFFFFFFF || */
c->NumInStreams != 1 || c->NumStreams != 1
c->NumOutStreams != 1 || || f->NumPackStreams != 1
f->NumPackStreams != 1 || || f->PackStreams[0] != 0
f->PackStreams[0] != 0 || || f->NumBonds != 1
f->NumBindPairs != 1 || || f->Bonds[0].InIndex != 1
f->BindPairs[0].InIndex != 1 || || f->Bonds[0].OutIndex != 0)
f->BindPairs[0].OutIndex != 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
switch ((UInt32)c->MethodID) switch ((UInt32)c->MethodID)
{ {
case k_Delta:
case k_BCJ: case k_BCJ:
case k_PPC:
case k_IA64:
case k_SPARC:
case k_ARM: case k_ARM:
case k_ARMT:
break; break;
default: default:
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
return SZ_OK; return SZ_OK;
} }
#endif
if (f->NumCoders == 4) if (f->NumCoders == 4)
{ {
if (!IS_SUPPORTED_CODER(&f->Coders[1]) || if (!IS_SUPPORTED_CODER(&f->Coders[1])
!IS_SUPPORTED_CODER(&f->Coders[2]) || || !IS_SUPPORTED_CODER(&f->Coders[2])
!IS_BCJ2(&f->Coders[3])) || !IS_BCJ2(&f->Coders[3]))
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (f->NumPackStreams != 4 || if (f->NumPackStreams != 4
f->PackStreams[0] != 2 || || f->PackStreams[0] != 2
f->PackStreams[1] != 6 || || f->PackStreams[1] != 6
f->PackStreams[2] != 1 || || f->PackStreams[2] != 1
f->PackStreams[3] != 0 || || f->PackStreams[3] != 0
f->NumBindPairs != 3 || || f->NumBonds != 3
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
return SZ_OK; return SZ_OK;
} }
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
@@ -364,7 +405,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
if (outSizeCur != unpackSize) if (outSizeCur != unpackSize)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
if (temp == 0 && outSizeCur != 0) if (!temp && outSizeCur != 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
outBufCur = tempBuf[1 - ci] = temp; outBufCur = tempBuf[1 - ci] = temp;
tempSizes[1 - ci] = outSizeCur; tempSizes[1 - ci] = outSizeCur;
@@ -393,66 +434,118 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
{ {
RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
} }
#ifndef _7Z_NO_METHOD_LZMA2
else if (coder->MethodID == k_LZMA2) else if (coder->MethodID == k_LZMA2)
{ {
RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
} }
else #endif
#ifdef _7ZIP_PPMD_SUPPPORT
else if (coder->MethodID == k_PPMD)
{ {
#ifdef _7ZIP_PPMD_SUPPPORT
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
#else
return SZ_ERROR_UNSUPPORTED;
#endif
} }
#endif
else
return SZ_ERROR_UNSUPPORTED;
} }
else if (coder->MethodID == k_BCJ2) else if (coder->MethodID == k_BCJ2)
{ {
UInt64 offset = packPositions[1]; UInt64 offset = packPositions[1];
UInt64 s3Size = packPositions[2] - offset; UInt64 s3Size = packPositions[2] - offset;
SRes res;
if (ci != 3) if (ci != 3)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
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 *)IAlloc_Alloc(allocMain, tempSizes[2]);
if (tempBuf[2] == 0 && tempSizes[2] != 0) if (!tempBuf[2] && tempSizes[2] != 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
RINOK(res) RINOK(LookInStream_SeekTo(inStream, startPos + offset));
RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
if ((tempSizes[0] & 3) != 0 ||
(tempSizes[1] & 3) != 0 ||
tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
return SZ_ERROR_DATA;
res = Bcj2_Decode(
tempBuf3, tempSize3,
tempBuf[0], tempSizes[0],
tempBuf[1], tempSizes[1],
tempBuf[2], tempSizes[2],
outBuffer, outSize);
RINOK(res)
}
else
{
if (ci != 1)
return SZ_ERROR_UNSUPPORTED;
switch (coder->MethodID)
{ {
case k_BCJ: CBcj2Dec p;
p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3;
p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
p.dest = outBuffer;
p.destLim = outBuffer + outSize;
Bcj2Dec_Init(&p);
RINOK(Bcj2Dec_Decode(&p));
{ {
UInt32 state; unsigned i;
x86_Convert_Init(state); for (i = 0; i < 4; i++)
x86_Convert(outBuffer, outSize, 0, &state, 0); if (p.bufs[i] != p.lims[i])
break; return SZ_ERROR_DATA;
if (!Bcj2Dec_IsFinished(&p))
return SZ_ERROR_DATA;
if (p.dest != p.destLim
|| p.state != BCJ2_STREAM_MAIN)
return SZ_ERROR_DATA;
} }
CASE_BRA_CONV(ARM)
default:
return SZ_ERROR_UNSUPPORTED;
} }
} }
#ifndef _7Z_NO_METHODS_FILTERS
else if (ci == 1)
{
if (coder->MethodID == k_Delta)
{
if (coder->PropsSize != 1)
return SZ_ERROR_UNSUPPORTED;
{
Byte state[DELTA_STATE_SIZE];
Delta_Init(state);
Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
}
}
else
{
if (coder->PropsSize != 0)
return SZ_ERROR_UNSUPPORTED;
switch (coder->MethodID)
{
case k_BCJ:
{
UInt32 state;
x86_Convert_Init(state);
x86_Convert(outBuffer, outSize, 0, &state, 0);
break;
}
CASE_BRA_CONV(PPC)
CASE_BRA_CONV(IA64)
CASE_BRA_CONV(SPARC)
CASE_BRA_CONV(ARM)
CASE_BRA_CONV(ARMT)
default:
return SZ_ERROR_UNSUPPORTED;
}
}
}
#endif
else
return SZ_ERROR_UNSUPPORTED;
} }
return SZ_OK; return SZ_OK;
} }
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,
@@ -461,33 +554,38 @@ SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
SRes res; SRes res;
CSzFolder folder; CSzFolder folder;
CSzData sd; CSzData sd;
CSzData sdSizes;
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[folderIndex + 1] - p->FoCodersOffsets[folderIndex];
sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex]; res = SzGetNextFolderItem(&folder, &sd);
sdSizes.Size =
p->FoSizesOffsets[folderIndex + 1] -
p->FoSizesOffsets[folderIndex];
res = SzGetNextFolderItem(&folder, &sd, &sdSizes);
if (res != SZ_OK) if (res != SZ_OK)
return res; return res;
if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.MainOutStream]) if (sd.Size != 0
|| folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
|| outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
return SZ_ERROR_FAIL; return SZ_ERROR_FAIL;
{ {
int i; unsigned i;
Byte *tempBuf[3] = { 0, 0, 0}; Byte *tempBuf[3] = { 0, 0, 0};
res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes,
res = SzFolder_Decode2(&folder, data,
&p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
p->PackPositions + p->FoStartPackStreamIndex[folderIndex], p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
inStream, startPos, inStream, startPos,
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]); IAlloc_Free(allocMain, tempBuf[i]);
if (res == SZ_OK)
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
res = SZ_ERROR_CRC;
return res; return res;
} }
} }

View File

@@ -1,10 +1,19 @@
#define MY_VER_MAJOR 9 #define MY_VER_MAJOR 15
#define MY_VER_MINOR 35 #define MY_VER_MINOR 14
#define MY_VER_BUILD 00 #define MY_VER_BUILD 0
#define MY_VERSION "9.35 beta" #define MY_VERSION_NUMBERS "15.14"
// #define MY_7ZIP_VERSION "9.35" #define MY_VERSION "15.14"
#define MY_DATE "2014-12-07" #define MY_DATE "2015-12-31"
#undef MY_COPYRIGHT #undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE #undef MY_VERSION_COPYRIGHT_DATE
#define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR
#else
#define MY_COPYRIGHT MY_COPYRIGHT_PD
#endif
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " : " MY_COPYRIGHT " : " MY_DATE

29
C/Aes.c
View File

@@ -1,5 +1,5 @@
/* Aes.c -- AES encryption / decryption /* Aes.c -- AES encryption / decryption
2013-11-12 : Igor Pavlov : Public domain */ 2015-02-23 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -7,7 +7,7 @@
#include "CpuArch.h" #include "CpuArch.h"
static UInt32 T[256 * 4]; static UInt32 T[256 * 4];
static Byte Sbox[256] = { static const Byte Sbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
@@ -40,7 +40,7 @@ AES_CODE_FUNC g_AesCtr_Code;
static UInt32 D[256 * 4]; static UInt32 D[256 * 4];
static Byte InvS[256]; static Byte InvS[256];
static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; static const Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF) #define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)
@@ -56,6 +56,7 @@ void AesGenTables(void)
unsigned i; unsigned i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
InvS[Sbox[i]] = (Byte)i; InvS[Sbox[i]] = (Byte)i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
{ {
@@ -82,9 +83,11 @@ void AesGenTables(void)
D[0x300 + i] = Ui32(a9, aD, aB, aE); D[0x300 + i] = Ui32(a9, aD, aB, aE);
} }
} }
g_AesCbc_Encode = AesCbc_Encode; g_AesCbc_Encode = AesCbc_Encode;
g_AesCbc_Decode = AesCbc_Decode; g_AesCbc_Decode = AesCbc_Decode;
g_AesCtr_Code = AesCtr_Code; g_AesCtr_Code = AesCtr_Code;
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
if (CPU_Is_Aes_Supported()) if (CPU_Is_Aes_Supported())
{ {
@@ -95,34 +98,38 @@ void AesGenTables(void)
#endif #endif
} }
#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])] #define HT(i, x, s) (T + (x << 8))[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) ^ \
HT(i, 1, s) ^ \ HT(i, 1, s) ^ \
HT(i, 2, s) ^ \ HT(i, 2, s) ^ \
HT(i, 3, s) ^ w[p + i] HT(i, 3, s) ^ w[p + i]
/* such order (2031) in HT16 is for VC6/K8 speed optimization) */
#define HT16(m, s, p) \ #define HT16(m, s, p) \
HT4(m, 2, s, p); \
HT4(m, 0, s, p); \ HT4(m, 0, s, p); \
HT4(m, 3, s, p); \
HT4(m, 1, s, p); \ HT4(m, 1, s, p); \
HT4(m, 2, 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) (D + (x << 8))[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) ^ \
HD(i, 1, s) ^ \ HD(i, 1, s) ^ \
HD(i, 2, s) ^ \ HD(i, 2, s) ^ \
HD(i, 3, s) ^ w[p + i]; HD(i, 3, s) ^ w[p + i];
/* such order (0231) in HD16 is for VC6/K8 speed optimization) */
#define HD16(m, s, p) \ #define HD16(m, s, p) \
HD4(m, 0, s, p); \ HD4(m, 0, s, p); \
HD4(m, 1, s, p); \
HD4(m, 2, s, p); \ HD4(m, 2, s, p); \
HD4(m, 3, s, p); \ HD4(m, 3, s, p); \
HD4(m, 1, 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];
@@ -169,7 +176,7 @@ void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)
/* Aes_Encode and Aes_Decode functions work with little-endian words. /* Aes_Encode and Aes_Decode functions work with little-endian words.
src and dest are pointers to 4 UInt32 words. src and dest are pointers to 4 UInt32 words.
arc and dest can point to same block */ src and dest can point to same block */
static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src) static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src)
{ {
@@ -271,13 +278,17 @@ void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)
UInt32 temp[4]; UInt32 temp[4];
Byte buf[16]; Byte buf[16];
int 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]); SetUi32(buf, temp[0]);
SetUi32(buf + 4, temp[1]); SetUi32(buf + 4, temp[1]);
SetUi32(buf + 8, temp[2]); SetUi32(buf + 8, temp[2]);
SetUi32(buf + 12, temp[3]); SetUi32(buf + 12, temp[3]);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
*data++ ^= buf[i]; *data++ ^= buf[i];
} }

View File

@@ -1,5 +1,5 @@
/* Alloc.c -- Memory allocation functions /* Alloc.c -- Memory allocation functions
2013-11-12 : Igor Pavlov : Public domain */ 2015-02-21 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -125,3 +125,12 @@ void BigFree(void *address)
} }
#endif #endif
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); }
ISzAlloc g_Alloc = { SzAlloc, SzFree };
static void *SzBigAlloc(void *p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }
static void SzBigFree(void *p, void *address) { UNUSED_VAR(p); BigFree(address); }
ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };

View File

@@ -1,14 +1,12 @@
/* Alloc.h -- Memory allocation functions /* Alloc.h -- Memory allocation functions
2009-02-07 : Igor Pavlov : Public domain */ 2015-02-21 : Igor Pavlov : Public domain */
#ifndef __COMMON_ALLOC_H #ifndef __COMMON_ALLOC_H
#define __COMMON_ALLOC_H #define __COMMON_ALLOC_H
#include <stddef.h> #include "7zTypes.h"
#ifdef __cplusplus EXTERN_C_BEGIN
extern "C" {
#endif
void *MyAlloc(size_t size); void *MyAlloc(size_t size);
void MyFree(void *address); void MyFree(void *address);
@@ -31,8 +29,9 @@ void BigFree(void *address);
#endif #endif
#ifdef __cplusplus extern ISzAlloc g_Alloc;
} extern ISzAlloc g_BigAlloc;
#endif
EXTERN_C_END
#endif #endif

332
C/Bcj2.c
View File

@@ -1,134 +1,256 @@
/* Bcj2.c -- Converter for x86 code (BCJ2) /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
2008-10-04 : Igor Pavlov : Public domain */ 2015-08-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "Bcj2.h" #include "Bcj2.h"
#include "CpuArch.h"
#ifdef _LZMA_PROB32
#define CProb UInt32
#else
#define CProb UInt16 #define CProb UInt16
#endif
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define kTopValue ((UInt32)1 << 24)
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #define kNumModelBits 11
#define kBitModelTotal (1 << kNumModelBits)
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5 #define kNumMoveBits 5
#define RC_READ_BYTE (*buffer++) #define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } #define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ #define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } void Bcj2Dec_Init(CBcj2Dec *p)
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
int Bcj2_Decode(
const Byte *buf0, SizeT size0,
const Byte *buf1, SizeT size1,
const Byte *buf2, SizeT size2,
const Byte *buf3, SizeT size3,
Byte *outBuf, SizeT outSize)
{ {
CProb p[256 + 2]; unsigned i;
SizeT inPos = 0, outPos = 0;
const Byte *buffer, *bufferLim; p->state = BCJ2_DEC_STATE_OK;
UInt32 range, code; p->ip = 0;
Byte prevByte = 0; p->temp[3] = 0;
p->range = 0;
p->code = 0;
for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
p->probs[i] = kBitModelTotal >> 1;
}
unsigned int i; SRes Bcj2Dec_Decode(CBcj2Dec *p)
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) {
p[i] = kBitModelTotal >> 1; if (p->range <= 5)
{
p->state = BCJ2_DEC_STATE_OK;
for (; p->range != 5; p->range++)
{
if (p->range == 1 && p->code != 0)
return SZ_ERROR_DATA;
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
{
p->state = BCJ2_STREAM_RC;
return SZ_OK;
}
buffer = buf3; p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
bufferLim = buffer + size3; }
RC_INIT2
if (p->code == 0xFFFFFFFF)
return SZ_ERROR_DATA;
p->range = 0xFFFFFFFF;
}
else if (p->state >= BCJ2_DEC_STATE_ORIG_0)
{
while (p->state <= BCJ2_DEC_STATE_ORIG_3)
{
Byte *dest = p->dest;
if (dest == p->destLim)
return SZ_OK;
*dest = p->temp[p->state++ - BCJ2_DEC_STATE_ORIG_0];
p->dest = dest + 1;
}
}
if (outSize == 0) /*
return SZ_OK; if (BCJ2_IS_32BIT_STREAM(p->state))
{
const Byte *cur = p->bufs[p->state];
if (cur == p->lims[p->state])
return SZ_OK;
p->bufs[p->state] = cur + 4;
{
UInt32 val;
Byte *dest;
SizeT rem;
p->ip += 4;
val = GetBe32(cur) - p->ip;
dest = p->dest;
rem = p->destLim - dest;
if (rem < 4)
{
SizeT i;
SetUi32(p->temp, val);
for (i = 0; i < rem; i++)
dest[i] = p->temp[i];
p->dest = dest + rem;
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
return SZ_OK;
}
SetUi32(dest, val);
p->temp[3] = (Byte)(val >> 24);
p->dest = dest + 4;
p->state = BCJ2_DEC_STATE_OK;
}
}
*/
for (;;) for (;;)
{ {
Byte b; if (BCJ2_IS_32BIT_STREAM(p->state))
CProb *prob; p->state = BCJ2_DEC_STATE_OK;
UInt32 bound;
UInt32 ttt;
SizeT limit = size0 - inPos;
if (outSize - outPos < limit)
limit = outSize - outPos;
while (limit != 0)
{
Byte b = buf0[inPos];
outBuf[outPos++] = b;
if (IsJ(prevByte, b))
break;
inPos++;
prevByte = b;
limit--;
}
if (limit == 0 || outPos == outSize)
break;
b = buf0[inPos++];
if (b == 0xE8)
prob = p + prevByte;
else if (b == 0xE9)
prob = p + 256;
else
prob = p + 257;
IF_BIT_0(prob)
{
UPDATE_0(prob)
prevByte = b;
}
else else
{ {
UInt32 dest; if (p->range < kTopValue)
const Byte *v;
UPDATE_1(prob)
if (b == 0xE8)
{ {
v = buf1; if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
if (size1 < 4) {
return SZ_ERROR_DATA; p->state = BCJ2_STREAM_RC;
buf1 += 4; return SZ_OK;
size1 -= 4; }
p->range <<= 8;
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
} }
else
{ {
v = buf2; const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
if (size2 < 4) const Byte *srcLim;
return SZ_ERROR_DATA; Byte *dest;
buf2 += 4; SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
size2 -= 4;
if (num == 0)
{
p->state = BCJ2_STREAM_MAIN;
return SZ_OK;
}
dest = p->dest;
if (num > (SizeT)(p->destLim - dest))
{
num = p->destLim - dest;
if (num == 0)
{
p->state = BCJ2_DEC_STATE_ORIG;
return SZ_OK;
}
}
srcLim = src + num;
if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)
*dest = src[0];
else for (;;)
{
Byte b = *src;
*dest = b;
if (b != 0x0F)
{
if ((b & 0xFE) == 0xE8)
break;
dest++;
if (++src != srcLim)
continue;
break;
}
dest++;
if (++src == srcLim)
break;
if ((*src & 0xF0) != 0x80)
continue;
*dest = *src;
break;
}
num = src - p->bufs[BCJ2_STREAM_MAIN];
if (src == srcLim)
{
p->temp[3] = src[-1];
p->bufs[BCJ2_STREAM_MAIN] = src;
p->ip += (UInt32)num;
p->dest += num;
p->state =
p->bufs[BCJ2_STREAM_MAIN] ==
p->lims[BCJ2_STREAM_MAIN] ?
(unsigned)BCJ2_STREAM_MAIN :
(unsigned)BCJ2_DEC_STATE_ORIG;
return SZ_OK;
}
{
UInt32 bound, ttt;
CProb *prob;
Byte b = src[0];
Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);
p->temp[3] = b;
p->bufs[BCJ2_STREAM_MAIN] = src + 1;
num++;
p->ip += (UInt32)num;
p->dest += num;
prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));
_IF_BIT_0
{
_UPDATE_0
continue;
}
_UPDATE_1
}
} }
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | }
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
outBuf[outPos++] = (Byte)dest; {
if (outPos == outSize) UInt32 val;
unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
const Byte *cur = p->bufs[cj];
Byte *dest;
SizeT rem;
if (cur == p->lims[cj])
{
p->state = cj;
break; break;
outBuf[outPos++] = (Byte)(dest >> 8); }
if (outPos == outSize)
val = GetBe32(cur);
p->bufs[cj] = cur + 4;
p->ip += 4;
val -= p->ip;
dest = p->dest;
rem = p->destLim - dest;
if (rem < 4)
{
SizeT i;
SetUi32(p->temp, val);
for (i = 0; i < rem; i++)
dest[i] = p->temp[i];
p->dest = dest + rem;
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
break; break;
outBuf[outPos++] = (Byte)(dest >> 16); }
if (outPos == outSize)
break; SetUi32(dest, val);
outBuf[outPos++] = prevByte = (Byte)(dest >> 24); p->temp[3] = (Byte)(val >> 24);
p->dest = dest + 4;
} }
} }
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
{
p->range <<= 8;
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
}
return SZ_OK;
} }

150
C/Bcj2.h
View File

@@ -1,5 +1,5 @@
/* Bcj2.h -- Converter for x86 code (BCJ2) /* Bcj2.h -- BCJ2 Converter for x86 code
2013-01-18 : Igor Pavlov : Public domain */ 2014-11-10 : Igor Pavlov : Public domain */
#ifndef __BCJ2_H #ifndef __BCJ2_H
#define __BCJ2_H #define __BCJ2_H
@@ -8,26 +8,138 @@
EXTERN_C_BEGIN EXTERN_C_BEGIN
#define BCJ2_NUM_STREAMS 4
enum
{
BCJ2_STREAM_MAIN,
BCJ2_STREAM_CALL,
BCJ2_STREAM_JUMP,
BCJ2_STREAM_RC
};
enum
{
BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,
BCJ2_DEC_STATE_ORIG_1,
BCJ2_DEC_STATE_ORIG_2,
BCJ2_DEC_STATE_ORIG_3,
BCJ2_DEC_STATE_ORIG,
BCJ2_DEC_STATE_OK
};
enum
{
BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,
BCJ2_ENC_STATE_OK
};
#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP)
/* /*
Conditions: CBcj2Dec / CBcj2Enc
outSize <= FullOutputSize, bufs sizes:
where FullOutputSize is full size of output stream of x86_2 filter. BUF_SIZE(n) = lims[n] - bufs[n]
bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4:
If buf0 overlaps outBuf, there are two required conditions: (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
1) (buf0 >= outBuf) (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
2) (buf0 + size0 >= outBuf + FullOutputSize).
Returns:
SZ_OK
SZ_ERROR_DATA - Data error
*/ */
int Bcj2_Decode( /*
const Byte *buf0, SizeT size0, CBcj2Dec:
const Byte *buf1, SizeT size1, dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:
const Byte *buf2, SizeT size2, bufs[BCJ2_STREAM_MAIN] >= dest &&
const Byte *buf3, SizeT size3, bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv +
Byte *outBuf, SizeT outSize); BUF_SIZE(BCJ2_STREAM_CALL) +
BUF_SIZE(BCJ2_STREAM_JUMP)
tempReserv = 0 : for first call of Bcj2Dec_Decode
tempReserv = 4 : for any other calls of Bcj2Dec_Decode
overlap with offset = 1 is not allowed
*/
typedef struct
{
const Byte *bufs[BCJ2_NUM_STREAMS];
const Byte *lims[BCJ2_NUM_STREAMS];
Byte *dest;
const Byte *destLim;
unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */
UInt32 ip;
Byte temp[4];
UInt32 range;
UInt32 code;
UInt16 probs[2 + 256];
} CBcj2Dec;
void Bcj2Dec_Init(CBcj2Dec *p);
/* Returns: SZ_OK or SZ_ERROR_DATA */
SRes Bcj2Dec_Decode(CBcj2Dec *p);
#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0)
typedef enum
{
BCJ2_ENC_FINISH_MODE_CONTINUE,
BCJ2_ENC_FINISH_MODE_END_BLOCK,
BCJ2_ENC_FINISH_MODE_END_STREAM
} EBcj2Enc_FinishMode;
typedef struct
{
Byte *bufs[BCJ2_NUM_STREAMS];
const Byte *lims[BCJ2_NUM_STREAMS];
const Byte *src;
const Byte *srcLim;
unsigned state;
EBcj2Enc_FinishMode finishMode;
Byte prevByte;
Byte cache;
UInt32 range;
UInt64 low;
UInt64 cacheSize;
UInt32 ip;
/* 32-bit ralative offset in JUMP/CALL commands is
- (mod 4 GB) in 32-bit mode
- signed Int32 in 64-bit mode
We use (mod 4 GB) check for fileSize.
Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */
UInt32 fileIp;
UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */
UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */
UInt32 tempTarget;
unsigned tempPos;
Byte temp[4 * 2];
unsigned flushPos;
UInt16 probs[2 + 256];
} CBcj2Enc;
void Bcj2Enc_Init(CBcj2Enc *p);
void Bcj2Enc_Encode(CBcj2Enc *p);
#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos)
#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5)
#define BCJ2_RELAT_LIMIT_NUM_BITS 26
#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS)
/* limit for CBcj2Enc::fileSize variable */
#define BCJ2_FileSize_MAX ((UInt32)1 << 31)
EXTERN_C_END EXTERN_C_END

312
C/Bcj2Enc.c Normal file
View File

@@ -0,0 +1,312 @@
/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)
2014-11-10 : Igor Pavlov : Public domain */
#include "Precomp.h"
/* #define SHOW_STAT */
#ifdef SHOW_STAT
#include <stdio.h>
#define PRF(x) x
#else
#define PRF(x)
#endif
#include <windows.h>
#include <string.h>
#include "Bcj2.h"
#include "CpuArch.h"
#define CProb UInt16
#define kTopValue ((UInt32)1 << 24)
#define kNumModelBits 11
#define kBitModelTotal (1 << kNumModelBits)
#define kNumMoveBits 5
void Bcj2Enc_Init(CBcj2Enc *p)
{
unsigned i;
p->state = BCJ2_ENC_STATE_OK;
p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
p->prevByte = 0;
p->cache = 0;
p->range = 0xFFFFFFFF;
p->low = 0;
p->cacheSize = 1;
p->ip = 0;
p->fileIp = 0;
p->fileSize = 0;
p->relatLimit = BCJ2_RELAT_LIMIT;
p->tempPos = 0;
p->flushPos = 0;
for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
p->probs[i] = kBitModelTotal >> 1;
}
static Bool MY_FAST_CALL RangeEnc_ShiftLow(CBcj2Enc *p)
{
if ((UInt32)p->low < (UInt32)0xFF000000 || (UInt32)(p->low >> 32) != 0)
{
Byte *buf = p->bufs[BCJ2_STREAM_RC];
do
{
if (buf == p->lims[BCJ2_STREAM_RC])
{
p->state = BCJ2_STREAM_RC;
p->bufs[BCJ2_STREAM_RC] = buf;
return True;
}
*buf++ = (Byte)(p->cache + (Byte)(p->low >> 32));
p->cache = 0xFF;
}
while (--p->cacheSize);
p->bufs[BCJ2_STREAM_RC] = buf;
p->cache = (Byte)((UInt32)p->low >> 24);
}
p->cacheSize++;
p->low = (UInt32)p->low << 8;
return False;
}
static void Bcj2Enc_Encode_2(CBcj2Enc *p)
{
if (BCJ2_IS_32BIT_STREAM(p->state))
{
Byte *cur = p->bufs[p->state];
if (cur == p->lims[p->state])
return;
SetBe32(cur, p->tempTarget);
p->bufs[p->state] = cur + 4;
}
p->state = BCJ2_ENC_STATE_ORIG;
for (;;)
{
if (p->range < kTopValue)
{
if (RangeEnc_ShiftLow(p))
return;
p->range <<= 8;
}
{
{
const Byte *src = p->src;
const Byte *srcLim;
Byte *dest;
SizeT num = p->srcLim - src;
if (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE)
{
if (num <= 4)
return;
num -= 4;
}
else if (num == 0)
break;
dest = p->bufs[BCJ2_STREAM_MAIN];
if (num > (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest))
{
num = p->lims[BCJ2_STREAM_MAIN] - dest;
if (num == 0)
{
p->state = BCJ2_STREAM_MAIN;
return;
}
}
srcLim = src + num;
if (p->prevByte == 0x0F && (src[0] & 0xF0) == 0x80)
*dest = src[0];
else for (;;)
{
Byte b = *src;
*dest = b;
if (b != 0x0F)
{
if ((b & 0xFE) == 0xE8)
break;
dest++;
if (++src != srcLim)
continue;
break;
}
dest++;
if (++src == srcLim)
break;
if ((*src & 0xF0) != 0x80)
continue;
*dest = *src;
break;
}
num = src - p->src;
if (src == srcLim)
{
p->prevByte = src[-1];
p->bufs[BCJ2_STREAM_MAIN] = dest;
p->src = src;
p->ip += (UInt32)num;
continue;
}
{
Byte context = (Byte)(num == 0 ? p->prevByte : src[-1]);
Bool needConvert;
p->bufs[BCJ2_STREAM_MAIN] = dest + 1;
p->ip += (UInt32)num + 1;
src++;
needConvert = False;
if ((SizeT)(p->srcLim - src) >= 4)
{
UInt32 relatVal = GetUi32(src);
if ((p->fileSize == 0 || (UInt32)(p->ip + 4 + relatVal - p->fileIp) < p->fileSize)
&& ((relatVal + p->relatLimit) >> 1) < p->relatLimit)
needConvert = True;
}
{
UInt32 bound;
unsigned ttt;
Byte b = src[-1];
CProb *prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)context : (b == 0xE9 ? 1 : 0));
ttt = *prob;
bound = (p->range >> kNumModelBits) * ttt;
if (!needConvert)
{
p->range = bound;
*prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
p->src = src;
p->prevByte = b;
continue;
}
p->low += bound;
p->range -= bound;
*prob = (CProb)(ttt - (ttt >> kNumMoveBits));
{
UInt32 relatVal = GetUi32(src);
UInt32 absVal;
p->ip += 4;
absVal = p->ip + relatVal;
p->prevByte = src[3];
src += 4;
p->src = src;
{
unsigned cj = (b == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
Byte *cur = p->bufs[cj];
if (cur == p->lims[cj])
{
p->state = cj;
p->tempTarget = absVal;
return;
}
SetBe32(cur, absVal);
p->bufs[cj] = cur + 4;
}
}
}
}
}
}
}
if (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM)
return;
for (; p->flushPos < 5; p->flushPos++)
if (RangeEnc_ShiftLow(p))
return;
p->state = BCJ2_ENC_STATE_OK;
}
void Bcj2Enc_Encode(CBcj2Enc *p)
{
PRF(printf("\n"));
PRF(printf("---- ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
if (p->tempPos != 0)
{
unsigned extra = 0;
for (;;)
{
const Byte *src = p->src;
const Byte *srcLim = p->srcLim;
unsigned finishMode = p->finishMode;
p->src = p->temp;
p->srcLim = p->temp + p->tempPos;
if (src != srcLim)
p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
PRF(printf(" ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
Bcj2Enc_Encode_2(p);
{
unsigned num = (unsigned)(p->src - p->temp);
unsigned tempPos = p->tempPos - num;
unsigned i;
p->tempPos = tempPos;
for (i = 0; i < tempPos; i++)
p->temp[i] = p->temp[i + num];
p->src = src;
p->srcLim = srcLim;
p->finishMode = finishMode;
if (p->state != BCJ2_ENC_STATE_ORIG || src == srcLim)
return;
if (extra >= tempPos)
{
p->src = src - tempPos;
p->tempPos = 0;
break;
}
p->temp[tempPos] = src[0];
p->tempPos = tempPos + 1;
p->src = src + 1;
extra++;
}
}
}
PRF(printf("++++ ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
Bcj2Enc_Encode_2(p);
if (p->state == BCJ2_ENC_STATE_ORIG)
{
const Byte *src = p->src;
unsigned rem = (unsigned)(p->srcLim - src);
unsigned i;
for (i = 0; i < rem; i++)
p->temp[i] = src[i];
p->tempPos = rem;
p->src = src + rem;
}
}

48
C/Blake2.h Normal file
View File

@@ -0,0 +1,48 @@
/* Blake2.h -- BLAKE2 Hash
2015-06-30 : Igor Pavlov : Public domain
2015 : Samuel Neves : Public domain */
#ifndef __BLAKE2_H
#define __BLAKE2_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define BLAKE2S_BLOCK_SIZE 64
#define BLAKE2S_DIGEST_SIZE 32
#define BLAKE2SP_PARALLEL_DEGREE 8
typedef struct
{
UInt32 h[8];
UInt32 t[2];
UInt32 f[2];
Byte buf[BLAKE2S_BLOCK_SIZE];
UInt32 bufPos;
UInt32 lastNode_f1;
UInt32 dummy[2]; /* for sizeof(CBlake2s) alignment */
} CBlake2s;
/* You need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
/*
void Blake2s_Init0(CBlake2s *p);
void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size);
void Blake2s_Final(CBlake2s *p, Byte *digest);
*/
typedef struct
{
CBlake2s S[BLAKE2SP_PARALLEL_DEGREE];
unsigned bufPos;
} CBlake2sp;
void Blake2sp_Init(CBlake2sp *p);
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size);
void Blake2sp_Final(CBlake2sp *p, Byte *digest);
EXTERN_C_END
#endif

244
C/Blake2s.c Normal file
View File

@@ -0,0 +1,244 @@
/* Blake2s.c -- BLAKE2s and BLAKE2sp Hash
2015-06-30 : Igor Pavlov : Public domain
2015 : Samuel Neves : Public domain */
#include <string.h>
#include "Blake2.h"
#include "CpuArch.h"
#include "RotateDefs.h"
#define rotr32 rotrFixed
#define BLAKE2S_NUM_ROUNDS 10
#define BLAKE2S_FINAL_FLAG (~(UInt32)0)
static const UInt32 k_Blake2s_IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
static const Byte k_Blake2s_Sigma[BLAKE2S_NUM_ROUNDS][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
};
void Blake2s_Init0(CBlake2s *p)
{
unsigned i;
for (i = 0; i < 8; i++)
p->h[i] = k_Blake2s_IV[i];
p->t[0] = 0;
p->t[1] = 0;
p->f[0] = 0;
p->f[1] = 0;
p->bufPos = 0;
p->lastNode_f1 = 0;
}
static void Blake2s_Compress(CBlake2s *p)
{
UInt32 m[16];
UInt32 v[16];
{
unsigned i;
for (i = 0; i < 16; i++)
m[i] = GetUi32(p->buf + i * sizeof(m[i]));
for (i = 0; i < 8; i++)
v[i] = p->h[i];
}
v[ 8] = k_Blake2s_IV[0];
v[ 9] = k_Blake2s_IV[1];
v[10] = k_Blake2s_IV[2];
v[11] = k_Blake2s_IV[3];
v[12] = p->t[0] ^ k_Blake2s_IV[4];
v[13] = p->t[1] ^ k_Blake2s_IV[5];
v[14] = p->f[0] ^ k_Blake2s_IV[6];
v[15] = p->f[1] ^ k_Blake2s_IV[7];
#define G(r,i,a,b,c,d) \
a += b + m[sigma[2*i+0]]; d ^= a; d = rotr32(d, 16); c += d; b ^= c; b = rotr32(b, 12); \
a += b + m[sigma[2*i+1]]; d ^= a; d = rotr32(d, 8); c += d; b ^= c; b = rotr32(b, 7); \
#define R(r) \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
{
unsigned r;
for (r = 0; r < BLAKE2S_NUM_ROUNDS; r++)
{
const Byte *sigma = k_Blake2s_Sigma[r];
R(r);
}
/* R(0); R(1); R(2); R(3); R(4); R(5); R(6); R(7); R(8); R(9); */
}
#undef G
#undef R
{
unsigned i;
for (i = 0; i < 8; i++)
p->h[i] ^= v[i] ^ v[i + 8];
}
}
#define Blake2s_Increment_Counter(S, inc) \
{ p->t[0] += (inc); p->t[1] += (p->t[0] < (inc)); }
#define Blake2s_Set_LastBlock(p) \
{ p->f[0] = BLAKE2S_FINAL_FLAG; p->f[1] = p->lastNode_f1; }
static void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size)
{
while (size != 0)
{
unsigned pos = (unsigned)p->bufPos;
unsigned rem = BLAKE2S_BLOCK_SIZE - pos;
if (size <= rem)
{
memcpy(p->buf + pos, data, size);
p->bufPos += (UInt32)size;
return;
}
memcpy(p->buf + pos, data, rem);
Blake2s_Increment_Counter(S, BLAKE2S_BLOCK_SIZE);
Blake2s_Compress(p);
p->bufPos = 0;
data += rem;
size -= rem;
}
}
static void Blake2s_Final(CBlake2s *p, Byte *digest)
{
unsigned i;
Blake2s_Increment_Counter(S, (UInt32)p->bufPos);
Blake2s_Set_LastBlock(p);
memset(p->buf + p->bufPos, 0, BLAKE2S_BLOCK_SIZE - p->bufPos);
Blake2s_Compress(p);
for (i = 0; i < 8; i++)
SetUi32(digest + sizeof(p->h[i]) * i, p->h[i]);
}
/* ---------- BLAKE2s ---------- */
/* we need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */
/*
typedef struct
{
Byte digest_length;
Byte key_length;
Byte fanout;
Byte depth;
UInt32 leaf_length;
Byte node_offset[6];
Byte node_depth;
Byte inner_length;
Byte salt[BLAKE2S_SALTBYTES];
Byte personal[BLAKE2S_PERSONALBYTES];
} CBlake2sParam;
*/
static void Blake2sp_Init_Spec(CBlake2s *p, unsigned node_offset, unsigned node_depth)
{
Blake2s_Init0(p);
p->h[0] ^= (BLAKE2S_DIGEST_SIZE | ((UInt32)BLAKE2SP_PARALLEL_DEGREE << 16) | ((UInt32)2 << 24));
p->h[2] ^= ((UInt32)node_offset);
p->h[3] ^= ((UInt32)node_depth << 16) | ((UInt32)BLAKE2S_DIGEST_SIZE << 24);
/*
P->digest_length = BLAKE2S_DIGEST_SIZE;
P->key_length = 0;
P->fanout = BLAKE2SP_PARALLEL_DEGREE;
P->depth = 2;
P->leaf_length = 0;
store48(P->node_offset, node_offset);
P->node_depth = node_depth;
P->inner_length = BLAKE2S_DIGEST_SIZE;
*/
}
void Blake2sp_Init(CBlake2sp *p)
{
unsigned i;
p->bufPos = 0;
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
Blake2sp_Init_Spec(&p->S[i], i, 0);
p->S[BLAKE2SP_PARALLEL_DEGREE - 1].lastNode_f1 = BLAKE2S_FINAL_FLAG;
}
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size)
{
unsigned pos = p->bufPos;
while (size != 0)
{
unsigned index = pos / BLAKE2S_BLOCK_SIZE;
unsigned rem = BLAKE2S_BLOCK_SIZE - (pos & (BLAKE2S_BLOCK_SIZE - 1));
if (rem > size)
rem = (unsigned)size;
Blake2s_Update(&p->S[index], data, rem);
size -= rem;
data += rem;
pos += rem;
pos &= (BLAKE2S_BLOCK_SIZE * BLAKE2SP_PARALLEL_DEGREE - 1);
}
p->bufPos = pos;
}
void Blake2sp_Final(CBlake2sp *p, Byte *digest)
{
CBlake2s R;
unsigned i;
Blake2sp_Init_Spec(&R, 0, 1);
R.lastNode_f1 = BLAKE2S_FINAL_FLAG;
for (i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++)
{
Byte hash[BLAKE2S_DIGEST_SIZE];
Blake2s_Final(&p->S[i], hash);
Blake2s_Update(&R, hash, BLAKE2S_DIGEST_SIZE);
}
Blake2s_Final(&R, digest);
}

View File

@@ -513,4 +513,3 @@ UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
#endif #endif
return Groups[0]; return Groups[0];
} }

View File

@@ -1,5 +1,5 @@
/* Compiler.h -- Compiler ypes /* Compiler.h
2013-11-12 : Igor Pavlov : Public domain */ 2015-08-02 : Igor Pavlov : Public domain */
#ifndef __7Z_COMPILER_H #ifndef __7Z_COMPILER_H
#define __7Z_COMPILER_H #define __7Z_COMPILER_H
@@ -18,6 +18,7 @@
#else #else
#pragma warning(disable : 4511) // copy constructor could not be generated #pragma warning(disable : 4511) // copy constructor could not be generated
#pragma warning(disable : 4512) // assignment operator could not be generated #pragma warning(disable : 4512) // assignment operator could not be generated
#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 : 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
@@ -25,4 +26,7 @@
#endif #endif
#define UNUSED_VAR(x) (void)x;
/* #define UNUSED_VAR(x) x=x; */
#endif #endif

View File

@@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code /* CpuArch.c -- CPU specific code
2012-05-29: Igor Pavlov : Public domain */ 2015-03-25: Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -54,7 +54,7 @@ static UInt32 CheckFlag(UInt32 flag)
#define CHECK_CPUID_IS_SUPPORTED #define CHECK_CPUID_IS_SUPPORTED
#endif #endif
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{ {
#ifdef USE_ASM #ifdef USE_ASM
@@ -116,7 +116,7 @@ Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
return True; return True;
} }
static UInt32 kVendors[][3] = static const UInt32 kVendors[][3] =
{ {
{ 0x756E6547, 0x49656E69, 0x6C65746E}, { 0x756E6547, 0x49656E69, 0x6C65746E},
{ 0x68747541, 0x69746E65, 0x444D4163}, { 0x68747541, 0x69746E65, 0x444D4163},
@@ -144,18 +144,21 @@ Bool CPU_Is_InOrder()
UInt32 family, model; UInt32 family, model;
if (!x86cpuid_CheckAndRead(&p)) if (!x86cpuid_CheckAndRead(&p))
return True; return True;
family = x86cpuid_GetFamily(&p);
model = x86cpuid_GetModel(&p); family = x86cpuid_GetFamily(p.ver);
model = x86cpuid_GetModel(p.ver);
firm = x86cpuid_GetFirm(&p); firm = x86cpuid_GetFirm(&p);
switch (firm) switch (firm)
{ {
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
/* Atom CPU */ /* In-Order Atom CPU */
model == 0x100C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
|| model == 0x2006 /* 45 nm, Z6xx */ || model == 0x26 /* 45 nm, Z6xx */
|| model == 0x2007 /* 32 nm, Z2460 */ || model == 0x27 /* 32 nm, Z2460 */
|| model == 0x3005 /* 32 nm, Z2760 */ || model == 0x35 /* 32 nm, Z2760 */
|| model == 0x3006 /* 32 nm, N2xxx, D2xxx */ || model == 0x36 /* 32 nm, N2xxx, D2xxx */
))); )));
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));

View File

@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code /* CpuArch.h -- CPU specific code
2013-11-12: Igor Pavlov : Public domain */ 2015-12-01: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H #ifndef __CPU_ARCH_H
#define __CPU_ARCH_H #define __CPU_ARCH_H
@@ -10,18 +10,25 @@ EXTERN_C_BEGIN
/* /*
MY_CPU_LE means that CPU is LITTLE ENDIAN. MY_CPU_LE means that CPU is LITTLE ENDIAN.
If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). MY_CPU_BE means that CPU is BIG ENDIAN.
If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.
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 MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
*/ */
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) #if defined(_M_X64) \
#define MY_CPU_AMD64 || defined(_M_AMD64) \
|| defined(__x86_64__) \
|| defined(__AMD64__) \
|| defined(__amd64__)
#define MY_CPU_AMD64
#endif #endif
#if defined(MY_CPU_AMD64) || defined(_M_IA64) #if defined(MY_CPU_AMD64) \
#define MY_CPU_64BIT || defined(_M_IA64) \
|| defined(__AARCH64EL__) \
|| defined(__AARCH64EB__)
#define MY_CPU_64BIT
#endif #endif
#if defined(_M_IX86) || defined(__i386__) #if defined(_M_IX86) || defined(__i386__)
@@ -32,8 +39,13 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define MY_CPU_X86_OR_AMD64 #define MY_CPU_X86_OR_AMD64
#endif #endif
#if defined(MY_CPU_X86) || defined(_M_ARM) #if defined(MY_CPU_X86) \
#define MY_CPU_32BIT || defined(_M_ARM) \
|| defined(__ARMEL__) \
|| defined(__THUMBEL__) \
|| defined(__ARMEB__) \
|| defined(__THUMBEB__)
#define MY_CPU_32BIT
#endif #endif
#if defined(_WIN32) && defined(_M_ARM) #if defined(_WIN32) && defined(_M_ARM)
@@ -44,34 +56,63 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define MY_CPU_IA64_LE #define MY_CPU_IA64_LE
#endif #endif
#if defined(MY_CPU_X86_OR_AMD64) #if defined(MY_CPU_X86_OR_AMD64) \
#define MY_CPU_LE_UNALIGN || defined(MY_CPU_ARM_LE) \
|| defined(MY_CPU_IA64_LE) \
|| defined(__LITTLE_ENDIAN__) \
|| defined(__ARMEL__) \
|| defined(__THUMBEL__) \
|| defined(__AARCH64EL__) \
|| defined(__MIPSEL__) \
|| defined(__MIPSEL) \
|| defined(_MIPSEL) \
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
#define MY_CPU_LE
#endif #endif
#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) #if defined(__BIG_ENDIAN__) \
#define MY_CPU_LE || defined(__ARMEB__) \
#endif || defined(__THUMBEB__) \
|| defined(__AARCH64EB__) \
#if defined(__BIG_ENDIAN__) || defined(__m68k__) || defined(__ARMEB__) || defined(__MIPSEB__) || defined(__MIPSEB__) \
#define MY_CPU_BE || defined(__MIPSEB) \
|| defined(_MIPSEB) \
|| defined(__m68k__) \
|| defined(__s390__) \
|| defined(__s390x__) \
|| defined(__zarch__) \
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
#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 Stop_Compiling_Bad_Endian
#endif #endif
#ifdef MY_CPU_LE
#if defined(MY_CPU_X86_OR_AMD64) \
/* || defined(__AARCH64EL__) */
#define MY_CPU_LE_UNALIGN
#endif
#endif
#ifdef MY_CPU_LE_UNALIGN #ifdef MY_CPU_LE_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(const void *)(p)) #define GetUi16(p) (*(const UInt16 *)(const void *)(p))
#define GetUi32(p) (*(const UInt32 *)(const void *)(p)) #define GetUi32(p) (*(const UInt32 *)(const void *)(p))
#define GetUi64(p) (*(const UInt64 *)(const void *)(p)) #define GetUi64(p) (*(const UInt64 *)(const void *)(p))
#define SetUi16(p, d) *(UInt16 *)(p) = (d);
#define SetUi32(p, d) *(UInt32 *)(p) = (d); #define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
#define SetUi64(p, d) *(UInt64 *)(p) = (d); #define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
#else #else
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) #define GetUi16(p) ( (UInt16) ( \
((const Byte *)(p))[0] | \
((UInt16)((const Byte *)(p))[1] << 8) ))
#define GetUi32(p) ( \ #define GetUi32(p) ( \
((const Byte *)(p))[0] | \ ((const Byte *)(p))[0] | \
@@ -81,23 +122,26 @@ Stop_Compiling_Bad_Endian
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
#define SetUi16(p, d) { UInt32 _x_ = (d); \ #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
((Byte *)(p))[0] = (Byte)_x_; \ _ppp_[0] = (Byte)_vvv_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); } _ppp_[1] = (Byte)(_vvv_ >> 8); }
#define SetUi32(p, d) { UInt32 _x_ = (d); \ #define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
((Byte *)(p))[0] = (Byte)_x_; \ _ppp_[0] = (Byte)_vvv_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ _ppp_[1] = (Byte)(_vvv_ >> 8); \
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ _ppp_[2] = (Byte)(_vvv_ >> 16); \
((Byte *)(p))[3] = (Byte)(_x_ >> 24); } _ppp_[3] = (Byte)(_vvv_ >> 24); }
#define SetUi64(p, d) { UInt64 _x64_ = (d); \ #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
SetUi32(p, (UInt32)_x64_); \ SetUi32(_ppp2_ , (UInt32)_vvv2_); \
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); } SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }
#endif #endif
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
/* Note: we use bswap instruction, that is unsupported in 386 cpu */
#include <stdlib.h> #include <stdlib.h>
@@ -106,6 +150,15 @@ Stop_Compiling_Bad_Endian
#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)
#elif defined(MY_CPU_LE_UNALIGN) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
#else #else
#define GetBe32(p) ( \ #define GetBe32(p) ( \
@@ -116,9 +169,19 @@ Stop_Compiling_Bad_Endian
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
_ppp_[0] = (Byte)(_vvv_ >> 24); \
_ppp_[1] = (Byte)(_vvv_ >> 16); \
_ppp_[2] = (Byte)(_vvv_ >> 8); \
_ppp_[3] = (Byte)_vvv_; }
#endif #endif
#define GetBe16(p) ((UInt16)(((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]))
#define GetBe16(p) ( (UInt16) ( \
((UInt16)((const Byte *)(p))[0] << 8) | \
((const Byte *)(p))[1] ))
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
@@ -140,12 +203,14 @@ enum
CPU_FIRM_VIA CPU_FIRM_VIA
}; };
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
Bool x86cpuid_CheckAndRead(Cx86cpuid *p); Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p); int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F) #define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F) #define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF) #define x86cpuid_GetStepping(ver) (ver & 0xF)
Bool CPU_Is_InOrder(); Bool CPU_Is_InOrder();
Bool CPU_Is_Aes_Supported(); Bool CPU_Is_Aes_Supported();

View File

@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms /* LzFind.c -- Match finder for LZ algorithms
2009-04-22 : Igor Pavlov : Public domain */ 2015-10-15 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -11,8 +11,8 @@
#define kEmptyHashValue 0 #define kEmptyHashValue 0
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
#define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
#define kMaxHistorySize ((UInt32)3 << 30) #define kMaxHistorySize ((UInt32)7 << 29)
#define kStartMaxLen 3 #define kStartMaxLen 3
@@ -21,7 +21,7 @@ static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
if (!p->directInput) if (!p->directInput)
{ {
alloc->Free(alloc, p->bufferBase); alloc->Free(alloc, p->bufferBase);
p->bufferBase = 0; p->bufferBase = NULL;
} }
} }
@@ -35,17 +35,16 @@ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *a
p->blockSize = blockSize; p->blockSize = blockSize;
return 1; return 1;
} }
if (p->bufferBase == 0 || p->blockSize != blockSize) if (!p->bufferBase || p->blockSize != blockSize)
{ {
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 *)alloc->Alloc(alloc, (size_t)blockSize);
} }
return (p->bufferBase != 0); return (p->bufferBase != NULL);
} }
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
@@ -60,9 +59,12 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
{ {
if (p->streamEndWasReached || p->result != SZ_OK) if (p->streamEndWasReached || p->result != SZ_OK)
return; return;
/* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
if (p->directInput) if (p->directInput)
{ {
UInt32 curSize = 0xFFFFFFFF - p->streamPos; UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
if (curSize > p->directInputRem) if (curSize > p->directInputRem)
curSize = (UInt32)p->directInputRem; curSize = (UInt32)p->directInputRem;
p->directInputRem -= curSize; p->directInputRem -= curSize;
@@ -71,12 +73,14 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
p->streamEndWasReached = 1; p->streamEndWasReached = 1;
return; return;
} }
for (;;) for (;;)
{ {
Byte *dest = p->buffer + (p->streamPos - p->pos); Byte *dest = p->buffer + (p->streamPos - p->pos);
size_t size = (p->bufferBase + p->blockSize - dest); size_t size = (p->bufferBase + p->blockSize - dest);
if (size == 0) if (size == 0)
return; return;
p->result = p->stream->Read(p->stream, dest, &size); p->result = p->stream->Read(p->stream, dest, &size);
if (p->result != SZ_OK) if (p->result != SZ_OK)
return; return;
@@ -94,8 +98,8 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
void MatchFinder_MoveBlock(CMatchFinder *p) void MatchFinder_MoveBlock(CMatchFinder *p)
{ {
memmove(p->bufferBase, memmove(p->bufferBase,
p->buffer - p->keepSizeBefore, p->buffer - p->keepSizeBefore,
(size_t)(p->streamPos - p->pos + p->keepSizeBefore)); (size_t)(p->streamPos - p->pos) + p->keepSizeBefore);
p->buffer = p->bufferBase + p->keepSizeBefore; p->buffer = p->bufferBase + p->keepSizeBefore;
} }
@@ -135,15 +139,15 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
void MatchFinder_Construct(CMatchFinder *p) void MatchFinder_Construct(CMatchFinder *p)
{ {
UInt32 i; UInt32 i;
p->bufferBase = 0; p->bufferBase = NULL;
p->directInput = 0; p->directInput = 0;
p->hash = 0; p->hash = NULL;
MatchFinder_SetDefaultSettings(p); MatchFinder_SetDefaultSettings(p);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
UInt32 r = i; UInt32 r = i;
int 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 & ~((r & 1) - 1));
p->crc[i] = r; p->crc[i] = r;
@@ -153,7 +157,7 @@ void MatchFinder_Construct(CMatchFinder *p)
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
{ {
alloc->Free(alloc, p->hash); alloc->Free(alloc, p->hash);
p->hash = 0; p->hash = NULL;
} }
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
@@ -162,11 +166,11 @@ void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
LzInWindow_Free(p, alloc); LzInWindow_Free(p, alloc);
} }
static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) static CLzRef* AllocRefs(size_t num, ISzAlloc *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 0; return NULL;
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
} }
@@ -175,19 +179,24 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
ISzAlloc *alloc) ISzAlloc *alloc)
{ {
UInt32 sizeReserv; UInt32 sizeReserv;
if (historySize > kMaxHistorySize) if (historySize > kMaxHistorySize)
{ {
MatchFinder_Free(p, alloc); MatchFinder_Free(p, alloc);
return 0; return 0;
} }
sizeReserv = historySize >> 1; sizeReserv = historySize >> 1;
if (historySize > ((UInt32)2 << 30)) if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3;
sizeReserv = historySize >> 2; else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2;
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
if (LzInWindow_Create(p, sizeReserv, alloc)) if (LzInWindow_Create(p, sizeReserv, alloc))
{ {
UInt32 newCyclicBufferSize = historySize + 1; UInt32 newCyclicBufferSize = historySize + 1;
@@ -212,6 +221,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
hs = (1 << 24) - 1; hs = (1 << 24) - 1;
else else
hs >>= 1; hs >>= 1;
/* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
} }
} }
p->hashMask = hs; p->hashMask = hs;
@@ -223,24 +233,32 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
} }
{ {
UInt32 prevSize = p->hashSizeSum + p->numSons; size_t newSize;
UInt32 newSize; size_t numSons;
p->historySize = historySize; p->historySize = historySize;
p->hashSizeSum = hs; p->hashSizeSum = hs;
p->cyclicBufferSize = newCyclicBufferSize; p->cyclicBufferSize = newCyclicBufferSize;
p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
newSize = p->hashSizeSum + p->numSons; numSons = newCyclicBufferSize;
if (p->hash != 0 && prevSize == newSize) if (p->btMode)
numSons <<= 1;
newSize = hs + numSons;
if (p->hash && p->numRefs == newSize)
return 1; return 1;
MatchFinder_FreeThisClassMemory(p, alloc); MatchFinder_FreeThisClassMemory(p, alloc);
p->numRefs = newSize;
p->hash = AllocRefs(newSize, alloc); p->hash = AllocRefs(newSize, alloc);
if (p->hash != 0)
if (p->hash)
{ {
p->son = p->hash + p->hashSizeSum; p->son = p->hash + p->hashSizeSum;
return 1; return 1;
} }
} }
} }
MatchFinder_Free(p, alloc); MatchFinder_Free(p, alloc);
return 0; return 0;
} }
@@ -249,9 +267,11 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
{ {
UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit = kMaxValForNormalize - p->pos;
UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
if (limit2 < limit) if (limit2 < limit)
limit = limit2; limit = limit2;
limit2 = p->streamPos - p->pos; limit2 = p->streamPos - p->pos;
if (limit2 <= p->keepSizeAfter) if (limit2 <= p->keepSizeAfter)
{ {
if (limit2 > 0) if (limit2 > 0)
@@ -259,8 +279,10 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
} }
else else
limit2 -= p->keepSizeAfter; limit2 -= p->keepSizeAfter;
if (limit2 < limit) if (limit2 < limit)
limit = limit2; limit = limit2;
{ {
UInt32 lenLimit = p->streamPos - p->pos; UInt32 lenLimit = p->streamPos - p->pos;
if (lenLimit > p->matchMaxLen) if (lenLimit > p->matchMaxLen)
@@ -270,28 +292,39 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
p->posLimit = p->pos + limit; p->posLimit = p->pos + limit;
} }
void MatchFinder_Init(CMatchFinder *p) void MatchFinder_Init_2(CMatchFinder *p, int readData)
{ {
UInt32 i; UInt32 i;
for (i = 0; i < p->hashSizeSum; i++) UInt32 *hash = p->hash;
p->hash[i] = kEmptyHashValue; UInt32 num = p->hashSizeSum;
for (i = 0; i < num; i++)
hash[i] = kEmptyHashValue;
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;
MatchFinder_ReadBlock(p);
if (readData)
MatchFinder_ReadBlock(p);
MatchFinder_SetLimits(p); MatchFinder_SetLimits(p);
} }
void MatchFinder_Init(CMatchFinder *p)
{
MatchFinder_Init_2(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;
} }
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)
{ {
UInt32 i; size_t i;
for (i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
{ {
UInt32 value = items[i]; UInt32 value = items[i];
@@ -306,7 +339,7 @@ void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
static void MatchFinder_Normalize(CMatchFinder *p) static void MatchFinder_Normalize(CMatchFinder *p)
{ {
UInt32 subValue = MatchFinder_GetSubValue(p); UInt32 subValue = MatchFinder_GetSubValue(p);
MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_Normalize3(subValue, p->hash, p->numRefs);
MatchFinder_ReduceOffsets(p, subValue); MatchFinder_ReduceOffsets(p, subValue);
} }
@@ -467,7 +500,7 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
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 hashValue; const Byte *cur; UInt32 curMatch; \ UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
cur = p->buffer; cur = p->buffer;
@@ -483,13 +516,20 @@ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define SKIP_FOOTER \ #define SKIP_FOOTER \
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
#define UPDATE_maxLen { \
ptrdiff_t diff = (ptrdiff_t)0 - d2; \
const Byte *c = cur + maxLen; \
const Byte *lim = cur + lenLimit; \
for (; c != lim; c++) if (*(c + diff) != *c) break; \
maxLen = (UInt32)(c - cur); }
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 offset; UInt32 offset;
GET_MATCHES_HEADER(2) GET_MATCHES_HEADER(2)
HASH2_CALC; HASH2_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
offset = 0; offset = 0;
GET_MATCHES_FOOTER(offset, 1) GET_MATCHES_FOOTER(offset, 1)
} }
@@ -499,35 +539,38 @@ UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 offset; UInt32 offset;
GET_MATCHES_HEADER(3) GET_MATCHES_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
offset = 0; offset = 0;
GET_MATCHES_FOOTER(offset, 2) GET_MATCHES_FOOTER(offset, 2)
} }
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 hash2Value, delta2, maxLen, offset; UInt32 h2, d2, maxLen, offset, pos;
UInt32 *hash;
GET_MATCHES_HEADER(3) GET_MATCHES_HEADER(3)
HASH3_CALC; HASH3_CALC;
delta2 = p->pos - p->hash[hash2Value]; hash = p->hash;
curMatch = p->hash[kFix3HashSize + hashValue]; pos = p->pos;
p->hash[hash2Value] =
p->hash[kFix3HashSize + hashValue] = p->pos;
d2 = pos - hash[h2];
curMatch = hash[kFix3HashSize + hv];
hash[h2] = pos;
hash[kFix3HashSize + hv] = pos;
maxLen = 2; maxLen = 2;
offset = 0; offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{ {
for (; maxLen != lenLimit; maxLen++) UPDATE_maxLen
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[0] = maxLen; distances[0] = maxLen;
distances[1] = delta2 - 1; distances[1] = d2 - 1;
offset = 2; offset = 2;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
@@ -535,44 +578,51 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
MOVE_POS_RET; MOVE_POS_RET;
} }
} }
GET_MATCHES_FOOTER(offset, maxLen) GET_MATCHES_FOOTER(offset, maxLen)
} }
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; UInt32 h2, h3, d2, d3, maxLen, offset, pos;
UInt32 *hash;
GET_MATCHES_HEADER(4) GET_MATCHES_HEADER(4)
HASH4_CALC; HASH4_CALC;
delta2 = p->pos - p->hash[ hash2Value]; hash = p->hash;
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; pos = p->pos;
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] =
p->hash[kFix3HashSize + hash3Value] =
p->hash[kFix4HashSize + hashValue] = p->pos;
maxLen = 1; d2 = pos - hash[ h2];
d3 = pos - hash[kFix3HashSize + h3];
curMatch = hash[kFix4HashSize + hv];
hash[ h2] = pos;
hash[kFix3HashSize + h3] = pos;
hash[kFix4HashSize + hv] = pos;
maxLen = 0;
offset = 0; offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{ {
distances[0] = maxLen = 2; distances[0] = maxLen = 2;
distances[1] = delta2 - 1; distances[1] = d2 - 1;
offset = 2; offset = 2;
} }
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{ {
maxLen = 3; maxLen = 3;
distances[offset + 1] = delta3 - 1; distances[offset + 1] = d3 - 1;
offset += 2; offset += 2;
delta2 = delta3; d2 = d3;
} }
if (offset != 0) if (offset != 0)
{ {
for (; maxLen != lenLimit; maxLen++) UPDATE_maxLen
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[offset - 2] = maxLen; distances[offset - 2] = maxLen;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
@@ -580,46 +630,131 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
MOVE_POS_RET; MOVE_POS_RET;
} }
} }
if (maxLen < 3) if (maxLen < 3)
maxLen = 3; maxLen = 3;
GET_MATCHES_FOOTER(offset, maxLen) GET_MATCHES_FOOTER(offset, maxLen)
} }
/*
static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
UInt32 *hash;
GET_MATCHES_HEADER(5)
HASH5_CALC;
hash = p->hash;
pos = p->pos;
d2 = pos - hash[ h2];
d3 = pos - hash[kFix3HashSize + h3];
d4 = pos - hash[kFix4HashSize + h4];
curMatch = hash[kFix5HashSize + hv];
hash[ h2] = pos;
hash[kFix3HashSize + h3] = pos;
hash[kFix4HashSize + h4] = pos;
hash[kFix5HashSize + hv] = pos;
maxLen = 0;
offset = 0;
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
distances[0] = maxLen = 2;
distances[1] = d2 - 1;
offset = 2;
if (*(cur - d2 + 2) == cur[2])
distances[0] = maxLen = 3;
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
distances[2] = maxLen = 3;
distances[3] = d3 - 1;
offset = 4;
d2 = d3;
}
}
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
distances[0] = maxLen = 3;
distances[1] = d3 - 1;
offset = 2;
d2 = d3;
}
if (d2 != d4 && d4 < p->cyclicBufferSize
&& *(cur - d4) == *cur
&& *(cur - d4 + 3) == *(cur + 3))
{
maxLen = 4;
distances[offset + 1] = d4 - 1;
offset += 2;
d2 = d4;
}
if (offset != 0)
{
UPDATE_maxLen
distances[offset - 2] = maxLen;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
if (maxLen < 4)
maxLen = 4;
GET_MATCHES_FOOTER(offset, maxLen)
}
*/
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; UInt32 h2, h3, d2, d3, maxLen, offset, pos;
UInt32 *hash;
GET_MATCHES_HEADER(4) GET_MATCHES_HEADER(4)
HASH4_CALC; HASH4_CALC;
delta2 = p->pos - p->hash[ hash2Value]; hash = p->hash;
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; pos = p->pos;
curMatch = p->hash[kFix4HashSize + hashValue];
d2 = pos - hash[ h2];
d3 = pos - hash[kFix3HashSize + h3];
curMatch = hash[kFix4HashSize + hv];
p->hash[ hash2Value] = hash[ h2] = pos;
p->hash[kFix3HashSize + hash3Value] = hash[kFix3HashSize + h3] = pos;
p->hash[kFix4HashSize + hashValue] = p->pos; hash[kFix4HashSize + hv] = pos;
maxLen = 1; maxLen = 0;
offset = 0; offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{ {
distances[0] = maxLen = 2; distances[0] = maxLen = 2;
distances[1] = delta2 - 1; distances[1] = d2 - 1;
offset = 2; offset = 2;
} }
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{ {
maxLen = 3; maxLen = 3;
distances[offset + 1] = delta3 - 1; distances[offset + 1] = d3 - 1;
offset += 2; offset += 2;
delta2 = delta3; d2 = d3;
} }
if (offset != 0) if (offset != 0)
{ {
for (; maxLen != lenLimit; maxLen++) UPDATE_maxLen
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[offset - 2] = maxLen; distances[offset - 2] = maxLen;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
@@ -627,22 +762,103 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
MOVE_POS_RET; MOVE_POS_RET;
} }
} }
if (maxLen < 3) if (maxLen < 3)
maxLen = 3; maxLen = 3;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances + offset, maxLen) - (distances)); distances + offset, maxLen) - (distances));
MOVE_POS_RET MOVE_POS_RET
} }
/*
static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
UInt32 *hash;
GET_MATCHES_HEADER(5)
HASH5_CALC;
hash = p->hash;
pos = p->pos;
d2 = pos - hash[ h2];
d3 = pos - hash[kFix3HashSize + h3];
d4 = pos - hash[kFix4HashSize + h4];
curMatch = hash[kFix5HashSize + hv];
hash[ h2] = pos;
hash[kFix3HashSize + h3] = pos;
hash[kFix4HashSize + h4] = pos;
hash[kFix5HashSize + hv] = pos;
maxLen = 0;
offset = 0;
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
distances[0] = maxLen = 2;
distances[1] = d2 - 1;
offset = 2;
if (*(cur - d2 + 2) == cur[2])
distances[0] = maxLen = 3;
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
distances[2] = maxLen = 3;
distances[3] = d3 - 1;
offset = 4;
d2 = d3;
}
}
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
distances[0] = maxLen = 3;
distances[1] = d3 - 1;
offset = 2;
d2 = d3;
}
if (d2 != d4 && d4 < p->cyclicBufferSize
&& *(cur - d4) == *cur
&& *(cur - d4 + 3) == *(cur + 3))
{
maxLen = 4;
distances[offset + 1] = d4 - 1;
offset += 2;
d2 = d4;
}
if (offset != 0)
{
UPDATE_maxLen
distances[offset - 2] = maxLen;
if (maxLen == lenLimit)
{
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS_RET;
}
}
if (maxLen < 4)
maxLen = 4;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances + offset, maxLen) - (distances));
MOVE_POS_RET
}
*/
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{ {
UInt32 offset; UInt32 offset;
GET_MATCHES_HEADER(3) GET_MATCHES_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances, 2) - (distances)); distances, 2) - (distances));
MOVE_POS_RET MOVE_POS_RET
} }
@@ -652,8 +868,8 @@ static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
SKIP_HEADER(2) SKIP_HEADER(2)
HASH2_CALC; HASH2_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
@@ -665,8 +881,8 @@ void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
SKIP_HEADER(3) SKIP_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
@@ -676,12 +892,14 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
do do
{ {
UInt32 hash2Value; UInt32 h2;
UInt32 *hash;
SKIP_HEADER(3) SKIP_HEADER(3)
HASH3_CALC; HASH3_CALC;
curMatch = p->hash[kFix3HashSize + hashValue]; hash = p->hash;
p->hash[hash2Value] = curMatch = hash[kFix3HashSize + hv];
p->hash[kFix3HashSize + hashValue] = p->pos; hash[h2] =
hash[kFix3HashSize + hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
@@ -691,43 +909,90 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
do do
{ {
UInt32 hash2Value, hash3Value; UInt32 h2, h3;
UInt32 *hash;
SKIP_HEADER(4) SKIP_HEADER(4)
HASH4_CALC; HASH4_CALC;
curMatch = p->hash[kFix4HashSize + hashValue]; hash = p->hash;
p->hash[ hash2Value] = curMatch = hash[kFix4HashSize + hv];
p->hash[kFix3HashSize + hash3Value] = p->pos; hash[ h2] =
p->hash[kFix4HashSize + hashValue] = p->pos; hash[kFix3HashSize + h3] =
hash[kFix4HashSize + hv] = p->pos;
SKIP_FOOTER SKIP_FOOTER
} }
while (--num != 0); while (--num != 0);
} }
/*
static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 h2, h3, h4;
UInt32 *hash;
SKIP_HEADER(5)
HASH5_CALC;
hash = p->hash;
curMatch = hash[kFix5HashSize + hv];
hash[ h2] =
hash[kFix3HashSize + h3] =
hash[kFix4HashSize + h4] =
hash[kFix5HashSize + hv] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
*/
static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
do do
{ {
UInt32 hash2Value, hash3Value; UInt32 h2, h3;
UInt32 *hash;
SKIP_HEADER(4) SKIP_HEADER(4)
HASH4_CALC; HASH4_CALC;
curMatch = p->hash[kFix4HashSize + hashValue]; hash = p->hash;
p->hash[ hash2Value] = curMatch = hash[kFix4HashSize + hv];
p->hash[kFix3HashSize + hash3Value] = hash[ h2] =
p->hash[kFix4HashSize + hashValue] = p->pos; hash[kFix3HashSize + h3] =
hash[kFix4HashSize + hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS MOVE_POS
} }
while (--num != 0); while (--num != 0);
} }
/*
static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 h2, h3, h4;
UInt32 *hash;
SKIP_HEADER(5)
HASH5_CALC;
hash = p->hash;
curMatch = p->hash[kFix5HashSize + hv];
hash[ h2] =
hash[kFix3HashSize + h3] =
hash[kFix4HashSize + h4] =
hash[kFix5HashSize + hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
while (--num != 0);
}
*/
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{ {
do do
{ {
SKIP_HEADER(3) SKIP_HEADER(3)
HASH_ZIP_CALC; HASH_ZIP_CALC;
curMatch = p->hash[hashValue]; curMatch = p->hash[hv];
p->hash[hashValue] = p->pos; p->hash[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS MOVE_POS
} }
@@ -737,13 +1002,22 @@ void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
{ {
vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->Init = (Mf_Init_Func)MatchFinder_Init;
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
if (!p->btMode) if (!p->btMode)
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; /* if (p->numHashBytes <= 4) */
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; {
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
}
/*
else
{
vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
}
*/
} }
else if (p->numHashBytes == 2) else if (p->numHashBytes == 2)
{ {
@@ -755,9 +1029,16 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
} }
else else /* if (p->numHashBytes == 4) */
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
} }
/*
else
{
vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;
}
*/
} }

View File

@@ -1,5 +1,5 @@
/* LzFind.h -- Match finder for LZ algorithms /* LzFind.h -- Match finder for LZ algorithms
2013-01-18 : Igor Pavlov : Public domain */ 2015-10-15 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_H #ifndef __LZ_FIND_H
#define __LZ_FIND_H #define __LZ_FIND_H
@@ -21,6 +21,11 @@ typedef struct _CMatchFinder
UInt32 cyclicBufferPos; UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
Byte streamEndWasReached;
Byte btMode;
Byte bigHash;
Byte directInput;
UInt32 matchMaxLen; UInt32 matchMaxLen;
CLzRef *hash; CLzRef *hash;
CLzRef *son; CLzRef *son;
@@ -29,30 +34,30 @@ typedef struct _CMatchFinder
Byte *bufferBase; Byte *bufferBase;
ISeqInStream *stream; ISeqInStream *stream;
int streamEndWasReached;
UInt32 blockSize; UInt32 blockSize;
UInt32 keepSizeBefore; UInt32 keepSizeBefore;
UInt32 keepSizeAfter; UInt32 keepSizeAfter;
UInt32 numHashBytes; UInt32 numHashBytes;
int directInput;
size_t directInputRem; size_t directInputRem;
int btMode;
int bigHash;
UInt32 historySize; UInt32 historySize;
UInt32 fixedHashSize; UInt32 fixedHashSize;
UInt32 hashSizeSum; UInt32 hashSizeSum;
UInt32 numSons;
SRes result; SRes result;
UInt32 crc[256]; UInt32 crc[256];
size_t numRefs;
} CMatchFinder; } CMatchFinder;
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
#define Inline_MatchFinder_IsFinishedOK(p) \
((p)->streamEndWasReached \
&& (p)->streamPos == (p)->pos \
&& (!(p)->directInput || (p)->directInputRem == 0))
int MatchFinder_NeedMove(CMatchFinder *p); int MatchFinder_NeedMove(CMatchFinder *p);
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p);
@@ -68,7 +73,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc); ISzAlloc *alloc);
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 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);
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
@@ -82,7 +87,6 @@ Conditions:
*/ */
typedef void (*Mf_Init_Func)(void *object); typedef void (*Mf_Init_Func)(void *object);
typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
@@ -91,7 +95,6 @@ typedef void (*Mf_Skip_Func)(void *object, UInt32);
typedef struct _IMatchFinder typedef struct _IMatchFinder
{ {
Mf_Init_Func Init; Mf_Init_Func Init;
Mf_GetIndexByte_Func GetIndexByte;
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
Mf_GetMatches_Func GetMatches; Mf_GetMatches_Func GetMatches;
@@ -100,9 +103,12 @@ 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(CMatchFinder *p); void MatchFinder_Init(CMatchFinder *p);
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);

View File

@@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms /* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2013-11-12 : Igor Pavlov : Public domain */ 2015-10-15 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -7,7 +7,7 @@
#include "LzFindMt.h" #include "LzFindMt.h"
void MtSync_Construct(CMtSync *p) static void MtSync_Construct(CMtSync *p)
{ {
p->wasCreated = False; p->wasCreated = False;
p->csWasInitialized = False; p->csWasInitialized = False;
@@ -20,7 +20,7 @@ void MtSync_Construct(CMtSync *p)
Semaphore_Construct(&p->filledSemaphore); Semaphore_Construct(&p->filledSemaphore);
} }
void MtSync_GetNextBlock(CMtSync *p) static void MtSync_GetNextBlock(CMtSync *p)
{ {
if (p->needStart) if (p->needStart)
{ {
@@ -48,7 +48,7 @@ void MtSync_GetNextBlock(CMtSync *p)
/* MtSync_StopWriting must be called if Writing was started */ /* MtSync_StopWriting must be called if Writing was started */
void MtSync_StopWriting(CMtSync *p) static void MtSync_StopWriting(CMtSync *p)
{ {
UInt32 myNumBlocks = p->numProcessedBlocks; UInt32 myNumBlocks = p->numProcessedBlocks;
if (!Thread_WasCreated(&p->thread) || p->needStart) if (!Thread_WasCreated(&p->thread) || p->needStart)
@@ -71,7 +71,7 @@ void MtSync_StopWriting(CMtSync *p)
p->needStart = True; p->needStart = True;
} }
void MtSync_Destruct(CMtSync *p) static void MtSync_Destruct(CMtSync *p)
{ {
if (Thread_WasCreated(&p->thread)) if (Thread_WasCreated(&p->thread))
{ {
@@ -134,20 +134,20 @@ void MtSync_Init(CMtSync *p) { p->needStart = True; }
#define kMtMaxValForNormalize 0xFFFFFFFF #define kMtMaxValForNormalize 0xFFFFFFFF
#define DEF_GetHeads2(name, v, action) \ #define DEF_GetHeads2(name, v, action) \
static void GetHeads ## name(const Byte *p, UInt32 pos, \ static void GetHeads ## name(const Byte *p, UInt32 pos, \
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
{ action; for (; numHeads != 0; numHeads--) { \ { action; for (; numHeads != 0; numHeads--) { \
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; ) DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), UNUSED_VAR(hashMask); UNUSED_VAR(crc); )
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */ /* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
void HashThreadFunc(CMatchFinderMt *mt) static void HashThreadFunc(CMatchFinderMt *mt)
{ {
CMtSync *p = &mt->hashSync; CMtSync *p = &mt->hashSync;
for (;;) for (;;)
@@ -173,12 +173,12 @@ void HashThreadFunc(CMatchFinderMt *mt)
CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->btSync.cs);
CriticalSection_Enter(&mt->hashSync.cs); CriticalSection_Enter(&mt->hashSync.cs);
{ {
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf);
const Byte *afterPtr; ptrdiff_t offset;
MatchFinder_MoveBlock(mf); MatchFinder_MoveBlock(mf);
afterPtr = MatchFinder_GetPointerToCurrentPos(mf); offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf);
mt->pointerToCurPos -= beforePtr - afterPtr; mt->pointerToCurPos -= offset;
mt->buffer -= beforePtr - afterPtr; mt->buffer -= offset;
} }
CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->btSync.cs);
CriticalSection_Leave(&mt->hashSync.cs); CriticalSection_Leave(&mt->hashSync.cs);
@@ -192,7 +192,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
{ {
UInt32 subValue = (mf->pos - mf->historySize - 1); UInt32 subValue = (mf->pos - mf->historySize - 1);
MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_ReduceOffsets(mf, subValue);
MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1);
} }
{ {
UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
@@ -217,7 +217,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
} }
} }
void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
{ {
MtSync_GetNextBlock(&p->hashSync); MtSync_GetNextBlock(&p->hashSync);
p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
@@ -233,7 +233,7 @@ void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
#define NO_INLINE MY_FAST_CALL #define NO_INLINE MY_FAST_CALL
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
{ {
@@ -310,12 +310,14 @@ Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CL
#endif #endif
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);
distances[1] = p->hashNumAvail; distances[1] = p->hashNumAvail;
while (curPos < limit) while (curPos < limit)
{ {
if (p->hashBufPos == p->hashBufPosLimit) if (p->hashBufPos == p->hashBufPosLimit)
@@ -324,9 +326,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
distances[1] = numProcessed + p->hashNumAvail; distances[1] = numProcessed + p->hashNumAvail;
if (p->hashNumAvail >= p->numHashBytes) if (p->hashNumAvail >= p->numHashBytes)
continue; continue;
distances[0] = curPos + p->hashNumAvail;
distances += curPos;
for (; p->hashNumAvail != 0; p->hashNumAvail--) for (; p->hashNumAvail != 0; p->hashNumAvail--)
distances[curPos++] = 0; *distances++ = 0;
break; return;
} }
{ {
UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 size = p->hashBufPosLimit - p->hashBufPos;
@@ -343,13 +347,14 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
if (size2 < size) if (size2 < size)
size = size2; size = size2;
} }
#ifndef MFMT_GM_INLINE #ifndef MFMT_GM_INLINE
while (curPos < limit && size-- != 0) while (curPos < limit && size-- != 0)
{ {
UInt32 *startDistances = distances + curPos; UInt32 *startDistances = distances + curPos;
UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
startDistances + 1, p->numHashBytes - 1) - startDistances); startDistances + 1, p->numHashBytes - 1) - startDistances);
*startDistances = num - 1; *startDistances = num - 1;
curPos += num; curPos += num;
cyclicBufferPos++; cyclicBufferPos++;
@@ -360,7 +365,7 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
{ {
UInt32 posRes; UInt32 posRes;
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, curPos = limit - 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, (Int32)(limit - curPos), size, &posRes);
p->hashBufPos += posRes - pos; p->hashBufPos += posRes - pos;
cyclicBufferPos += posRes - pos; cyclicBufferPos += posRes - pos;
p->buffer += posRes - pos; p->buffer += posRes - pos;
@@ -376,10 +381,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
p->cyclicBufferPos = cyclicBufferPos; p->cyclicBufferPos = cyclicBufferPos;
} }
} }
distances[0] = curPos; distances[0] = curPos;
} }
void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
{ {
CMtSync *sync = &p->hashSync; CMtSync *sync = &p->hashSync;
if (!sync->needStart) if (!sync->needStart)
@@ -393,7 +399,7 @@ void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
{ {
UInt32 subValue = p->pos - p->cyclicBufferSize; UInt32 subValue = p->pos - p->cyclicBufferSize;
MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2);
p->pos -= subValue; p->pos -= subValue;
} }
@@ -432,15 +438,15 @@ void BtThreadFunc(CMatchFinderMt *mt)
void MatchFinderMt_Construct(CMatchFinderMt *p) void MatchFinderMt_Construct(CMatchFinderMt *p)
{ {
p->hashBuf = 0; p->hashBuf = NULL;
MtSync_Construct(&p->hashSync); MtSync_Construct(&p->hashSync);
MtSync_Construct(&p->btSync); MtSync_Construct(&p->btSync);
} }
void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
{ {
alloc->Free(alloc, p->hashBuf); alloc->Free(alloc, p->hashBuf);
p->hashBuf = 0; p->hashBuf = NULL;
} }
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
@@ -457,10 +463,11 @@ static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { Has
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)
{ {
Byte allocaDummy[0x180]; Byte allocaDummy[0x180];
int i = 0; unsigned i = 0;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
allocaDummy[i] = (Byte)i; allocaDummy[i] = (Byte)0;
BtThreadFunc((CMatchFinderMt *)p); if (allocaDummy[0] == 0)
BtThreadFunc((CMatchFinderMt *)p);
return 0; return 0;
} }
@@ -471,10 +478,10 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
p->historySize = historySize; p->historySize = historySize;
if (kMtBtBlockSize <= matchMaxLen * 4) if (kMtBtBlockSize <= matchMaxLen * 4)
return SZ_ERROR_PARAM; return SZ_ERROR_PARAM;
if (p->hashBuf == 0) if (!p->hashBuf)
{ {
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
if (p->hashBuf == 0) if (!p->hashBuf)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
p->btBuf = p->hashBuf + kHashBufferSize; p->btBuf = p->hashBuf + kHashBufferSize;
} }
@@ -494,8 +501,11 @@ void MatchFinderMt_Init(CMatchFinderMt *p)
CMatchFinder *mf = p->MatchFinder; CMatchFinder *mf = p->MatchFinder;
p->btBufPos = p->btBufPosLimit = 0; p->btBufPos = p->btBufPosLimit = 0;
p->hashBufPos = p->hashBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0;
MatchFinder_Init(mf);
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); /* Init without data reading. We don't want to read data in this thread */
MatchFinder_Init_2(mf, False);
p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);
p->btNumAvailBytes = 0; p->btNumAvailBytes = 0;
p->lzPos = p->historySize + 1; p->lzPos = p->historySize + 1;
@@ -520,13 +530,13 @@ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
/* p->MatchFinder->ReleaseStream(); */ /* p->MatchFinder->ReleaseStream(); */
} }
void MatchFinderMt_Normalize(CMatchFinderMt *p) static void MatchFinderMt_Normalize(CMatchFinderMt *p)
{ {
MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
p->lzPos = p->historySize + 1; p->lzPos = p->historySize + 1;
} }
void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
{ {
UInt32 blockIndex; UInt32 blockIndex;
MtSync_GetNextBlock(&p->btSync); MtSync_GetNextBlock(&p->btSync);
@@ -538,34 +548,29 @@ void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
MatchFinderMt_Normalize(p); MatchFinderMt_Normalize(p);
} }
const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
{ {
return p->pointerToCurPos; return p->pointerToCurPos;
} }
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
{ {
GET_NEXT_BLOCK_IF_REQUIRED; GET_NEXT_BLOCK_IF_REQUIRED;
return p->btNumAvailBytes; return p->btNumAvailBytes;
} }
Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{ {
return p->pointerToCurPos[index]; UInt32 h2, curMatch2;
}
UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{
UInt32 hash2Value, curMatch2;
UInt32 *hash = p->hash; UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos; const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos; UInt32 lzPos = p->lzPos;
MT_HASH2_CALC MT_HASH2_CALC
curMatch2 = hash[hash2Value]; curMatch2 = hash[h2];
hash[hash2Value] = lzPos; hash[h2] = lzPos;
if (curMatch2 >= matchMinPos) if (curMatch2 >= matchMinPos)
if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
@@ -573,23 +578,23 @@ UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
*distances++ = 2; *distances++ = 2;
*distances++ = lzPos - curMatch2 - 1; *distances++ = lzPos - curMatch2 - 1;
} }
return distances; return distances;
} }
UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{ {
UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 h2, h3, curMatch2, curMatch3;
UInt32 *hash = p->hash; UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos; const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos; UInt32 lzPos = p->lzPos;
MT_HASH3_CALC MT_HASH3_CALC
curMatch2 = hash[ hash2Value]; curMatch2 = hash[ h2];
curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch3 = hash[kFix3HashSize + h3];
hash[ hash2Value] = hash[ h2] = lzPos;
hash[kFix3HashSize + hash3Value] = hash[kFix3HashSize + h3] = lzPos;
lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{ {
@@ -602,43 +607,45 @@ UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
distances[0] = 2; distances[0] = 2;
distances += 2; distances += 2;
} }
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
{ {
*distances++ = 3; *distances++ = 3;
*distances++ = lzPos - curMatch3 - 1; *distances++ = lzPos - curMatch3 - 1;
} }
return distances; return distances;
} }
/* /*
UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{ {
UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4;
UInt32 *hash = p->hash; UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos; const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos; UInt32 lzPos = p->lzPos;
MT_HASH4_CALC MT_HASH4_CALC
curMatch2 = hash[ hash2Value]; curMatch2 = hash[ h2];
curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch3 = hash[kFix3HashSize + h3];
curMatch4 = hash[kFix4HashSize + hash4Value]; curMatch4 = hash[kFix4HashSize + h4];
hash[ hash2Value] = hash[ h2] = lzPos;
hash[kFix3HashSize + hash3Value] = hash[kFix3HashSize + h3] = lzPos;
hash[kFix4HashSize + hash4Value] = hash[kFix4HashSize + h4] = lzPos;
lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{ {
distances[1] = lzPos - curMatch2 - 1; distances[1] = lzPos - curMatch2 - 1;
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
{ {
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
return distances + 2; return distances + 2;
} }
distances[0] = 2; distances[0] = 2;
distances += 2; distances += 2;
} }
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
{ {
distances[1] = lzPos - curMatch3 - 1; distances[1] = lzPos - curMatch3 - 1;
@@ -660,13 +667,14 @@ UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
*distances++ = 4; *distances++ = 4;
*distances++ = lzPos - curMatch4 - 1; *distances++ = lzPos - curMatch4 - 1;
} }
return distances; return distances;
} }
*/ */
#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
{ {
const UInt32 *btBuf = p->btBuf + p->btBufPos; const UInt32 *btBuf = p->btBuf + p->btBufPos;
UInt32 len = *btBuf++; UInt32 len = *btBuf++;
@@ -684,7 +692,7 @@ UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
return len; return len;
} }
UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
{ {
const UInt32 *btBuf = p->btBuf + p->btBufPos; const UInt32 *btBuf = p->btBuf + p->btBufPos;
UInt32 len = *btBuf++; UInt32 len = *btBuf++;
@@ -692,6 +700,7 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
if (len == 0) if (len == 0)
{ {
/* change for bt5 ! */
if (p->btNumAvailBytes-- >= 4) if (p->btNumAvailBytes-- >= 4)
len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
} }
@@ -707,7 +716,7 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
*distances2++ = *btBuf++; *distances2++ = *btBuf++;
} }
while ((len -= 2) != 0); while ((len -= 2) != 0);
len = (UInt32)(distances2 - (distances)); len = (UInt32)(distances2 - (distances));
} }
INCREASE_LZ_POS INCREASE_LZ_POS
return len; return len;
@@ -717,41 +726,41 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); #define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
{ {
SKIP_HEADER2_MT { p->btNumAvailBytes--; SKIP_HEADER2_MT { p->btNumAvailBytes--;
SKIP_FOOTER_MT SKIP_FOOTER_MT
} }
void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
{ {
SKIP_HEADER_MT(2) SKIP_HEADER_MT(2)
UInt32 hash2Value; UInt32 h2;
MT_HASH2_CALC MT_HASH2_CALC
hash[hash2Value] = p->lzPos; hash[h2] = p->lzPos;
SKIP_FOOTER_MT SKIP_FOOTER_MT
} }
void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
{ {
SKIP_HEADER_MT(3) SKIP_HEADER_MT(3)
UInt32 hash2Value, hash3Value; UInt32 h2, h3;
MT_HASH3_CALC MT_HASH3_CALC
hash[kFix3HashSize + hash3Value] = hash[kFix3HashSize + h3] =
hash[ hash2Value] = hash[ h2] =
p->lzPos; p->lzPos;
SKIP_FOOTER_MT SKIP_FOOTER_MT
} }
/* /*
void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
{ {
SKIP_HEADER_MT(4) SKIP_HEADER_MT(4)
UInt32 hash2Value, hash3Value, hash4Value; UInt32 h2, h3, h4;
MT_HASH4_CALC MT_HASH4_CALC
hash[kFix4HashSize + hash4Value] = hash[kFix4HashSize + h4] =
hash[kFix3HashSize + hash3Value] = hash[kFix3HashSize + h3] =
hash[ hash2Value] = hash[ h2] =
p->lzPos; p->lzPos;
SKIP_FOOTER_MT SKIP_FOOTER_MT
} }
@@ -760,11 +769,11 @@ void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
{ {
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
switch(p->MatchFinder->numHashBytes)
switch (p->MatchFinder->numHashBytes)
{ {
case 2: case 2:
p->GetHeadsFunc = GetHeads2; p->GetHeadsFunc = GetHeads2;
@@ -780,7 +789,6 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
default: default:
/* case 4: */ /* case 4: */
p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
/* p->GetHeadsFunc = GetHeads4; */
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
break; break;

View File

@@ -1,5 +1,5 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms /* LzFindMt.h -- multithreaded Match finder for LZ algorithms
2013-01-18 : Igor Pavlov : Public domain */ 2015-05-03 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_MT_H #ifndef __LZ_FIND_MT_H
#define __LZ_FIND_MT_H #define __LZ_FIND_MT_H
@@ -75,7 +75,7 @@ typedef struct _CMatchFinderMt
UInt32 matchMaxLen; UInt32 matchMaxLen;
UInt32 numHashBytes; UInt32 numHashBytes;
UInt32 pos; UInt32 pos;
Byte *buffer; const Byte *buffer;
UInt32 cyclicBufferPos; UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cyclicBufferSize; /* it must be historySize + 1 */
UInt32 cutValue; UInt32 cutValue;

View File

@@ -1,5 +1,5 @@
/* LzHash.h -- HASH functions for LZ algorithms /* LzHash.h -- HASH functions for LZ algorithms
2009-02-07 : Igor Pavlov : Public domain */ 2015-04-12 : Igor Pavlov : Public domain */
#ifndef __LZ_HASH_H #ifndef __LZ_HASH_H
#define __LZ_HASH_H #define __LZ_HASH_H
@@ -12,43 +12,46 @@
#define kFix4HashSize (kHash2Size + kHash3Size) #define kFix4HashSize (kHash2Size + kHash3Size)
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
#define HASH3_CALC { \ #define HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
#define HASH4_CALC { \ #define HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } h3 = temp & (kHash3Size - 1); \
hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
#define HASH5_CALC { \ #define HASH5_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ h3 = temp & (kHash3Size - 1); \
hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ temp ^= (p->crc[cur[3]] << 5); \
hash4Value &= (kHash4Size - 1); } h4 = temp & (kHash4Size - 1); \
hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ /* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; #define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
#define MT_HASH2_CALC \ #define MT_HASH2_CALC \
hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
#define MT_HASH3_CALC { \ #define MT_HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
#define MT_HASH4_CALC { \ #define MT_HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \ h2 = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ temp ^= ((UInt32)cur[2] << 8); \
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } h3 = temp & (kHash3Size - 1); \
h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
#endif #endif

View File

@@ -1,5 +1,5 @@
/* Lzma2Dec.c -- LZMA2 Decoder /* Lzma2Dec.c -- LZMA2 Decoder
2010-12-15 : Igor Pavlov : Public domain */ 2015-11-09 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */ /* #define SHOW_DEBUG_INFO */
@@ -99,12 +99,12 @@ void Lzma2Dec_Init(CLzma2Dec *p)
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
{ {
switch(p->state) switch (p->state)
{ {
case LZMA2_STATE_CONTROL: case LZMA2_STATE_CONTROL:
p->control = b; p->control = b;
PRF(printf("\n %4X ", p->decoder.dicPos)); PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos));
PRF(printf(" %2X", b)); PRF(printf(" %2X", (unsigned)b));
if (p->control == 0) if (p->control == 0)
return LZMA2_STATE_FINISHED; return LZMA2_STATE_FINISHED;
if (LZMA2_IS_UNCOMPRESSED_STATE(p)) if (LZMA2_IS_UNCOMPRESSED_STATE(p))
@@ -124,7 +124,7 @@ 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(" %8d", p->unpackSize)); PRF(printf(" %8u", (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:
@@ -134,13 +134,13 @@ 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(" %8d", p->packSize)); PRF(printf(" %8u", (unsigned)p->packSize));
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
case LZMA2_STATE_PROP: case LZMA2_STATE_PROP:
{ {
int lc, lp; unsigned lc, lp;
if (b >= (9 * 5 * 5)) if (b >= (9 * 5 * 5))
return LZMA2_STATE_ERROR; return LZMA2_STATE_ERROR;
lc = b % 9; lc = b % 9;
@@ -179,13 +179,16 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
while (p->state != LZMA2_STATE_FINISHED) while (p->state != LZMA2_STATE_FINISHED)
{ {
SizeT dicPos = p->decoder.dicPos; SizeT dicPos = p->decoder.dicPos;
if (p->state == LZMA2_STATE_ERROR) if (p->state == LZMA2_STATE_ERROR)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
{ {
*status = LZMA_STATUS_NOT_FINISHED; *status = LZMA_STATUS_NOT_FINISHED;
return SZ_OK; return SZ_OK;
} }
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{ {
if (*srcLen == inSize) if (*srcLen == inSize)
@@ -195,8 +198,15 @@ 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)
{
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
}
continue; continue;
} }
{ {
SizeT destSizeCur = dicLimit - dicPos; SizeT destSizeCur = dicLimit - dicPos;
SizeT srcSizeCur = inSize - *srcLen; SizeT srcSizeCur = inSize - *srcLen;
@@ -222,7 +232,10 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (initDic) if (initDic)
p->needInitProp = p->needInitState = True; p->needInitProp = p->needInitState = True;
else if (p->needInitDic) else if (p->needInitDic)
{
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
}
p->needInitDic = False; p->needInitDic = False;
LzmaDec_InitDicAndState(&p->decoder, initDic, False); LzmaDec_InitDicAndState(&p->decoder, initDic, False);
} }
@@ -231,7 +244,10 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
srcSizeCur = destSizeCur; srcSizeCur = destSizeCur;
if (srcSizeCur == 0) if (srcSizeCur == 0)
{
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
}
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
@@ -247,17 +263,21 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (p->state == LZMA2_STATE_DATA) if (p->state == LZMA2_STATE_DATA)
{ {
int mode = LZMA2_GET_LZMA_MODE(p); unsigned mode = LZMA2_GET_LZMA_MODE(p);
Bool initDic = (mode == 3); Bool initDic = (mode == 3);
Bool initState = (mode > 0); Bool initState = (mode != 0);
if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
{
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
}
LzmaDec_InitDicAndState(&p->decoder, initDic, initState); LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
p->needInitDic = False; p->needInitDic = False;
p->needInitState = False; p->needInitState = False;
p->state = LZMA2_STATE_DATA_CONT; p->state = LZMA2_STATE_DATA_CONT;
} }
if (srcSizeCur > p->packSize) if (srcSizeCur > p->packSize)
srcSizeCur = (SizeT)p->packSize; srcSizeCur = (SizeT)p->packSize;
@@ -276,16 +296,22 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (srcSizeCur == 0 && outSizeProcessed == 0) if (srcSizeCur == 0 && outSizeProcessed == 0)
{ {
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
p->unpackSize != 0 || p->packSize != 0) || p->unpackSize != 0
|| p->packSize != 0)
{
p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
}
p->state = LZMA2_STATE_CONTROL; p->state = LZMA2_STATE_CONTROL;
} }
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
*status = LZMA_STATUS_NOT_FINISHED; *status = LZMA_STATUS_NOT_FINISHED;
} }
} }
} }
*status = LZMA_STATUS_FINISHED_WITH_MARK; *status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK; return SZ_OK;
} }

View File

@@ -1,5 +1,5 @@
/* Lzma2Dec.h -- LZMA2 Decoder /* Lzma2Dec.h -- LZMA2 Decoder
2013-01-18 : Igor Pavlov : Public domain */ 2015-05-13 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H #ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H #define __LZMA2_DEC_H
@@ -15,7 +15,7 @@ typedef struct
CLzmaDec decoder; CLzmaDec decoder;
UInt32 packSize; UInt32 packSize;
UInt32 unpackSize; UInt32 unpackSize;
int state; unsigned state;
Byte control; Byte control;
Bool needInitDic; Bool needInitDic;
Bool needInitState; Bool needInitState;

View File

@@ -1,5 +1,5 @@
/* Lzma2Enc.c -- LZMA2 Encoder /* Lzma2Enc.c -- LZMA2 Encoder
2012-06-19 : Igor Pavlov : Public domain */ 2015-10-04 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -109,6 +109,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
{ {
size_t destPos = 0; size_t destPos = 0;
PRF(printf("################# COPY ")); PRF(printf("################# COPY "));
while (unpackSize > 0) while (unpackSize > 0)
{ {
UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE; UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
@@ -121,6 +122,7 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
unpackSize -= u; unpackSize -= u;
destPos += u; destPos += u;
p->srcPos += u; p->srcPos += u;
if (outStream) if (outStream)
{ {
*packSizeRes += destPos; *packSizeRes += destPos;
@@ -132,9 +134,11 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
*packSizeRes = destPos; *packSizeRes = destPos;
/* needInitState = True; */ /* needInitState = True; */
} }
LzmaEnc_RestoreState(p->enc); LzmaEnc_RestoreState(p->enc);
return SZ_OK; return SZ_OK;
} }
{ {
size_t destPos = 0; size_t destPos = 0;
UInt32 u = unpackSize - 1; UInt32 u = unpackSize - 1;
@@ -160,11 +164,13 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
if (outStream) if (outStream)
if (outStream->Write(outStream, outBuf, destPos) != destPos) if (outStream->Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE; return SZ_ERROR_WRITE;
*packSizeRes = destPos; *packSizeRes = destPos;
return SZ_OK; return SZ_OK;
} }
} }
/* ---------- Lzma2 Props ---------- */ /* ---------- Lzma2 Props ---------- */
void Lzma2EncProps_Init(CLzma2EncProps *p) void Lzma2EncProps_Init(CLzma2EncProps *p)
@@ -221,6 +227,8 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
LzmaEncProps_Normalize(&p->lzmaProps); LzmaEncProps_Normalize(&p->lzmaProps);
t1 = p->lzmaProps.numThreads;
if (p->blockSize == 0) if (p->blockSize == 0)
{ {
UInt32 dictSize = p->lzmaProps.dictSize; UInt32 dictSize = p->lzmaProps.dictSize;
@@ -232,28 +240,34 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
if (blockSize < dictSize) blockSize = dictSize; if (blockSize < dictSize) blockSize = dictSize;
p->blockSize = (size_t)blockSize; p->blockSize = (size_t)blockSize;
} }
if (t2 > 1)
if (t2 > 1 && p->lzmaProps.reduceSize != (UInt64)(Int64)-1)
{ {
UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1; UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1;
if (temp > p->lzmaProps.reduceSize) if (temp > p->lzmaProps.reduceSize)
{ {
UInt64 numBlocks = temp / p->blockSize; UInt64 numBlocks = temp / p->blockSize;
if (numBlocks < t2) if (numBlocks < (unsigned)t2)
{ {
t2 = (UInt32)numBlocks; t2 = (unsigned)numBlocks;
if (t2 == 0)
t2 = 1;
t3 = t1 * t2; t3 = t1 * t2;
} }
} }
} }
p->numBlockThreads = t2; p->numBlockThreads = t2;
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 && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
} }
/* ---------- Lzma2 ---------- */ /* ---------- Lzma2 ---------- */
typedef struct typedef struct
@@ -283,15 +297,17 @@ static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
UInt64 packTotal = 0; UInt64 packTotal = 0;
SRes res = SZ_OK; SRes res = SZ_OK;
if (mainEncoder->outBuf == 0) if (!mainEncoder->outBuf)
{ {
mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
if (mainEncoder->outBuf == 0) if (!mainEncoder->outBuf)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
} }
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props)); RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE, RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
mainEncoder->alloc, mainEncoder->allocBig)); mainEncoder->alloc, mainEncoder->allocBig));
for (;;) for (;;)
{ {
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
@@ -305,16 +321,20 @@ static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
if (packSize == 0) if (packSize == 0)
break; break;
} }
LzmaEnc_Finish(p->enc); LzmaEnc_Finish(p->enc);
if (res == SZ_OK) if (res == SZ_OK)
{ {
Byte b = 0; Byte b = 0;
if (outStream->Write(outStream, &b, 1) != 1) if (outStream->Write(outStream, &b, 1) != 1)
return SZ_ERROR_WRITE; return SZ_ERROR_WRITE;
} }
return res; return res;
} }
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
typedef struct typedef struct
@@ -362,10 +382,12 @@ static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *des
break; break;
} }
} }
LzmaEnc_Finish(p->enc); LzmaEnc_Finish(p->enc);
if (res != SZ_OK) if (res != SZ_OK)
return res; return res;
} }
if (finished) if (finished)
{ {
if (*destSize == destLim) if (*destSize == destLim)
@@ -378,12 +400,13 @@ static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *des
#endif #endif
/* ---------- Lzma2Enc ---------- */ /* ---------- Lzma2Enc ---------- */
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig) CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc)); CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
if (p == 0) if (!p)
return NULL; return NULL;
Lzma2EncProps_Init(&p->props); Lzma2EncProps_Init(&p->props);
Lzma2EncProps_Normalize(&p->props); Lzma2EncProps_Normalize(&p->props);
@@ -395,6 +418,7 @@ CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
p->coders[i].enc = 0; p->coders[i].enc = 0;
} }
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
MtCoder_Construct(&p->mtCoder); MtCoder_Construct(&p->mtCoder);
#endif #endif
@@ -455,22 +479,17 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
for (i = 0; i < p->props.numBlockThreads; i++) for (i = 0; i < p->props.numBlockThreads; i++)
{ {
CLzma2EncInt *t = &p->coders[i]; CLzma2EncInt *t = &p->coders[(unsigned)i];
if (t->enc == NULL) if (!t->enc)
{ {
t->enc = LzmaEnc_Create(p->alloc); t->enc = LzmaEnc_Create(p->alloc);
if (t->enc == NULL) if (!t->enc)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
} }
} }
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
if (p->props.numBlockThreads <= 1) if (p->props.numBlockThreads > 1)
#endif
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
#ifndef _7ZIP_ST
{ {
CMtCallbackImp mtCallback; CMtCallbackImp mtCallback;
@@ -485,9 +504,17 @@ SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
p->mtCoder.blockSize = p->props.blockSize; p->mtCoder.blockSize = p->props.blockSize;
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16; 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;
if (p->mtCoder.destBlockSize < p->props.blockSize)
return SZ_ERROR_FAIL;
}
p->mtCoder.numThreads = p->props.numBlockThreads; p->mtCoder.numThreads = p->props.numBlockThreads;
return MtCoder_Code(&p->mtCoder); return MtCoder_Code(&p->mtCoder);
} }
#endif #endif
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
} }

View File

@@ -1,5 +1,7 @@
/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder
2009-08-14 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "Lzma86.h" #include "Lzma86.h"
@@ -7,8 +9,8 @@
#include "Bra.h" #include "Bra.h"
#include "LzmaDec.h" #include "LzmaDec.h"
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); } 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)
{ {

View File

@@ -1,5 +1,7 @@
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
2009-08-14 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include <string.h> #include <string.h>
@@ -11,8 +13,8 @@
#define SZE_OUT_OVERFLOW SZE_DATA_ERROR #define SZE_OUT_OVERFLOW SZE_DATA_ERROR
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); } 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)

View File

@@ -1,5 +1,5 @@
/* LzmaDec.c -- LZMA Decoder /* LzmaDec.c -- LZMA Decoder
2011-09-03 : Igor Pavlov : Public domain */ 2015-06-23 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -114,14 +114,14 @@
#define Literal (RepLenCoder + kNumLenProbs) #define Literal (RepLenCoder + kNumLenProbs)
#define LZMA_BASE_SIZE 1846 #define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768 #define LZMA_LIT_SIZE 0x300
#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
#if Literal != LZMA_BASE_SIZE #if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG StopCompilingDueBUG
#endif #endif
#define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
#define LZMA_DIC_MIN (1 << 12) #define LZMA_DIC_MIN (1 << 12)
/* First LZMA-symbol is always decoded. /* First LZMA-symbol is always decoded.
@@ -133,8 +133,8 @@ Out:
p->remainLen: p->remainLen:
< kMatchSpecLenStart : normal remain < kMatchSpecLenStart : normal remain
= kMatchSpecLenStart : finished = kMatchSpecLenStart : finished
= kMatchSpecLenStart + 1 : Flush marker = kMatchSpecLenStart + 1 : Flush marker (unused now)
= kMatchSpecLenStart + 2 : State Init Marker = kMatchSpecLenStart + 2 : State Init Marker (unused now)
*/ */
static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
@@ -172,9 +172,10 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
unsigned symbol; unsigned symbol;
UPDATE_0(prob); UPDATE_0(prob);
prob = probs + Literal; prob = probs + Literal;
if (checkDicSize != 0 || processedPos != 0) if (processedPos != 0 || checkDicSize != 0)
prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + prob += ((UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
(dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
processedPos++;
if (state < kNumLitStates) if (state < kNumLitStates)
{ {
@@ -195,7 +196,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
} }
else else
{ {
unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
unsigned offs = 0x100; unsigned offs = 0x100;
state -= (state < 10) ? 3 : 6; state -= (state < 10) ? 3 : 6;
symbol = 1; symbol = 1;
@@ -222,11 +223,11 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
} }
#endif #endif
} }
dic[dicPos++] = (Byte)symbol; dic[dicPos++] = (Byte)symbol;
processedPos++;
continue; continue;
} }
else
{ {
UPDATE_1(prob); UPDATE_1(prob);
prob = probs + IsRep + state; prob = probs + IsRep + state;
@@ -249,7 +250,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
IF_BIT_0(prob) IF_BIT_0(prob)
{ {
UPDATE_0(prob); UPDATE_0(prob);
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
dicPos++; dicPos++;
processedPos++; processedPos++;
state = state < kNumLitStates ? 9 : 11; state = state < kNumLitStates ? 9 : 11;
@@ -290,6 +291,8 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
state = state < kNumLitStates ? 8 : 11; state = state < kNumLitStates ? 8 : 11;
prob = probs + RepLenCoder; prob = probs + RepLenCoder;
} }
#ifdef _LZMA_SIZE_OPT
{ {
unsigned limit, offset; unsigned limit, offset;
CLzmaProb *probLen = prob + LenChoice; CLzmaProb *probLen = prob + LenChoice;
@@ -322,6 +325,42 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
TREE_DECODE(probLen, limit, len); TREE_DECODE(probLen, limit, len);
len += offset; len += offset;
} }
#else
{
CLzmaProb *probLen = prob + LenChoice;
IF_BIT_0(probLen)
{
UPDATE_0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits);
len = 1;
TREE_GET_BIT(probLen, len);
TREE_GET_BIT(probLen, len);
TREE_GET_BIT(probLen, len);
len -= 8;
}
else
{
UPDATE_1(probLen);
probLen = prob + LenChoice2;
IF_BIT_0(probLen)
{
UPDATE_0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits);
len = 1;
TREE_GET_BIT(probLen, len);
TREE_GET_BIT(probLen, len);
TREE_GET_BIT(probLen, len);
}
else
{
UPDATE_1(probLen);
probLen = prob + LenHigh;
TREE_DECODE(probLen, (1 << kLenNumHighBits), len);
len += kLenNumLowSymbols + kLenNumMidSymbols;
}
}
}
#endif
if (state >= kNumStates) if (state >= kNumStates)
{ {
@@ -332,7 +371,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
if (distance >= kStartPosModelIndex) if (distance >= kStartPosModelIndex)
{ {
unsigned posSlot = (unsigned)distance; unsigned posSlot = (unsigned)distance;
int numDirectBits = (int)(((distance >> 1) - 1)); unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));
distance = (2 | (distance & 1)); distance = (2 | (distance & 1));
if (posSlot < kEndPosModelIndex) if (posSlot < kEndPosModelIndex)
{ {
@@ -391,6 +430,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
} }
} }
} }
rep3 = rep2; rep3 = rep2;
rep2 = rep1; rep2 = rep1;
rep1 = rep0; rep1 = rep0;
@@ -398,26 +438,39 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
if (checkDicSize == 0) if (checkDicSize == 0)
{ {
if (distance >= processedPos) if (distance >= processedPos)
{
p->dicPos = dicPos;
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
}
} }
else if (distance >= checkDicSize) else if (distance >= checkDicSize)
{
p->dicPos = dicPos;
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
}
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
} }
len += kMatchMinLen; len += kMatchMinLen;
if (limit == dicPos)
return SZ_ERROR_DATA;
{ {
SizeT rem = limit - dicPos; SizeT rem;
unsigned curLen = ((rem < len) ? (unsigned)rem : len); unsigned curLen;
SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); SizeT pos;
if ((rem = limit - dicPos) == 0)
{
p->dicPos = dicPos;
return SZ_ERROR_DATA;
}
curLen = ((rem < len) ? (unsigned)rem : len);
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
processedPos += curLen; processedPos += curLen;
len -= curLen; len -= curLen;
if (pos + curLen <= dicBufSize) if (curLen <= dicBufSize - pos)
{ {
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;
@@ -441,7 +494,9 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
} }
} }
while (dicPos < limit && buf < bufLimit); while (dicPos < limit && buf < bufLimit);
NORMALIZE; NORMALIZE;
p->buf = buf; p->buf = buf;
p->range = range; p->range = range;
p->code = code; p->code = code;
@@ -465,9 +520,10 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
SizeT dicPos = p->dicPos; SizeT dicPos = p->dicPos;
SizeT dicBufSize = p->dicBufSize; SizeT dicBufSize = p->dicBufSize;
unsigned len = p->remainLen; unsigned len = p->remainLen;
UInt32 rep0 = p->reps[0]; SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
if (limit - dicPos < len) SizeT rem = limit - dicPos;
len = (unsigned)(limit - dicPos); if (rem < len)
len = (unsigned)(rem);
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;
@@ -477,7 +533,7 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
while (len != 0) while (len != 0)
{ {
len--; len--;
dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
dicPos++; dicPos++;
} }
p->dicPos = dicPos; p->dicPos = dicPos;
@@ -495,17 +551,19 @@ static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte
if (limit - p->dicPos > rem) if (limit - p->dicPos > rem)
limit2 = p->dicPos + rem; limit2 = p->dicPos + rem;
} }
RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
if (p->processedPos >= p->prop.dicSize)
if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
p->checkDicSize = p->prop.dicSize; p->checkDicSize = p->prop.dicSize;
LzmaDec_WriteRem(p, limit); LzmaDec_WriteRem(p, limit);
} }
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
if (p->remainLen > kMatchSpecLenStart) if (p->remainLen > kMatchSpecLenStart)
{
p->remainLen = kMatchSpecLenStart; p->remainLen = kMatchSpecLenStart;
}
return 0; return 0;
} }
@@ -522,12 +580,12 @@ 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;
CLzmaProb *probs = p->probs; const CLzmaProb *probs = p->probs;
unsigned state = p->state; unsigned state = p->state;
ELzmaDummy res; ELzmaDummy res;
{ {
CLzmaProb *prob; const CLzmaProb *prob;
UInt32 bound; UInt32 bound;
unsigned ttt; unsigned ttt;
unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
@@ -541,9 +599,9 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
prob = probs + Literal; prob = probs + Literal;
if (p->checkDicSize != 0 || p->processedPos != 0) if (p->checkDicSize != 0 || p->processedPos != 0)
prob += (LZMA_LIT_SIZE * prob += ((UInt32)LZMA_LIT_SIZE *
((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
(p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
if (state < kNumLitStates) if (state < kNumLitStates)
{ {
@@ -553,13 +611,13 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
else else
{ {
unsigned matchByte = p->dic[p->dicPos - p->reps[0] + unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; (p->dicPos < p->reps[0] ? p->dicBufSize : 0)];
unsigned offs = 0x100; unsigned offs = 0x100;
unsigned symbol = 1; unsigned symbol = 1;
do do
{ {
unsigned bit; unsigned bit;
CLzmaProb *probLit; const CLzmaProb *probLit;
matchByte <<= 1; matchByte <<= 1;
bit = (matchByte & offs); bit = (matchByte & offs);
probLit = prob + offs + bit + symbol; probLit = prob + offs + bit + symbol;
@@ -629,7 +687,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
} }
{ {
unsigned limit, offset; unsigned limit, offset;
CLzmaProb *probLen = prob + LenChoice; const CLzmaProb *probLen = prob + LenChoice;
IF_BIT_0_CHECK(probLen) IF_BIT_0_CHECK(probLen)
{ {
UPDATE_0_CHECK; UPDATE_0_CHECK;
@@ -669,7 +727,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex) if (posSlot >= kStartPosModelIndex)
{ {
int numDirectBits = ((posSlot >> 1) - 1); unsigned numDirectBits = ((posSlot >> 1) - 1);
/* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
@@ -708,13 +766,6 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
} }
static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
{
p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
p->range = 0xFFFFFFFF;
p->needFlush = 0;
}
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
{ {
p->needFlush = 1; p->needFlush = 1;
@@ -739,8 +790,8 @@ void LzmaDec_Init(CLzmaDec *p)
static void LzmaDec_InitStateReal(CLzmaDec *p) static void LzmaDec_InitStateReal(CLzmaDec *p)
{ {
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
UInt32 i; SizeT i;
CLzmaProb *probs = p->probs; CLzmaProb *probs = p->probs;
for (i = 0; i < numProbs; i++) for (i = 0; i < numProbs; i++)
probs[i] = kBitModelTotal >> 1; probs[i] = kBitModelTotal >> 1;
@@ -762,7 +813,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
{ {
int checkEndMarkNow; int checkEndMarkNow;
if (p->needFlush != 0) if (p->needFlush)
{ {
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
p->tempBuf[p->tempBufSize++] = *src++; p->tempBuf[p->tempBufSize++] = *src++;
@@ -773,8 +824,13 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
} }
if (p->tempBuf[0] != 0) if (p->tempBuf[0] != 0)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
p->code =
LzmaDec_InitRc(p, p->tempBuf); ((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; p->tempBufSize = 0;
} }
@@ -858,7 +914,16 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
p->buf = p->tempBuf; p->buf = p->tempBuf;
if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
{
unsigned kkk = (unsigned)(p->buf - p->tempBuf);
if (rem < kkk)
return SZ_ERROR_FAIL; /* some internal error */
rem -= kkk;
if (lookAhead < rem)
return SZ_ERROR_FAIL; /* some internal error */
lookAhead -= rem;
}
(*srcLen) += lookAhead; (*srcLen) += lookAhead;
src += lookAhead; src += lookAhead;
inSize -= lookAhead; inSize -= lookAhead;
@@ -913,13 +978,13 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *sr
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
{ {
alloc->Free(alloc, p->probs); alloc->Free(alloc, p->probs);
p->probs = 0; p->probs = NULL;
} }
static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
{ {
alloc->Free(alloc, p->dic); alloc->Free(alloc, p->dic);
p->dic = 0; p->dic = NULL;
} }
void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
@@ -957,12 +1022,12 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
{ {
UInt32 numProbs = LzmaProps_GetNumProbs(propNew); UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
if (p->probs == 0 || 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 *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
p->numProbs = numProbs; p->numProbs = numProbs;
if (p->probs == 0) if (!p->probs)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
} }
return SZ_OK; return SZ_OK;
@@ -983,12 +1048,22 @@ SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAll
SizeT dicBufSize; SizeT dicBufSize;
RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaProps_Decode(&propNew, props, propsSize));
RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
dicBufSize = propNew.dicSize;
if (p->dic == 0 || dicBufSize != p->dicBufSize) {
UInt32 dictSize = propNew.dicSize;
SizeT mask = ((UInt32)1 << 12) - 1;
if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1;
else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;;
dicBufSize = ((SizeT)dictSize + mask) & ~mask;
if (dicBufSize < dictSize)
dicBufSize = dictSize;
}
if (!p->dic || dicBufSize != p->dicBufSize)
{ {
LzmaDec_FreeDict(p, alloc); LzmaDec_FreeDict(p, alloc);
p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
if (p->dic == 0) if (!p->dic)
{ {
LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeProbs(p, alloc);
return SZ_ERROR_MEM; return SZ_ERROR_MEM;

View File

@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder /* LzmaEnc.c -- LZMA Encoder
2012-11-20 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -20,9 +20,12 @@
#endif #endif
#ifdef SHOW_STAT #ifdef SHOW_STAT
static int ttt = 0; static unsigned g_STAT_OFFSET = 0;
#endif #endif
#define kMaxHistorySize ((UInt32)3 << 29)
/* #define kMaxHistorySize ((UInt32)7 << 29) */
#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
#define kBlockSize (9 << 10) #define kBlockSize (9 << 10)
@@ -58,6 +61,7 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
int level = p->level; int level = p->level;
if (level < 0) level = 5; if (level < 0) level = 5;
p->level = level; p->level = level;
if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
if (p->dictSize > p->reduceSize) if (p->dictSize > p->reduceSize)
{ {
@@ -68,14 +72,17 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
} }
} }
if (p->lc < 0) p->lc = 3; if (p->lc < 0) p->lc = 3;
if (p->lp < 0) p->lp = 0; if (p->lp < 0) p->lp = 0;
if (p->pb < 0) p->pb = 2; if (p->pb < 0) p->pb = 2;
if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
if (p->numHashBytes < 0) p->numHashBytes = 4; if (p->numHashBytes < 0) p->numHashBytes = 4;
if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
if (p->numThreads < 0) if (p->numThreads < 0)
p->numThreads = p->numThreads =
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
@@ -92,17 +99,18 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
return props.dictSize; return props.dictSize;
} }
#if (_MSC_VER >= 1400)
/* BSR code is fast for some new CPUs */
/* #define LZMA_LOG_BSR */ /* #define LZMA_LOG_BSR */
/* Define it for Intel's CPU */ #endif
#ifdef LZMA_LOG_BSR #ifdef LZMA_LOG_BSR
#define kDicLogSizeMaxCompress 30 #define kDicLogSizeMaxCompress 32
#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
UInt32 GetPosSlot1(UInt32 pos) static UInt32 GetPosSlot1(UInt32 pos)
{ {
UInt32 res; UInt32 res;
BSR2_RET(pos, res); BSR2_RET(pos, res);
@@ -113,27 +121,44 @@ UInt32 GetPosSlot1(UInt32 pos)
#else #else
#define kNumLogBits (9 + (int)sizeof(size_t) / 2) #define kNumLogBits (9 + sizeof(size_t) / 2)
/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */
#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
void LzmaEnc_FastPosInit(Byte *g_FastPos) static void LzmaEnc_FastPosInit(Byte *g_FastPos)
{ {
int c = 2, slotFast; unsigned slot;
g_FastPos[0] = 0; g_FastPos[0] = 0;
g_FastPos[1] = 1; g_FastPos[1] = 1;
g_FastPos += 2;
for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) for (slot = 2; slot < kNumLogBits * 2; slot++)
{ {
UInt32 k = (1 << ((slotFast >> 1) - 1)); size_t k = ((size_t)1 << ((slot >> 1) - 1));
UInt32 j; size_t j;
for (j = 0; j < k; j++, c++) for (j = 0; j < k; j++)
g_FastPos[c] = (Byte)slotFast; g_FastPos[j] = (Byte)slot;
g_FastPos += k;
} }
} }
/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
/*
#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ #define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
(0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
res = p->g_FastPos[pos >> i] + (i * 2); } res = p->g_FastPos[pos >> i] + (i * 2); }
*/
/*
#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
(0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
res = p->g_FastPos[pos >> i] + (i * 2); }
*/
#define BSR2_RET(pos, res) { UInt32 i = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
res = p->g_FastPos[pos >> i] + (i * 2); }
/* /*
#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
p->g_FastPos[pos >> 6] + 12 : \ p->g_FastPos[pos >> 6] + 12 : \
@@ -213,6 +238,7 @@ typedef struct
#define kNumStates 12 #define kNumStates 12
typedef struct typedef struct
{ {
CLzmaProb choice; CLzmaProb choice;
@@ -222,14 +248,16 @@ typedef struct
CLzmaProb high[kLenNumHighSymbols]; CLzmaProb high[kLenNumHighSymbols];
} CLenEnc; } CLenEnc;
typedef struct typedef struct
{ {
CLenEnc p; CLenEnc p;
UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
UInt32 tableSize; UInt32 tableSize;
UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
UInt32 counters[LZMA_NUM_PB_STATES_MAX]; UInt32 counters[LZMA_NUM_PB_STATES_MAX];
} CLenPriceEnc; } CLenPriceEnc;
typedef struct typedef struct
{ {
UInt32 range; UInt32 range;
@@ -244,10 +272,14 @@ typedef struct
SRes res; SRes res;
} CRangeEnc; } CRangeEnc;
typedef struct typedef struct
{ {
CLzmaProb *litProbs; CLzmaProb *litProbs;
UInt32 state;
UInt32 reps[LZMA_NUM_REPS];
CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
CLzmaProb isRep[kNumStates]; CLzmaProb isRep[kNumStates];
CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG0[kNumStates];
@@ -261,15 +293,49 @@ typedef struct
CLenPriceEnc lenEnc; CLenPriceEnc lenEnc;
CLenPriceEnc repLenEnc; CLenPriceEnc repLenEnc;
UInt32 reps[LZMA_NUM_REPS];
UInt32 state;
} CSaveState; } CSaveState;
typedef struct typedef struct
{ {
IMatchFinder matchFinder;
void *matchFinderObj; void *matchFinderObj;
IMatchFinder matchFinder;
UInt32 optimumEndIndex;
UInt32 optimumCurrentIndex;
UInt32 longestMatchLength;
UInt32 numPairs;
UInt32 numAvail;
UInt32 numFastBytes;
UInt32 additionalOffset;
UInt32 reps[LZMA_NUM_REPS];
UInt32 state;
unsigned lc, lp, pb;
unsigned lpMask, pbMask;
unsigned lclp;
CLzmaProb *litProbs;
Bool fastMode;
Bool writeEndMark;
Bool finished;
Bool multiThread;
Bool needInit;
UInt64 nowPos64;
UInt32 matchPriceCount;
UInt32 alignPriceCount;
UInt32 distTableSize;
UInt32 dictSize;
SRes result;
CRangeEnc rc;
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
Bool mtMode; Bool mtMode;
@@ -282,12 +348,6 @@ typedef struct
Byte pad[128]; Byte pad[128];
#endif #endif
UInt32 optimumEndIndex;
UInt32 optimumCurrentIndex;
UInt32 longestMatchLength;
UInt32 numPairs;
UInt32 numAvail;
COptimal opt[kNumOpts]; COptimal opt[kNumOpts];
#ifndef LZMA_LOG_BSR #ifndef LZMA_LOG_BSR
@@ -296,22 +356,10 @@ typedef struct
UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
UInt32 numFastBytes;
UInt32 additionalOffset;
UInt32 reps[LZMA_NUM_REPS];
UInt32 state;
UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
UInt32 alignPrices[kAlignTableSize]; UInt32 alignPrices[kAlignTableSize];
UInt32 alignPriceCount;
UInt32 distTableSize;
unsigned lc, lp, pb;
unsigned lpMask, pbMask;
CLzmaProb *litProbs;
CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
CLzmaProb isRep[kNumStates]; CLzmaProb isRep[kNumStates];
@@ -327,26 +375,14 @@ typedef struct
CLenPriceEnc lenEnc; CLenPriceEnc lenEnc;
CLenPriceEnc repLenEnc; CLenPriceEnc repLenEnc;
unsigned lclp;
Bool fastMode;
CRangeEnc rc;
Bool writeEndMark;
UInt64 nowPos64;
UInt32 matchPriceCount;
Bool finished;
Bool multiThread;
SRes result;
UInt32 dictSize;
int needInit;
CSaveState saveState; CSaveState saveState;
#ifndef _7ZIP_ST
Byte pad2[128];
#endif
} CLzmaEnc; } CLzmaEnc;
void LzmaEnc_SaveState(CLzmaEncHandle pp) void LzmaEnc_SaveState(CLzmaEncHandle pp)
{ {
CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEnc *p = (CLzmaEnc *)pp;
@@ -370,7 +406,7 @@ void LzmaEnc_SaveState(CLzmaEncHandle pp)
memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->reps, p->reps, sizeof(p->reps));
memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));
} }
void LzmaEnc_RestoreState(CLzmaEncHandle pp) void LzmaEnc_RestoreState(CLzmaEncHandle pp)
@@ -396,7 +432,7 @@ void LzmaEnc_RestoreState(CLzmaEncHandle pp)
memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->reps, p->reps, sizeof(p->reps));
memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));
} }
SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
@@ -405,9 +441,13 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
CLzmaEncProps props = *props2; CLzmaEncProps props = *props2;
LzmaEncProps_Normalize(&props); LzmaEncProps_Normalize(&props);
if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || if (props.lc > LZMA_LC_MAX
props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30)) || props.lp > LZMA_LP_MAX
|| props.pb > LZMA_PB_MAX
|| props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)
|| props.dictSize > kMaxHistorySize)
return SZ_ERROR_PARAM; return SZ_ERROR_PARAM;
p->dictSize = props.dictSize; p->dictSize = props.dictSize;
{ {
unsigned fb = props.fb; unsigned fb = props.fb;
@@ -421,7 +461,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
p->lp = props.lp; p->lp = props.lp;
p->pb = props.pb; p->pb = props.pb;
p->fastMode = (props.algo == 0); p->fastMode = (props.algo == 0);
p->matchFinderBase.btMode = props.btMode; p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);
{ {
UInt32 numHashBytes = 4; UInt32 numHashBytes = 4;
if (props.btMode) if (props.btMode)
@@ -465,8 +505,8 @@ static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11,
static void RangeEnc_Construct(CRangeEnc *p) static void RangeEnc_Construct(CRangeEnc *p)
{ {
p->outStream = 0; p->outStream = NULL;
p->bufBase = 0; p->bufBase = NULL;
} }
#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
@@ -474,10 +514,10 @@ static void RangeEnc_Construct(CRangeEnc *p)
#define RC_BUF_SIZE (1 << 16) #define RC_BUF_SIZE (1 << 16)
static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
{ {
if (p->bufBase == 0) if (!p->bufBase)
{ {
p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
if (p->bufBase == 0) if (!p->bufBase)
return 0; return 0;
p->bufLim = p->bufBase + RC_BUF_SIZE; p->bufLim = p->bufBase + RC_BUF_SIZE;
} }
@@ -518,7 +558,7 @@ static void RangeEnc_FlushStream(CRangeEnc *p)
static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
{ {
if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) if ((UInt32)p->low < (UInt32)0xFF000000 || (unsigned)(p->low >> 32) != 0)
{ {
Byte temp = p->cache; Byte temp = p->cache;
do do
@@ -544,7 +584,7 @@ static void RangeEnc_FlushData(CRangeEnc *p)
RangeEnc_ShiftLow(p); RangeEnc_ShiftLow(p);
} }
static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, unsigned numBits)
{ {
do do
{ {
@@ -607,7 +647,7 @@ static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol,
while (symbol < 0x10000); while (symbol < 0x10000);
} }
void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
{ {
UInt32 i; UInt32 i;
for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
@@ -643,7 +683,7 @@ void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const UInt32 *ProbPrices)
{ {
UInt32 price = 0; UInt32 price = 0;
symbol |= 0x100; symbol |= 0x100;
@@ -656,7 +696,7 @@ static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *Pro
return price; return price;
} }
static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const UInt32 *ProbPrices)
{ {
UInt32 price = 0; UInt32 price = 0;
UInt32 offs = 0x100; UInt32 offs = 0x100;
@@ -700,7 +740,7 @@ static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLeve
} }
} }
static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)
{ {
UInt32 price = 0; UInt32 price = 0;
symbol |= (1 << numBitLevels); symbol |= (1 << numBitLevels);
@@ -712,7 +752,7 @@ static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 s
return price; return price;
} }
static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)
{ {
UInt32 price = 0; UInt32 price = 0;
UInt32 m = 1; UInt32 m = 1;
@@ -763,7 +803,7 @@ static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posSt
} }
} }
static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, const UInt32 *ProbPrices)
{ {
UInt32 a0 = GET_PRICE_0a(p->choice); UInt32 a0 = GET_PRICE_0a(p->choice);
UInt32 a1 = GET_PRICE_1a(p->choice); UInt32 a1 = GET_PRICE_1a(p->choice);
@@ -786,20 +826,20 @@ static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UIn
prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
} }
static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, const UInt32 *ProbPrices)
{ {
LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
p->counters[posState] = p->tableSize; p->counters[posState] = p->tableSize;
} }
static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, const UInt32 *ProbPrices)
{ {
UInt32 posState; UInt32 posState;
for (posState = 0; posState < numPosStates; posState++) for (posState = 0; posState < numPosStates; posState++)
LenPriceEnc_UpdateTable(p, posState, ProbPrices); LenPriceEnc_UpdateTable(p, posState, ProbPrices);
} }
static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, const UInt32 *ProbPrices)
{ {
LenEnc_Encode(&p->p, rc, symbol, posState); LenEnc_Encode(&p->p, rc, symbol, posState);
if (updatePrice) if (updatePrice)
@@ -813,9 +853,10 @@ static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32
static void MovePos(CLzmaEnc *p, UInt32 num) static void MovePos(CLzmaEnc *p, UInt32 num)
{ {
#ifdef SHOW_STAT #ifdef SHOW_STAT
ttt += num; g_STAT_OFFSET += num;
printf("\n MovePos %d", num); printf("\n MovePos %u", num);
#endif #endif
if (num != 0) if (num != 0)
{ {
p->additionalOffset += num; p->additionalOffset += num;
@@ -828,28 +869,32 @@ static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
UInt32 lenRes = 0, numPairs; UInt32 lenRes = 0, numPairs;
p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
#ifdef SHOW_STAT #ifdef SHOW_STAT
printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); printf("\n i = %u numPairs = %u ", g_STAT_OFFSET, numPairs / 2);
ttt++; g_STAT_OFFSET++;
{ {
UInt32 i; UInt32 i;
for (i = 0; i < numPairs; i += 2) for (i = 0; i < numPairs; i += 2)
printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); printf("%2u %6u | ", p->matches[i], p->matches[i + 1]);
} }
#endif #endif
if (numPairs > 0) if (numPairs > 0)
{ {
lenRes = p->matches[numPairs - 2]; lenRes = p->matches[numPairs - 2];
if (lenRes == p->numFastBytes) if (lenRes == p->numFastBytes)
{ {
const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
UInt32 distance = p->matches[numPairs - 1] + 1;
UInt32 numAvail = p->numAvail; UInt32 numAvail = p->numAvail;
if (numAvail > LZMA_MATCH_LEN_MAX) if (numAvail > LZMA_MATCH_LEN_MAX)
numAvail = LZMA_MATCH_LEN_MAX; numAvail = LZMA_MATCH_LEN_MAX;
{ {
const Byte *pby2 = pby - distance; const Byte *pbyCur = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); const Byte *pby = pbyCur + lenRes;
ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[numPairs - 1];
const Byte *pbyLim = pbyCur + numAvail;
for (; pby != pbyLim && *pby == pby[dif]; pby++);
lenRes = (UInt32)(pby - pbyCur);
} }
} }
} }
@@ -934,7 +979,7 @@ static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
return p->optimumCurrentIndex; return p->optimumCurrentIndex;
} }
#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * (UInt32)0x300)
static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
{ {
@@ -978,7 +1023,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
UInt32 lenTest; UInt32 lenTest;
const Byte *data2; const Byte *data2;
reps[i] = p->reps[i]; reps[i] = p->reps[i];
data2 = data - (reps[i] + 1); data2 = data - reps[i] - 1;
if (data[0] != data2[0] || data[1] != data2[1]) if (data[0] != data2[0] || data[1] != data2[1])
{ {
repLens[i] = 0; repLens[i] = 0;
@@ -1122,12 +1167,12 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
cur = 0; cur = 0;
#ifdef SHOW_STAT2 #ifdef SHOW_STAT2
if (position >= 0) /* if (position >= 0) */
{ {
unsigned i; unsigned i;
printf("\n pos = %4X", position); printf("\n pos = %4X", position);
for (i = cur; i <= lenEnd; i++) for (i = cur; i <= lenEnd; i++)
printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
} }
#endif #endif
@@ -1279,7 +1324,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
/* try Literal + rep0 */ /* try Literal + rep0 */
UInt32 temp; UInt32 temp;
UInt32 lenTest2; UInt32 lenTest2;
const Byte *data2 = data - (reps[0] + 1); const Byte *data2 = data - reps[0] - 1;
UInt32 limit = p->numFastBytes + 1; UInt32 limit = p->numFastBytes + 1;
if (limit > numAvailFull) if (limit > numAvailFull)
limit = numAvailFull; limit = numAvailFull;
@@ -1322,7 +1367,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
UInt32 lenTest; UInt32 lenTest;
UInt32 lenTestTemp; UInt32 lenTestTemp;
UInt32 price; UInt32 price;
const Byte *data2 = data - (reps[repIndex] + 1); const Byte *data2 = data - reps[repIndex] - 1;
if (data[0] != data2[0] || data[1] != data2[1]) if (data[0] != data2[0] || data[1] != data2[1])
continue; continue;
for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
@@ -1352,13 +1397,13 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
{ {
UInt32 lenTest2 = lenTest + 1; UInt32 lenTest2 = lenTest + 1;
UInt32 limit = lenTest2 + p->numFastBytes; UInt32 limit = lenTest2 + p->numFastBytes;
UInt32 nextRepMatchPrice;
if (limit > numAvailFull) if (limit > numAvailFull)
limit = numAvailFull; limit = numAvailFull;
for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
lenTest2 -= lenTest + 1; lenTest2 -= lenTest + 1;
if (lenTest2 >= 2) if (lenTest2 >= 2)
{ {
UInt32 nextRepMatchPrice;
UInt32 state2 = kRepNextStates[state]; UInt32 state2 = kRepNextStates[state];
UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 posStateNext = (position + lenTest) & p->pbMask;
UInt32 curAndLenCharPrice = UInt32 curAndLenCharPrice =
@@ -1439,16 +1484,16 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
if (/*_maxMode && */lenTest == matches[offs]) if (/*_maxMode && */lenTest == matches[offs])
{ {
/* Try Match + Literal + Rep0 */ /* Try Match + Literal + Rep0 */
const Byte *data2 = data - (curBack + 1); const Byte *data2 = data - curBack - 1;
UInt32 lenTest2 = lenTest + 1; UInt32 lenTest2 = lenTest + 1;
UInt32 limit = lenTest2 + p->numFastBytes; UInt32 limit = lenTest2 + p->numFastBytes;
UInt32 nextRepMatchPrice;
if (limit > numAvailFull) if (limit > numAvailFull)
limit = numAvailFull; limit = numAvailFull;
for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
lenTest2 -= lenTest + 1; lenTest2 -= lenTest + 1;
if (lenTest2 >= 2) if (lenTest2 >= 2)
{ {
UInt32 nextRepMatchPrice;
UInt32 state2 = kMatchNextStates[state]; UInt32 state2 = kMatchNextStates[state];
UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 posStateNext = (position + lenTest) & p->pbMask;
UInt32 curAndLenCharPrice = curAndLenPrice + UInt32 curAndLenCharPrice = curAndLenPrice +
@@ -1522,7 +1567,7 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
for (i = 0; i < LZMA_NUM_REPS; i++) for (i = 0; i < LZMA_NUM_REPS; i++)
{ {
UInt32 len; UInt32 len;
const Byte *data2 = data - (p->reps[i] + 1); const Byte *data2 = data - p->reps[i] - 1;
if (data[0] != data2[0] || data[1] != data2[1]) if (data[0] != data2[0] || data[1] != data2[1])
continue; continue;
for (len = 2; len < numAvail && data[len] == data2[len]; len++); for (len = 2; len < numAvail && data[len] == data2[len]; len++);
@@ -1591,7 +1636,7 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
for (i = 0; i < LZMA_NUM_REPS; i++) for (i = 0; i < LZMA_NUM_REPS; i++)
{ {
UInt32 len, limit; UInt32 len, limit;
const Byte *data2 = data - (p->reps[i] + 1); const Byte *data2 = data - p->reps[i] - 1;
if (data[0] != data2[0] || data[1] != data2[1]) if (data[0] != data2[0] || data[1] != data2[1])
continue; continue;
limit = mainLen - 1; limit = mainLen - 1;
@@ -1687,6 +1732,7 @@ void LzmaEnc_Construct(CLzmaEnc *p)
{ {
RangeEnc_Construct(&p->rc); RangeEnc_Construct(&p->rc);
MatchFinder_Construct(&p->matchFinderBase); MatchFinder_Construct(&p->matchFinderBase);
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
MatchFinderMt_Construct(&p->matchFinderMt); MatchFinderMt_Construct(&p->matchFinderMt);
p->matchFinderMt.MatchFinder = &p->matchFinderBase; p->matchFinderMt.MatchFinder = &p->matchFinderBase;
@@ -1703,15 +1749,15 @@ void LzmaEnc_Construct(CLzmaEnc *p)
#endif #endif
LzmaEnc_InitPriceTables(p->ProbPrices); LzmaEnc_InitPriceTables(p->ProbPrices);
p->litProbs = 0; p->litProbs = NULL;
p->saveState.litProbs = 0; p->saveState.litProbs = NULL;
} }
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
{ {
void *p; void *p;
p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
if (p != 0) if (p)
LzmaEnc_Construct((CLzmaEnc *)p); LzmaEnc_Construct((CLzmaEnc *)p);
return p; return p;
} }
@@ -1720,8 +1766,8 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
{ {
alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->litProbs);
alloc->Free(alloc, p->saveState.litProbs); alloc->Free(alloc, p->saveState.litProbs);
p->litProbs = 0; p->litProbs = NULL;
p->saveState.litProbs = 0; p->saveState.litProbs = NULL;
} }
void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
@@ -1729,6 +1775,7 @@ void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
#endif #endif
MatchFinder_Free(&p->matchFinderBase, allocBig); MatchFinder_Free(&p->matchFinderBase, allocBig);
LzmaEnc_FreeLits(p, alloc); LzmaEnc_FreeLits(p, alloc);
RangeEnc_Free(&p->rc, alloc); RangeEnc_Free(&p->rc, alloc);
@@ -1765,7 +1812,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
ReadMatchDistances(p, &numPairs); ReadMatchDistances(p, &numPairs);
RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
p->state = kLiteralNextStates[p->state]; p->state = kLiteralNextStates[p->state];
curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
LitEnc_Encode(&p->rc, p->litProbs, curByte); LitEnc_Encode(&p->rc, p->litProbs, curByte);
p->additionalOffset--; p->additionalOffset--;
nowPos32++; nowPos32++;
@@ -1782,7 +1829,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
len = GetOptimum(p, nowPos32, &pos); len = GetOptimum(p, nowPos32, &pos);
#ifdef SHOW_STAT2 #ifdef SHOW_STAT2
printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); printf("\n pos = %4X, len = %u pos = %u", nowPos32, len, pos);
#endif #endif
posState = nowPos32 & p->pbMask; posState = nowPos32 & p->pbMask;
@@ -1891,7 +1938,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
break; break;
} }
else if (processed >= (1 << 15)) else if (processed >= (1 << 17))
{ {
p->nowPos64 += nowPos32 - startPos32; p->nowPos64 += nowPos32 - startPos32;
return CheckErrors(p); return CheckErrors(p);
@@ -1907,22 +1954,21 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
UInt32 beforeSize = kNumOpts; UInt32 beforeSize = kNumOpts;
Bool btMode;
if (!RangeEnc_Alloc(&p->rc, alloc)) if (!RangeEnc_Alloc(&p->rc, alloc))
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
btMode = (p->matchFinderBase.btMode != 0);
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
p->mtMode = (p->multiThread && !p->fastMode && btMode); p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));
#endif #endif
{ {
unsigned lclp = p->lc + p->lp; unsigned lclp = p->lc + p->lp;
if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
{ {
LzmaEnc_FreeLits(p, alloc); LzmaEnc_FreeLits(p, alloc);
p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
if (p->litProbs == 0 || p->saveState.litProbs == 0) if (!p->litProbs || !p->saveState.litProbs)
{ {
LzmaEnc_FreeLits(p, alloc); LzmaEnc_FreeLits(p, alloc);
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
@@ -1931,7 +1977,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
} }
} }
p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
if (beforeSize + p->dictSize < keepWindowSize) if (beforeSize + p->dictSize < keepWindowSize)
beforeSize = keepWindowSize - p->dictSize; beforeSize = keepWindowSize - p->dictSize;
@@ -1951,6 +1997,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
p->matchFinderObj = &p->matchFinderBase; p->matchFinderObj = &p->matchFinderBase;
MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
} }
return SZ_OK; return SZ_OK;
} }
@@ -1979,9 +2026,10 @@ void LzmaEnc_Init(CLzmaEnc *p)
} }
{ {
UInt32 num = 0x300 << (p->lp + p->lc); UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
CLzmaProb *probs = p->litProbs;
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
p->litProbs[i] = kProbInitValue; probs[i] = kProbInitValue;
} }
{ {
@@ -2088,10 +2136,11 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
if (p->mtMode) if (p->mtMode)
MatchFinderMt_ReleaseStream(&p->matchFinderMt); MatchFinderMt_ReleaseStream(&p->matchFinderMt);
#else #else
pp = pp; UNUSED_VAR(pp);
#endif #endif
} }
typedef struct typedef struct
{ {
ISeqOutStream funcTable; ISeqOutStream funcTable;
@@ -2121,12 +2170,14 @@ UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
} }
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
{ {
const CLzmaEnc *p = (CLzmaEnc *)pp; const CLzmaEnc *p = (CLzmaEnc *)pp;
return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
} }
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
{ {
@@ -2161,23 +2212,23 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
return res; return res;
} }
static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
Byte allocaDummy[0x300]; Byte allocaDummy[0x300];
int i = 0; allocaDummy[0] = 0;
for (i = 0; i < 16; i++) allocaDummy[1] = allocaDummy[0];
allocaDummy[i] = (Byte)i;
#endif #endif
for (;;) for (;;)
{ {
res = LzmaEnc_CodeOneBlock(p, False, 0, 0); res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
if (res != SZ_OK || p->finished != 0) if (res != SZ_OK || p->finished)
break; break;
if (progress != 0) if (progress)
{ {
res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
if (res != SZ_OK) if (res != SZ_OK)
@@ -2187,10 +2238,19 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
} }
} }
} }
LzmaEnc_Finish(p); LzmaEnc_Finish(p);
/*
if (res == S_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
res = SZ_ERROR_FAIL;
}
*/
return res; return res;
} }
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
ISzAlloc *alloc, ISzAlloc *allocBig) ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
@@ -2198,28 +2258,27 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
} }
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
{ {
CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEnc *p = (CLzmaEnc *)pp;
int i; unsigned i;
UInt32 dictSize = p->dictSize; UInt32 dictSize = p->dictSize;
if (*size < LZMA_PROPS_SIZE) if (*size < LZMA_PROPS_SIZE)
return SZ_ERROR_PARAM; return SZ_ERROR_PARAM;
*size = LZMA_PROPS_SIZE; *size = LZMA_PROPS_SIZE;
props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
for (i = 11; i <= 30; i++) if (dictSize >= ((UInt32)1 << 22))
{ {
if (dictSize <= ((UInt32)2 << i)) UInt32 kDictMask = ((UInt32)1 << 20) - 1;
{ if (dictSize < (UInt32)0xFFFFFFFF - kDictMask)
dictSize = (2 << i); dictSize = (dictSize + kDictMask) & ~kDictMask;
break; }
} else for (i = 11; i <= 30; i++)
if (dictSize <= ((UInt32)3 << i)) {
{ if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; }
dictSize = (3 << i); if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; }
break;
}
} }
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
@@ -2227,6 +2286,7 @@ SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
return SZ_OK; return SZ_OK;
} }
SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
@@ -2235,19 +2295,22 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
CSeqOutStreamBuf outStream; CSeqOutStreamBuf outStream;
LzmaEnc_SetInputBuf(p, src, srcLen);
outStream.funcTable.Write = MyWrite; outStream.funcTable.Write = MyWrite;
outStream.data = dest; outStream.data = dest;
outStream.rem = *destLen; outStream.rem = *destLen;
outStream.overflow = False; outStream.overflow = False;
p->writeEndMark = writeEndMark; p->writeEndMark = writeEndMark;
p->rc.outStream = &outStream.funcTable; p->rc.outStream = &outStream.funcTable;
res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
if (res == SZ_OK) if (res == SZ_OK)
{
res = LzmaEnc_Encode2(p, progress); res = LzmaEnc_Encode2(p, progress);
if (res == SZ_OK && p->nowPos64 != srcLen)
res = SZ_ERROR_FAIL;
}
*destLen -= outStream.rem; *destLen -= outStream.rem;
if (outStream.overflow) if (outStream.overflow)
@@ -2255,13 +2318,14 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
return res; return res;
} }
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, ISzAlloc *alloc, ISzAlloc *allocBig)
{ {
CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
SRes res; SRes res;
if (p == 0) if (!p)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = LzmaEnc_SetProps(p, props); res = LzmaEnc_SetProps(p, props);

View File

@@ -1,18 +1,12 @@
/* LzmaLib.c -- LZMA library wrapper /* LzmaLib.c -- LZMA library wrapper
2008-08-05 2015-06-13 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#include "LzmaEnc.h"
#include "LzmaDec.h"
#include "Alloc.h" #include "Alloc.h"
#include "LzmaDec.h"
#include "LzmaEnc.h"
#include "LzmaLib.h" #include "LzmaLib.h"
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
unsigned char *outProps, size_t *outPropsSize, unsigned char *outProps, size_t *outPropsSize,
int level, /* 0 <= level <= 9, default = 5 */ int level, /* 0 <= level <= 9, default = 5 */
unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
@@ -38,7 +32,7 @@ MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned cha
} }
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen,
const unsigned char *props, size_t propsSize) const unsigned char *props, size_t propsSize)
{ {
ELzmaStatus status; ELzmaStatus status;

View File

@@ -1,10 +1,8 @@
/* MtCoder.c -- Multi-thread Coder /* MtCoder.c -- Multi-thread Coder
2010-09-24 : Igor Pavlov : Public domain */ 2015-10-13 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <stdio.h>
#include "MtCoder.h" #include "MtCoder.h"
void LoopThread_Construct(CLoopThread *p) void LoopThread_Construct(CLoopThread *p)
@@ -120,7 +118,7 @@ void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
LoopThread_Construct(&p->thread); 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 void CMtThread_CloseEvents(CMtThread *p)
{ {

View File

@@ -1,10 +1,10 @@
/* Ppmd7.c -- PPMdH codec /* Ppmd7.c -- PPMdH codec
2010-03-12 : Igor Pavlov : Public domain 2015-09-28 : 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"
#include <memory.h> #include <string.h>
#include "Ppmd7.h" #include "Ppmd7.h"
@@ -66,7 +66,7 @@ void Ppmd7_Construct(CPpmd7 *p)
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
{ {
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
do { p->Units2Indx[k++] = (Byte)i; } while(--step); do { p->Units2Indx[k++] = (Byte)i; } while (--step);
p->Indx2Units[i] = (Byte)k; p->Indx2Units[i] = (Byte)k;
} }
@@ -257,7 +257,7 @@ static void *AllocUnits(CPpmd7 *p, unsigned indx)
#define MyMem12Cpy(dest, src, num) \ #define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); } do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while (--n); }
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{ {

View File

@@ -1,5 +1,5 @@
/* Ppmd7Enc.c -- PPMdH Encoder /* Ppmd7Enc.c -- PPMdH Encoder
2010-03-12 : Igor Pavlov : Public domain 2015-09-28 : 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"
@@ -26,7 +26,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32))); p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
temp = 0xFF; temp = 0xFF;
} }
while(--p->CacheSize != 0); while (--p->CacheSize != 0);
p->Cache = (Byte)((UInt32)p->Low >> 24); p->Cache = (Byte)((UInt32)p->Low >> 24);
} }
p->CacheSize++; p->CacheSize++;

View File

@@ -1,10 +1,10 @@
/* Ppmd8.c -- PPMdI codec /* Ppmd8.c -- PPMdI codec
2013-11-12 : Igor Pavlov : Public domain 2015-09-28 : Igor Pavlov : Public domain
This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */ This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <memory.h> #include <string.h>
#include "Ppmd8.h" #include "Ppmd8.h"
@@ -67,7 +67,7 @@ void Ppmd8_Construct(CPpmd8 *p)
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
{ {
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
do { p->Units2Indx[k++] = (Byte)i; } while(--step); do { p->Units2Indx[k++] = (Byte)i; } while (--step);
p->Indx2Units[i] = (Byte)k; p->Indx2Units[i] = (Byte)k;
} }
@@ -241,7 +241,7 @@ static void *AllocUnits(CPpmd8 *p, unsigned indx)
#define MyMem12Cpy(dest, src, num) \ #define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); } do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while (--n); }
static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU) static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{ {

View File

@@ -1,5 +1,5 @@
/* RotateDefs.h -- Rotate functions /* RotateDefs.h -- Rotate functions
2013-11-12 : Igor Pavlov : Public domain */ 2015-03-25 : Igor Pavlov : Public domain */
#ifndef __ROTATE_DEFS_H #ifndef __ROTATE_DEFS_H
#define __ROTATE_DEFS_H #define __ROTATE_DEFS_H
@@ -8,16 +8,20 @@
#include <stdlib.h> #include <stdlib.h>
// #if (_MSC_VER >= 1200) /* don't use _rotl with MINGW. It can insert slow call to function. */
/* #if (_MSC_VER >= 1200) */
#pragma intrinsic(_rotl) #pragma intrinsic(_rotl)
#pragma intrinsic(_rotr) #pragma intrinsic(_rotr)
// #endif /* #endif */
#define rotlFixed(x, n) _rotl((x), (n)) #define rotlFixed(x, n) _rotl((x), (n))
#define rotrFixed(x, n) _rotr((x), (n)) #define rotrFixed(x, n) _rotr((x), (n))
#else #else
/* new compilers can translate these macros to fast commands. */
#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) #define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))

334
C/Sha1.c Normal file
View File

@@ -0,0 +1,334 @@
/* Sha1.c -- SHA-1 Hash
2015-05-10 : Igor Pavlov : Public domain
This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */
#include "Precomp.h"
#include <string.h>
#include "CpuArch.h"
#include "RotateDefs.h"
#include "Sha1.h"
// define it for speed optimization
// #define _SHA1_UNROLL
#ifdef _SHA1_UNROLL
#define kNumW 16
#define WW(i) W[(i)&15]
#else
#define kNumW 80
#define WW(i) W[i]
#endif
#define w0(i) (W[i] = data[i])
#define w1(i) (WW(i) = rotlFixed(WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16), 1))
#define f1(x,y,z) (z^(x&(y^z)))
#define f2(x,y,z) (x^y^z)
#define f3(x,y,z) ((x&y)|(z&(x|y)))
#define f4(x,y,z) (x^y^z)
#define RK(a,b,c,d,e, fx, w, k) e += fx(b,c,d) + w + k + rotlFixed(a,5); b = rotlFixed(b,30);
#define R0(a,b,c,d,e, i) RK(a,b,c,d,e, f1, w0(i), 0x5A827999)
#define R1(a,b,c,d,e, i) RK(a,b,c,d,e, f1, w1(i), 0x5A827999)
#define R2(a,b,c,d,e, i) RK(a,b,c,d,e, f2, w1(i), 0x6ED9EBA1)
#define R3(a,b,c,d,e, i) RK(a,b,c,d,e, f3, w1(i), 0x8F1BBCDC)
#define R4(a,b,c,d,e, i) RK(a,b,c,d,e, f4, w1(i), 0xCA62C1D6)
#define RX_1_4(rx1, rx4, i) \
rx1(a,b,c,d,e, i); \
rx4(e,a,b,c,d, i+1); \
rx4(d,e,a,b,c, i+2); \
rx4(c,d,e,a,b, i+3); \
rx4(b,c,d,e,a, i+4); \
#define RX_5(rx, i) RX_1_4(rx, rx, i);
#ifdef _SHA1_UNROLL
#define RX_15 \
RX_5(R0, 0); \
RX_5(R0, 5); \
RX_5(R0, 10);
#define RX_20(rx, i) \
RX_5(rx, i); \
RX_5(rx, i + 5); \
RX_5(rx, i + 10); \
RX_5(rx, i + 15);
#else
#define RX_15 { unsigned i; for (i = 0; i < 15; i += 5) { RX_5(R0, i); } }
#define RX_20(rx, ii) { unsigned i; i = ii; for (; i < ii + 20; i += 5) { RX_5(rx, i); } }
#endif
void Sha1_Init(CSha1 *p)
{
p->state[0] = 0x67452301;
p->state[1] = 0xEFCDAB89;
p->state[2] = 0x98BADCFE;
p->state[3] = 0x10325476;
p->state[4] = 0xC3D2E1F0;
p->count = 0;
}
void Sha1_GetBlockDigest(CSha1 *p, const UInt32 *data, UInt32 *destDigest)
{
UInt32 a, b, c, d, e;
UInt32 W[kNumW];
a = p->state[0];
b = p->state[1];
c = p->state[2];
d = p->state[3];
e = p->state[4];
RX_15
RX_1_4(R0, R1, 15);
RX_20(R2, 20);
RX_20(R3, 40);
RX_20(R4, 60);
destDigest[0] = p->state[0] + a;
destDigest[1] = p->state[1] + b;
destDigest[2] = p->state[2] + c;
destDigest[3] = p->state[3] + d;
destDigest[4] = p->state[4] + e;
}
void Sha1_UpdateBlock_Rar(CSha1 *p, UInt32 *data, int returnRes)
{
UInt32 a, b, c, d, e;
UInt32 W[kNumW];
a = p->state[0];
b = p->state[1];
c = p->state[2];
d = p->state[3];
e = p->state[4];
RX_15
RX_1_4(R0, R1, 15);
RX_20(R2, 20);
RX_20(R3, 40);
RX_20(R4, 60);
p->state[0] += a;
p->state[1] += b;
p->state[2] += c;
p->state[3] += d;
p->state[4] += e;
if (returnRes)
{
unsigned i;
for (i = 0 ; i < SHA1_NUM_BLOCK_WORDS; i++)
data[i] = W[kNumW - SHA1_NUM_BLOCK_WORDS + i];
}
}
#define Sha1_UpdateBlock(p) Sha1_GetBlockDigest(p, p->buffer, p->state)
void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
{
unsigned pos, pos2;
if (size == 0)
return;
pos = (unsigned)p->count & 0x3F;
p->count += size;
pos2 = pos & 3;
pos >>= 2;
if (pos2 != 0)
{
UInt32 w = ((UInt32)data[0]) << 24;
if (--size && pos2 < 3)
{
w |= ((UInt32)data[1]) << 16;
if (--size && pos2 < 2)
{
w |= ((UInt32)data[2]) << 8;
--size;
}
}
data += 4 - pos2;
p->buffer[pos++] |= (w >> (8 * pos2));
}
for (;;)
{
if (pos == SHA1_NUM_BLOCK_WORDS)
{
for (;;)
{
unsigned i;
Sha1_UpdateBlock(p);
if (size < SHA1_BLOCK_SIZE)
break;
size -= SHA1_BLOCK_SIZE;
for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i += 2)
{
p->buffer[i ] = GetBe32(data);
p->buffer[i + 1] = GetBe32(data + 4);
data += 8;
}
}
pos = 0;
}
if (size < 4)
break;
p->buffer[pos] = GetBe32(data);
data += 4;
size -= 4;
pos++;
}
if (size != 0)
{
UInt32 w = ((UInt32)data[0]) << 24;
if (size > 1)
{
w |= ((UInt32)data[1]) << 16;
if (size > 2)
w |= ((UInt32)data[2]) << 8;
}
p->buffer[pos] = w;
}
}
void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size, int rar350Mode)
{
int returnRes = False;
unsigned pos = (unsigned)p->count & 0x3F;
p->count += size;
while (size--)
{
unsigned pos2 = (pos & 3);
UInt32 v = ((UInt32)*data++) << (8 * (3 - pos2));
UInt32 *ref = &(p->buffer[pos >> 2]);
pos++;
if (pos2 == 0)
{
*ref = v;
continue;
}
*ref |= v;
if (pos == SHA1_BLOCK_SIZE)
{
pos = 0;
Sha1_UpdateBlock_Rar(p, p->buffer, returnRes);
if (returnRes)
{
unsigned i;
for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
{
UInt32 d = p->buffer[i];
Byte *prev = data + i * 4 - SHA1_BLOCK_SIZE;
SetUi32(prev, d);
}
}
returnRes = rar350Mode;
}
}
}
void Sha1_Final(CSha1 *p, Byte *digest)
{
unsigned pos = (unsigned)p->count & 0x3F;
unsigned pos2 = (pos & 3);
UInt64 numBits;
UInt32 w;
unsigned i;
pos >>= 2;
w = 0;
if (pos2 != 0)
w = p->buffer[pos];
p->buffer[pos++] = w | (((UInt32)0x80000000) >> (8 * pos2));
while (pos != (SHA1_NUM_BLOCK_WORDS - 2))
{
pos &= 0xF;
if (pos == 0)
Sha1_UpdateBlock(p);
p->buffer[pos++] = 0;
}
numBits = (p->count << 3);
p->buffer[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32);
p->buffer[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits);
Sha1_UpdateBlock(p);
for (i = 0; i < SHA1_NUM_DIGEST_WORDS; i++)
{
UInt32 v = p->state[i];
SetBe32(digest, v);
digest += 4;
}
Sha1_Init(p);
}
void Sha1_32_PrepareBlock(const CSha1 *p, UInt32 *block, unsigned size)
{
const UInt64 numBits = (p->count + size) << 5;
block[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32);
block[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits);
block[size++] = 0x80000000;
while (size != (SHA1_NUM_BLOCK_WORDS - 2))
block[size++] = 0;
}
void Sha1_32_Update(CSha1 *p, const UInt32 *data, size_t size)
{
unsigned pos = (unsigned)p->count & 0xF;
p->count += size;
while (size--)
{
p->buffer[pos++] = *data++;
if (pos == SHA1_NUM_BLOCK_WORDS)
{
pos = 0;
Sha1_UpdateBlock(p);
}
}
}
void Sha1_32_Final(CSha1 *p, UInt32 *digest)
{
UInt64 numBits;
unsigned pos = (unsigned)p->count & 0xF;
p->buffer[pos++] = 0x80000000;
while (pos != (SHA1_NUM_BLOCK_WORDS - 2))
{
pos &= 0xF;
if (pos == 0)
Sha1_UpdateBlock(p);
p->buffer[pos++] = 0;
}
numBits = (p->count << 5);
p->buffer[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32);
p->buffer[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits);
Sha1_GetBlockDigest(p, p->buffer, digest);
Sha1_Init(p);
}

38
C/Sha1.h Normal file
View File

@@ -0,0 +1,38 @@
/* Sha1.h -- SHA-1 Hash
2015-03-04 : Igor Pavlov : Public domain */
#ifndef __7Z_SHA1_H
#define __7Z_SHA1_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define SHA1_NUM_BLOCK_WORDS 16
#define SHA1_NUM_DIGEST_WORDS 5
#define SHA1_BLOCK_SIZE (SHA1_NUM_BLOCK_WORDS * 4)
#define SHA1_DIGEST_SIZE (SHA1_NUM_DIGEST_WORDS * 4)
typedef struct
{
UInt32 state[SHA1_NUM_DIGEST_WORDS];
UInt64 count;
UInt32 buffer[SHA1_NUM_BLOCK_WORDS];
} CSha1;
void Sha1_Init(CSha1 *p);
void Sha1_GetBlockDigest(CSha1 *p, const UInt32 *data, UInt32 *destDigest);
void Sha1_Update(CSha1 *p, const Byte *data, size_t size);
void Sha1_Final(CSha1 *p, Byte *digest);
void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size, int rar350Mode);
void Sha1_32_PrepareBlock(const CSha1 *p, UInt32 *block, unsigned size);
void Sha1_32_Update(CSha1 *p, const UInt32 *data, size_t size);
void Sha1_32_Final(CSha1 *p, UInt32 *digest);
EXTERN_C_END
#endif

View File

@@ -1,14 +1,21 @@
/* Crypto/Sha256.c -- SHA-256 Hash /* Crypto/Sha256.c -- SHA-256 Hash
2010-06-11 : Igor Pavlov : Public domain 2015-11-14 : 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"
#include <string.h>
#include "CpuArch.h"
#include "RotateDefs.h" #include "RotateDefs.h"
#include "Sha256.h" #include "Sha256.h"
/* define it for speed optimization */ /* define it for speed optimization */
/* #define _SHA256_UNROLL */ #ifndef _SFX
#define _SHA256_UNROLL
#define _SHA256_UNROLL2
#endif
/* #define _SHA256_UNROLL2 */ /* #define _SHA256_UNROLL2 */
void Sha256_Init(CSha256 *p) void Sha256_Init(CSha256 *p)
@@ -29,26 +36,18 @@ void Sha256_Init(CSha256 *p)
#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) #define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3))
#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10)) #define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10))
#define blk0(i) (W[i] = data[i]) #define blk0(i) (W[i])
#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15])) #define blk2(i) (W[i] += s1(W[((i)-2)&15]) + W[((i)-7)&15] + s0(W[((i)-15)&15]))
#define Ch(x,y,z) (z^(x&(y^z))) #define Ch(x,y,z) (z^(x&(y^z)))
#define Maj(x,y,z) ((x&y)|(z&(x|y))) #define Maj(x,y,z) ((x&y)|(z&(x|y)))
#define a(i) T[(0-(i))&7]
#define b(i) T[(1-(i))&7]
#define c(i) T[(2-(i))&7]
#define d(i) T[(3-(i))&7]
#define e(i) T[(4-(i))&7]
#define f(i) T[(5-(i))&7]
#define g(i) T[(6-(i))&7]
#define h(i) T[(7-(i))&7]
#ifdef _SHA256_UNROLL2 #ifdef _SHA256_UNROLL2
#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));\ #define R(a,b,c,d,e,f,g,h, i) \
d += h; h += S0(a) + Maj(a, b, c) h += S1(e) + Ch(e,f,g) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \
d += h; \
h += S0(a) + Maj(a, b, c)
#define RX_8(i) \ #define RX_8(i) \
R(a,b,c,d,e,f,g,h, i); \ R(a,b,c,d,e,f,g,h, i); \
@@ -60,14 +59,32 @@ void Sha256_Init(CSha256 *p)
R(c,d,e,f,g,h,a,b, i+6); \ R(c,d,e,f,g,h,a,b, i+6); \
R(b,c,d,e,f,g,h,a, i+7) R(b,c,d,e,f,g,h,a, i+7)
#define RX_16 RX_8(0); RX_8(8);
#else #else
#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\ #define a(i) T[(0-(i))&7]
d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) #define b(i) T[(1-(i))&7]
#define c(i) T[(2-(i))&7]
#define d(i) T[(3-(i))&7]
#define e(i) T[(4-(i))&7]
#define f(i) T[(5-(i))&7]
#define g(i) T[(6-(i))&7]
#define h(i) T[(7-(i))&7]
#define R(i) \
h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \
d(i) += h(i); \
h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) \
#ifdef _SHA256_UNROLL #ifdef _SHA256_UNROLL
#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7); #define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);
#define RX_16 RX_8(0); RX_8(8);
#else
#define RX_16 unsigned i; for (i = 0; i < 16; i++) { R(i); }
#endif #endif
@@ -92,12 +109,30 @@ static const UInt32 K[64] = {
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
}; };
static void Sha256_Transform(UInt32 *state, const UInt32 *data) static void Sha256_WriteByteBlock(CSha256 *p)
{ {
UInt32 W[16]; UInt32 W[16];
unsigned j; unsigned j;
UInt32 *state;
#ifdef _SHA256_UNROLL2 #ifdef _SHA256_UNROLL2
UInt32 a,b,c,d,e,f,g,h; UInt32 a,b,c,d,e,f,g,h;
#else
UInt32 T[8];
#endif
for (j = 0; j < 16; j += 4)
{
const Byte *ccc = p->buffer + j * 4;
W[j ] = GetBe32(ccc);
W[j + 1] = GetBe32(ccc + 4);
W[j + 2] = GetBe32(ccc + 8);
W[j + 3] = GetBe32(ccc + 12);
}
state = p->state;
#ifdef _SHA256_UNROLL2
a = state[0]; a = state[0];
b = state[1]; b = state[1];
c = state[2]; c = state[2];
@@ -107,19 +142,13 @@ static void Sha256_Transform(UInt32 *state, const UInt32 *data)
g = state[6]; g = state[6];
h = state[7]; h = state[7];
#else #else
UInt32 T[8];
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
T[j] = state[j]; T[j] = state[j];
#endif #endif
for (j = 0; j < 64; j += 16) for (j = 0; j < 64; j += 16)
{ {
#if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2) RX_16
RX_8(0); RX_8(8);
#else
unsigned i;
for (i = 0; i < 16; i++) { R(i); }
#endif
} }
#ifdef _SHA256_UNROLL2 #ifdef _SHA256_UNROLL2
@@ -146,61 +175,74 @@ static void Sha256_Transform(UInt32 *state, const UInt32 *data)
#undef s0 #undef s0
#undef s1 #undef s1
static void Sha256_WriteByteBlock(CSha256 *p)
{
UInt32 data32[16];
unsigned i;
for (i = 0; i < 16; i++)
data32[i] =
((UInt32)(p->buffer[i * 4 ]) << 24) +
((UInt32)(p->buffer[i * 4 + 1]) << 16) +
((UInt32)(p->buffer[i * 4 + 2]) << 8) +
((UInt32)(p->buffer[i * 4 + 3]));
Sha256_Transform(p->state, data32);
}
void Sha256_Update(CSha256 *p, const Byte *data, size_t size) void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
{ {
UInt32 curBufferPos = (UInt32)p->count & 0x3F; if (size == 0)
while (size > 0) return;
{ {
p->buffer[curBufferPos++] = *data++; unsigned pos = (unsigned)p->count & 0x3F;
p->count++; unsigned num;
size--;
if (curBufferPos == 64) p->count += size;
num = 64 - pos;
if (num > size)
{ {
curBufferPos = 0; memcpy(p->buffer + pos, data, size);
Sha256_WriteByteBlock(p); return;
} }
size -= num;
memcpy(p->buffer + pos, data, num);
data += num;
} }
for (;;)
{
Sha256_WriteByteBlock(p);
if (size < 64)
break;
size -= 64;
memcpy(p->buffer, data, 64);
data += 64;
}
if (size != 0)
memcpy(p->buffer, data, size);
} }
void Sha256_Final(CSha256 *p, Byte *digest) void Sha256_Final(CSha256 *p, Byte *digest)
{ {
UInt64 lenInBits = (p->count << 3); unsigned pos = (unsigned)p->count & 0x3F;
UInt32 curBufferPos = (UInt32)p->count & 0x3F;
unsigned i; unsigned i;
p->buffer[curBufferPos++] = 0x80;
while (curBufferPos != (64 - 8)) p->buffer[pos++] = 0x80;
while (pos != (64 - 8))
{ {
curBufferPos &= 0x3F; pos &= 0x3F;
if (curBufferPos == 0) if (pos == 0)
Sha256_WriteByteBlock(p); Sha256_WriteByteBlock(p);
p->buffer[curBufferPos++] = 0; p->buffer[pos++] = 0;
} }
for (i = 0; i < 8; i++)
{ {
p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56); UInt64 numBits = (p->count << 3);
lenInBits <<= 8; SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32));
SetBe32(p->buffer + 64 - 4, (UInt32)(numBits));
} }
Sha256_WriteByteBlock(p); Sha256_WriteByteBlock(p);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i += 2)
{ {
*digest++ = (Byte)(p->state[i] >> 24); UInt32 v0 = p->state[i];
*digest++ = (Byte)(p->state[i] >> 16); UInt32 v1 = p->state[i + 1];
*digest++ = (Byte)(p->state[i] >> 8); SetBe32(digest , v0);
*digest++ = (Byte)(p->state[i]); SetBe32(digest + 4, v1);
digest += 8;
} }
Sha256_Init(p); Sha256_Init(p);
} }

View File

@@ -1,9 +1,9 @@
/* Threads.c -- multithreading library /* Threads.c -- multithreading library
2013-11-12 : Igor Pavlov : Public domain */ 2014-09-21 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#ifndef _WIN32_WCE #ifndef UNDER_CE
#include <process.h> #include <process.h>
#endif #endif

View File

@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /Yu"Precomp.h" /FD /c # ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAcs /Yu"Precomp.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
@@ -165,6 +165,10 @@ SOURCE=..\..\Bra86.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\BraIA64.c
# End Source File
# Begin Source File
SOURCE=..\..\CpuArch.c SOURCE=..\..\CpuArch.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -173,6 +177,14 @@ SOURCE=..\..\CpuArch.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Delta.c
# End Source File
# Begin Source File
SOURCE=..\..\Delta.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,5 +1,5 @@
/* 7zMain.c - Test application for 7z Decoder /* 7zMain.c - Test application for 7z Decoder
2014-06-17 : Igor Pavlov : Public domain */ 2015-08-02 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -34,75 +34,117 @@ static int Buf_EnsureSize(CBuf *dest, size_t size)
} }
#ifndef _WIN32 #ifndef _WIN32
#define _USE_UTF8
#endif
static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; /* #define _USE_UTF8 */
static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen) #ifdef _USE_UTF8
#define _UTF8_START(n) (0x100 - (1 << (7 - (n))))
#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6))
#define _UTF8_HEAD(n, val) ((Byte)(_UTF8_START(n) + (val >> (6 * (n)))))
#define _UTF8_CHAR(n, val) ((Byte)(0x80 + (((val) >> (6 * (n))) & 0x3F)))
static size_t Utf16_To_Utf8_Calc(const UInt16 *src, const UInt16 *srcLim)
{ {
size_t destPos = 0, srcPos = 0; size_t size = 0;
for (;;) for (;;)
{ {
unsigned numAdds; UInt32 val;
UInt32 value; if (src == srcLim)
if (srcPos == srcLen) return size;
size++;
val = *src++;
if (val < 0x80)
continue;
if (val < _UTF8_RANGE(1))
{ {
*destLen = destPos; size++;
return True;
}
value = src[srcPos++];
if (value < 0x80)
{
if (dest)
dest[destPos] = (char)value;
destPos++;
continue; continue;
} }
if (value >= 0xD800 && value < 0xE000)
if (val >= 0xD800 && val < 0xDC00 && src != srcLim)
{ {
UInt32 c2; UInt32 c2 = *src;
if (value >= 0xDC00 || srcPos == srcLen) if (c2 >= 0xDC00 && c2 < 0xE000)
break; {
c2 = src[srcPos++]; src++;
if (c2 < 0xDC00 || c2 >= 0xE000) size += 3;
break; continue;
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; }
} }
for (numAdds = 1; numAdds < 5; numAdds++)
if (value < (((UInt32)1) << (numAdds * 5 + 6))) size += 2;
break; }
if (dest) }
dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
destPos++; static Byte *Utf16_To_Utf8(Byte *dest, const UInt16 *src, const UInt16 *srcLim)
do {
{ for (;;)
numAdds--; {
if (dest) UInt32 val;
dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); if (src == srcLim)
destPos++; return dest;
}
while (numAdds != 0); val = *src++;
if (val < 0x80)
{
*dest++ = (char)val;
continue;
}
if (val < _UTF8_RANGE(1))
{
dest[0] = _UTF8_HEAD(1, val);
dest[1] = _UTF8_CHAR(0, val);
dest += 2;
continue;
}
if (val >= 0xD800 && val < 0xDC00 && src != srcLim)
{
UInt32 c2 = *src;
if (c2 >= 0xDC00 && c2 < 0xE000)
{
src++;
val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
dest[0] = _UTF8_HEAD(3, val);
dest[1] = _UTF8_CHAR(2, val);
dest[2] = _UTF8_CHAR(1, val);
dest[3] = _UTF8_CHAR(0, val);
dest += 4;
continue;
}
}
dest[0] = _UTF8_HEAD(2, val);
dest[1] = _UTF8_CHAR(1, val);
dest[2] = _UTF8_CHAR(0, val);
dest += 3;
} }
*destLen = destPos;
return False;
} }
static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen) static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)
{ {
size_t destLen = 0; size_t destLen = Utf16_To_Utf8_Calc(src, src + srcLen);
Bool res;
Utf16_To_Utf8(NULL, &destLen, src, srcLen);
destLen += 1; destLen += 1;
if (!Buf_EnsureSize(dest, destLen)) if (!Buf_EnsureSize(dest, destLen))
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen); *Utf16_To_Utf8(dest->data, src, src + srcLen) = 0;
dest->data[destLen] = 0; return SZ_OK;
return res ? SZ_OK : SZ_ERROR_FAIL;
} }
#endif #endif
static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s
#ifdef _WIN32 #ifndef _USE_UTF8
, UINT codePage , UINT codePage
#endif #endif
) )
@@ -110,7 +152,7 @@ static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s
unsigned len = 0; unsigned len = 0;
for (len = 0; s[len] != 0; len++); for (len = 0; s[len] != 0; len++);
#ifdef _WIN32 #ifndef _USE_UTF8
{ {
unsigned size = len * 3 + 100; unsigned size = len * 3 + 100;
if (!Buf_EnsureSize(buf, size)) if (!Buf_EnsureSize(buf, size))
@@ -191,7 +233,7 @@ static SRes PrintString(const UInt16 *s)
SRes res; SRes res;
Buf_Init(&buf); Buf_Init(&buf);
res = Utf16_To_Char(&buf, s res = Utf16_To_Char(&buf, s
#ifdef _WIN32 #ifndef _USE_UTF8
, CP_OEMCP , CP_OEMCP
#endif #endif
); );
@@ -286,22 +328,20 @@ void PrintError(char *sz)
printf("\nERROR: %s\n", sz); printf("\nERROR: %s\n", sz);
} }
#ifdef USE_WINDOWS_FILE
static void GetAttribString(UInt32 wa, Bool isDir, char *s) static void GetAttribString(UInt32 wa, Bool isDir, char *s)
{ {
#ifdef USE_WINDOWS_FILE
s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.'); s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');
s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.'); s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');
s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.'); s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.');
s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.'); s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.');
s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.'); s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.');
s[5] = '\0'; s[5] = 0;
#else
s[0] = (char)(((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.');
s[1] = 0;
#endif
} }
#else
static void GetAttribString(UInt32, Bool, char *s)
{
s[0] = '\0';
}
#endif
// #define NUM_PARENTS_MAX 128 // #define NUM_PARENTS_MAX 128
@@ -318,6 +358,7 @@ int MY_CDECL main(int numargs, char *args[])
// UInt32 parents[NUM_PARENTS_MAX]; // UInt32 parents[NUM_PARENTS_MAX];
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n"); printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");
if (numargs == 1) if (numargs == 1)
{ {
printf( printf(
@@ -329,6 +370,7 @@ int MY_CDECL main(int numargs, char *args[])
" x: eXtract files with full paths\n"); " x: eXtract files with full paths\n");
return 0; return 0;
} }
if (numargs < 3) if (numargs < 3)
{ {
PrintError("incorrect command"); PrintError("incorrect command");
@@ -364,15 +406,18 @@ int MY_CDECL main(int numargs, char *args[])
CrcGenerateTable(); CrcGenerateTable();
SzArEx_Init(&db); SzArEx_Init(&db);
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if (res == SZ_OK) if (res == SZ_OK)
{ {
char *command = args[1]; char *command = args[1];
int listCommand = 0, testCommand = 0, extractCommand = 0, fullPaths = 0; int listCommand = 0, testCommand = 0, fullPaths = 0;
if (strcmp(command, "l") == 0) listCommand = 1; if (strcmp(command, "l") == 0) listCommand = 1;
else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1;
else if (strcmp(command, "e") == 0) extractCommand = 1; else if (strcmp(command, "e") == 0) { }
else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; } else if (strcmp(command, "x") == 0) { fullPaths = 1; }
else else
{ {
PrintError("incorrect command"); PrintError("incorrect command");
@@ -397,7 +442,7 @@ int MY_CDECL main(int numargs, char *args[])
size_t outSizeProcessed = 0; size_t outSizeProcessed = 0;
// const CSzFileItem *f = db.Files + i; // const CSzFileItem *f = db.Files + i;
size_t len; size_t len;
int isDir = SzArEx_IsDir(&db, i); unsigned isDir = SzArEx_IsDir(&db, i);
if (listCommand == 0 && isDir && !fullPaths) if (listCommand == 0 && isDir && !fullPaths)
continue; continue;
len = SzArEx_GetFileNameUtf16(&db, i, NULL); len = SzArEx_GetFileNameUtf16(&db, i, NULL);
@@ -433,6 +478,7 @@ int MY_CDECL main(int numargs, char *args[])
fileSize = SzArEx_GetFileSize(&db, i); fileSize = SzArEx_GetFileSize(&db, i);
UInt64ToStr(fileSize, s); UInt64ToStr(fileSize, s);
if (SzBitWithVals_Check(&db.MTime, i)) if (SzBitWithVals_Check(&db.MTime, i))
ConvertFileTimeToString(&db.MTime.Vals[i], t); ConvertFileTimeToString(&db.MTime.Vals[i], t);
else else
@@ -452,6 +498,7 @@ int MY_CDECL main(int numargs, char *args[])
printf("\n"); printf("\n");
continue; continue;
} }
fputs(testCommand ? fputs(testCommand ?
"Testing ": "Testing ":
"Extracting ", "Extracting ",
@@ -459,6 +506,7 @@ int MY_CDECL main(int numargs, char *args[])
res = PrintString(temp); res = PrintString(temp);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (isDir) if (isDir)
printf("/"); printf("/");
else else
@@ -470,6 +518,7 @@ int MY_CDECL main(int numargs, char *args[])
if (res != SZ_OK) if (res != SZ_OK)
break; break;
} }
if (!testCommand) if (!testCommand)
{ {
CSzFile outFile; CSzFile outFile;
@@ -477,6 +526,7 @@ int MY_CDECL main(int numargs, char *args[])
size_t j; size_t j;
UInt16 *name = (UInt16 *)temp; UInt16 *name = (UInt16 *)temp;
const UInt16 *destPath = (const UInt16 *)name; const UInt16 *destPath = (const UInt16 *)name;
for (j = 0; name[j] != 0; j++) for (j = 0; name[j] != 0; j++)
if (name[j] == '/') if (name[j] == '/')
{ {
@@ -502,19 +552,23 @@ int MY_CDECL main(int numargs, char *args[])
res = SZ_ERROR_FAIL; res = SZ_ERROR_FAIL;
break; break;
} }
processedSize = outSizeProcessed; processedSize = outSizeProcessed;
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)
{ {
PrintError("can not write output file"); PrintError("can not write output file");
res = SZ_ERROR_FAIL; res = SZ_ERROR_FAIL;
break; break;
} }
if (File_Close(&outFile)) if (File_Close(&outFile))
{ {
PrintError("can not close output file"); PrintError("can not close output file");
res = SZ_ERROR_FAIL; res = SZ_ERROR_FAIL;
break; break;
} }
#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]); SetFileAttributesW(destPath, db.Attribs.Vals[i]);
@@ -525,15 +579,18 @@ int MY_CDECL main(int numargs, char *args[])
IAlloc_Free(&allocImp, outBuffer); IAlloc_Free(&allocImp, outBuffer);
} }
} }
SzArEx_Free(&db, &allocImp); SzArEx_Free(&db, &allocImp);
SzFree(NULL, temp); SzFree(NULL, temp);
File_Close(&archiveStream.file); File_Close(&archiveStream.file);
if (res == SZ_OK) if (res == SZ_OK)
{ {
printf("\nEverything is Ok\n"); printf("\nEverything is Ok\n");
return 0; return 0;
} }
if (res == SZ_ERROR_UNSUPPORTED) if (res == SZ_ERROR_UNSUPPORTED)
PrintError("decoder doesn't support this archive"); PrintError("decoder doesn't support this archive");
else if (res == SZ_ERROR_MEM) else if (res == SZ_ERROR_MEM)
@@ -542,5 +599,6 @@ int MY_CDECL main(int numargs, char *args[])
PrintError("CRC error"); PrintError("CRC error");
else else
printf("\nERROR #%d\n", res); printf("\nERROR #%d\n", res);
return 1; return 1;
} }

View File

@@ -1,4 +1,3 @@
# MY_STATIC_LINK=1
CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT
PROG = 7zDec.exe PROG = 7zDec.exe
@@ -15,7 +14,9 @@ C_OBJS = \
$O\Bcj2.obj \ $O\Bcj2.obj \
$O\Bra.obj \ $O\Bra.obj \
$O\Bra86.obj \ $O\Bra86.obj \
$O\BraIA64.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Delta.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\Ppmd7.obj \ $O\Ppmd7.obj \

View File

@@ -1,10 +1,10 @@
PROG = 7zDec PROG = 7zDec
CXX = g++ CXX = gcc
LIB = LIB =
RM = rm -f RM = rm -f
CFLAGS = -c -O2 -Wall CFLAGS = -c -O2 -Wall
OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o Delta.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o BraIA64.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o
all: $(PROG) all: $(PROG)
@@ -38,6 +38,9 @@ $(PROG): $(OBJS)
CpuArch.o: ../../CpuArch.c CpuArch.o: ../../CpuArch.c
$(CXX) $(CFLAGS) ../../CpuArch.c $(CXX) $(CFLAGS) ../../CpuArch.c
Delta.o: ../../Delta.c
$(CXX) $(CFLAGS) ../../Delta.c
LzmaDec.o: ../../LzmaDec.c LzmaDec.o: ../../LzmaDec.c
$(CXX) $(CFLAGS) ../../LzmaDec.c $(CXX) $(CFLAGS) ../../LzmaDec.c
@@ -50,6 +53,9 @@ Bra.o: ../../Bra.c
Bra86.o: ../../Bra86.c Bra86.o: ../../Bra86.c
$(CXX) $(CFLAGS) ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c
BraIA64.o: ../../BraIA64.c
$(CXX) $(CFLAGS) ../../BraIA64.c
Bcj2.o: ../../Bcj2.c Bcj2.o: ../../Bcj2.c
$(CXX) $(CFLAGS) ../../Bcj2.c $(CXX) $(CFLAGS) ../../Bcj2.c
@@ -67,4 +73,3 @@ Ppmd7Dec.o: ../../Ppmd7Dec.c
clean: clean:
-$(RM) $(PROG) $(OBJS) -$(RM) $(PROG) $(OBJS)

BIN
C/Util/7zipInstall/7zip.ico Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,231 @@
# Microsoft Developer Studio Project File - Name="7zipInstall" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=7zipInstall - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "7zipInstall.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "7zipInstall.mak" CFG="7zipInstall - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "7zipInstall - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "7zipInstall - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "7zipInstall - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE2" /D "UNICODE2" /Yu"Precomp.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
!ELSEIF "$(CFG)" == "7zipInstall - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE2" /D "UNICODE2" /Yu"Precomp.h" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "7zipInstall - Win32 Release"
# Name "7zipInstall - Win32 Debug"
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\7z.h
# End Source File
# Begin Source File
SOURCE=..\..\7zAlloc.c
# End Source File
# Begin Source File
SOURCE=..\..\7zAlloc.h
# End Source File
# Begin Source File
SOURCE=..\..\7zArcIn.c
# End Source File
# Begin Source File
SOURCE=..\..\7zBuf.c
# End Source File
# Begin Source File
SOURCE=..\..\7zBuf.h
# End Source File
# Begin Source File
SOURCE=..\..\7zCrc.c
# End Source File
# Begin Source File
SOURCE=..\..\7zCrc.h
# End Source File
# Begin Source File
SOURCE=..\..\7zCrcOpt.c
# End Source File
# Begin Source File
SOURCE=..\..\7zDec.c
# End Source File
# Begin Source File
SOURCE=..\..\7zFile.c
# End Source File
# Begin Source File
SOURCE=..\..\7zFile.h
# End Source File
# Begin Source File
SOURCE=..\..\7zStream.c
# End Source File
# Begin Source File
SOURCE=..\..\7zTypes.h
# End Source File
# Begin Source File
SOURCE=..\..\7zVersion.h
# End Source File
# Begin Source File
SOURCE=..\..\Bcj2.c
# End Source File
# Begin Source File
SOURCE=..\..\Bcj2.h
# End Source File
# Begin Source File
SOURCE=..\..\Bra.c
# End Source File
# Begin Source File
SOURCE=..\..\Bra.h
# End Source File
# Begin Source File
SOURCE=..\..\Bra86.c
# End Source File
# Begin Source File
SOURCE=..\..\BraIA64.c
# End Source File
# Begin Source File
SOURCE=..\..\CpuArch.c
# End Source File
# Begin Source File
SOURCE=..\..\CpuArch.h
# End Source File
# Begin Source File
SOURCE=..\..\Delta.c
# End Source File
# Begin Source File
SOURCE=..\..\Delta.h
# End Source File
# Begin Source File
SOURCE=..\..\Lzma2Dec.c
# End Source File
# Begin Source File
SOURCE=..\..\Lzma2Dec.h
# End Source File
# Begin Source File
SOURCE=..\..\LzmaDec.c
# End Source File
# Begin Source File
SOURCE=..\..\LzmaDec.h
# End Source File
# End Group
# Begin Group "Spec"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\Precomp.c
# ADD CPP /Yc"Precomp.h"
# End Source File
# Begin Source File
SOURCE=.\Precomp.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\7zipInstall.c
# End Source File
# Begin Source File
SOURCE=.\resource.rc
# End Source File
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "7zipInstall"=.\7zipInstall.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.7zipInstall" type="win32"/>
<description>7-Zip Installer</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges></security></trustInfo>
<dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application></compatibility>
<asmv3:application><asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware></asmv3:windowsSettings></asmv3:application>
</assembly>

View File

@@ -0,0 +1,4 @@
/* Precomp.c -- StdAfx
2013-01-21 : Igor Pavlov : Public domain */
#include "Precomp.h"

View File

@@ -0,0 +1,11 @@
/* Precomp.h -- StdAfx
2015-05-24 : Igor Pavlov : Public domain */
#ifndef __7Z_PRECOMP_H
#define __7Z_PRECOMP_H
#include "../../Compiler.h"
#include "../../7zTypes.h"
#endif

View File

@@ -0,0 +1,40 @@
PROG = 7zipInstall.exe
!IFDEF _64BIT_INSTALLER
CFLAGS = $(CFLAGS) -D_64BIT_INSTALLER
!ENDIF
CFLAGS = $(CFLAGS) -D_LZMA_SIZE_OPT
CFLAGS = $(CFLAGS) \
-D_7Z_NO_METHOD_LZMA2 \
-D_7Z_NO_METHODS_FILTERS
MAIN_OBJS = \
$O\7zipInstall.obj \
C_OBJS = \
$O\7zAlloc.obj \
$O\7zArcIn.obj \
$O\7zBuf.obj \
$O\7zBuf2.obj \
$O\7zCrc.obj \
$O\7zCrcOpt.obj \
$O\7zFile.obj \
$O\7zDec.obj \
$O\7zStream.obj \
$O\Bcj2.obj \
$O\CpuArch.obj \
$O\LzmaDec.obj \
OBJS = \
$(MAIN_OBJS) \
$(C_OBJS) \
$O\resource.res
!include "../../../CPP/Build.mak"
$(MAIN_OBJS): $(*B).c
$(COMPL_O1)
$(C_OBJS): ../../$(*B).c
$(COMPL_O1)

View File

@@ -0,0 +1,9 @@
#define IDD_INSTALL 100
#define IDT_EXTRACT_EXTRACT_TO 110
#define IDE_EXTRACT_PATH 111
#define IDB_EXTRACT_SET_PATH 112
#define IDT_CUR_FILE 113
#define IDC_PROGRESS 114
#define IDI_ICON 1

View File

@@ -0,0 +1,47 @@
#include <winnt.h>
#include <WinUser.h>
#include <CommCtrl.h>
#define USE_COPYRIGHT_CR
#include "../../7zVersion.rc"
#include "resource.h"
MY_VERSION_INFO(MY_VFT_APP, "7-Zip Installer", "7zipInstall", "7zipInstall.exe")
1 ICON "7zip.ico"
#define xc 184
#define yc 96
#define m 8
#define bxs 64
#define bys 16
#define bxsDots 20
#define xs (xc + m + m)
#define ys (yc + m + m)
#define bx1 (xs - m - bxs)
#define bx2 (bx1 - m - bxs)
#define by (ys - m - bys)
IDD_INSTALL DIALOG 0, 0, xs, ys
STYLE DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Install 7-Zip"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Destination folder:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8
EDITTEXT IDE_EXTRACT_PATH, m, 21, xc - bxsDots - 12, 14, ES_AUTOHSCROLL
PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, 20, bxsDots, bys, WS_GROUP
LTEXT "", IDT_CUR_FILE, m, 50, xc, 8
CONTROL "", IDC_PROGRESS, "msctls_progress32", WS_BORDER, m, 64, xc, 10
DEFPUSHBUTTON "&Install", IDOK, bx2, by, bxs, bys, WS_GROUP
PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
END
#ifndef UNDER_CE
1 24 MOVEABLE PURE "7zipInstall.manifest"
#endif

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,124 @@
# Microsoft Developer Studio Project File - Name="7zipUninstall" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=7zipUninstall - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "7zipUninstall.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "7zipUninstall.mak" CFG="7zipUninstall - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "7zipUninstall - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "7zipUninstall - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "7zipUninstall - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE2" /D "UNICODE2" /Yu"Precomp.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/Uninstall.exe"
!ELSEIF "$(CFG)" == "7zipUninstall - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE2" /D "UNICODE2" /Yu"Precomp.h" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Uninstall.exe" /pdbtype:sept
!ENDIF
# Begin Target
# Name "7zipUninstall - Win32 Release"
# Name "7zipUninstall - Win32 Debug"
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\7zTypes.h
# End Source File
# Begin Source File
SOURCE=..\..\7zVersion.h
# End Source File
# End Group
# Begin Group "Spec"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\Precomp.c
# ADD CPP /Yc"Precomp.h"
# End Source File
# Begin Source File
SOURCE=.\Precomp.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\7zipUninstall.c
# End Source File
# Begin Source File
SOURCE=.\resource.rc
# End Source File
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "7zipUninstall"=.\7zipUninstall.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.Uninstall" type="win32"/>
<description>7-Zip Uninstaller</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges></security></trustInfo>
<dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application></compatibility>
<asmv3:application><asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware></asmv3:windowsSettings></asmv3:application>
</assembly>

View File

@@ -0,0 +1,4 @@
/* Precomp.c -- StdAfx
2013-01-21 : Igor Pavlov : Public domain */
#include "Precomp.h"

View File

@@ -0,0 +1,11 @@
/* Precomp.h -- StdAfx
2015-05-24 : Igor Pavlov : Public domain */
#ifndef __7Z_PRECOMP_H
#define __7Z_PRECOMP_H
#include "../../Compiler.h"
#include "../../7zTypes.h"
#endif

View File

@@ -0,0 +1,17 @@
PROG = 7zipUninstall.exe
!IFDEF _64BIT_INSTALLER
CFLAGS = $(CFLAGS) -D_64BIT_INSTALLER
!ENDIF
MAIN_OBJS = \
$O\7zipUninstall.obj \
OBJS = \
$(MAIN_OBJS) \
$O\resource.res
!include "../../../CPP/Build.mak"
$(MAIN_OBJS): $(*B).c
$(COMPL_O1)

View File

@@ -0,0 +1,9 @@
#define IDD_INSTALL 100
#define IDT_EXTRACT_EXTRACT_TO 110
#define IDE_EXTRACT_PATH 111
#define IDT_CUR_FILE 113
#define IDC_PROGRESS 114
#define IDI_ICON 1

View File

@@ -0,0 +1,47 @@
#include <winnt.h>
#include <WinUser.h>
#include <CommCtrl.h>
#define USE_COPYRIGHT_CR
#include "../../7zVersion.rc"
#include "resource.h"
MY_VERSION_INFO(MY_VFT_APP, "7-Zip Uninstaller", "Uninstall", "Uninstall.exe")
1 ICON "7zipUninstall.ico"
#define xc 184
#define yc 96
#define m 8
#define bxs 64
#define bys 16
#define xs (xc + m + m)
#define ys (yc + m + m)
#define bx1 (xs - m - bxs)
#define bx2 (bx1 - m - bxs)
#define by (ys - m - bys)
IDD_INSTALL DIALOG 0, 0, xs, ys
STYLE DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Uninstall 7-Zip"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Uninstall from:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8
EDITTEXT IDE_EXTRACT_PATH, m, 21, xc, 14, ES_AUTOHSCROLL | WS_DISABLED
LTEXT "", IDT_CUR_FILE, m, 50, xc, 8
CONTROL "", IDC_PROGRESS, "msctls_progress32", WS_BORDER, m, 64, xc, 10
DEFPUSHBUTTON "&Uninstall", IDOK, bx2, by, bxs, bys, WS_GROUP
PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
END
#ifndef UNDER_CE
1 24 MOVEABLE PURE "7zipUninstall.manifest"
#endif

View File

@@ -1,5 +1,5 @@
/* LzmaUtil.c -- Test application for LZMA compression /* LzmaUtil.c -- Test application for LZMA compression
2014-06-17 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "../../Precomp.h" #include "../../Precomp.h"
@@ -18,10 +18,6 @@ const char *kCantWriteMessage = "Can not write output file";
const char *kCantAllocateMessage = "Can not allocate memory"; const char *kCantAllocateMessage = "Can not allocate memory";
const char *kDataErrorMessage = "Data error"; const char *kDataErrorMessage = "Data error";
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
void PrintHelp(char *buffer) void PrintHelp(char *buffer)
{ {
strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
@@ -92,7 +88,7 @@ static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inS
outPos = 0; outPos = 0;
if (res != SZ_OK || thereIsSize && unpackSize == 0) if (res != SZ_OK || (thereIsSize && unpackSize == 0))
return res; return res;
if (inProcessed == 0 && outProcessed == 0) if (inProcessed == 0 && outProcessed == 0)
@@ -137,7 +133,7 @@ static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 file
SRes res; SRes res;
CLzmaEncProps props; CLzmaEncProps props;
rs = rs; UNUSED_VAR(rs);
enc = LzmaEnc_Create(&g_Alloc); enc = LzmaEnc_Create(&g_Alloc);
if (enc == 0) if (enc == 0)

View File

@@ -1,12 +1,14 @@
/* LzmaLibExports.c -- LZMA library DLL Entry point /* LzmaLibExports.c -- LZMA library DLL Entry point
2008-10-04 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "../../Precomp.h"
#include <windows.h> #include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{ {
hInstance = hInstance; UNUSED_VAR(hInstance);
dwReason = dwReason; UNUSED_VAR(dwReason);
lpReserved = lpReserved; UNUSED_VAR(lpReserved);
return TRUE; return TRUE;
} }

View File

@@ -1,5 +1,5 @@
/* SfxSetup.c - 7z SFX Setup /* SfxSetup.c - 7z SFX Setup
2014-12-07 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -23,7 +23,7 @@
#define k_EXE_ExtIndex 2 #define k_EXE_ExtIndex 2
static const char *kExts[] = static const char * const kExts[] =
{ {
"bat" "bat"
, "cmd" , "cmd"
@@ -37,7 +37,7 @@ static const char *kExts[] =
, "htm" , "htm"
}; };
static const char *kNames[] = static const char * const kNames[] =
{ {
"setup" "setup"
, "install" , "install"
@@ -63,7 +63,7 @@ static unsigned FindExt(const wchar_t *s, unsigned *extLen)
#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c))) #define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))
static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len) static unsigned FindItem(const char * const *items, unsigned num, const wchar_t *s, unsigned len)
{ {
unsigned i; unsigned i;
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
@@ -75,7 +75,7 @@ static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, uns
continue; continue;
for (j = 0; j < len; j++) for (j = 0; j < len; j++)
{ {
unsigned c = item[j]; unsigned c = (Byte)item[j];
if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j]) if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j])
break; break;
} }
@@ -88,7 +88,7 @@ static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, uns
#ifdef _CONSOLE #ifdef _CONSOLE
static BOOL WINAPI HandlerRoutine(DWORD ctrlType) static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
{ {
ctrlType = ctrlType; UNUSED_VAR(ctrlType);
return TRUE; return TRUE;
} }
#endif #endif
@@ -144,7 +144,7 @@ static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
processed -= k7zStartHeaderSize; processed -= k7zStartHeaderSize;
for (pos = 0; pos <= processed; pos++) for (pos = 0; pos <= processed; pos++)
{ {
for (; buf[pos] != '7' && pos <= processed; pos++); for (; pos <= processed && buf[pos] != '7'; pos++);
if (pos > processed) if (pos > processed)
break; break;
if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)
@@ -182,6 +182,7 @@ static WRes RemoveDirWithSubItems(WCHAR *path)
path[len] = L'\0'; path[len] = L'\0';
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
return GetLastError(); return GetLastError();
for (;;) for (;;)
{ {
if (wcscmp(fd.cFileName, L".") != 0 && if (wcscmp(fd.cFileName, L".") != 0 &&
@@ -199,9 +200,11 @@ static WRes RemoveDirWithSubItems(WCHAR *path)
if (DeleteFileW(path) == 0) if (DeleteFileW(path) == 0)
res = GetLastError(); res = GetLastError();
} }
if (res != 0) if (res != 0)
break; break;
} }
if (!FindNextFileW(handle, &fd)) if (!FindNextFileW(handle, &fd))
{ {
res = GetLastError(); res = GetLastError();
@@ -210,6 +213,7 @@ static WRes RemoveDirWithSubItems(WCHAR *path)
break; break;
} }
} }
path[len] = L'\0'; path[len] = L'\0';
FindClose(handle); FindClose(handle);
if (res == 0) if (res == 0)
@@ -248,14 +252,15 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
const wchar_t *cmdLineParams; const wchar_t *cmdLineParams;
const char *errorMessage = NULL; const char *errorMessage = NULL;
Bool useShellExecute = True; Bool useShellExecute = True;
DWORD exitCode = 0;
#ifdef _CONSOLE #ifdef _CONSOLE
SetConsoleCtrlHandler(HandlerRoutine, TRUE); SetConsoleCtrlHandler(HandlerRoutine, TRUE);
#else #else
hInstance = hInstance; UNUSED_VAR(hInstance);
hPrevInstance = hPrevInstance; UNUSED_VAR(hPrevInstance);
lpCmdLine = lpCmdLine; UNUSED_VAR(lpCmdLine);
nCmdShow = nCmdShow; UNUSED_VAR(nCmdShow);
#endif #endif
CrcGenerateTable(); CrcGenerateTable();
@@ -315,7 +320,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
{ {
unsigned t = value & 0xF; unsigned t = value & 0xF;
value >>= 4; value >>= 4;
s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
} }
s[k] = '\0'; s[k] = '\0';
} }
@@ -584,6 +589,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
if (hProcess != 0) if (hProcess != 0)
{ {
WaitForSingleObject(hProcess, INFINITE); WaitForSingleObject(hProcess, INFINITE);
if (!GetExitCodeProcess(hProcess, &exitCode))
exitCode = 1;
CloseHandle(hProcess); CloseHandle(hProcess);
} }
@@ -596,7 +603,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
RemoveDirWithSubItems(path); RemoveDirWithSubItems(path);
if (res == SZ_OK) if (res == SZ_OK)
return 0; return (int)exitCode;
{ {
if (res == SZ_ERROR_UNSUPPORTED) if (res == SZ_ERROR_UNSUPPORTED)
@@ -610,6 +617,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
if (!errorMessage) if (!errorMessage)
errorMessage = "ERROR"; errorMessage = "ERROR";
} }
if (errorMessage) if (errorMessage)
PrintErrorMessage(errorMessage); PrintErrorMessage(errorMessage);
} }

View File

@@ -167,6 +167,10 @@ SOURCE=..\..\Bra86.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\BraIA64.c
# End Source File
# Begin Source File
SOURCE=..\..\CpuArch.c SOURCE=..\..\CpuArch.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -175,6 +179,14 @@ SOURCE=..\..\CpuArch.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Delta.c
# End Source File
# Begin Source File
SOURCE=..\..\Delta.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

@@ -13,7 +13,9 @@ C_OBJS = \
$O\Bcj2.obj \ $O\Bcj2.obj \
$O\Bra.obj \ $O\Bra.obj \
$O\Bra86.obj \ $O\Bra86.obj \
$O\BraIA64.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Delta.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \

View File

@@ -14,7 +14,9 @@ C_OBJS = \
$O\Bcj2.obj \ $O\Bcj2.obj \
$O\Bra.obj \ $O\Bra.obj \
$O\Bra86.obj \ $O\Bra86.obj \
$O\BraIA64.obj \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\Delta.obj \
$O\Lzma2Dec.obj \ $O\Lzma2Dec.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \

10
C/Xz.c
View File

@@ -1,5 +1,5 @@
/* Xz.c - Xz /* Xz.c - Xz
2009-04-15 : Igor Pavlov : Public domain */ 2015-05-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -8,8 +8,8 @@
#include "Xz.h" #include "Xz.h"
#include "XzCrc64.h" #include "XzCrc64.h"
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 };
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)
{ {
@@ -40,11 +40,11 @@ void Xz_Free(CXzStream *p, ISzAlloc *alloc)
unsigned XzFlags_GetCheckSize(CXzStreamFlags f) unsigned XzFlags_GetCheckSize(CXzStreamFlags f)
{ {
int t = XzFlags_GetCheckType(f); unsigned t = XzFlags_GetCheckType(f);
return (t == 0) ? 0 : (4 << ((t - 1) / 3)); return (t == 0) ? 0 : (4 << ((t - 1) / 3));
} }
void XzCheck_Init(CXzCheck *p, int mode) void XzCheck_Init(CXzCheck *p, unsigned mode)
{ {
p->mode = mode; p->mode = mode;
switch (mode) switch (mode)

20
C/Xz.h
View File

@@ -1,5 +1,5 @@
/* Xz.h - Xz interface /* Xz.h - Xz interface
2013-11-19 : Igor Pavlov : Public domain */ 2015-05-01 : Igor Pavlov : Public domain */
#ifndef __XZ_H #ifndef __XZ_H
#define __XZ_H #define __XZ_H
@@ -59,8 +59,8 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt
#define XZ_SIG_SIZE 6 #define XZ_SIG_SIZE 6
#define XZ_FOOTER_SIG_SIZE 2 #define XZ_FOOTER_SIG_SIZE 2
extern Byte XZ_SIG[XZ_SIG_SIZE]; extern const Byte XZ_SIG[XZ_SIG_SIZE];
extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE]; extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
#define XZ_STREAM_FLAGS_SIZE 2 #define XZ_STREAM_FLAGS_SIZE 2
#define XZ_STREAM_CRC_SIZE 4 #define XZ_STREAM_CRC_SIZE 4
@@ -76,13 +76,13 @@ extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
typedef struct typedef struct
{ {
int mode; unsigned mode;
UInt32 crc; UInt32 crc;
UInt64 crc64; UInt64 crc64;
CSha256 sha; CSha256 sha;
} CXzCheck; } CXzCheck;
void XzCheck_Init(CXzCheck *p, int mode); void XzCheck_Init(CXzCheck *p, unsigned mode);
void XzCheck_Update(CXzCheck *p, const void *data, size_t size); void XzCheck_Update(CXzCheck *p, const void *data, size_t size);
int XzCheck_Final(CXzCheck *p, Byte *digest); int XzCheck_Final(CXzCheck *p, Byte *digest);
@@ -163,7 +163,7 @@ typedef struct
{ {
ISzAlloc *alloc; ISzAlloc *alloc;
Byte *buf; Byte *buf;
int numCoders; unsigned numCoders;
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];
@@ -174,7 +174,7 @@ typedef struct
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc); void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);
void MixCoder_Free(CMixCoder *p); void MixCoder_Free(CMixCoder *p);
void MixCoder_Init(CMixCoder *p); void MixCoder_Init(CMixCoder *p);
SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId); SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId);
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int srcWasFinished, const Byte *src, SizeT *srcLen, int srcWasFinished,
ECoderFinishMode finishMode, ECoderStatus *status); ECoderFinishMode finishMode, ECoderStatus *status);
@@ -229,8 +229,8 @@ void XzUnpacker_Free(CXzUnpacker *p);
/* /*
finishMode: finishMode:
It has meaning only if the decoding reaches output limit (*destLen). It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - use smallest number of input bytes CODER_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding CODER_FINISH_END - read EndOfStream marker after decoding
Returns: Returns:
SZ_OK SZ_OK
@@ -255,7 +255,7 @@ Returns:
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode, const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode,
ECoderStatus *status); ECoderStatus *status);
Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p); Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);

View File

@@ -1,5 +1,5 @@
/* XzCrc64.c -- CRC64 calculation /* XzCrc64.c -- CRC64 calculation
2011-06-28 : Igor Pavlov : Public domain */ 2015-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -13,14 +13,15 @@
#else #else
#define CRC_NUM_TABLES 5 #define CRC_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)) \
((v >> 24) & ((UInt64)0xFF << 16)) | \ | ((v >> 24) & ((UInt64)0xFF << 16)) \
((v >> 8) & ((UInt64)0xFF << 24)) | \ | ((v >> 8) & ((UInt64)0xFF << 24)) \
((v << 8) & ((UInt64)0xFF << 32)) | \ | ((v << 8) & ((UInt64)0xFF << 32)) \
((v << 24) & ((UInt64)0xFF << 40)) | \ | ((v << 24) & ((UInt64)0xFF << 40)) \
((v << 40) & ((UInt64)0xFF << 48)) | \ | ((v << 40) & ((UInt64)0xFF << 48)) \
(v << 56)) | ((v << 56)))
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);
#endif #endif
@@ -64,11 +65,6 @@ void MY_FAST_CALL Crc64GenerateTable()
g_Crc64Update = XzCrc64UpdateT4; g_Crc64Update = XzCrc64UpdateT4;
#else #else
{ {
#ifndef MY_CPU_BE #ifndef MY_CPU_BE

View File

@@ -1,14 +1,14 @@
/* XzCrc64Opt.c -- CRC64 calculation /* XzCrc64Opt.c -- CRC64 calculation
2011-06-28 : Igor Pavlov : Public domain */ 2015-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "CpuArch.h" #include "CpuArch.h"
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
#ifndef MY_CPU_BE #ifndef MY_CPU_BE
#define CRC_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;
@@ -17,11 +17,11 @@ UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, con
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 = CRC_UPDATE_BYTE_2(v, *p);
@@ -34,36 +34,36 @@ UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, con
#ifndef MY_CPU_LE #ifndef MY_CPU_LE
#define CRC_UINT64_SWAP(v) \ #define CRC_UINT64_SWAP(v) \
((v >> 56) | \ ((v >> 56) \
((v >> 40) & ((UInt64)0xFF << 8)) | \ | ((v >> 40) & ((UInt64)0xFF << 8)) \
((v >> 24) & ((UInt64)0xFF << 16)) | \ | ((v >> 24) & ((UInt64)0xFF << 16)) \
((v >> 8) & ((UInt64)0xFF << 24)) | \ | ((v >> 8) & ((UInt64)0xFF << 24)) \
((v << 8) & ((UInt64)0xFF << 32)) | \ | ((v << 8) & ((UInt64)0xFF << 32)) \
((v << 24) & ((UInt64)0xFF << 40)) | \ | ((v << 24) & ((UInt64)0xFF << 40)) \
((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))
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)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
v = CRC_UINT64_SWAP(v);
table += 0x100; table += 0x100;
v = CRC_UINT64_SWAP(v);
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_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))];
} }
table -= 0x100;
v = CRC_UINT64_SWAP(v);
for (; size > 0; size--, p++) for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2_BE(v, *p);
return v; return CRC_UINT64_SWAP(v);
} }
#endif #endif

View File

@@ -1,5 +1,5 @@
/* XzDec.c -- Xz Decode /* XzDec.c -- Xz Decode
2014-05-09 : Igor Pavlov : Public domain */ 2015-11-09 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -32,9 +32,9 @@
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
{ {
int i, limit; unsigned i, limit;
*value = 0; *value = 0;
limit = (maxSize > 9) ? 9 : (int)maxSize; limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
for (i = 0; i < limit;) for (i = 0; i < limit;)
{ {
@@ -66,15 +66,15 @@ typedef struct
Byte buf[BRA_BUF_SIZE]; Byte buf[BRA_BUF_SIZE];
} CBraState; } CBraState;
void BraState_Free(void *pp, ISzAlloc *alloc) static void BraState_Free(void *pp, ISzAlloc *alloc)
{ {
alloc->Free(alloc, pp); alloc->Free(alloc, pp);
} }
SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
{ {
CBraState *p = ((CBraState *)pp); CBraState *p = ((CBraState *)pp);
alloc = alloc; UNUSED_VAR(alloc);
p->ip = 0; p->ip = 0;
if (p->methodId == XZ_ID_Delta) if (p->methodId == XZ_ID_Delta)
{ {
@@ -87,7 +87,7 @@ SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *a
if (propSize == 4) if (propSize == 4)
{ {
UInt32 v = GetUi32(props); UInt32 v = GetUi32(props);
switch(p->methodId) switch (p->methodId)
{ {
case XZ_ID_PPC: case XZ_ID_PPC:
case XZ_ID_ARM: case XZ_ID_ARM:
@@ -112,7 +112,7 @@ SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *a
return SZ_OK; return SZ_OK;
} }
void BraState_Init(void *pp) static void BraState_Init(void *pp)
{ {
CBraState *p = ((CBraState *)pp); CBraState *p = ((CBraState *)pp);
p->bufPos = p->bufConv = p->bufTotal = 0; p->bufPos = p->bufConv = p->bufTotal = 0;
@@ -129,9 +129,9 @@ static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src,
CBraState *p = ((CBraState *)pp); CBraState *p = ((CBraState *)pp);
SizeT destLenOrig = *destLen; SizeT destLenOrig = *destLen;
SizeT srcLenOrig = *srcLen; SizeT srcLenOrig = *srcLen;
UNUSED_VAR(finishMode);
*destLen = 0; *destLen = 0;
*srcLen = 0; *srcLen = 0;
finishMode = finishMode;
*wasFinished = 0; *wasFinished = 0;
while (destLenOrig > 0) while (destLenOrig > 0)
{ {
@@ -163,7 +163,7 @@ static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src,
} }
if (p->bufTotal == 0) if (p->bufTotal == 0)
break; break;
switch(p->methodId) switch (p->methodId)
{ {
case XZ_ID_Delta: case XZ_ID_Delta:
if (p->encodeMode) if (p->encodeMode)
@@ -209,7 +209,7 @@ SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc
id != XZ_ID_SPARC) id != XZ_ID_SPARC)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
p->p = 0; p->p = 0;
decoder = alloc->Alloc(alloc, sizeof(CBraState)); decoder = (CBraState *)alloc->Alloc(alloc, sizeof(CBraState));
if (decoder == 0) if (decoder == 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
decoder->methodId = (UInt32)id; decoder->methodId = (UInt32)id;
@@ -235,9 +235,9 @@ static void SbState_Free(void *pp, ISzAlloc *alloc)
static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
{ {
pp = pp; UNUSED_VAR(pp);
props = props; UNUSED_VAR(props);
alloc = alloc; UNUSED_VAR(alloc);
return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
} }
@@ -251,7 +251,7 @@ static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src,
{ {
CSbDec *p = (CSbDec *)pp; CSbDec *p = (CSbDec *)pp;
SRes res; SRes res;
srcWasFinished = srcWasFinished; UNUSED_VAR(srcWasFinished);
p->dest = dest; p->dest = dest;
p->destLen = *destLen; p->destLen = *destLen;
p->src = src; p->src = src;
@@ -308,14 +308,14 @@ static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *sr
ELzmaStatus status; ELzmaStatus status;
/* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status); SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status);
srcWasFinished = srcWasFinished; UNUSED_VAR(srcWasFinished);
*wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
return res; return res;
} }
static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
{ {
CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec)); CLzma2Dec *decoder = (CLzma2Dec *)alloc->Alloc(alloc, sizeof(CLzma2Dec));
p->p = decoder; p->p = decoder;
if (decoder == 0) if (decoder == 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
@@ -330,9 +330,9 @@ static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc) void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
{ {
int i; unsigned i;
p->alloc = alloc; p->alloc = alloc;
p->buf = 0; p->buf = NULL;
p->numCoders = 0; p->numCoders = 0;
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
p->coders[i].p = NULL; p->coders[i].p = NULL;
@@ -340,7 +340,7 @@ void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
void MixCoder_Free(CMixCoder *p) void MixCoder_Free(CMixCoder *p)
{ {
int i; unsigned i;
for (i = 0; i < p->numCoders; i++) for (i = 0; i < p->numCoders; i++)
{ {
IStateCoder *sc = &p->coders[i]; IStateCoder *sc = &p->coders[i];
@@ -351,14 +351,14 @@ void MixCoder_Free(CMixCoder *p)
if (p->buf) if (p->buf)
{ {
p->alloc->Free(p->alloc, p->buf); p->alloc->Free(p->alloc, p->buf);
p->buf = 0; /* 9.31: the BUG was fixed */ p->buf = NULL; /* 9.31: the BUG was fixed */
} }
} }
void MixCoder_Init(CMixCoder *p) void MixCoder_Init(CMixCoder *p)
{ {
int i; unsigned i;
for (i = 0; i < p->numCoders - 1; i++) for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
{ {
p->size[i] = 0; p->size[i] = 0;
p->pos[i] = 0; p->pos[i] = 0;
@@ -371,11 +371,11 @@ void MixCoder_Init(CMixCoder *p)
} }
} }
SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId) SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId)
{ {
IStateCoder *sc = &p->coders[coderIndex]; IStateCoder *sc = &p->coders[coderIndex];
p->ids[coderIndex] = methodId; p->ids[coderIndex] = methodId;
switch(methodId) switch (methodId)
{ {
case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc); case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);
#ifdef USE_SUBBLOCK #ifdef USE_SUBBLOCK
@@ -398,10 +398,10 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
*srcLen = 0; *srcLen = 0;
*status = CODER_STATUS_NOT_FINISHED; *status = CODER_STATUS_NOT_FINISHED;
if (p->buf == 0) if (!p->buf)
{ {
p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
if (p->buf == 0) if (!p->buf)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
} }
@@ -411,7 +411,7 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
for (;;) for (;;)
{ {
Bool processed = False; Bool processed = False;
int i; unsigned i;
/* /*
if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY) if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
break; break;
@@ -520,8 +520,8 @@ static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *b
SRes XzBlock_Parse(CXzBlock *p, const Byte *header) SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
{ {
unsigned pos; unsigned pos;
int numFilters, i; unsigned numFilters, i;
UInt32 headerSize = (UInt32)header[0] << 2; unsigned headerSize = (unsigned)header[0] << 2;
if (CrcCalc(header, headerSize) != GetUi32(header + headerSize)) if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
@@ -555,9 +555,9 @@ SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
pos += (unsigned)size; pos += (unsigned)size;
#ifdef XZ_DUMP #ifdef XZ_DUMP
printf("\nf[%d] = %2X: ", i, filter->id); printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
{ {
int i; unsigned i;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
printf(" %2X", filter->props[i]); printf(" %2X", filter->props[i]);
} }
@@ -572,9 +572,10 @@ SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
SRes XzDec_Init(CMixCoder *p, const CXzBlock *block) SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
{ {
int i; unsigned i;
Bool needReInit = True; Bool needReInit = True;
int numFilters = XzBlock_GetNumFilters(block); unsigned numFilters = XzBlock_GetNumFilters(block);
if (numFilters == p->numCoders) if (numFilters == p->numCoders)
{ {
for (i = 0; i < numFilters; i++) for (i = 0; i < numFilters; i++)
@@ -582,6 +583,7 @@ SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
break; break;
needReInit = (i != numFilters); needReInit = (i != numFilters);
} }
if (needReInit) if (needReInit)
{ {
MixCoder_Free(p); MixCoder_Free(p);
@@ -592,12 +594,14 @@ SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
RINOK(MixCoder_SetFromMethod(p, i, f->id)); RINOK(MixCoder_SetFromMethod(p, i, f->id));
} }
} }
for (i = 0; i < numFilters; i++) for (i = 0; i < numFilters; i++)
{ {
const CXzFilter *f = &block->filters[numFilters - 1 - i]; const CXzFilter *f = &block->filters[numFilters - 1 - i];
IStateCoder *sc = &p->coders[i]; IStateCoder *sc = &p->coders[i];
RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)); RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
} }
MixCoder_Init(p); MixCoder_Init(p);
return SZ_OK; return SZ_OK;
} }
@@ -624,7 +628,7 @@ void XzUnpacker_Free(CXzUnpacker *p)
} }
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status) const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status)
{ {
SizeT destLenOrig = *destLen; SizeT destLenOrig = *destLen;
SizeT srcLenOrig = *srcLen; SizeT srcLenOrig = *srcLen;

View File

@@ -1,5 +1,5 @@
/* XzEnc.c -- Xz Encode /* XzEnc.c -- Xz Encode
2013-11-12 : Igor Pavlov : Public domain */ 2015-09-16 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -10,6 +10,7 @@
#include "Alloc.h" #include "Alloc.h"
#include "Bra.h" #include "Bra.h"
#include "CpuArch.h" #include "CpuArch.h"
#ifdef USE_SUBBLOCK #ifdef USE_SUBBLOCK
#include "Bcj3Enc.c" #include "Bcj3Enc.c"
#include "SbFind.c" #include "SbFind.c"
@@ -18,14 +19,6 @@
#include "XzEnc.h" #include "XzEnc.h"
static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); }
static void SzBigFree(void *p, void *address) { p = p; BigFree(address); }
static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
#define XzBlock_ClearFlags(p) (p)->flags = 0; #define XzBlock_ClearFlags(p) (p)->flags = 0;
#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1); #define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1);
#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE; #define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE;
@@ -42,7 +35,7 @@ static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UIn
return WriteBytes(s, buf, size); return WriteBytes(s, buf, size);
} }
SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s) static SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)
{ {
UInt32 crc; UInt32 crc;
Byte header[XZ_STREAM_HEADER_SIZE]; Byte header[XZ_STREAM_HEADER_SIZE];
@@ -54,17 +47,19 @@ SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)
return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE); return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE);
} }
SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
static SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
{ {
Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
unsigned pos = 1; unsigned pos = 1;
int numFilters, i; unsigned numFilters, i;
header[pos++] = p->flags; header[pos++] = p->flags;
if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize); if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize);
if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize); if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize);
numFilters = XzBlock_GetNumFilters(p); numFilters = XzBlock_GetNumFilters(p);
for (i = 0; i < numFilters; i++) for (i = 0; i < numFilters; i++)
{ {
const CXzFilter *f = &p->filters[i]; const CXzFilter *f = &p->filters[i];
@@ -73,14 +68,17 @@ SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
memcpy(header + pos, f->props, f->propsSize); memcpy(header + pos, f->props, f->propsSize);
pos += f->propsSize; pos += f->propsSize;
} }
while((pos & 3) != 0)
while ((pos & 3) != 0)
header[pos++] = 0; header[pos++] = 0;
header[0] = (Byte)(pos >> 2); header[0] = (Byte)(pos >> 2);
SetUi32(header + pos, CrcCalc(header, pos)); SetUi32(header + pos, CrcCalc(header, pos));
return WriteBytes(s, header, pos + 4); return WriteBytes(s, header, pos + 4);
} }
SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
static SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
{ {
Byte buf[32]; Byte buf[32];
UInt64 globalPos; UInt64 globalPos;
@@ -92,6 +90,7 @@ SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
globalPos = pos; globalPos = pos;
buf[0] = 0; buf[0] = 0;
RINOK(WriteBytesAndCrc(s, buf, pos, &crc)); RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
for (i = 0; i < p->numBlocks; i++) for (i = 0; i < p->numBlocks; i++)
{ {
const CXzBlockSizes *block = &p->blocks[i]; const CXzBlockSizes *block = &p->blocks[i];
@@ -100,7 +99,9 @@ SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
globalPos += pos; globalPos += pos;
RINOK(WriteBytesAndCrc(s, buf, pos, &crc)); RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
} }
pos = ((unsigned)globalPos & 3); pos = ((unsigned)globalPos & 3);
if (pos != 0) if (pos != 0)
{ {
buf[0] = buf[1] = buf[2] = 0; buf[0] = buf[1] = buf[2] = 0;
@@ -125,34 +126,36 @@ SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
} }
} }
SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)
static SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)
{ {
if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks) if (!p->blocks || p->numBlocksAllocated == p->numBlocks)
{ {
size_t num = (p->numBlocks + 1) * 2; size_t num = p->numBlocks * 2 + 1;
size_t newSize = sizeof(CXzBlockSizes) * num; size_t newSize = sizeof(CXzBlockSizes) * num;
CXzBlockSizes *blocks; CXzBlockSizes *blocks;
if (newSize / sizeof(CXzBlockSizes) != num) if (newSize / sizeof(CXzBlockSizes) != num)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
blocks = alloc->Alloc(alloc, newSize); blocks = (CXzBlockSizes *)alloc->Alloc(alloc, newSize);
if (blocks == 0) if (!blocks)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
if (p->numBlocks != 0) if (p->numBlocks != 0)
{ {
memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes)); memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes));
Xz_Free(p, alloc); alloc->Free(alloc, p->blocks);
} }
p->blocks = blocks; p->blocks = blocks;
p->numBlocksAllocated = num; p->numBlocksAllocated = num;
} }
{ {
CXzBlockSizes *block = &p->blocks[p->numBlocks++]; CXzBlockSizes *block = &p->blocks[p->numBlocks++];
block->totalSize = totalSize;
block->unpackSize = unpackSize; block->unpackSize = unpackSize;
block->totalSize = totalSize;
} }
return SZ_OK; return SZ_OK;
} }
/* ---------- CSeqCheckInStream ---------- */ /* ---------- CSeqCheckInStream ---------- */
typedef struct typedef struct
@@ -163,13 +166,13 @@ typedef struct
CXzCheck check; CXzCheck check;
} CSeqCheckInStream; } CSeqCheckInStream;
void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode) static void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned mode)
{ {
p->processed = 0; p->processed = 0;
XzCheck_Init(&p->check, mode); XzCheck_Init(&p->check, mode);
} }
void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest) static void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)
{ {
XzCheck_Final(&p->check, digest); XzCheck_Final(&p->check, digest);
} }
@@ -183,6 +186,7 @@ static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size)
return res; return res;
} }
/* ---------- CSeqSizeOutStream ---------- */ /* ---------- CSeqSizeOutStream ---------- */
typedef struct typedef struct
@@ -200,6 +204,7 @@ static size_t MyWrite(void *pp, const void *data, size_t size)
return size; return size;
} }
/* ---------- CSeqInFilter ---------- */ /* ---------- CSeqInFilter ---------- */
#define FILTER_BUF_SIZE (1 << 20) #define FILTER_BUF_SIZE (1 << 20)
@@ -222,6 +227,7 @@ static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)
if (sizeOriginal == 0) if (sizeOriginal == 0)
return SZ_OK; return SZ_OK;
*size = 0; *size = 0;
for (;;) for (;;)
{ {
if (!p->srcWasFinished && p->curPos == p->endPos) if (!p->srcWasFinished && p->curPos == p->endPos)
@@ -279,6 +285,7 @@ static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props)
return SZ_OK; return SZ_OK;
} }
/* ---------- CSbEncInStream ---------- */ /* ---------- CSbEncInStream ---------- */
#ifdef USE_SUBBLOCK #ifdef USE_SUBBLOCK
@@ -296,6 +303,7 @@ static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)
size_t sizeOriginal = *size; size_t sizeOriginal = *size;
if (sizeOriginal == 0) if (sizeOriginal == 0)
return S_OK; return S_OK;
for (;;) for (;;)
{ {
if (p->enc.needRead && !p->enc.readWasFinished) if (p->enc.needRead && !p->enc.readWasFinished)
@@ -310,6 +318,7 @@ static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)
} }
p->enc.needRead = False; p->enc.needRead = False;
} }
*size = sizeOriginal; *size = sizeOriginal;
RINOK(SbEnc_Read(&p->enc, data, size)); RINOK(SbEnc_Read(&p->enc, data, size));
if (*size != 0 || !p->enc.needRead) if (*size != 0 || !p->enc.needRead)
@@ -362,7 +371,7 @@ static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, IS
static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p) static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)
{ {
p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc); p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc);
if (p->lzma2 == 0) if (!p->lzma2)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
return SZ_OK; return SZ_OK;
} }
@@ -380,10 +389,11 @@ static void Lzma2WithFilters_Free(CLzma2WithFilters *p)
} }
} }
void XzProps_Init(CXzProps *p) void XzProps_Init(CXzProps *p)
{ {
p->lzma2Props = 0; p->lzma2Props = NULL;
p->filterProps = 0; p->filterProps = NULL;
p->checkId = XZ_CHECK_CRC32; p->checkId = XZ_CHECK_CRC32;
} }
@@ -391,10 +401,11 @@ void XzFilterProps_Init(CXzFilterProps *p)
{ {
p->id = 0; p->id = 0;
p->delta = 0; p->delta = 0;
p->ip= 0; p->ip = 0;
p->ipDefined = False; p->ipDefined = False;
} }
static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf, static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
ISeqOutStream *outStream, ISeqInStream *inStream, ISeqOutStream *outStream, ISeqInStream *inStream,
const CXzProps *props, ICompressProgress *progress) const CXzProps *props, ICompressProgress *progress)
@@ -408,7 +419,7 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
CSeqCheckInStream checkInStream; CSeqCheckInStream checkInStream;
CSeqSizeOutStream seqSizeOutStream; CSeqSizeOutStream seqSizeOutStream;
CXzBlock block; CXzBlock block;
int filterIndex = 0; unsigned filterIndex = 0;
CXzFilter *filter = NULL; CXzFilter *filter = NULL;
const CXzFilterProps *fp = props->filterProps; const CXzFilterProps *fp = props->filterProps;
@@ -420,6 +431,7 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
filter = &block.filters[filterIndex++]; filter = &block.filters[filterIndex++];
filter->id = fp->id; filter->id = fp->id;
filter->propsSize = 0; filter->propsSize = 0;
if (fp->id == XZ_ID_Delta) if (fp->id == XZ_ID_Delta)
{ {
filter->props[0] = (Byte)(fp->delta - 1); filter->props[0] = (Byte)(fp->delta - 1);
@@ -467,14 +479,16 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
{ {
UInt64 packPos = seqSizeOutStream.processed; UInt64 packPos = seqSizeOutStream.processed;
SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p, SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,
fp ? fp ?
#ifdef USE_SUBBLOCK #ifdef USE_SUBBLOCK
(fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p: (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p:
#endif #endif
&lzmaf->filter.p: &lzmaf->filter.p:
&checkInStream.p, &checkInStream.p,
progress); progress);
RINOK(res); RINOK(res);
block.unpackSize = checkInStream.processed; block.unpackSize = checkInStream.processed;
block.packSize = seqSizeOutStream.processed - packPos; block.packSize = seqSizeOutStream.processed - packPos;
@@ -483,7 +497,7 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
{ {
unsigned padSize = 0; unsigned padSize = 0;
Byte buf[128]; Byte buf[128];
while((((unsigned)block.packSize + padSize) & 3) != 0) while ((((unsigned)block.packSize + padSize) & 3) != 0)
buf[padSize++] = 0; buf[padSize++] = 0;
SeqCheckInStream_GetDigest(&checkInStream, buf + padSize); SeqCheckInStream_GetDigest(&checkInStream, buf + padSize);
RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags))); RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags)));
@@ -493,6 +507,7 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
return Xz_WriteFooter(xz, outStream); return Xz_WriteFooter(xz, outStream);
} }
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
const CXzProps *props, ICompressProgress *progress) const CXzProps *props, ICompressProgress *progress)
{ {
@@ -509,6 +524,7 @@ SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
return res; return res;
} }
SRes Xz_EncodeEmpty(ISeqOutStream *outStream) SRes Xz_EncodeEmpty(ISeqOutStream *outStream)
{ {
SRes res; SRes res;

View File

@@ -1,5 +1,5 @@
/* XzIn.c - Xz input /* XzIn.c - Xz input
2013-11-12 : Igor Pavlov : Public domain */ 2015-11-08 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@@ -72,7 +72,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, ISzAlloc *alloc)
{ {
size_t i, numBlocks, crcStartPos, pos = 1; size_t numBlocks, pos = 1;
UInt32 crc; UInt32 crc;
if (size < 5 || buf[0] != 0) if (size < 5 || buf[0] != 0)
@@ -91,10 +91,10 @@ static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
} }
crcStartPos = pos;
Xz_Free(p, alloc); Xz_Free(p, alloc);
if (numBlocks != 0) if (numBlocks != 0)
{ {
size_t i;
p->numBlocks = numBlocks; p->numBlocks = numBlocks;
p->numBlocksAllocated = numBlocks; p->numBlocksAllocated = numBlocks;
p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
@@ -135,55 +135,58 @@ static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize,
return res; return res;
} }
static SRes SeekFromCur(ILookInStream *inStream, Int64 *res) static SRes LookInStream_SeekRead_ForArc(ILookInStream *stream, UInt64 offset, void *buf, size_t size)
{ {
return inStream->Seek(inStream, res, SZ_SEEK_CUR); RINOK(LookInStream_SeekTo(stream, offset));
return LookInStream_Read(stream, buf, size);
/* 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, ISzAlloc *alloc)
{ {
UInt64 indexSize; UInt64 indexSize;
Byte buf[XZ_STREAM_FOOTER_SIZE]; Byte buf[XZ_STREAM_FOOTER_SIZE];
UInt64 pos = *startOffset;
if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE) if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE)
return SZ_ERROR_NO_ARCHIVE; return SZ_ERROR_NO_ARCHIVE;
*startOffset = -XZ_STREAM_FOOTER_SIZE;
RINOK(SeekFromCur(stream, startOffset));
RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); pos -= 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 (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
{ {
UInt32 total = 0; UInt32 total = 0;
*startOffset += XZ_STREAM_FOOTER_SIZE; pos += XZ_STREAM_FOOTER_SIZE;
for (;;) for (;;)
{ {
size_t i; size_t i;
#define TEMP_BUF_SIZE (1 << 10) #define TEMP_BUF_SIZE (1 << 10)
Byte tempBuf[TEMP_BUF_SIZE]; Byte temp[TEMP_BUF_SIZE];
if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16))
return SZ_ERROR_NO_ARCHIVE; i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos;
i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset; pos -= i;
RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i));
total += (UInt32)i; total += (UInt32)i;
*startOffset = -(Int64)i;
RINOK(SeekFromCur(stream, startOffset));
RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE));
for (; i != 0; i--) for (; i != 0; i--)
if (tempBuf[i - 1] != 0) if (temp[i - 1] != 0)
break; break;
if (i != 0) if (i != 0)
{ {
if ((i & 3) != 0) if ((i & 3) != 0)
return SZ_ERROR_NO_ARCHIVE; return SZ_ERROR_NO_ARCHIVE;
*startOffset += i; pos += i;
break; break;
} }
if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16))
return SZ_ERROR_NO_ARCHIVE;
} }
if (*startOffset < XZ_STREAM_FOOTER_SIZE)
if (pos < XZ_STREAM_FOOTER_SIZE)
return SZ_ERROR_NO_ARCHIVE; return SZ_ERROR_NO_ARCHIVE;
*startOffset -= XZ_STREAM_FOOTER_SIZE; pos -= XZ_STREAM_FOOTER_SIZE;
RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE));
RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));
if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
return SZ_ERROR_NO_ARCHIVE; return SZ_ERROR_NO_ARCHIVE;
} }
@@ -198,20 +201,22 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2;
*startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE); if (pos < indexSize)
RINOK(SeekFromCur(stream, startOffset)); return SZ_ERROR_ARCHIVE;
pos -= indexSize;
RINOK(LookInStream_SeekTo(stream, pos));
RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)); RINOK(Xz_ReadIndex(p, stream, indexSize, alloc));
{ {
UInt64 totalSize = Xz_GetPackSize(p); UInt64 totalSize = Xz_GetPackSize(p);
UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize; if (totalSize == XZ_SIZE_OVERFLOW
if (totalSize == XZ_SIZE_OVERFLOW || || totalSize >= ((UInt64)1 << 63)
sum >= ((UInt64)1 << 63) || || pos < totalSize + XZ_STREAM_HEADER_SIZE)
totalSize >= ((UInt64)1 << 63))
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
*startOffset = -(Int64)sum; pos -= (totalSize + XZ_STREAM_HEADER_SIZE);
RINOK(SeekFromCur(stream, startOffset)); RINOK(LookInStream_SeekTo(stream, pos));
*startOffset = pos;
} }
{ {
CXzStreamFlags headerFlags; CXzStreamFlags headerFlags;
@@ -292,14 +297,15 @@ SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompr
if (data == 0) if (data == 0)
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
p->numAllocated = newNum; p->numAllocated = newNum;
memcpy(data, p->streams, p->num * sizeof(CXzStream)); if (p->num != 0)
memcpy(data, p->streams, p->num * sizeof(CXzStream));
alloc->Free(alloc, p->streams); alloc->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(stream->Seek(stream, startOffset, SZ_SEEK_SET)); RINOK(LookInStream_SeekTo(stream, *startOffset));
if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK) if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)
return SZ_ERROR_PROGRESS; return SZ_ERROR_PROGRESS;
} }

View File

@@ -158,14 +158,6 @@ SOURCE=.\7zFolderInStream.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\7zFolderOutStream.cpp
# End Source File
# Begin Source File
SOURCE=.\7zFolderOutStream.h
# End Source File
# Begin Source File
SOURCE=.\7zHandler.cpp SOURCE=.\7zHandler.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -350,22 +342,6 @@ SOURCE=..\Common\CoderMixer2.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Common\CoderMixer2MT.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\CoderMixer2MT.h
# End Source File
# Begin Source File
SOURCE=..\Common\CrossThreadProgress.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\CrossThreadProgress.h
# End Source File
# Begin Source File
SOURCE=..\Common\HandlerOut.cpp SOURCE=..\Common\HandlerOut.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -9,37 +9,62 @@
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
struct CMethodFull: public CProps struct CMethodFull: public CMethodProps
{ {
CMethodId Id; CMethodId Id;
UInt32 NumInStreams; UInt32 NumStreams;
UInt32 NumOutStreams;
bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } bool IsSimpleCoder() const { return NumStreams == 1; }
}; };
struct CBind struct CBond2
{ {
UInt32 InCoder;
UInt32 InStream;
UInt32 OutCoder; UInt32 OutCoder;
UInt32 OutStream; UInt32 OutStream;
UInt32 InCoder;
}; };
struct CCompressionMethodMode struct CCompressionMethodMode
{ {
/*
if (Bonds.Empty()), then default bonds must be created
if (Filter_was_Inserted)
{
Methods[0] is filter method
Bonds don't contain bonds for filter (these bonds must be created)
}
*/
CObjectVector<CMethodFull> Methods; CObjectVector<CMethodFull> Methods;
CRecordVector<CBind> Binds; CRecordVector<CBond2> Bonds;
bool IsThereBond_to_Coder(unsigned coderIndex) const
{
FOR_VECTOR(i, Bonds)
if (Bonds[i].InCoder == coderIndex)
return true;
return false;
}
bool DefaultMethod_was_Inserted;
bool Filter_was_Inserted;
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
UInt32 NumThreads; UInt32 NumThreads;
bool MultiThreadMixer;
#endif #endif
bool PasswordIsDefined; bool PasswordIsDefined;
UString Password; UString Password;
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
CCompressionMethodMode(): PasswordIsDefined(false) CCompressionMethodMode():
DefaultMethod_was_Inserted(false),
Filter_was_Inserted(false),
PasswordIsDefined(false)
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
, NumThreads(1) , NumThreads(1)
, MultiThreadMixer(true)
#endif #endif
{} {}
}; };

View File

@@ -3,7 +3,6 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../Common/LimitedStreams.h" #include "../../Common/LimitedStreams.h"
#include "../../Common/LockedStream.h"
#include "../../Common/ProgressUtils.h" #include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h" #include "../../Common/StreamObjects.h"
@@ -12,50 +11,70 @@
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, class CDecProgress:
CBindInfoEx &bindInfo) public ICompressProgressInfo,
public CMyUnknownImp
{ {
bindInfo.Clear(); CMyComPtr<ICompressProgressInfo> _progress;
bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size()); public:
CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
MY_UNKNOWN_IMP1(ICompressProgressInfo)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize)
{
return _progress->SetRatioInfo(NULL, outSize);
}
static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)
{
bi.Clear();
bi.Bonds.ClearAndSetSize(folder.Bonds.Size());
unsigned i; unsigned i;
for (i = 0; i < folder.BindPairs.Size(); i++) for (i = 0; i < folder.Bonds.Size(); i++)
{ {
NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i]; NCoderMixer2::CBond &bond = bi.Bonds[i];
bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; const N7z::CBond &folderBond = folder.Bonds[i];
bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; bond.PackIndex = folderBond.PackIndex;
bond.UnpackIndex = folderBond.UnpackIndex;
} }
bindInfo.Coders.ClearAndSetSize(folder.Coders.Size()); bi.Coders.ClearAndSetSize(folder.Coders.Size());
bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size()); bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
UInt32 outStreamIndex = 0;
for (i = 0; i < folder.Coders.Size(); i++) for (i = 0; i < folder.Coders.Size(); i++)
{ {
NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
const CCoderInfo &coderInfo = folder.Coders[i]; const CCoderInfo &coderInfo = folder.Coders[i];
coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; bi.Coders[i].NumStreams = coderInfo.NumStreams;
coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; bi.CoderMethodIDs[i] = coderInfo.MethodID;
bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;
for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
bindInfo.OutStreams.Add(outStreamIndex);
} }
bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());
/*
if (!bi.SetUnpackCoder())
throw 1112;
*/
bi.UnpackCoder = folder.UnpackCoder;
bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
for (i = 0; i < folder.PackStreams.Size(); i++) for (i = 0; i < folder.PackStreams.Size(); i++)
bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i]; bi.PackStreams[i] = folder.PackStreams[i];
} }
static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, static inline bool AreCodersEqual(
const NCoderMixer::CCoderStreamsInfo &a2) const NCoderMixer2::CCoderStreamsInfo &a1,
const NCoderMixer2::CCoderStreamsInfo &a2)
{ {
return (a1.NumInStreams == a2.NumInStreams) && return (a1.NumStreams == a2.NumStreams);
(a1.NumOutStreams == a2.NumOutStreams);
} }
static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) static inline bool AreBondsEqual(
const NCoderMixer2::CBond &a1,
const NCoderMixer2::CBond &a2)
{ {
return (a1.InIndex == a2.InIndex) && return
(a1.OutIndex == a2.OutIndex); (a1.PackIndex == a2.PackIndex) &&
(a1.UnpackIndex == a2.UnpackIndex);
} }
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
@@ -66,186 +85,290 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
for (i = 0; i < a1.Coders.Size(); i++) for (i = 0; i < a1.Coders.Size(); i++)
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
return false; return false;
if (a1.BindPairs.Size() != a2.BindPairs.Size())
if (a1.Bonds.Size() != a2.Bonds.Size())
return false; return false;
for (i = 0; i < a1.BindPairs.Size(); i++) for (i = 0; i < a1.Bonds.Size(); i++)
if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))
return false; return false;
for (i = 0; i < a1.CoderMethodIDs.Size(); i++) for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
return false; return false;
if (a1.InStreams.Size() != a2.InStreams.Size())
if (a1.PackStreams.Size() != a2.PackStreams.Size())
return false; return false;
if (a1.OutStreams.Size() != a2.OutStreams.Size()) for (i = 0; i < a1.PackStreams.Size(); i++)
if (a1.PackStreams[i] != a2.PackStreams[i])
return false;
/*
if (a1.UnpackCoder != a2.UnpackCoder)
return false; return false;
*/
return true; return true;
} }
CDecoder::CDecoder(bool multiThread) CDecoder::CDecoder(bool useMixerMT):
_bindInfoPrev_Defined(false),
_useMixerMT(useMixerMT)
{}
struct CLockedInStream:
public IUnknown,
public CMyUnknownImp
{ {
#ifndef _ST_MODE CMyComPtr<IInStream> Stream;
multiThread = true; UInt64 Pos;
MY_UNKNOWN_IMP
#ifdef USE_MIXER_MT
NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif #endif
_multiThread = multiThread; };
_bindInfoExPrevIsDefined = false;
#ifdef USE_MIXER_MT
class CLockedSequentialInStreamMT:
public ISequentialInStream,
public CMyUnknownImp
{
CLockedInStream *_glob;
UInt64 _pos;
CMyComPtr<IUnknown> _globRef;
public:
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
{
_globRef = lockedInStream;
_glob = lockedInStream;
_pos = startPos;
}
MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
if (_pos != _glob->Pos)
{
RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
_glob->Pos = _pos;
}
UInt32 realProcessedSize = 0;
HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
_pos += realProcessedSize;
_glob->Pos = _pos;
if (processedSize)
*processedSize = realProcessedSize;
return res;
} }
#endif
#ifdef USE_MIXER_ST
class CLockedSequentialInStreamST:
public ISequentialInStream,
public CMyUnknownImp
{
CLockedInStream *_glob;
UInt64 _pos;
CMyComPtr<IUnknown> _globRef;
public:
void Init(CLockedInStream *lockedInStream, UInt64 startPos)
{
_globRef = lockedInStream;
_glob = lockedInStream;
_pos = startPos;
}
MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (_pos != _glob->Pos)
{
RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
_glob->Pos = _pos;
}
UInt32 realProcessedSize = 0;
HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
_pos += realProcessedSize;
_glob->Pos = _pos;
if (processedSize)
*processedSize = realProcessedSize;
return res;
}
#endif
HRESULT CDecoder::Decode( HRESULT CDecoder::Decode(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream, IInStream *inStream,
UInt64 startPos, UInt64 startPos,
const CFolders &folders, int folderIndex, const CFolders &folders, unsigned folderIndex,
ISequentialOutStream *outStream, const UInt64 *unpackSize
ICompressProgressInfo *compressProgress
, ISequentialOutStream *outStream
, ICompressProgressInfo *compressProgress
, ISequentialInStream **
#ifdef USE_MIXER_ST
inStreamMainRes
#endif
_7Z_DECODER_CRYPRO_VARS_DECL _7Z_DECODER_CRYPRO_VARS_DECL
#if !defined(_7ZIP_ST) && !defined(_SFX) #if !defined(_7ZIP_ST) && !defined(_SFX)
, bool mtMode, UInt32 numThreads , bool mtMode, UInt32 numThreads
#endif #endif
) )
{ {
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]]; const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
CFolder folderInfo; CFolderEx folderInfo;
folders.ParseFolderInfo(folderIndex, folderInfo); folders.ParseFolderEx(folderIndex, folderInfo);
if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex))) if (!folderInfo.IsDecodingSupported())
return E_NOTIMPL;
CBindInfoEx bindInfo;
Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);
if (!bindInfo.CalcMapsAndCheck())
return E_NOTIMPL; return E_NOTIMPL;
UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);
bool fullUnpack = true;
if (unpackSize)
{
if (*unpackSize > folderUnpackSize)
return E_FAIL;
fullUnpack = (*unpackSize == folderUnpackSize);
}
/* /*
We don't need to init isEncrypted and passwordIsDefined We don't need to init isEncrypted and passwordIsDefined
We must upgrade them only We must upgrade them only
#ifndef _NO_CRYPTO #ifndef _NO_CRYPTO
isEncrypted = false; isEncrypted = false;
passwordIsDefined = false; passwordIsDefined = false;
#endif #endif
*/ */
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
CLockedInStream lockedInStream; if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
lockedInStream.Init(inStream);
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
{ {
CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; _mixerRef.Release();
CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream = streamSpec;
streamSpec->SetStream(lockedStreamImp);
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
inStreams.Add(inStream);
}
unsigned numCoders = folderInfo.Coders.Size();
CBindInfoEx bindInfo;
ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
bool createNewCoders;
if (!_bindInfoExPrevIsDefined)
createNewCoders = true;
else
createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
if (createNewCoders)
{
unsigned i;
_decoders.Clear();
// _decoders2.Clear();
_mixerCoder.Release();
if (_multiThread) #ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST
if (_useMixerMT)
#endif
{ {
_mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerMT = new NCoderMixer2::CMixerMT(false);
_mixerCoder = _mixerCoderMTSpec; _mixerRef = _mixerMT;
_mixerCoderCommon = _mixerCoderMTSpec; _mixer = _mixerMT;
} }
#ifdef USE_MIXER_ST
else else
#endif
#endif
{ {
#ifdef _ST_MODE #ifdef USE_MIXER_ST
_mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerST = new NCoderMixer2::CMixerST(false);
_mixerCoder = _mixerCoderSTSpec; _mixerRef = _mixerST;
_mixerCoderCommon = _mixerCoderSTSpec; _mixer = _mixerST;
#endif #endif
} }
RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
for (i = 0; i < numCoders; i++) RINOK(_mixer->SetBindInfo(bindInfo));
FOR_VECTOR(i, folderInfo.Coders)
{ {
const CCoderInfo &coderInfo = folderInfo.Coders[i]; const CCoderInfo &coderInfo = folderInfo.Coders[i];
#ifndef _SFX
// we don't support RAR codecs here
if ((coderInfo.MethodID >> 8) == 0x403)
return E_NOTIMPL;
#endif
CMyComPtr<ICompressCoder> decoder; CCreatedCoder cod;
CMyComPtr<ICompressCoder2> decoder2;
RINOK(CreateCoder( RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS
coderInfo.MethodID, decoder, decoder2, false)); coderInfo.MethodID, false, cod));
CMyComPtr<IUnknown> decoderUnknown;
if (coderInfo.IsSimpleCoder()) if (coderInfo.IsSimpleCoder())
{ {
if (decoder == 0) if (!cod.Coder)
return E_NOTIMPL; return E_NOTIMPL;
// CMethodId m = coderInfo.MethodID;
decoderUnknown = (IUnknown *)decoder; // isFilter = (IsFilterMethod(m) || m == k_AES);
if (_multiThread)
_mixerCoderMTSpec->AddCoder(decoder);
#ifdef _ST_MODE
else
_mixerCoderSTSpec->AddCoder(decoder, false);
#endif
} }
else else
{ {
if (decoder2 == 0) if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
return E_NOTIMPL; return E_NOTIMPL;
decoderUnknown = (IUnknown *)decoder2;
if (_multiThread)
_mixerCoderMTSpec->AddCoder2(decoder2);
#ifdef _ST_MODE
else
_mixerCoderSTSpec->AddCoder2(decoder2, false);
#endif
} }
_decoders.Add(decoderUnknown); _mixer->AddCoder(cod);
// now there is no codec that uses another external codec
/*
#ifdef EXTERNAL_CODECS #ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo) if (setCompressCodecsInfo)
{ {
// we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
} }
#endif #endif
*/
} }
_bindInfoExPrev = bindInfo;
_bindInfoExPrevIsDefined = true; _bindInfoPrev = bindInfo;
_bindInfoPrev_Defined = true;
} }
unsigned i;
_mixerCoderCommon->ReInit(); _mixer->ReInit();
UInt32 packStreamIndex = 0; UInt32 packStreamIndex = 0;
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex]; UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
UInt32 unpackStreamIndex = unpackStreamIndexStart;
UInt32 coderIndex = 0; unsigned i;
// UInt32 coder2Index = 0;
for (i = 0; i < folderInfo.Coders.Size(); i++)
for (i = 0; i < numCoders; i++)
{ {
const CCoderInfo &coderInfo = folderInfo.Coders[i]; const CCoderInfo &coderInfo = folderInfo.Coders[i];
CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
{ {
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
if (setDecoderProperties) if (setDecoderProperties)
{ {
const CByteBuffer &props = coderInfo.Props; const CByteBuffer &props = coderInfo.Props;
size_t size = props.Size(); size_t size = props.Size();
if (size > 0xFFFFFFFF) if (size > 0xFFFFFFFF)
return E_NOTIMPL; return E_NOTIMPL;
// if (size > 0) HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
{ if (res == E_INVALIDARG)
RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); res = E_NOTIMPL;
} RINOK(res);
} }
} }
@@ -253,7 +376,7 @@ HRESULT CDecoder::Decode(
if (mtMode) if (mtMode)
{ {
CMyComPtr<ICompressSetCoderMt> setCoderMt; CMyComPtr<ICompressSetCoderMt> setCoderMt;
decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
if (setCoderMt) if (setCoderMt)
{ {
RINOK(setCoderMt->SetNumberOfThreads(numThreads)); RINOK(setCoderMt->SetNumberOfThreads(numThreads));
@@ -264,7 +387,7 @@ HRESULT CDecoder::Decode(
#ifndef _NO_CRYPTO #ifndef _NO_CRYPTO
{ {
CMyComPtr<ICryptoSetPassword> cryptoSetPassword; CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
if (cryptoSetPassword) if (cryptoSetPassword)
{ {
isEncrypted = true; isEncrypted = true;
@@ -273,9 +396,13 @@ HRESULT CDecoder::Decode(
CMyComBSTR passwordBSTR; CMyComBSTR passwordBSTR;
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
passwordIsDefined = true; passwordIsDefined = true;
password.Empty();
size_t len = 0; size_t len = 0;
if (passwordBSTR) if (passwordBSTR)
len = MyStringLen((BSTR)passwordBSTR); {
password = passwordBSTR;
len = password.Len();
}
CByteBuffer buffer(len * 2); CByteBuffer buffer(len * 2);
for (size_t i = 0; i < len; i++) for (size_t i = 0; i < len; i++)
{ {
@@ -288,56 +415,129 @@ HRESULT CDecoder::Decode(
} }
#endif #endif
coderIndex++;
UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
CObjArray<UInt64> packSizes(numInStreams);
CObjArray<const UInt64 *> packSizesPointers(numInStreams);
CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);
UInt32 j;
for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];
for (j = 0; j < numInStreams; j++, packStreamIndex++)
{ {
int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); CMyComPtr<ICompressSetFinishMode> setFinishMode;
if (bindPairIndex >= 0) decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]; if (setFinishMode)
else
{ {
int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
if (index < 0)
return S_FALSE; // check it
packSizes[j] = packPositions[index + 1] - packPositions[index];
packSizesPointers[j] = &packSizes[j];
} }
} }
_mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers); UInt32 numStreams = (UInt32)coderInfo.NumStreams;
}
UInt32 mainCoder, temp; CObjArray<UInt64> packSizes(numStreams);
bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); CObjArray<const UInt64 *> packSizesPointers(numStreams);
for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
{
int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
if (bond >= 0)
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
else
{
int index = folderInfo.Find_in_PackStreams(packStreamIndex);
if (index < 0)
return E_NOTIMPL;
packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
packSizesPointers[j] = &packSizes[j];
}
}
if (_multiThread) const UInt64 *unpackSizesPointer =
_mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); (unpackSize && i == bindInfo.UnpackCoder) ?
/* unpackSize :
else &folders.CoderUnpackSizes[unpackStreamIndexStart + i];
_mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
*/ _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
}
if (outStream)
{
_mixer->SelectMainCoder(!fullUnpack);
}
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
CLockedInStream *lockedInStreamSpec = new CLockedInStream;
CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
bool needMtLock = false;
if (folderInfo.PackStreams.Size() > 1)
{
// lockedInStream.Pos = (UInt64)(Int64)-1;
// RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
lockedInStreamSpec->Stream = inStream;
#ifdef USE_MIXER_ST
if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
#endif
needMtLock = true;
}
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
{
CMyComPtr<ISequentialInStream> packStream;
UInt64 packPos = startPos + packPositions[j];
if (folderInfo.PackStreams.Size() == 1)
{
RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));
packStream = inStream;
}
else
{
#ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST
if (_useMixerMT || needMtLock)
#endif
{
CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
packStream = lockedStreamImpSpec;
lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
}
#ifdef USE_MIXER_ST
else
#endif
#endif
{
#ifdef USE_MIXER_ST
CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
packStream = lockedStreamImpSpec;
lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
#endif
}
}
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
inStreams.AddNew() = streamSpec;
streamSpec->SetStream(packStream);
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
}
if (numCoders == 0)
return 0;
unsigned num = inStreams.Size(); unsigned num = inStreams.Size();
CObjArray<ISequentialInStream *> inStreamPointers(num); CObjArray<ISequentialInStream *> inStreamPointers(num);
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
inStreamPointers[i] = inStreams[i]; inStreamPointers[i] = inStreams[i];
ISequentialOutStream *outStreamPointer = outStream;
return _mixerCoder->Code( if (outStream)
inStreamPointers, NULL, num, {
&outStreamPointer, NULL, 1, CMyComPtr<ICompressProgressInfo> progress2;
compressProgress); if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))
progress2 = new CDecProgress(compressProgress);
ISequentialOutStream *outStreamPointer = outStream;
return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);
}
#ifdef USE_MIXER_ST
return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
#else
return E_FAIL;
#endif
} }
}} }}

View File

@@ -3,25 +3,17 @@
#ifndef __7Z_DECODE_H #ifndef __7Z_DECODE_H
#define __7Z_DECODE_H #define __7Z_DECODE_H
#include "../../IStream.h"
#include "../../IPassword.h"
#include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2.h"
#include "../Common/CoderMixer2MT.h"
#ifdef _ST_MODE
#include "../Common/CoderMixer2ST.h"
#endif
#include "../../Common/CreateCoder.h"
#include "7zIn.h" #include "7zIn.h"
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
struct CBindInfoEx: public NCoderMixer::CBindInfo struct CBindInfoEx: public NCoderMixer2::CBindInfo
{ {
CRecordVector<CMethodId> CoderMethodIDs; CRecordVector<CMethodId> CoderMethodIDs;
void Clear() void Clear()
{ {
CBindInfo::Clear(); CBindInfo::Clear();
@@ -31,29 +23,40 @@ struct CBindInfoEx: public NCoderMixer::CBindInfo
class CDecoder class CDecoder
{ {
bool _bindInfoExPrevIsDefined; bool _bindInfoPrev_Defined;
CBindInfoEx _bindInfoExPrev; CBindInfoEx _bindInfoPrev;
bool _multiThread; bool _useMixerMT;
#ifdef _ST_MODE
NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #ifdef USE_MIXER_ST
NCoderMixer2::CMixerST *_mixerST;
#endif #endif
NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;
NCoderMixer::CCoderMixer2 *_mixerCoderCommon;
CMyComPtr<ICompressCoder2> _mixerCoder; #ifdef USE_MIXER_MT
CObjectVector<CMyComPtr<IUnknown> > _decoders; NCoderMixer2::CMixerMT *_mixerMT;
// CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; #endif
NCoderMixer2::CMixer *_mixer;
CMyComPtr<IUnknown> _mixerRef;
public: public:
CDecoder(bool multiThread);
CDecoder(bool useMixerMT);
HRESULT Decode( HRESULT Decode(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream, IInStream *inStream,
UInt64 startPos, UInt64 startPos,
const CFolders &folders, int folderIndex, const CFolders &folders, unsigned folderIndex,
ISequentialOutStream *outStream, const UInt64 *unpackSize // if (!unpackSize), then full folder is required
ICompressProgressInfo *compressProgress // if (unpackSize), then only *unpackSize bytes from folder are required
, ISequentialOutStream *outStream
, ICompressProgressInfo *compressProgress
, ISequentialInStream **inStreamMainRes
_7Z_DECODER_CRYPRO_VARS_DECL _7Z_DECODER_CRYPRO_VARS_DECL
#if !defined(_7ZIP_ST) && !defined(_SFX) #if !defined(_7ZIP_ST) && !defined(_SFX)
, bool mtMode, UInt32 numThreads , bool mtMode, UInt32 numThreads
#endif #endif

View File

@@ -12,43 +12,80 @@
#include "7zEncode.h" #include "7zEncode.h"
#include "7zSpecStream.h" #include "7zSpecStream.h"
static const UInt64 k_Delta = 0x03;
static const UInt64 k_BCJ = 0x03030103;
static const UInt64 k_BCJ2 = 0x0303011B;
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, void CEncoder::InitBindConv()
const CRecordVector<CMethodId> decompressionMethods,
CFolder &folder)
{ {
// bindInfo.CoderMethodIDs.Clear(); unsigned numIn = _bindInfo.Coders.Size();
// folder.OutStreams.Clear();
folder.BindPairs.SetSize(bindInfo.BindPairs.Size()); _SrcIn_to_DestOut.ClearAndSetSize(numIn);
unsigned i; _DestOut_to_SrcIn.ClearAndSetSize(numIn);
for (i = 0; i < bindInfo.BindPairs.Size(); i++)
unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();
_SrcOut_to_DestIn.ClearAndSetSize(numOut);
// _DestIn_to_SrcOut.ClearAndSetSize(numOut);
UInt32 destIn = 0;
UInt32 destOut = 0;
for (unsigned i = _bindInfo.Coders.Size(); i != 0;)
{ {
CBindPair &bp = folder.BindPairs[i]; i--;
const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];
bp.InIndex = mixerBp.InIndex; const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];
bp.OutIndex = mixerBp.OutIndex;
numIn--;
numOut -= coder.NumStreams;
_SrcIn_to_DestOut[numIn] = destOut;
_DestOut_to_SrcIn[destOut] = numIn;
destOut++;
for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)
{
UInt32 index = numOut + j;
_SrcOut_to_DestIn[index] = destIn;
// _DestIn_to_SrcOut[destIn] = index;
}
} }
folder.Coders.SetSize(bindInfo.Coders.Size()); }
for (i = 0; i < bindInfo.Coders.Size(); i++)
void CEncoder::SetFolder(CFolder &folder)
{
folder.Bonds.SetSize(_bindInfo.Bonds.Size());
unsigned i;
for (i = 0; i < _bindInfo.Bonds.Size(); i++)
{
CBond &fb = folder.Bonds[i];
const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];
fb.PackIndex = _SrcOut_to_DestIn[mixerBond.PackIndex];
fb.UnpackIndex = _SrcIn_to_DestOut[mixerBond.UnpackIndex];
}
folder.Coders.SetSize(_bindInfo.Coders.Size());
for (i = 0; i < _bindInfo.Coders.Size(); i++)
{ {
CCoderInfo &coderInfo = folder.Coders[i]; CCoderInfo &coderInfo = folder.Coders[i];
const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];
coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.NumStreams = coderStreamsInfo.NumStreams;
coderInfo.MethodID = decompressionMethods[i]; coderInfo.MethodID = _decompressionMethods[i];
// coderInfo.Props can be nonFree; // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.
} }
folder.PackStreams.SetSize(bindInfo.InStreams.Size());
for (i = 0; i < bindInfo.InStreams.Size(); i++) folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());
folder.PackStreams[i] = bindInfo.InStreams[i];
for (i = 0; i < _bindInfo.PackStreams.Size(); i++)
folder.PackStreams[i] = _SrcOut_to_DestIn[_bindInfo.PackStreams[i]];
} }
static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder) static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
{ {
CMyComPtr<ICompressSetCoderProperties> setCoderProperties; CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
@@ -58,30 +95,75 @@ static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce,
return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK; return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
} }
void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
{
_progress = progress;
OutSize = 0;
}
STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
{
UInt64 outSize2;
{
#ifndef _7ZIP_ST
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
#endif
outSize2 = OutSize;
}
if (_progress)
return _progress->SetRatioInfo(inSize, &outSize2);
return S_OK;
}
HRESULT CEncoder::CreateMixerCoder( HRESULT CEncoder::CreateMixerCoder(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce) const UInt64 *inSizeForReduce)
{ {
_mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; #ifdef USE_MIXER_MT
_mixerCoder = _mixerCoderSpec; #ifdef USE_MIXER_ST
RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); if (_options.MultiThreadMixer)
#endif
{
_mixerMT = new NCoderMixer2::CMixerMT(true);
_mixerRef = _mixerMT;
_mixer = _mixerMT;
}
#ifdef USE_MIXER_ST
else
#endif
#endif
{
#ifdef USE_MIXER_ST
_mixerST = new NCoderMixer2::CMixerST(true);
_mixerRef = _mixerST;
_mixer = _mixerST;
#endif
}
RINOK(_mixer->SetBindInfo(_bindInfo));
FOR_VECTOR (i, _options.Methods) FOR_VECTOR (i, _options.Methods)
{ {
const CMethodFull &methodFull = _options.Methods[i]; const CMethodFull &methodFull = _options.Methods[i];
CCoderInfo &encodingInfo = _codersInfo.AddNew();
encodingInfo.MethodID = methodFull.Id;
CMyComPtr<ICompressCoder> encoder;
CMyComPtr<ICompressCoder2> encoder2;
CCreatedCoder cod;
RINOK(CreateCoder( RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS
methodFull.Id, encoder, encoder2, true)); methodFull.Id, true, cod));
if (!encoder && !encoder2) if (cod.NumStreams != methodFull.NumStreams)
return E_FAIL;
if (!cod.Coder && !cod.Coder2)
return E_FAIL; return E_FAIL;
CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
{ {
@@ -105,21 +187,25 @@ HRESULT CEncoder::CreateMixerCoder(
} }
*/ */
// now there is no codec that uses another external codec
/*
#ifdef EXTERNAL_CODECS #ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo) if (setCompressCodecsInfo)
{ {
// we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
} }
#endif #endif
*/
CMyComPtr<ICryptoSetPassword> cryptoSetPassword; CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
if (cryptoSetPassword) if (cryptoSetPassword)
{ {
const UInt32 sizeInBytes = _options.Password.Len() * 2; const unsigned sizeInBytes = _options.Password.Len() * 2;
CByteBuffer buffer(sizeInBytes); CByteBuffer buffer(sizeInBytes);
for (unsigned i = 0; i < _options.Password.Len(); i++) for (unsigned i = 0; i < _options.Password.Len(); i++)
{ {
@@ -127,21 +213,79 @@ HRESULT CEncoder::CreateMixerCoder(
((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
} }
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes));
} }
if (encoder) _mixer->AddCoder(cod);
_mixerCoderSpec->AddCoder(encoder);
else
_mixerCoderSpec->AddCoder2(encoder2);
} }
return S_OK; return S_OK;
} }
class CSequentialOutTempBufferImp2:
public ISequentialOutStream,
public CMyUnknownImp
{
CInOutTempBuffer *_buf;
public:
CMtEncMultiProgress *_mtProgresSpec;
CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {}
void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
MY_UNKNOWN_IMP1(ISequentialOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed)
{
if (!_buf->Write(data, size))
{
if (processed)
*processed = 0;
return E_FAIL;
}
if (processed)
*processed = size;
if (_mtProgresSpec)
_mtProgresSpec->AddOutSize(size);
return S_OK;
}
class CSequentialOutMtNotify:
public ISequentialOutStream,
public CMyUnknownImp
{
public:
CMyComPtr<ISequentialOutStream> _stream;
CMtEncMultiProgress *_mtProgresSpec;
CSequentialOutMtNotify(): _mtProgresSpec(NULL) {}
MY_UNKNOWN_IMP1(ISequentialOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed)
{
UInt32 realProcessed = 0;
HRESULT res = _stream->Write(data, size, &realProcessed);
if (processed)
*processed = realProcessed;
if (_mtProgresSpec)
_mtProgresSpec->AddOutSize(size);
return res;
}
HRESULT CEncoder::Encode( HRESULT CEncoder::Encode(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, ISequentialInStream *inStream,
const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, // const UInt64 *inStreamSize,
const UInt64 *inSizeForReduce,
CFolder &folderItem, CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes, CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize, UInt64 &unpackSize,
@@ -151,27 +295,37 @@ HRESULT CEncoder::Encode(
{ {
RINOK(EncoderConstr()); RINOK(EncoderConstr());
if (!_mixerCoderSpec) if (!_mixerRef)
{ {
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
} }
_mixerCoderSpec->ReInit();
// _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); _mixer->ReInit();
CMtEncMultiProgress *mtProgressSpec = NULL;
CMyComPtr<ICompressProgressInfo> mtProgress;
CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
CObjectVector<CInOutTempBuffer> inOutTempBuffers; CObjectVector<CInOutTempBuffer> inOutTempBuffers;
CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
unsigned numMethods = _bindInfo.Coders.Size(); unsigned numMethods = _bindInfo.Coders.Size();
unsigned i; unsigned i;
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{ {
CInOutTempBuffer &iotb = inOutTempBuffers.AddNew(); CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();
iotb.Create(); iotb.Create();
iotb.InitWriting(); iotb.InitWriting();
} }
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{ {
CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2;
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
tempBuffers.Add(tempBuffer); tempBuffers.Add(tempBuffer);
@@ -179,94 +333,111 @@ HRESULT CEncoder::Encode(
} }
for (i = 0; i < numMethods; i++) for (i = 0; i < numMethods; i++)
_mixerCoderSpec->SetCoderInfo(i, NULL, NULL); _mixer->SetCoderInfo(i, NULL, NULL);
if (_bindInfo.InStreams.IsEmpty())
return E_FAIL; /* inStreamSize can be used by BCJ2 to set optimal range of conversion.
UInt32 mainCoderIndex, mainStreamIndex; But current BCJ2 encoder uses also another way to check exact size of current file.
_bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); So inStreamSize is not required. */
/*
if (inStreamSize) if (inStreamSize)
{ _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
CRecordVector<const UInt64 *> sizePointers; */
for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
if (i == mainStreamIndex)
sizePointers.Add(inStreamSize);
else
sizePointers.Add(NULL);
_mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
}
// UInt64 outStreamStartPos;
// RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
CMyComPtr<ISequentialOutStream> outStreamSizeCount; CMyComPtr<ISequentialOutStream> outStreamSizeCount;
inStreamSizeCountSpec->Init(inStream); inStreamSizeCountSpec->Init(inStream);
CRecordVector<ISequentialInStream *> inStreamPointers; ISequentialInStream *inStreamPointer = inStreamSizeCount;
CRecordVector<ISequentialOutStream *> outStreamPointers; CRecordVector<ISequentialOutStream *> outStreamPointers;
inStreamPointers.Add(inStreamSizeCount);
if (_bindInfo.OutStreams.Size() != 0) SetFolder(folderItem);
{
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
outStreamSizeCount = outStreamSizeCountSpec;
outStreamSizeCountSpec->SetStream(outStream);
outStreamSizeCountSpec->Init();
outStreamPointers.Add(outStreamSizeCount);
}
for (i = 1; i < _bindInfo.OutStreams.Size(); i++) for (i = 0; i < numMethods; i++)
outStreamPointers.Add(tempBuffers[i - 1]);
for (i = 0; i < _codersInfo.Size(); i++)
{ {
CCoderInfo &encodingInfo = _codersInfo[i]; IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
CMyComPtr<ICryptoResetInitVector> resetInitVector; CMyComPtr<ICryptoResetInitVector> resetInitVector;
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
if (resetInitVector) if (resetInitVector)
{ {
resetInitVector->ResetInitVector(); resetInitVector->ResetInitVector();
} }
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props;
if (writeCoderProperties) if (writeCoderProperties)
{ {
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
outStreamSpec->Init(); outStreamSpec->Init();
writeCoderProperties->WriteCoderProperties(outStream); writeCoderProperties->WriteCoderProperties(dynOutStream);
outStreamSpec->CopyToBuffer(encodingInfo.Props); outStreamSpec->CopyToBuffer(props);
}
else
props.Free();
}
_mixer->SelectMainCoder(false);
UInt32 mainCoder = _mixer->MainCoderIndex;
bool useMtProgress = false;
if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
{
#ifdef _7ZIP_ST
if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
#endif
useMtProgress = true;
}
if (useMtProgress)
{
mtProgressSpec = new CMtEncMultiProgress;
mtProgress = mtProgressSpec;
mtProgressSpec->Init(compressProgress);
mtOutStreamNotifySpec = new CSequentialOutMtNotify;
mtOutStreamNotify = mtOutStreamNotifySpec;
mtOutStreamNotifySpec->_stream = outStream;
mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;
FOR_VECTOR(i, tempBufferSpecs)
{
tempBufferSpecs[i]->_mtProgresSpec = mtProgressSpec;
} }
} }
UInt32 progressIndex = mainCoderIndex;
if (_bindInfo.PackStreams.Size() != 0)
for (i = 0; i + 1 < _codersInfo.Size(); i++)
{ {
UInt64 m = _codersInfo[i].MethodID; outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
if (m == k_Delta || m == k_BCJ || m == k_BCJ2) outStreamSizeCount = outStreamSizeCountSpec;
progressIndex = i + 1; outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);
outStreamSizeCountSpec->Init();
outStreamPointers.Add(outStreamSizeCount);
} }
_mixerCoderSpec->SetProgressCoderIndex(progressIndex); for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
outStreamPointers.Add(tempBuffers[i - 1]);
RINOK(_mixer->Code(
&inStreamPointer,
&outStreamPointers.Front(),
mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));
RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, if (_bindInfo.PackStreams.Size() != 0)
&outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
if (_bindInfo.OutStreams.Size() != 0)
packSizes.Add(outStreamSizeCountSpec->GetSize()); packSizes.Add(outStreamSizeCountSpec->GetSize());
for (i = 1; i < _bindInfo.OutStreams.Size(); i++) for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{ {
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
RINOK(inOutTempBuffer.WriteToStream(outStream)); RINOK(inOutTempBuffer.WriteToStream(outStream));
@@ -274,37 +445,45 @@ HRESULT CEncoder::Encode(
} }
unpackSize = 0; unpackSize = 0;
for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
for (i = 0; i < _bindInfo.Coders.Size(); i++)
{ {
int binder = _bindInfo.FindBinderForInStream( int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]);
_bindReverseConverter->DestOutToSrcInMap[i]);
UInt64 streamSize; UInt64 streamSize;
if (binder < 0) if (bond < 0)
{ {
streamSize = inStreamSizeCountSpec->GetSize(); streamSize = inStreamSizeCountSpec->GetSize();
unpackSize = streamSize; unpackSize = streamSize;
} }
else else
streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); streamSize = _mixer->GetBondStreamSize(bond);
coderUnpackSizes.Add(streamSize); coderUnpackSizes.Add(streamSize);
} }
for (i = 0; i < numMethods; i++)
folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;
return S_OK; return S_OK;
} }
CEncoder::CEncoder(const CCompressionMethodMode &options): CEncoder::CEncoder(const CCompressionMethodMode &options):
_bindReverseConverter(0), _constructed(false)
_constructed(false)
{ {
if (options.IsEmpty()) if (options.IsEmpty())
throw 1; throw 1;
_options = options; _options = options;
_mixerCoderSpec = NULL;
#ifdef USE_MIXER_ST
_mixerST = NULL;
#endif
#ifdef USE_MIXER_MT
_mixerMT = NULL;
#endif
_mixer = NULL;
} }
HRESULT CEncoder::EncoderConstr() HRESULT CEncoder::EncoderConstr()
{ {
if (_constructed) if (_constructed)
@@ -314,112 +493,125 @@ HRESULT CEncoder::EncoderConstr()
// it has only password method; // it has only password method;
if (!_options.PasswordIsDefined) if (!_options.PasswordIsDefined)
throw 1; throw 1;
if (!_options.Binds.IsEmpty()) if (!_options.Bonds.IsEmpty())
throw 1; throw 1;
NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
CMethodFull method; CMethodFull method;
method.NumInStreams = 1;
method.NumOutStreams = 1;
coderStreamsInfo.NumInStreams = 1;
coderStreamsInfo.NumOutStreams = 1;
method.Id = k_AES; method.Id = k_AES;
method.NumStreams = 1;
_options.Methods.Add(method); _options.Methods.Add(method);
NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
coderStreamsInfo.NumStreams = 1;
_bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.Coders.Add(coderStreamsInfo);
_bindInfo.InStreams.Add(0); _bindInfo.PackStreams.Add(0);
_bindInfo.OutStreams.Add(0); _bindInfo.UnpackCoder = 0;
} }
else else
{ {
UInt32 numInStreams = 0, numOutStreams = 0; UInt32 numOutStreams = 0;
unsigned i; unsigned i;
for (i = 0; i < _options.Methods.Size(); i++) for (i = 0; i < _options.Methods.Size(); i++)
{ {
const CMethodFull &methodFull = _options.Methods[i]; const CMethodFull &methodFull = _options.Methods[i];
NCoderMixer::CCoderStreamsInfo coderStreamsInfo; NCoderMixer2::CCoderStreamsInfo cod;
coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; cod.NumStreams = methodFull.NumStreams;
if (_options.Binds.IsEmpty())
if (_options.Bonds.IsEmpty())
{ {
if (i < _options.Methods.Size() - 1) // if there are no bonds in options, we create bonds via first streams of coders
if (i != _options.Methods.Size() - 1)
{ {
NCoderMixer::CBindPair bindPair; NCoderMixer2::CBond bond;
bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; bond.PackIndex = numOutStreams;
bindPair.OutIndex = numOutStreams; bond.UnpackIndex = i + 1; // it's next coder
_bindInfo.BindPairs.Add(bindPair); _bindInfo.Bonds.Add(bond);
} }
else if (coderStreamsInfo.NumOutStreams != 0) else if (cod.NumStreams != 0)
_bindInfo.OutStreams.Insert(0, numOutStreams); _bindInfo.PackStreams.Insert(0, numOutStreams);
for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
_bindInfo.OutStreams.Add(numOutStreams + j); for (UInt32 j = 1; j < cod.NumStreams; j++)
_bindInfo.PackStreams.Add(numOutStreams + j);
} }
numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += cod.NumStreams;
numOutStreams += coderStreamsInfo.NumOutStreams;
_bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.Coders.Add(cod);
} }
if (!_options.Binds.IsEmpty()) if (!_options.Bonds.IsEmpty())
{ {
for (i = 0; i < _options.Binds.Size(); i++) for (i = 0; i < _options.Bonds.Size(); i++)
{ {
NCoderMixer::CBindPair bindPair; NCoderMixer2::CBond mixerBond;
const CBind &bind = _options.Binds[i]; const CBond2 &bond = _options.Bonds[i];
bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; if (bond.InCoder >= _bindInfo.Coders.Size()
bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; || bond.OutCoder >= _bindInfo.Coders.Size()
_bindInfo.BindPairs.Add(bindPair); || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)
return E_INVALIDARG;
mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;
mixerBond.UnpackIndex = bond.InCoder;
_bindInfo.Bonds.Add(mixerBond);
} }
for (i = 0; i < (int)numOutStreams; i++)
if (_bindInfo.FindBinderForOutStream(i) == -1) for (i = 0; i < numOutStreams; i++)
_bindInfo.OutStreams.Add(i); if (_bindInfo.FindBond_for_PackStream(i) == -1)
_bindInfo.PackStreams.Add(i);
} }
for (i = 0; i < (int)numInStreams; i++) if (!_bindInfo.SetUnpackCoder())
if (_bindInfo.FindBinderForInStream(i) == -1) return E_INVALIDARG;
_bindInfo.InStreams.Add(i);
if (_bindInfo.InStreams.IsEmpty()) if (!_bindInfo.CalcMapsAndCheck())
throw 1; // this is error return E_INVALIDARG;
// Make main stream first in list if (_bindInfo.PackStreams.Size() != 1)
int inIndex = _bindInfo.InStreams[0];
for (;;)
{ {
UInt32 coderIndex, coderStreamIndex; /* main_PackStream is pack stream of main path of coders tree.
_bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); We find main_PackStream, and place to start of list of out streams.
UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); It allows to use more optimal memory usage for temp buffers,
int binder = _bindInfo.FindBinderForOutStream(outIndex); if main_PackStream is largest stream. */
if (binder >= 0)
UInt32 ci = _bindInfo.UnpackCoder;
for (;;)
{ {
inIndex = _bindInfo.BindPairs[binder].InIndex; if (_bindInfo.Coders[ci].NumStreams == 0)
continue;
}
for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
if (_bindInfo.OutStreams[i] == outIndex)
{
_bindInfo.OutStreams.Delete(i);
_bindInfo.OutStreams.Insert(0, outIndex);
break; break;
UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
int bond = _bindInfo.FindBond_for_PackStream(outIndex);
if (bond >= 0)
{
ci = _bindInfo.Bonds[bond].UnpackIndex;
continue;
} }
break;
int i = _bindInfo.FindStream_in_PackStreams(outIndex);
if (i >= 0)
_bindInfo.PackStreams.MoveToFront(i);
break;
}
} }
if (_options.PasswordIsDefined) if (_options.PasswordIsDefined)
{ {
unsigned numCryptoStreams = _bindInfo.OutStreams.Size(); unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
unsigned numInStreams = _bindInfo.Coders.Size();
for (i = 0; i < numCryptoStreams; i++) for (i = 0; i < numCryptoStreams; i++)
{ {
NCoderMixer::CBindPair bindPair; NCoderMixer2::CBond bond;
bindPair.InIndex = numInStreams + i; bond.UnpackIndex = numInStreams + i;
bindPair.OutIndex = _bindInfo.OutStreams[i]; bond.PackIndex = _bindInfo.PackStreams[i];
_bindInfo.BindPairs.Add(bindPair); _bindInfo.Bonds.Add(bond);
} }
_bindInfo.OutStreams.Clear(); _bindInfo.PackStreams.Clear();
/* /*
if (numCryptoStreams == 0) if (numCryptoStreams == 0)
@@ -428,37 +620,37 @@ HRESULT CEncoder::EncoderConstr()
for (i = 0; i < numCryptoStreams; i++) for (i = 0; i < numCryptoStreams; i++)
{ {
NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
CMethodFull method; CMethodFull method;
method.NumInStreams = 1; method.NumStreams = 1;
method.NumOutStreams = 1;
coderStreamsInfo.NumInStreams = method.NumOutStreams;
coderStreamsInfo.NumOutStreams = method.NumInStreams;
method.Id = k_AES; method.Id = k_AES;
_options.Methods.Add(method); _options.Methods.Add(method);
_bindInfo.Coders.Add(coderStreamsInfo);
_bindInfo.OutStreams.Add(numOutStreams + i); NCoderMixer2::CCoderStreamsInfo cod;
cod.NumStreams = 1;
_bindInfo.Coders.Add(cod);
_bindInfo.PackStreams.Add(numOutStreams++);
} }
} }
} }
for (int i = _options.Methods.Size() - 1; i >= 0; i--) for (unsigned i = _options.Methods.Size(); i != 0;)
{ _decompressionMethods.Add(_options.Methods[--i].Id);
const CMethodFull &methodFull = _options.Methods[i];
_decompressionMethods.Add(methodFull.Id);
}
_bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); if (_bindInfo.Coders.Size() > 16)
_bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); return E_INVALIDARG;
if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)
return E_INVALIDARG;
if (!_bindInfo.CalcMapsAndCheck())
return E_INVALIDARG;
InitBindConv();
_constructed = true; _constructed = true;
return S_OK; return S_OK;
} }
CEncoder::~CEncoder() CEncoder::~CEncoder() {}
{
delete _bindReverseConverter;
}
}} }}

View File

@@ -3,47 +3,82 @@
#ifndef __7Z_ENCODE_H #ifndef __7Z_ENCODE_H
#define __7Z_ENCODE_H #define __7Z_ENCODE_H
// #include "../../Common/StreamObjects.h"
#include "7zCompressionMode.h" #include "7zCompressionMode.h"
#include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2.h"
#include "../Common/CoderMixer2MT.h"
#ifdef _ST_MODE
#include "../Common/CoderMixer2ST.h"
#endif
#include "7zItem.h"
#include "../../Common/CreateCoder.h" #include "7zItem.h"
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
class CMtEncMultiProgress:
public ICompressProgressInfo,
public CMyUnknownImp
{
CMyComPtr<ICompressProgressInfo> _progress;
#ifndef _7ZIP_ST
NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif
public:
UInt64 OutSize;
CMtEncMultiProgress(): OutSize(0) {}
void Init(ICompressProgressInfo *progress);
void AddOutSize(UInt64 addOutSize)
{
#ifndef _7ZIP_ST
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
#endif
OutSize += addOutSize;
}
MY_UNKNOWN_IMP1(ICompressProgressInfo)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
class CEncoder class CEncoder
{ {
NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; #ifdef USE_MIXER_ST
CMyComPtr<ICompressCoder2> _mixerCoder; NCoderMixer2::CMixerST *_mixerST;
#endif
CObjectVector<CCoderInfo> _codersInfo; #ifdef USE_MIXER_MT
NCoderMixer2::CMixerMT *_mixerMT;
#endif
NCoderMixer2::CMixer *_mixer;
CMyComPtr<IUnknown> _mixerRef;
CCompressionMethodMode _options; CCompressionMethodMode _options;
NCoderMixer::CBindInfo _bindInfo; NCoderMixer2::CBindInfo _bindInfo;
NCoderMixer::CBindInfo _decompressBindInfo;
NCoderMixer::CBindReverseConverter *_bindReverseConverter;
CRecordVector<CMethodId> _decompressionMethods; CRecordVector<CMethodId> _decompressionMethods;
CRecordVector<UInt32> _SrcIn_to_DestOut;
CRecordVector<UInt32> _SrcOut_to_DestIn;
// CRecordVector<UInt32> _DestIn_to_SrcOut;
CRecordVector<UInt32> _DestOut_to_SrcIn;
void InitBindConv();
void SetFolder(CFolder &folder);
HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce); const UInt64 *inSizeForReduce);
bool _constructed; bool _constructed;
public: public:
CEncoder(const CCompressionMethodMode &options); CEncoder(const CCompressionMethodMode &options);
~CEncoder(); ~CEncoder();
HRESULT EncoderConstr(); HRESULT EncoderConstr();
HRESULT Encode( HRESULT Encode(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, ISequentialInStream *inStream,
const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, // const UInt64 *inStreamSize,
const UInt64 *inSizeForReduce,
CFolder &folderItem, CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes, CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize, UInt64 &unpackSize,

View File

@@ -2,205 +2,335 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../../C/7zCrc.h"
#include "../../../Common/ComTry.h" #include "../../../Common/ComTry.h"
#include "../../Common/ProgressUtils.h" #include "../../Common/ProgressUtils.h"
#include "7zDecode.h" #include "7zDecode.h"
// #include "7z1Decode.h"
#include "7zFolderOutStream.h"
#include "7zHandler.h" #include "7zHandler.h"
// EXTERN_g_ExternalCodecs
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
struct CExtractFolderInfo class CFolderOutStream:
public ISequentialOutStream,
public CMyUnknownImp
{ {
#ifdef _7Z_VOL CMyComPtr<ISequentialOutStream> _stream;
int VolumeIndex; public:
#endif bool TestMode;
CNum FileIndex; bool CheckCrc;
CNum FolderIndex; private:
CBoolVector ExtractStatuses; bool _fileIsOpen;
UInt64 UnpackSize; bool _calcCrc;
CExtractFolderInfo( UInt32 _crc;
#ifdef _7Z_VOL UInt64 _rem;
int volumeIndex,
#endif const UInt32 *_indexes;
CNum fileIndex, CNum folderIndex): unsigned _numFiles;
#ifdef _7Z_VOL unsigned _fileIndex;
VolumeIndex(volumeIndex),
#endif HRESULT OpenFile(bool isCorrupted = false);
FileIndex(fileIndex), HRESULT CloseFile_and_SetResult(Int32 res);
FolderIndex(folderIndex), HRESULT CloseFile();
UnpackSize(0) HRESULT ProcessEmptyFiles();
{
if (fileIndex != kNumNoIndex) public:
{ MY_UNKNOWN_IMP1(ISequentialOutStream)
ExtractStatuses.ClearAndSetSize(1);
ExtractStatuses[0] = true; const CDbEx *_db;
} CMyComPtr<IArchiveExtractCallback> ExtractCallback;
};
bool ExtraWriteWasCut;
CFolderOutStream():
TestMode(false),
CheckCrc(true)
{}
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles);
HRESULT FlushCorrupted(Int32 callbackOperationResult);
bool WasWritingFinished() const { return _numFiles == 0; }
}; };
HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles)
{
_fileIndex = startIndex;
_indexes = indexes;
_numFiles = numFiles;
_fileIsOpen = false;
ExtraWriteWasCut = false;
return ProcessEmptyFiles();
}
HRESULT CFolderOutStream::OpenFile(bool isCorrupted)
{
const CFileItem &fi = _db->Files[_fileIndex];
UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex);
Int32 askMode = (_fileIndex == nextFileIndex) ?
(TestMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract) :
NExtract::NAskMode::kSkip;
if (isCorrupted
&& askMode == NExtract::NAskMode::kExtract
&& !_db->IsItemAnti(_fileIndex)
&& !fi.IsDir)
askMode = NExtract::NAskMode::kTest;
CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode));
_stream = realOutStream;
_crc = CRC_INIT_VAL;
_calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir);
_fileIsOpen = true;
_rem = fi.Size;
if (askMode == NExtract::NAskMode::kExtract
&& !realOutStream
&& !_db->IsItemAnti(_fileIndex)
&& !fi.IsDir)
askMode = NExtract::NAskMode::kSkip;
return ExtractCallback->PrepareOperation(askMode);
}
HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res)
{
_stream.Release();
_fileIsOpen = false;
if (!_indexes)
_numFiles--;
else if (*_indexes == _fileIndex)
{
_indexes++;
_numFiles--;
}
_fileIndex++;
return ExtractCallback->SetOperationResult(res);
}
HRESULT CFolderOutStream::CloseFile()
{
const CFileItem &fi = _db->Files[_fileIndex];
return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ?
NExtract::NOperationResult::kOK :
NExtract::NOperationResult::kCRCError);
}
HRESULT CFolderOutStream::ProcessEmptyFiles()
{
while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0)
{
RINOK(OpenFile());
RINOK(CloseFile());
}
return S_OK;
}
STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
while (size != 0)
{
if (_fileIsOpen)
{
UInt32 cur = (size < _rem ? size : (UInt32)_rem);
HRESULT result = S_OK;
if (_stream)
result = _stream->Write(data, cur, &cur);
if (_calcCrc)
_crc = CrcUpdate(_crc, data, cur);
if (processedSize)
*processedSize += cur;
data = (const Byte *)data + cur;
size -= cur;
_rem -= cur;
if (_rem == 0)
{
RINOK(CloseFile());
RINOK(ProcessEmptyFiles());
}
RINOK(result);
if (cur == 0)
break;
continue;
}
RINOK(ProcessEmptyFiles());
if (_numFiles == 0)
{
// we support partial extracting
/*
if (processedSize)
*processedSize += size;
break;
*/
ExtraWriteWasCut = true;
// return S_FALSE;
return k_My_HRESULT_WritingWasCut;
}
RINOK(OpenFile());
}
return S_OK;
}
HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult)
{
while (_numFiles != 0)
{
if (_fileIsOpen)
{
RINOK(CloseFile_and_SetResult(callbackOperationResult));
}
else
{
RINOK(OpenFile(true));
}
}
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
bool testMode = (testModeSpec != 0);
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
UInt64 importantTotalUnpacked = 0; UInt64 importantTotalUnpacked = 0;
// numItems = (UInt32)(Int32)-1;
bool allFilesMode = (numItems == (UInt32)(Int32)-1); bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode) if (allFilesMode)
numItems = numItems = _db.Files.Size();
#ifdef _7Z_VOL
_refs.Size();
#else
_db.Files.Size();
#endif
if(numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
/*
if(_volumes.Size() != 1)
return E_FAIL;
const CVolume &volume = _volumes.Front();
const CDbEx &_db = volume.Database;
IInStream *_inStream = volume.Stream;
*/
CObjectVector<CExtractFolderInfo> extractFolderInfoVector;
for (UInt32 ii = 0; ii < numItems; ii++)
{ {
// UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; CNum prevFolder = kNumNoIndex;
UInt32 ref2Index = allFilesMode ? ii : indices[ii]; UInt32 nextFile = 0;
// const CRef2 &ref2 = _refs[ref2Index];
UInt32 i;
// for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
for (i = 0; i < numItems; i++)
{ {
#ifdef _7Z_VOL UInt32 fileIndex = allFilesMode ? i : indices[i];
// const CRef &ref = ref2.Refs[ri]; CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
const CRef &ref = _refs[ref2Index];
int volumeIndex = ref.VolumeIndex;
const CVolume &volume = _volumes[volumeIndex];
const CDbEx &db = volume.Database;
UInt32 fileIndex = ref.ItemIndex;
#else
const CDbEx &db = _db;
UInt32 fileIndex = ref2Index;
#endif
CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex];
if (folderIndex == kNumNoIndex) if (folderIndex == kNumNoIndex)
{
extractFolderInfoVector.Add(CExtractFolderInfo(
#ifdef _7Z_VOL
volumeIndex,
#endif
fileIndex, kNumNoIndex));
continue; continue;
} if (folderIndex != prevFolder || fileIndex < nextFile)
if (extractFolderInfoVector.IsEmpty() || nextFile = _db.FolderStartFileIndex[folderIndex];
folderIndex != extractFolderInfoVector.Back().FolderIndex for (CNum index = nextFile; index <= fileIndex; index++)
#ifdef _7Z_VOL importantTotalUnpacked += _db.Files[index].Size;
|| volumeIndex != extractFolderInfoVector.Back().VolumeIndex nextFile = fileIndex + 1;
#endif prevFolder = folderIndex;
)
{
extractFolderInfoVector.Add(CExtractFolderInfo(
#ifdef _7Z_VOL
volumeIndex,
#endif
kNumNoIndex, folderIndex));
UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex);
importantTotalUnpacked += unpackSize;
extractFolderInfoVector.Back().UnpackSize = unpackSize;
}
CExtractFolderInfo &efi = extractFolderInfoVector.Back();
// const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
CNum startIndex = db.FolderStartFileIndex[folderIndex];
for (CNum index = efi.ExtractStatuses.Size();
index <= fileIndex - startIndex; index++)
{
// UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize;
// Count partial_folder_size
// efi.UnpackSize += unpackSize;
// importantTotalUnpacked += unpackSize;
efi.ExtractStatuses.Add(index == fileIndex - startIndex);
}
} }
} }
RINOK(extractCallback->SetTotal(importantTotalUnpacked)); RINOK(extractCallback->SetTotal(importantTotalUnpacked));
CDecoder decoder(
#ifdef _ST_MODE
false
#else
true
#endif
);
// CDecoder1 decoder;
UInt64 totalPacked = 0;
UInt64 totalUnpacked = 0;
UInt64 curPacked, curUnpacked;
CLocalProgress *lps = new CLocalProgress; CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps; CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false); lps->Init(extractCallback, false);
for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked) CDecoder decoder(
#if !defined(USE_MIXER_MT)
false
#elif !defined(USE_MIXER_ST)
true
#elif !defined(__7Z_SET_PROPERTIES)
#ifdef _7ZIP_ST
false
#else
true
#endif
#else
_useMultiThreadMixer
#endif
);
UInt64 curPacked, curUnpacked;
CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;
extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage);
CFolderOutStream *folderOutStream = new CFolderOutStream;
CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
folderOutStream->_db = &_db;
folderOutStream->ExtractCallback = extractCallback;
folderOutStream->TestMode = (testModeSpec != 0);
folderOutStream->CheckCrc = (_crcSize != 0);
for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked)
{ {
lps->OutSize = totalUnpacked;
lps->InSize = totalPacked;
RINOK(lps->SetCur()); RINOK(lps->SetCur());
if (i >= extractFolderInfoVector.Size()) if (i >= numItems)
break; break;
const CExtractFolderInfo &efi = extractFolderInfoVector[i]; curUnpacked = 0;
curUnpacked = efi.UnpackSize;
curPacked = 0; curPacked = 0;
CFolderOutStream *folderOutStream = new CFolderOutStream; UInt32 fileIndex = allFilesMode ? i : indices[i];
CMyComPtr<ISequentialOutStream> outStream(folderOutStream); CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
#ifdef _7Z_VOL UInt32 numSolidFiles = 1;
const CVolume &volume = _volumes[efi.VolumeIndex];
const CDbEx &db = volume.Database;
#else
const CDbEx &db = _db;
#endif
CNum startIndex; if (folderIndex != kNumNoIndex)
if (efi.FileIndex != kNumNoIndex) {
startIndex = efi.FileIndex; curPacked = _db.GetFolderFullPackSize(folderIndex);
else UInt32 nextFile = fileIndex + 1;
startIndex = db.FolderStartFileIndex[efi.FolderIndex]; fileIndex = _db.FolderStartFileIndex[folderIndex];
UInt32 k;
HRESULT result = folderOutStream->Init(&db, for (k = i + 1; k < numItems; k++)
#ifdef _7Z_VOL {
volume.StartRef2Index, UInt32 fileIndex2 = allFilesMode ? k : indices[k];
#else if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex
0, || fileIndex2 < nextFile)
#endif break;
startIndex, nextFile = fileIndex2 + 1;
&efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); }
numSolidFiles = k - i;
for (k = fileIndex; k < nextFile; k++)
curUnpacked += _db.Files[k].Size;
}
HRESULT result = folderOutStream->Init(fileIndex,
allFilesMode ? NULL : indices + i,
numSolidFiles);
i += numSolidFiles;
RINOK(result); RINOK(result);
if (efi.FileIndex != kNumNoIndex) // to test solid block with zero unpacked size we disable that code
if (folderOutStream->WasWritingFinished())
continue; continue;
CNum folderIndex = efi.FolderIndex;
curPacked = _db.GetFolderFullPackSize(folderIndex);
#ifndef _NO_CRYPTO #ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword; CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (extractCallback) if (extractCallback)
@@ -212,50 +342,64 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
#ifndef _NO_CRYPTO #ifndef _NO_CRYPTO
bool isEncrypted = false; bool isEncrypted = false;
bool passwordIsDefined = false; bool passwordIsDefined = false;
UString password;
#endif #endif
HRESULT result = decoder.Decode( HRESULT result = decoder.Decode(
EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS
#ifdef _7Z_VOL _inStream,
volume.Stream, _db.ArcInfo.DataStartPosition,
#else _db, folderIndex,
_inStream, &curUnpacked,
#endif
db.ArcInfo.DataStartPosition,
db, folderIndex,
outStream, outStream,
progress progress,
NULL // *inStreamMainRes
_7Z_DECODER_CRYPRO_VARS _7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST) && !defined(_SFX) #if !defined(_7ZIP_ST) && !defined(_SFX)
, true, _numThreads , true, _numThreads
#endif #endif
); );
if (result == S_FALSE) if (result == S_FALSE || result == E_NOTIMPL)
{ {
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); bool wasFinished = folderOutStream->WasWritingFinished();
continue;
} int resOp = (result == S_FALSE ?
if (result == E_NOTIMPL) NExtract::NOperationResult::kDataError :
{ NExtract::NOperationResult::kUnsupportedMethod);
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod));
RINOK(folderOutStream->FlushCorrupted(resOp));
if (wasFinished)
{
// we don't show error, if it's after required files
if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage)
{
RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp));
}
}
continue; continue;
} }
if (result != S_OK) if (result != S_OK)
return result; return result;
if (folderOutStream->WasWritingFinished() != S_OK)
{ RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); continue;
continue;
}
} }
catch(...) catch(...)
{ {
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
continue; // continue;
return E_FAIL;
} }
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END
} }

View File

@@ -7,96 +7,103 @@
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
CFolderInStream::CFolderInStream()
{
_inStreamWithHashSpec = new CSequentialInStreamWithCRC;
_inStreamWithHash = _inStreamWithHashSpec;
}
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
const UInt32 *fileIndices, UInt32 numFiles) const UInt32 *indexes, unsigned numFiles)
{ {
_updateCallback = updateCallback; _updateCallback = updateCallback;
_indexes = indexes;
_numFiles = numFiles; _numFiles = numFiles;
_fileIndex = 0; _index = 0;
_fileIndices = fileIndices;
Processed.Clear(); Processed.ClearAndReserve(numFiles);
CRCs.Clear(); CRCs.ClearAndReserve(numFiles);
Sizes.Clear(); Sizes.ClearAndReserve(numFiles);
_fileIsOpen = false;
_currentSizeIsDefined = false; _pos = 0;
_crc = CRC_INIT_VAL;
_size_Defined = false;
_size = 0;
_stream.Release();
} }
HRESULT CFolderInStream::OpenStream() HRESULT CFolderInStream::OpenStream()
{ {
_filePos = 0; _pos = 0;
while (_fileIndex < _numFiles) _crc = CRC_INIT_VAL;
_size_Defined = false;
_size = 0;
while (_index < _numFiles)
{ {
CMyComPtr<ISequentialInStream> stream; CMyComPtr<ISequentialInStream> stream;
HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);
if (result != S_OK && result != S_FALSE) if (result != S_OK)
return result; {
_fileIndex++; if (result != S_FALSE)
_inStreamWithHashSpec->SetStream(stream); return result;
_inStreamWithHashSpec->Init(); }
_stream = stream;
if (stream) if (stream)
{ {
_fileIsOpen = true;
CMyComPtr<IStreamGetSize> streamGetSize; CMyComPtr<IStreamGetSize> streamGetSize;
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
if (streamGetSize) if (streamGetSize)
{ {
RINOK(streamGetSize->GetSize(&_currentSize)); if (streamGetSize->GetSize(&_size) == S_OK)
_currentSizeIsDefined = true; _size_Defined = true;
} }
return S_OK; return S_OK;
} }
_index++;
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
Sizes.Add(0); AddFileInfo(result == S_OK);
Processed.Add(result == S_OK);
AddDigest();
} }
return S_OK; return S_OK;
} }
void CFolderInStream::AddDigest() void CFolderInStream::AddFileInfo(bool isProcessed)
{ {
CRCs.Add(_inStreamWithHashSpec->GetCRC()); Processed.Add(isProcessed);
} Sizes.Add(_pos);
CRCs.Add(CRC_GET_DIGEST(_crc));
HRESULT CFolderInStream::CloseStream()
{
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
_inStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
_currentSizeIsDefined = false;
Processed.Add(true);
Sizes.Add(_filePos);
AddDigest();
return S_OK;
} }
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{ {
if (processedSize != 0) if (processedSize)
*processedSize = 0; *processedSize = 0;
while (size > 0) while (size != 0)
{ {
if (_fileIsOpen) if (_stream)
{ {
UInt32 processed2; UInt32 processed2;
RINOK(_inStreamWithHash->Read(data, size, &processed2)); RINOK(_stream->Read(data, size, &processed2));
if (processed2 == 0) if (processed2 != 0)
{ {
RINOK(CloseStream()); _crc = CrcUpdate(_crc, data, processed2);
continue; _pos += processed2;
if (processedSize)
*processedSize = processed2;
return S_OK;
} }
if (processedSize != 0)
*processedSize = processed2; _stream.Release();
_filePos += processed2; _index++;
break; AddFileInfo(true);
_pos = 0;
_crc = CRC_INIT_VAL;
_size_Defined = false;
_size = 0;
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
} }
if (_fileIndex >= _numFiles)
if (_index >= _numFiles)
break; break;
RINOK(OpenStream()); RINOK(OpenStream());
} }
@@ -106,17 +113,23 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{ {
*value = 0; *value = 0;
unsigned index2 = (unsigned)subStream;
if (subStream > Sizes.Size()) if (subStream > Sizes.Size())
return E_FAIL; return S_FALSE; // E_FAIL;
if (index2 < Sizes.Size())
unsigned index = (unsigned)subStream;
if (index < Sizes.Size())
{ {
*value = Sizes[index2]; *value = Sizes[index];
return S_OK; return S_OK;
} }
if (!_currentSizeIsDefined)
if (!_size_Defined)
{
*value = _pos;
return S_FALSE; return S_FALSE;
*value = _currentSize; }
*value = (_pos > _size ? _pos : _size);
return S_OK; return S_OK;
} }

View File

@@ -3,11 +3,13 @@
#ifndef __7Z_FOLDER_IN_STREAM_H #ifndef __7Z_FOLDER_IN_STREAM_H
#define __7Z_FOLDER_IN_STREAM_H #define __7Z_FOLDER_IN_STREAM_H
#include "../../../../C/7zCrc.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/MyVector.h"
#include "../../ICoder.h" #include "../../ICoder.h"
#include "../IArchive.h" #include "../IArchive.h"
#include "../Common/InStreamWithCRC.h"
#include "7zItem.h"
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
@@ -17,33 +19,34 @@ class CFolderInStream:
public ICompressGetSubStreamSize, public ICompressGetSubStreamSize,
public CMyUnknownImp public CMyUnknownImp
{ {
CSequentialInStreamWithCRC *_inStreamWithHashSpec; CMyComPtr<ISequentialInStream> _stream;
CMyComPtr<ISequentialInStream> _inStreamWithHash; UInt64 _pos;
UInt32 _crc;
bool _size_Defined;
UInt64 _size;
const UInt32 *_indexes;
unsigned _numFiles;
unsigned _index;
CMyComPtr<IArchiveUpdateCallback> _updateCallback; CMyComPtr<IArchiveUpdateCallback> _updateCallback;
bool _currentSizeIsDefined;
bool _fileIsOpen;
UInt64 _currentSize;
UInt64 _filePos;
const UInt32 *_fileIndices;
UInt32 _numFiles;
UInt32 _fileIndex;
HRESULT OpenStream(); HRESULT OpenStream();
HRESULT CloseStream(); void AddFileInfo(bool isProcessed);
void AddDigest();
public: public:
CRecordVector<bool> Processed; CRecordVector<bool> Processed;
CRecordVector<UInt32> CRCs; CRecordVector<UInt32> CRCs;
CRecordVector<UInt64> Sizes; CRecordVector<UInt64> Sizes;
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
CFolderInStream(); void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);
bool WasFinished() const { return _index == _numFiles; }
UInt64 GetFullSize() const UInt64 GetFullSize() const
{ {
UInt64 size = 0; UInt64 size = 0;

View File

@@ -1,149 +0,0 @@
// 7zFolderOutStream.cpp
#include "StdAfx.h"
#include "7zFolderOutStream.h"
namespace NArchive {
namespace N7z {
CFolderOutStream::CFolderOutStream()
{
_crcStreamSpec = new COutStreamWithCRC;
_crcStream = _crcStreamSpec;
}
HRESULT CFolderOutStream::Init(
const CDbEx *db,
UInt32 ref2Offset, UInt32 startIndex,
const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback,
bool testMode, bool checkCrc)
{
_db = db;
_ref2Offset = ref2Offset;
_startIndex = startIndex;
_extractStatuses = extractStatuses;
_extractCallback = extractCallback;
_testMode = testMode;
_checkCrc = checkCrc;
_currentIndex = 0;
_fileIsOpen = false;
return ProcessEmptyFiles();
}
HRESULT CFolderOutStream::OpenFile()
{
Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract) :
NExtract::NAskMode::kSkip;
CMyComPtr<ISequentialOutStream> realOutStream;
UInt32 index = _startIndex + _currentIndex;
RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
_crcStreamSpec->SetStream(realOutStream);
_crcStreamSpec->Init(_checkCrc);
_fileIsOpen = true;
const CFileItem &fi = _db->Files[index];
_rem = fi.Size;
if (askMode == NExtract::NAskMode::kExtract && !realOutStream &&
!_db->IsItemAnti(index) && !fi.IsDir)
askMode = NExtract::NAskMode::kSkip;
return _extractCallback->PrepareOperation(askMode);
}
HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)
{
_crcStreamSpec->ReleaseStream();
_fileIsOpen = false;
_currentIndex++;
return _extractCallback->SetOperationResult(res);
}
HRESULT CFolderOutStream::CloseFileAndSetResult()
{
const CFileItem &fi = _db->Files[_startIndex + _currentIndex];
return CloseFileAndSetResult(
(fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?
NExtract::NOperationResult::kOK :
NExtract::NOperationResult::kCRCError);
}
HRESULT CFolderOutStream::ProcessEmptyFiles()
{
while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
{
RINOK(OpenFile());
RINOK(CloseFileAndSetResult());
}
return S_OK;
}
STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize != NULL)
*processedSize = 0;
while (size != 0)
{
if (_fileIsOpen)
{
UInt32 cur = size < _rem ? size : (UInt32)_rem;
RINOK(_crcStream->Write(data, cur, &cur));
if (cur == 0)
break;
data = (const Byte *)data + cur;
size -= cur;
_rem -= cur;
if (processedSize != NULL)
*processedSize += cur;
if (_rem == 0)
{
RINOK(CloseFileAndSetResult());
RINOK(ProcessEmptyFiles());
continue;
}
}
else
{
RINOK(ProcessEmptyFiles());
if (_currentIndex == _extractStatuses->Size())
{
// we support partial extracting
if (processedSize != NULL)
*processedSize += size;
break;
}
RINOK(OpenFile());
}
}
return S_OK;
}
STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{
*value = 0;
if ((int)subStream >= _extractStatuses->Size())
return S_FALSE;
*value = _db->Files[_startIndex + (int)subStream].Size;
return S_OK;
}
HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
{
while (_currentIndex < _extractStatuses->Size())
{
if (_fileIsOpen)
{
RINOK(CloseFileAndSetResult(resultEOperationResult));
}
else
{
RINOK(OpenFile());
}
}
return S_OK;
}
}}

View File

@@ -1,58 +0,0 @@
// 7zFolderOutStream.h
#ifndef __7Z_FOLDER_OUT_STREAM_H
#define __7Z_FOLDER_OUT_STREAM_H
#include "../../IStream.h"
#include "../IArchive.h"
#include "../Common/OutStreamWithCRC.h"
#include "7zIn.h"
namespace NArchive {
namespace N7z {
class CFolderOutStream:
public ISequentialOutStream,
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
COutStreamWithCRC *_crcStreamSpec;
CMyComPtr<ISequentialOutStream> _crcStream;
const CDbEx *_db;
const CBoolVector *_extractStatuses;
CMyComPtr<IArchiveExtractCallback> _extractCallback;
UInt32 _ref2Offset;
UInt32 _startIndex;
unsigned _currentIndex;
bool _testMode;
bool _checkCrc;
bool _fileIsOpen;
UInt64 _rem;
HRESULT OpenFile();
HRESULT CloseFileAndSetResult(Int32 res);
HRESULT CloseFileAndSetResult();
HRESULT ProcessEmptyFiles();
public:
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
CFolderOutStream();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
HRESULT Init(
const CDbEx *db,
UInt32 ref2Offset, UInt32 startIndex,
const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback,
bool testMode, bool checkCrc);
HRESULT FlushCorrupted(Int32 resultEOperationResult);
HRESULT WasWritingFinished() const
{ return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
};
}}
#endif

View File

@@ -36,10 +36,14 @@ CHandler::CHandler()
#endif #endif
#ifdef EXTRACT_ONLY #ifdef EXTRACT_ONLY
_crcSize = 4; _crcSize = 4;
#ifdef __7Z_SET_PROPERTIES #ifdef __7Z_SET_PROPERTIES
_numThreads = NSystem::GetNumberOfProcessors(); _numThreads = NSystem::GetNumberOfProcessors();
_useMultiThreadMixer = true;
#endif #endif
#endif #endif
} }
@@ -150,22 +154,12 @@ static char *AddProp32(char *s, const char *name, UInt32 v)
void CHandler::AddMethodName(AString &s, UInt64 id) void CHandler::AddMethodName(AString &s, UInt64 id)
{ {
UString methodName; AString name;
FindMethod(EXTERNAL_CODECS_VARS id, methodName); FindMethod(EXTERNAL_CODECS_VARS id, name);
if (methodName.IsEmpty()) if (name.IsEmpty())
{
for (unsigned i = 0; i < methodName.Len(); i++)
if (methodName[i] >= 0x80)
{
methodName.Empty();
break;
}
}
if (methodName.IsEmpty())
ConvertMethodIdToString(s, id); ConvertMethodIdToString(s, id);
else else
for (unsigned i = 0; i < methodName.Len(); i++) s += name;
s += (char)methodName[i];
} }
#endif #endif
@@ -186,8 +180,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
FOR_VECTOR (i, pm.IDs) FOR_VECTOR (i, pm.IDs)
{ {
UInt64 id = pm.IDs[i]; UInt64 id = pm.IDs[i];
if (!s.IsEmpty()) s.Add_Space_if_NotEmpty();
s += ' ';
char temp[16]; char temp[16];
if (id == k_LZMA2) if (id == k_LZMA2)
{ {
@@ -321,13 +314,13 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
if (/* _db.IsTree && propID == kpidName || if (/* _db.IsTree && propID == kpidName ||
!_db.IsTree && */ propID == kpidPath) !_db.IsTree && */ propID == kpidPath)
{ {
const wchar_t *name = _db.GetName(index); if (_db.NameOffsets && _db.NamesBuf)
if (name)
{ {
size_t size = (_db.NameOffsets[index + 1] - _db.NameOffsets[index]) * 2; size_t offset = _db.NameOffsets[index];
size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
if (size < ((UInt32)1 << 31)) if (size < ((UInt32)1 << 31))
{ {
*data = (void *)name; *data = (const void *)(_db.NamesBuf + offset * 2);
*dataSize = (UInt32)size; *dataSize = (UInt32)size;
*propType = NPropDataType::kUtf16z; *propType = NPropDataType::kUtf16z;
} }
@@ -376,6 +369,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
// numCoders == 0 ??? // numCoders == 0 ???
CNum numCoders = inByte.ReadNum(); CNum numCoders = inByte.ReadNum();
bool needSpace = false; bool needSpace = false;
for (; numCoders != 0; numCoders--, needSpace = true) for (; numCoders != 0; numCoders--, needSpace = true)
{ {
if (pos < 32) // max size of property if (pos < 32) // max size of property
@@ -500,17 +494,8 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
} }
else else
{ {
UString methodName; AString methodName;
FindMethod(EXTERNAL_CODECS_VARS id64, methodName); FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
if (methodName.IsEmpty())
{
for (unsigned j = 0; j < methodName.Len(); j++)
if (methodName[j] >= 0x80)
{
methodName.Empty();
break;
}
}
if (needSpace) if (needSpace)
temp[--pos] = ' '; temp[--pos] = ' ';
if (methodName.IsEmpty()) if (methodName.IsEmpty())
@@ -522,10 +507,11 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
break; break;
pos -= len; pos -= len;
for (unsigned i = 0; i < len; i++) for (unsigned i = 0; i < len; i++)
temp[pos + i] = (char)methodName[i]; temp[pos + i] = methodName[i];
} }
} }
} }
if (numCoders != 0 && pos >= 4) if (numCoders != 0 && pos >= 4)
{ {
temp[--pos] = ' '; temp[--pos] = ' ';
@@ -533,6 +519,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
temp[--pos] = '.'; temp[--pos] = '.';
temp[--pos] = '.'; temp[--pos] = '.';
} }
return PropVarEm_Set_Str(prop, temp + pos); return PropVarEm_Set_Str(prop, temp + pos);
// } // }
} }
@@ -555,7 +542,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CFileItem &item = _db.Files[index]; const CFileItem &item = _db.Files[index];
UInt32 index2 = index; UInt32 index2 = index;
switch(propID) switch (propID)
{ {
case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break; case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
case kpidSize: case kpidSize:
@@ -607,8 +594,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
} }
*/ */
case kpidPath: return _db.GetPath(index, value); case kpidPath: return _db.GetPath_Prop(index, value);
#ifndef _SFX #ifndef _SFX
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value); case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
case kpidBlock: case kpidBlock:
{ {
@@ -617,30 +606,29 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
PropVarEm_Set_UInt32(value, (UInt32)folderIndex); PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
} }
break; break;
/*
case kpidPackedSize0: case kpidPackedSize0:
case kpidPackedSize1: case kpidPackedSize1:
case kpidPackedSize2: case kpidPackedSize2:
case kpidPackedSize3: case kpidPackedSize3:
case kpidPackedSize4: case kpidPackedSize4:
{ {
/*
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex) if (folderIndex != kNumNoIndex)
{ {
const CFolder &folderInfo = _db.Folders[folderIndex];
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) _db.FoStartPackStreamIndex[folderIndex + 1] -
_db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
{ {
prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
} }
else
prop = (UInt64)0;
} }
else else
prop = (UInt64)0; PropVarEm_Set_UInt64(value, 0);
*/
} }
break; break;
*/
#endif #endif
} }
// prop.Detach(value); // prop.Detach(value);
@@ -668,7 +656,13 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif #endif
CInArchive archive; CInArchive archive(
#ifdef __7Z_SET_PROPERTIES
_useMultiThreadMixer
#else
true
#endif
);
_db.IsArc = false; _db.IsArc = false;
RINOK(archive.Open(stream, maxCheckStartPosition)); RINOK(archive.Open(stream, maxCheckStartPosition));
_db.IsArc = true; _db.IsArc = true;
@@ -677,7 +671,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS
_db _db
#ifndef _NO_CRYPTO #ifndef _NO_CRYPTO
, getTextPassword, _isEncrypted, _passwordIsDefined , getTextPassword, _isEncrypted, _passwordIsDefined, _password
#endif #endif
); );
RINOK(result); RINOK(result);
@@ -688,8 +682,9 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
{ {
Close(); Close();
// return E_INVALIDARG; // return E_INVALIDARG;
// return S_FALSE;
// we must return out_of_memory here // we must return out_of_memory here
return S_FALSE; return E_OUTOFMEMORY;
} }
// _inStream = stream; // _inStream = stream;
#ifndef _SFX #ifndef _SFX
@@ -707,6 +702,7 @@ STDMETHODIMP CHandler::Close()
#ifndef _NO_CRYPTO #ifndef _NO_CRYPTO
_isEncrypted = false; _isEncrypted = false;
_passwordIsDefined = false; _passwordIsDefined = false;
_password.Empty();
#endif #endif
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END
@@ -715,11 +711,12 @@ STDMETHODIMP CHandler::Close()
#ifdef __7Z_SET_PROPERTIES #ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY #ifdef EXTRACT_ONLY
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
_numThreads = numProcessors; _numThreads = numProcessors;
_useMultiThreadMixer = true;
for (UInt32 i = 0; i < numProps; i++) for (UInt32 i = 0; i < numProps; i++)
{ {
@@ -729,10 +726,15 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
return E_INVALIDARG; return E_INVALIDARG;
const PROPVARIANT &value = values[i]; const PROPVARIANT &value = values[i];
UInt32 number; UInt32 number;
int index = ParseStringToUInt32(name, number); unsigned index = ParseStringToUInt32(name, number);
if (index == 0) if (index == 0)
{ {
if (name.IsPrefixedBy(L"mt")) if (name.IsEqualTo("mtf"))
{
RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
continue;
}
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{ {
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads)); RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
continue; continue;

View File

@@ -18,24 +18,14 @@
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
const UInt32 k_Copy = 0x0;
const UInt32 k_Delta = 3;
const UInt32 k_LZMA2 = 0x21;
const UInt32 k_LZMA = 0x030101;
const UInt32 k_PPMD = 0x030401;
const UInt32 k_BCJ = 0x03030103;
const UInt32 k_BCJ2 = 0x0303011B;
const UInt32 k_Deflate = 0x040108;
const UInt32 k_BZip2 = 0x040202;
#ifndef __7Z_SET_PROPERTIES #ifndef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY #ifdef EXTRACT_ONLY
#if !defined(_7ZIP_ST) && !defined(_SFX) #if !defined(_7ZIP_ST) && !defined(_SFX)
#define __7Z_SET_PROPERTIES #define __7Z_SET_PROPERTIES
#endif #endif
#else #else
#define __7Z_SET_PROPERTIES #define __7Z_SET_PROPERTIES
#endif #endif
#endif #endif
@@ -54,6 +44,7 @@ public:
UInt64 _numSolidBytes; UInt64 _numSolidBytes;
bool _numSolidBytesDefined; bool _numSolidBytesDefined;
bool _solidExtension; bool _solidExtension;
bool _useTypeSorting;
bool _compressHeaders; bool _compressHeaders;
bool _encryptHeadersSpecified; bool _encryptHeadersSpecified;
@@ -64,7 +55,9 @@ public:
CBoolPair Write_ATime; CBoolPair Write_ATime;
CBoolPair Write_MTime; CBoolPair Write_MTime;
bool _volumeMode; bool _useMultiThreadMixer;
// bool _volumeMode;
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
@@ -102,7 +95,7 @@ class CHandler:
{ {
public: public:
MY_QUERYINTERFACE_BEGIN2(IInArchive) MY_QUERYINTERFACE_BEGIN2(IInArchive)
// MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
#ifdef __7Z_SET_PROPERTIES #ifdef __7Z_SET_PROPERTIES
MY_QUERYINTERFACE_ENTRY(ISetProperties) MY_QUERYINTERFACE_ENTRY(ISetProperties)
#endif #endif
@@ -117,7 +110,7 @@ public:
INTERFACE_IArchiveGetRawProps(;) INTERFACE_IArchiveGetRawProps(;)
#ifdef __7Z_SET_PROPERTIES #ifdef __7Z_SET_PROPERTIES
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif #endif
#ifndef EXTRACT_ONLY #ifndef EXTRACT_ONLY
@@ -131,28 +124,29 @@ public:
private: private:
CMyComPtr<IInStream> _inStream; CMyComPtr<IInStream> _inStream;
NArchive::N7z::CDbEx _db; NArchive::N7z::CDbEx _db;
#ifndef _NO_CRYPTO #ifndef _NO_CRYPTO
bool _isEncrypted; bool _isEncrypted;
bool _passwordIsDefined; bool _passwordIsDefined;
UString _password;
#endif #endif
#ifdef EXTRACT_ONLY #ifdef EXTRACT_ONLY
#ifdef __7Z_SET_PROPERTIES #ifdef __7Z_SET_PROPERTIES
UInt32 _numThreads; UInt32 _numThreads;
bool _useMultiThreadMixer;
#endif #endif
UInt32 _crcSize; UInt32 _crcSize;
#else #else
CRecordVector<CBind> _binds; CRecordVector<CBond2> _bonds;
HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m); HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod); HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
void AddDefaultMethod(); HRESULT SetMainMethod(CCompressionMethodMode &method
HRESULT SetMainMethod(CCompressionMethodMode &method,
CObjectVector<COneMethodInfo> &methodsInfo
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
, UInt32 numThreads , UInt32 numThreads
#endif #endif

View File

@@ -18,11 +18,11 @@ using namespace NWindows;
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
static const wchar_t *k_LZMA_Name = L"LZMA"; static const char *k_LZMA_Name = "LZMA";
static const wchar_t *kDefaultMethodName = L"LZMA2"; static const char *kDefaultMethodName = "LZMA2";
static const wchar_t *k_Copy_Name = L"Copy"; static const char *k_Copy_Name = "Copy";
static const wchar_t *k_MatchFinder_ForHeaders = L"BT2"; static const char *k_MatchFinder_ForHeaders = "BT2";
static const UInt32 k_NumFastBytes_ForHeaders = 273; static const UInt32 k_NumFastBytes_ForHeaders = 273;
static const UInt32 k_Level_ForHeaders = 5; static const UInt32 k_Level_ForHeaders = 5;
static const UInt32 k_Dictionary_ForHeaders = static const UInt32 k_Dictionary_ForHeaders =
@@ -42,7 +42,7 @@ HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodI
{ {
if (!FindMethod( if (!FindMethod(
EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS
m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams)) m.MethodName, dest.Id, dest.NumStreams))
return E_INVALIDARG; return E_INVALIDARG;
(CProps &)dest = (CProps &)m; (CProps &)dest = (CProps &)m;
return S_OK; return S_OK;
@@ -54,48 +54,62 @@ HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
return S_OK; return S_OK;
COneMethodInfo m; COneMethodInfo m;
m.MethodName = k_LZMA_Name; m.MethodName = k_LZMA_Name;
m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders); m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders); m.AddProp_Level(k_Level_ForHeaders);
m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders); m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);
m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders); m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);
m.AddNumThreadsProp(1); m.AddProp_NumThreads(1);
CMethodFull methodFull; CMethodFull &methodFull = headerMethod.Methods.AddNew();
RINOK(PropsMethod_To_FullMethod(methodFull, m)); return PropsMethod_To_FullMethod(methodFull, m);
headerMethod.Methods.Add(methodFull);
return S_OK;
}
void CHandler::AddDefaultMethod()
{
FOR_VECTOR (i, _methods)
{
UString &methodName = _methods[i].MethodName;
if (methodName.IsEmpty())
methodName = kDefaultMethodName;
}
if (_methods.IsEmpty())
{
COneMethodInfo m;
m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
_methods.Add(m);
}
} }
HRESULT CHandler::SetMainMethod( HRESULT CHandler::SetMainMethod(
CCompressionMethodMode &methodMode, CCompressionMethodMode &methodMode
CObjectVector<COneMethodInfo> &methods
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
, UInt32 numThreads , UInt32 numThreads
#endif #endif
) )
{ {
AddDefaultMethod(); methodMode.Bonds = _bonds;
CObjectVector<COneMethodInfo> methods = _methods;
{
FOR_VECTOR (i, methods)
{
AString &methodName = methods[i].MethodName;
if (methodName.IsEmpty())
methodName = kDefaultMethodName;
}
if (methods.IsEmpty())
{
COneMethodInfo &m = methods.AddNew();
m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
methodMode.DefaultMethod_was_Inserted = true;
}
}
if (!_filterMethod.MethodName.IsEmpty())
{
// if (methodMode.Bonds.IsEmpty())
{
FOR_VECTOR (k, methodMode.Bonds)
{
CBond2 &bond = methodMode.Bonds[k];
bond.InCoder++;
bond.OutCoder++;
}
methods.Insert(0, _filterMethod);
methodMode.Filter_was_Inserted = true;
}
}
const UInt64 kSolidBytes_Min = (1 << 24); const UInt64 kSolidBytes_Min = (1 << 24);
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1; const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;
bool needSolid = false; bool needSolid = false;
FOR_VECTOR (i, methods) FOR_VECTOR (i, methods)
{ {
COneMethodInfo &oneMethodInfo = methods[i]; COneMethodInfo &oneMethodInfo = methods[i];
@@ -105,9 +119,8 @@ HRESULT CHandler::SetMainMethod(
#endif #endif
); );
CMethodFull methodFull; CMethodFull &methodFull = methodMode.Methods.AddNew();
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)); RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
methodMode.Methods.Add(methodFull);
if (methodFull.Id != k_Copy) if (methodFull.Id != k_Copy)
needSolid = true; needSolid = true;
@@ -125,6 +138,7 @@ HRESULT CHandler::SetMainMethod(
case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
default: continue; default: continue;
} }
_numSolidBytes = (UInt64)dicSize << 7; _numSolidBytes = (UInt64)dicSize << 7;
if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min; if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max; if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
@@ -268,7 +282,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
bool need_CTime = (Write_CTime.Def && Write_CTime.Val); bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
bool need_ATime = (Write_ATime.Def && Write_ATime.Val); bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def); bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
if (db)
if (db && !db->Files.IsEmpty())
{ {
if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
@@ -301,10 +316,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
const CFileItem &fi = db->Files[ui.IndexInArchive]; const CFileItem &fi = db->Files[ui.IndexInArchive];
if (!ui.NewProps) if (!ui.NewProps)
{ {
NCOM::CPropVariant prop; _db.GetPath(ui.IndexInArchive, name);
RINOK(_db.GetPath(ui.IndexInArchive, &prop));
if (prop.vt == VT_BSTR)
name = prop.bstrVal;
} }
ui.IsDir = fi.IsDir; ui.IsDir = fi.IsDir;
ui.Size = fi.Size; ui.Size = fi.Size;
@@ -497,14 +509,19 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.NewData) if (ui.NewData)
{ {
NCOM::CPropVariant prop; ui.Size = 0;
RINOK(updateCallback->GetProperty(i, kpidSize, &prop)); if (!ui.IsDir)
if (prop.vt != VT_UI8) {
return E_INVALIDARG; NCOM::CPropVariant prop;
ui.Size = (UInt64)prop.uhVal.QuadPart; RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
if (ui.Size != 0 && ui.IsAnti) if (prop.vt != VT_UI8)
return E_INVALIDARG; return E_INVALIDARG;
ui.Size = (UInt64)prop.uhVal.QuadPart;
if (ui.Size != 0 && ui.IsAnti)
return E_INVALIDARG;
}
} }
updateItems.Add(ui); updateItems.Add(ui);
} }
@@ -520,18 +537,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CCompressionMethodMode methodMode, headerMethod; CCompressionMethodMode methodMode, headerMethod;
HRESULT res = SetMainMethod(methodMode, _methods HRESULT res = SetMainMethod(methodMode
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
, _numThreads , _numThreads
#endif #endif
); );
RINOK(res); RINOK(res);
methodMode.Binds = _binds;
RINOK(SetHeaderMethod(headerMethod)); RINOK(SetHeaderMethod(headerMethod));
#ifndef _7ZIP_ST #ifndef _7ZIP_ST
methodMode.NumThreads = _numThreads; methodMode.NumThreads = _numThreads;
methodMode.MultiThreadMixer = _useMultiThreadMixer;
headerMethod.NumThreads = 1; headerMethod.NumThreads = 1;
headerMethod.MultiThreadMixer = _useMultiThreadMixer;
#endif #endif
CMyComPtr<ICryptoGetTextPassword2> getPassword2; CMyComPtr<ICryptoGetTextPassword2> getPassword2;
@@ -545,7 +564,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
Int32 passwordIsDefined; Int32 passwordIsDefined;
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)); RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
if (methodMode.PasswordIsDefined && (BSTR)password) if (methodMode.PasswordIsDefined && password)
methodMode.Password = password; methodMode.Password = password;
} }
@@ -553,6 +572,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
bool encryptHeaders = false; bool encryptHeaders = false;
#ifndef _NO_CRYPTO
if (!methodMode.PasswordIsDefined && _passwordIsDefined)
{
// if header is compressed, we use that password for updated archive
methodMode.PasswordIsDefined = true;
methodMode.Password = _password;
}
#endif
if (methodMode.PasswordIsDefined) if (methodMode.PasswordIsDefined)
{ {
if (_encryptHeadersSpecified) if (_encryptHeadersSpecified)
@@ -572,12 +600,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (numItems < 2) if (numItems < 2)
compressMainHeader = false; compressMainHeader = false;
int level = GetLevel();
CUpdateOptions options; CUpdateOptions options;
options.Method = &methodMode; options.Method = &methodMode;
options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL;
int level = GetLevel(); options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted);
options.UseFilters = level != 0 && _autoFilter; options.MaxFilter = (level >= 8);
options.MaxFilter = level >= 8; options.AnalysisLevel = GetAnalysisLevel();
options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.CompressMainHeader = compressMainHeader;
/* /*
@@ -589,8 +619,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.NumSolidFiles = _numSolidFiles; options.NumSolidFiles = _numSolidFiles;
options.NumSolidBytes = _numSolidBytes; options.NumSolidBytes = _numSolidBytes;
options.SolidExtension = _solidExtension; options.SolidExtension = _solidExtension;
options.UseTypeSorting = _useTypeSorting;
options.RemoveSfxBlock = _removeSfxBlock; options.RemoveSfxBlock = _removeSfxBlock;
options.VolumeMode = _volumeMode; // options.VolumeMode = _volumeMode;
options.MultiThreadMixer = _useMultiThreadMixer;
COutArchive archive; COutArchive archive;
CArchiveDatabaseOut newDatabase; CArchiveDatabaseOut newDatabase;
@@ -638,20 +672,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END COM_TRY_END
} }
static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
{ {
stream = 0; stream = 0;
int index = ParseStringToUInt32(srcString, coder); int index = ParseStringToUInt32(srcString, coder);
if (index == 0) if (index == 0)
return E_INVALIDARG; return E_INVALIDARG;
srcString.Delete(0, index); srcString.DeleteFrontal(index);
if (srcString[0] == 's') if (srcString[0] == 's')
{ {
srcString.Delete(0); srcString.Delete(0);
int index = ParseStringToUInt32(srcString, stream); int index = ParseStringToUInt32(srcString, stream);
if (index == 0) if (index == 0)
return E_INVALIDARG; return E_INVALIDARG;
srcString.Delete(0, index); srcString.DeleteFrontal(index);
} }
return S_OK; return S_OK;
} }
@@ -670,8 +704,12 @@ void COutHandler::InitProps()
Write_ATime.Init(); Write_ATime.Init();
Write_MTime.Init(); Write_MTime.Init();
_volumeMode = false; _useMultiThreadMixer = true;
// _volumeMode = false;
InitSolid(); InitSolid();
_useTypeSorting = false;
} }
HRESULT COutHandler::SetSolidFromString(const UString &s) HRESULT COutHandler::SetSolidFromString(const UString &s)
@@ -765,7 +803,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
UInt32 number; UInt32 number;
int index = ParseStringToUInt32(name, number); int index = ParseStringToUInt32(name, number);
UString realName = name.Ptr(index); // UString realName = name.Ptr(index);
if (index == 0) if (index == 0)
{ {
if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock); if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
@@ -790,15 +828,19 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime); if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime); if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
// if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
} }
return CMultiMethodProps::SetProperty(name, value); return CMultiMethodProps::SetProperty(name, value);
} }
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{ {
COM_TRY_BEGIN COM_TRY_BEGIN
_binds.Clear(); _bonds.Clear();
InitProps(); InitProps();
for (UInt32 i = 0; i < numProps; i++) for (UInt32 i = 0; i < numProps; i++)
@@ -815,15 +857,19 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (value.vt != VT_EMPTY) if (value.vt != VT_EMPTY)
return E_INVALIDARG; return E_INVALIDARG;
name.Delete(0); name.Delete(0);
CBind bind;
RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream)); CBond2 bond;
RINOK(ParseBond(name, bond.OutCoder, bond.OutStream));
if (name[0] != ':') if (name[0] != ':')
return E_INVALIDARG; return E_INVALIDARG;
name.Delete(0); name.Delete(0);
RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream)); UInt32 inStream = 0;
RINOK(ParseBond(name, bond.InCoder, inStream));
if (inStream != 0)
return E_INVALIDARG;
if (!name.IsEmpty()) if (!name.IsEmpty())
return E_INVALIDARG; return E_INVALIDARG;
_binds.Add(bind); _bonds.Add(bond);
continue; continue;
} }
@@ -834,40 +880,27 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (numEmptyMethods > 0) if (numEmptyMethods > 0)
{ {
unsigned k; unsigned k;
for (k = 0; k < _binds.Size(); k++) for (k = 0; k < _bonds.Size(); k++)
{ {
const CBind &bind = _binds[k]; const CBond2 &bond = _bonds[k];
if (bind.InCoder < (UInt32)numEmptyMethods || if (bond.InCoder < (UInt32)numEmptyMethods ||
bind.OutCoder < (UInt32)numEmptyMethods) bond.OutCoder < (UInt32)numEmptyMethods)
return E_INVALIDARG; return E_INVALIDARG;
} }
for (k = 0; k < _binds.Size(); k++) for (k = 0; k < _bonds.Size(); k++)
{ {
CBind &bind = _binds[k]; CBond2 &bond = _bonds[k];
bind.InCoder -= (UInt32)numEmptyMethods; bond.InCoder -= (UInt32)numEmptyMethods;
bind.OutCoder -= (UInt32)numEmptyMethods; bond.OutCoder -= (UInt32)numEmptyMethods;
} }
_methods.DeleteFrontal(numEmptyMethods); _methods.DeleteFrontal(numEmptyMethods);
} }
AddDefaultMethod(); FOR_VECTOR (k, _bonds)
if (!_filterMethod.MethodName.IsEmpty())
{ {
FOR_VECTOR (k, _binds) const CBond2 &bond = _bonds[k];
{ if (bond.InCoder >= (UInt32)_methods.Size() ||
CBind &bind = _binds[k]; bond.OutCoder >= (UInt32)_methods.Size())
bind.InCoder++;
bind.OutCoder++;
}
_methods.Insert(0, _filterMethod);
}
FOR_VECTOR (k, _binds)
{
const CBind &bind = _binds[k];
if (bind.InCoder >= (UInt32)_methods.Size() ||
bind.OutCoder >= (UInt32)_methods.Size())
return E_INVALIDARG; return E_INVALIDARG;
} }

View File

@@ -96,6 +96,53 @@ namespace NID
}; };
} }
const UInt32 k_Copy = 0;
const UInt32 k_Delta = 3;
const UInt32 k_LZMA2 = 0x21;
const UInt32 k_SWAP2 = 0x20302;
const UInt32 k_SWAP4 = 0x20304;
const UInt32 k_LZMA = 0x30101;
const UInt32 k_PPMD = 0x30401;
const UInt32 k_Deflate = 0x40108;
const UInt32 k_BZip2 = 0x40202;
const UInt32 k_BCJ = 0x3030103;
const UInt32 k_BCJ2 = 0x303011B;
const UInt32 k_PPC = 0x3030205;
const UInt32 k_IA64 = 0x3030401;
const UInt32 k_ARM = 0x3030501;
const UInt32 k_ARMT = 0x3030701;
const UInt32 k_SPARC = 0x3030805;
const UInt32 k_AES = 0x6F10701;
static inline bool IsFilterMethod(UInt64 m)
{
if (m > (UInt64)0xFFFFFFFF)
return false;
switch ((UInt32)m)
{
case k_Delta:
case k_BCJ:
case k_BCJ2:
case k_PPC:
case k_IA64:
case k_ARM:
case k_ARMT:
case k_SPARC:
case k_SWAP2:
case k_SWAP4:
return true;
}
return false;
}
}} }}
#endif #endif

View File

@@ -2,6 +2,12 @@
#include "StdAfx.h" #include "StdAfx.h"
#ifdef _WIN32
#include <wchar.h>
#else
#include <ctype.h>
#endif
#include "../../../../C/7zCrc.h" #include "../../../../C/7zCrc.h"
#include "../../../../C/CpuArch.h" #include "../../../../C/CpuArch.h"
@@ -26,9 +32,6 @@ using namespace NCOM;
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
static const UInt32 k_LZMA2 = 0x21;
static const UInt32 k_LZMA = 0x030101;
static void BoolVector_Fill_False(CBoolVector &v, unsigned size) static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
{ {
v.ClearAndSetSize(size); v.ClearAndSetSize(size);
@@ -37,78 +40,6 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
p[i] = false; p[i] = false;
} }
static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index)
{
if (index >= (UInt32)v.Size())
return true;
bool res = v[index];
v[index] = true;
return res;
}
bool CFolder::CheckStructure(unsigned numUnpackSizes) const
{
const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it
const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax
const unsigned kNumBindsMax = 32;
if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax)
return false;
{
CBoolVector v;
BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());
unsigned i;
for (i = 0; i < BindPairs.Size(); i++)
if (BoolVector_GetAndSet(v, BindPairs[i].InIndex))
return false;
for (i = 0; i < PackStreams.Size(); i++)
if (BoolVector_GetAndSet(v, PackStreams[i]))
return false;
BoolVector_Fill_False(v, numUnpackSizes);
for (i = 0; i < BindPairs.Size(); i++)
if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))
return false;
}
UInt32 mask[kMaskSize];
unsigned i;
for (i = 0; i < kMaskSize; i++)
mask[i] = 0;
{
CUIntVector inStreamToCoder, outStreamToCoder;
for (i = 0; i < Coders.Size(); i++)
{
CNum j;
const CCoderInfo &coder = Coders[i];
for (j = 0; j < coder.NumInStreams; j++)
inStreamToCoder.Add(i);
for (j = 0; j < coder.NumOutStreams; j++)
outStreamToCoder.Add(i);
}
for (i = 0; i < BindPairs.Size(); i++)
{
const CBindPair &bp = BindPairs[i];
mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]);
}
}
for (i = 0; i < kMaskSize; i++)
for (unsigned j = 0; j < kMaskSize; j++)
if (((1 << j) & mask[i]) != 0)
mask[i] |= mask[j];
for (i = 0; i < kMaskSize; i++)
if (((1 << i) & mask[i]) != 0)
return false;
return true;
}
class CInArchiveException {}; class CInArchiveException {};
class CUnsupportedFeatureException: public CInArchiveException {}; class CUnsupportedFeatureException: public CInArchiveException {};
@@ -187,6 +118,8 @@ Byte CInByte2::ReadByte()
void CInByte2::ReadBytes(Byte *data, size_t size) void CInByte2::ReadBytes(Byte *data, size_t size)
{ {
if (size == 0)
return;
if (size > _size - _pos) if (size > _size - _pos)
ThrowEndOfData(); ThrowEndOfData();
memcpy(data, _buffer + _pos, size); memcpy(data, _buffer + _pos, size);
@@ -212,41 +145,48 @@ static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
processed = 0; processed = 0;
return 0; return 0;
} }
Byte firstByte = *p++;
unsigned b = *p++;
size--; size--;
if ((firstByte & 0x80) == 0)
if ((b & 0x80) == 0)
{ {
processed = 1; processed = 1;
return firstByte; return b;
} }
Byte mask = 0x40;
if (size == 0) if (size == 0)
{ {
processed = 0; processed = 0;
return 0; return 0;
} }
UInt64 value = (UInt64)*p; UInt64 value = (UInt64)*p;
p++; p++;
size--; size--;
for (unsigned i = 1; i < 8; i++) for (unsigned i = 1; i < 8; i++)
{ {
if ((firstByte & mask) == 0) unsigned mask = (unsigned)0x80 >> i;
if ((b & mask) == 0)
{ {
UInt64 highPart = firstByte & (mask - 1); UInt64 high = b & (mask - 1);
value += (highPart << (i * 8)); value |= (high << (i * 8));
processed = i + 1; processed = i + 1;
return value; return value;
} }
if (size == 0) if (size == 0)
{ {
processed = 0; processed = 0;
return 0; return 0;
} }
value |= ((UInt64)*p << (i * 8)); value |= ((UInt64)*p << (i * 8));
p++; p++;
size--; size--;
mask >>= 1;
} }
processed = 9; processed = 9;
return value; return value;
} }
@@ -338,6 +278,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
for (;;) for (;;)
{ {
UInt32 readSize = kBufSize - kHeaderSize; UInt32 readSize = kBufSize - kHeaderSize;
if (searchHeaderSizeLimit)
{ {
UInt64 rem = *searchHeaderSizeLimit - offset; UInt64 rem = *searchHeaderSizeLimit - offset;
if (readSize > rem) if (readSize > rem)
@@ -345,10 +286,12 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
if (readSize == 0) if (readSize == 0)
return S_FALSE; return S_FALSE;
} }
UInt32 processed = 0; UInt32 processed = 0;
RINOK(stream->Read(buf + kHeaderSize, readSize, &processed)); RINOK(stream->Read(buf + kHeaderSize, readSize, &processed));
if (processed == 0) if (processed == 0)
return S_FALSE; return S_FALSE;
for (UInt32 pos = 0;;) for (UInt32 pos = 0;;)
{ {
const Byte *p = buf + pos + 1; const Byte *p = buf + pos + 1;
@@ -370,6 +313,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL); return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);
} }
} }
offset += processed; offset += processed;
memmove(buf, buf + processed, kHeaderSize); memmove(buf, buf + processed, kHeaderSize);
} }
@@ -409,13 +353,15 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
void CInByte2::ParseFolder(CFolder &folder) void CInByte2::ParseFolder(CFolder &folder)
{ {
CNum numCoders = ReadNum(); UInt32 numCoders = ReadNum();
if (numCoders == 0)
ThrowUnsupported();
folder.Coders.SetSize(numCoders); folder.Coders.SetSize(numCoders);
CNum numInStreams = 0; UInt32 numInStreams = 0;
CNum numOutStreams = 0; UInt32 i;
CNum i;
for (i = 0; i < numCoders; i++) for (i = 0; i < numCoders; i++)
{ {
CCoderInfo &coder = folder.Coders[i]; CCoderInfo &coder = folder.Coders[i];
@@ -435,14 +381,14 @@ void CInByte2::ParseFolder(CFolder &folder)
if ((mainByte & 0x10) != 0) if ((mainByte & 0x10) != 0)
{ {
coder.NumInStreams = ReadNum(); coder.NumStreams = ReadNum();
coder.NumOutStreams = ReadNum(); /* numOutStreams = */ ReadNum();
} }
else else
{ {
coder.NumInStreams = 1; coder.NumStreams = 1;
coder.NumOutStreams = 1;
} }
if ((mainByte & 0x20) != 0) if ((mainByte & 0x20) != 0)
{ {
CNum propsSize = ReadNum(); CNum propsSize = ReadNum();
@@ -452,27 +398,27 @@ void CInByte2::ParseFolder(CFolder &folder)
else else
coder.Props.Free(); coder.Props.Free();
} }
numInStreams += coder.NumInStreams; numInStreams += coder.NumStreams;
numOutStreams += coder.NumOutStreams;
} }
CNum numBindPairs = numOutStreams - 1; UInt32 numBonds = numCoders - 1;
folder.BindPairs.SetSize(numBindPairs); folder.Bonds.SetSize(numBonds);
for (i = 0; i < numBindPairs; i++) for (i = 0; i < numBonds; i++)
{ {
CBindPair &bp = folder.BindPairs[i]; CBond &bp = folder.Bonds[i];
bp.InIndex = ReadNum(); bp.PackIndex = ReadNum();
bp.OutIndex = ReadNum(); bp.UnpackIndex = ReadNum();
} }
if (numInStreams < numBindPairs) if (numInStreams < numBonds)
ThrowUnsupported(); ThrowUnsupported();
CNum numPackStreams = numInStreams - numBindPairs; UInt32 numPackStreams = numInStreams - numBonds;
folder.PackStreams.SetSize(numPackStreams); folder.PackStreams.SetSize(numPackStreams);
if (numPackStreams == 1) if (numPackStreams == 1)
{ {
for (i = 0; i < numInStreams; i++) for (i = 0; i < numInStreams; i++)
if (folder.FindBindPairForInStream(i) < 0) if (folder.FindBond_for_PackStream(i) < 0)
{ {
folder.PackStreams[0] = i; folder.PackStreams[0] = i;
break; break;
@@ -496,26 +442,83 @@ void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const
} }
HRESULT CDatabase::GetPath(unsigned index, PROPVARIANT *path) const void CDatabase::GetPath(unsigned index, UString &path) const
{
path.Empty();
if (!NameOffsets || !NamesBuf)
return;
size_t offset = NameOffsets[index];
size_t size = NameOffsets[index + 1] - offset;
if (size >= (1 << 28))
return;
wchar_t *s = path.GetBuf((unsigned)size - 1);
const Byte *p = ((const Byte *)NamesBuf + offset * 2);
#if defined(_WIN32) && defined(MY_CPU_LE)
wmemcpy(s, (const wchar_t *)p, size);
#else
for (size_t i = 0; i < size; i++)
{
*s = Get16(p);
p += 2;
s++;
}
#endif
path.ReleaseBuf_SetLen((unsigned)size - 1);
}
HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
{ {
PropVariant_Clear(path); PropVariant_Clear(path);
if (!NameOffsets || !NamesBuf) if (!NameOffsets || !NamesBuf)
return S_OK; return S_OK;
size_t offset = NameOffsets[index];
size_t size = NameOffsets[index + 1] - offset;
if (size >= (1 << 14))
return S_OK;
RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1));
wchar_t *s = path->bstrVal;
const Byte *p = ((const Byte *)NamesBuf + offset * 2);
for (size_t i = 0; i < size; i++)
{
wchar_t c = Get16(p);
p += 2;
#if WCHAR_PATH_SEPARATOR != L'/'
if (c == L'/')
c = WCHAR_PATH_SEPARATOR;
#endif
*s++ = c;
}
return S_OK;
/*
unsigned cur = index; unsigned cur = index;
unsigned size = 0; unsigned size = 0;
// for (int i = 0;; i++) for (int i = 0;; i++)
{ {
size_t len = NameOffsets[cur + 1] - NameOffsets[cur]; size_t len = NameOffsets[cur + 1] - NameOffsets[cur];
size += (unsigned)len; size += (unsigned)len;
if (/* i > 256 || */ len > (1 << 12) || size > (1 << 14)) if (i > 256 || len > (1 << 14) || size > (1 << 14))
return PropVarEm_Set_Str(path, "[TOO-LONG]"); return PropVarEm_Set_Str(path, "[TOO-LONG]");
/*
cur = Files[cur].Parent; cur = Files[cur].Parent;
if (cur < 0) if (cur < 0)
break; break;
*/
} }
size--; size--;
@@ -529,7 +532,7 @@ HRESULT CDatabase::GetPath(unsigned index, PROPVARIANT *path) const
{ {
unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1); unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);
const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2; const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;
do for (; len != 0; len--)
{ {
p -= 2; p -= 2;
--s; --s;
@@ -538,17 +541,14 @@ HRESULT CDatabase::GetPath(unsigned index, PROPVARIANT *path) const
c = WCHAR_PATH_SEPARATOR; c = WCHAR_PATH_SEPARATOR;
*s = c; *s = c;
} }
while (--len);
/*
const CFileItem &file = Files[cur]; const CFileItem &file = Files[cur];
cur = file.Parent; cur = file.Parent;
if (cur < 0) if (cur < 0)
*/
return S_OK; return S_OK;
/*
*(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR); *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR);
*/
} }
*/
} }
void CInArchive::WaitId(UInt64 id) void CInArchive::WaitId(UInt64 id)
@@ -579,6 +579,9 @@ void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
} }
} }
#define k_Scan_NumCoders_MAX 64
#define k_Scan_NumCodersStreams_in_Folder_MAX 64
void CInArchive::ReadPackInfo(CFolders &f) void CInArchive::ReadPackInfo(CFolders &f)
{ {
CNum numPackStreams = ReadNum(); CNum numPackStreams = ReadNum();
@@ -632,27 +635,31 @@ void CInArchive::ReadUnpackInfo(
folders.FoCodersDataOffset.Alloc(numFolders + 1); folders.FoCodersDataOffset.Alloc(numFolders + 1);
folders.FoToCoderUnpackSizes.Alloc(numFolders + 1); folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);
CRecordVector<bool> InStreamUsed; CBoolVector StreamUsed;
CRecordVector<bool> OutStreamUsed; CBoolVector CoderUsed;
CNum packStreamIndex = 0; CNum packStreamIndex = 0;
CNum fo; CNum fo;
CInByte2 *inByte = _inByteBack; CInByte2 *inByte = _inByteBack;
for (fo = 0; fo < numFolders; fo++) for (fo = 0; fo < numFolders; fo++)
{ {
UInt32 numOutStreams = 0;
UInt32 indexOfMainStream = 0; UInt32 indexOfMainStream = 0;
UInt32 numPackStreams = 0; UInt32 numPackStreams = 0;
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
numOutStreams = 0;
CNum numInStreams = 0; CNum numInStreams = 0;
CNum numCoders = inByte->ReadNum(); CNum numCoders = inByte->ReadNum();
if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
ThrowUnsupported();
for (CNum ci = 0; ci < numCoders; ci++) for (CNum ci = 0; ci < numCoders; ci++)
{ {
Byte mainByte = inByte->ReadByte(); Byte mainByte = inByte->ReadByte();
if ((mainByte & 0xC0) != 0) if ((mainByte & 0xC0) != 0)
ThrowUnsupported(); ThrowUnsupported();
unsigned idSize = (mainByte & 0xF); unsigned idSize = (mainByte & 0xF);
if (idSize > 8) if (idSize > 8)
ThrowUnsupported(); ThrowUnsupported();
@@ -665,19 +672,21 @@ void CInArchive::ReadUnpackInfo(
inByte->SkipDataNoCheck(idSize); inByte->SkipDataNoCheck(idSize);
if (folders.ParsedMethods.IDs.Size() < 128) if (folders.ParsedMethods.IDs.Size() < 128)
folders.ParsedMethods.IDs.AddToUniqueSorted(id); folders.ParsedMethods.IDs.AddToUniqueSorted(id);
CNum coderInStreams = 1; CNum coderInStreams = 1;
CNum coderOutStreams = 1;
if ((mainByte & 0x10) != 0) if ((mainByte & 0x10) != 0)
{ {
coderInStreams = inByte->ReadNum(); coderInStreams = inByte->ReadNum();
coderOutStreams = inByte->ReadNum(); if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
ThrowUnsupported();
if (inByte->ReadNum() != 1)
ThrowUnsupported();
} }
numInStreams += coderInStreams; numInStreams += coderInStreams;
if (numInStreams < coderInStreams) if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
ThrowUnsupported();
numOutStreams += coderOutStreams;
if (numOutStreams < coderOutStreams)
ThrowUnsupported(); ThrowUnsupported();
if ((mainByte & 0x20) != 0) if ((mainByte & 0x20) != 0)
{ {
CNum propsSize = inByte->ReadNum(); CNum propsSize = inByte->ReadNum();
@@ -699,7 +708,7 @@ void CInArchive::ReadUnpackInfo(
} }
} }
if (numOutStreams == 1 && numInStreams == 1) if (numCoders == 1 && numInStreams == 1)
{ {
indexOfMainStream = 0; indexOfMainStream = 0;
numPackStreams = 1; numPackStreams = 1;
@@ -707,55 +716,55 @@ void CInArchive::ReadUnpackInfo(
else else
{ {
UInt32 i; UInt32 i;
if (numOutStreams == 0) CNum numBonds = numCoders - 1;
ThrowUnsupported(); if (numInStreams < numBonds)
CNum numBindPairs = numOutStreams - 1;
if (numInStreams < numBindPairs)
ThrowUnsupported();
if (numInStreams >= 256 || numOutStreams >= 256)
ThrowUnsupported(); ThrowUnsupported();
InStreamUsed.ClearAndSetSize(numInStreams); BoolVector_Fill_False(StreamUsed, numInStreams);
for (i = 0; i < numInStreams; i++) BoolVector_Fill_False(CoderUsed, numCoders);
InStreamUsed[i] = false;
OutStreamUsed.ClearAndSetSize(numOutStreams); for (i = 0; i < numBonds; i++)
for (i = 0; i < numOutStreams; i++)
OutStreamUsed[i] = false;
for (i = 0; i < numBindPairs; i++)
{ {
CNum index = ReadNum(); CNum index = ReadNum();
if (index >= numInStreams || InStreamUsed[index]) if (index >= numInStreams || StreamUsed[index])
ThrowUnsupported(); ThrowUnsupported();
InStreamUsed[index] = true; StreamUsed[index] = true;
index = ReadNum(); index = ReadNum();
if (index >= numOutStreams || OutStreamUsed[index]) if (index >= numCoders || CoderUsed[index])
ThrowUnsupported(); ThrowUnsupported();
OutStreamUsed[index] = true; CoderUsed[index] = true;
} }
numPackStreams = numInStreams - numBindPairs; numPackStreams = numInStreams - numBonds;
if (numPackStreams != 1) if (numPackStreams != 1)
for (i = 0; i < numPackStreams; i++) for (i = 0; i < numPackStreams; i++)
inByte->ReadNum(); // PackStreams {
CNum index = inByte->ReadNum(); // PackStreams
if (index >= numInStreams || StreamUsed[index])
ThrowUnsupported();
StreamUsed[index] = true;
}
for (i = 0; i < numOutStreams; i++) for (i = 0; i < numCoders; i++)
if (!OutStreamUsed[i]) if (!CoderUsed[i])
{ {
indexOfMainStream = i; indexOfMainStream = i;
break; break;
} }
if (i == numOutStreams)
if (i == numCoders)
ThrowUnsupported(); ThrowUnsupported();
} }
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
numCodersOutStreams += numOutStreams; numCodersOutStreams += numCoders;
folders.FoStartPackStreamIndex[fo] = packStreamIndex; folders.FoStartPackStreamIndex[fo] = packStreamIndex;
packStreamIndex += numPackStreams; packStreamIndex += numPackStreams;
folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
} }
size_t dataSize = _inByteBack->GetPtr() - startBufPtr; size_t dataSize = _inByteBack->GetPtr() - startBufPtr;
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
folders.FoStartPackStreamIndex[fo] = packStreamIndex; folders.FoStartPackStreamIndex[fo] = packStreamIndex;
@@ -1045,13 +1054,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
unpackSizes, unpackSizes,
digests); digests);
CDecoder decoder( CDecoder decoder(_useMixerMT);
#ifdef _ST_MODE
false
#else
true
#endif
);
for (CNum i = 0; i < folders.NumFolders; i++) for (CNum i = 0; i < folders.NumFolders; i++)
{ {
@@ -1067,14 +1070,20 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
outStreamSpec->Init(data, unpackSize); outStreamSpec->Init(data, unpackSize);
HRESULT result = decoder.Decode( HRESULT result = decoder.Decode(
EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS
_stream, baseOffset + dataOffset, _stream, baseOffset + dataOffset,
folders, i, folders, i,
outStream, NULL NULL, // *unpackSize
_7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST) && !defined(_SFX) outStream,
, false, 1 NULL, // *compressProgress
#endif NULL // **inStreamMainRes
_7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST) && !defined(_SFX)
, false // mtMode
, 1 // numThreads
#endif
); );
RINOK(result); RINOK(result);
@@ -1148,7 +1157,7 @@ HRESULT CInArchive::ReadHeader(
db.ArcInfo.FileInfoPopIDs.Add(NID::kSize); db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
// if (!db.PackSizes.IsEmpty()) // if (!db.PackSizes.IsEmpty())
db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo); db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);
if (numFiles > 0 && !digests.Defs.IsEmpty()) if (numFiles > 0 && !digests.Defs.IsEmpty())
db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC); db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
CBoolVector emptyStreamVector; CBoolVector emptyStreamVector;
@@ -1171,7 +1180,7 @@ HRESULT CInArchive::ReadHeader(
bool isKnownType = true; bool isKnownType = true;
if (type > ((UInt32)1 << 30)) if (type > ((UInt32)1 << 30))
isKnownType = false; isKnownType = false;
else switch((UInt32)type) else switch ((UInt32)type)
{ {
case NID::kName: case NID::kName:
{ {
@@ -1329,13 +1338,16 @@ HRESULT CInArchive::ReadHeader(
db.UnsupportedFeatureWarning = true; db.UnsupportedFeatureWarning = true;
_inByteBack->SkipRem(); _inByteBack->SkipRem();
} }
// SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02) // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02)
if (_inByteBack->GetRem() != 0) if (_inByteBack->GetRem() != 0)
ThrowIncorrect(); ThrowIncorrect();
} }
type = ReadID(); // Read (NID::kEnd) end of headers type = ReadID(); // Read (NID::kEnd) end of headers
if (numFiles - numEmptyStreams != unpackSizes.Size())
ThrowUnsupported();
CNum emptyFileIndex = 0; CNum emptyFileIndex = 0;
CNum sizeIndex = 0; CNum sizeIndex = 0;
@@ -1343,7 +1355,7 @@ HRESULT CInArchive::ReadHeader(
for (i = 0; i < numEmptyStreams; i++) for (i = 0; i < numEmptyStreams; i++)
if (antiFileVector[i]) if (antiFileVector[i])
numAntiItems++; numAntiItems++;
for (i = 0; i < numFiles; i++) for (i = 0; i < numFiles; i++)
{ {
CFileItem &file = db.Files[i]; CFileItem &file = db.Files[i];
@@ -1384,13 +1396,13 @@ HRESULT CInArchive::ReadHeader(
void CDbEx::FillLinks() void CDbEx::FillLinks()
{ {
FolderStartFileIndex.ClearAndSetSize(NumFolders); FolderStartFileIndex.Alloc(NumFolders);
FileIndexToFolderIndexMap.Alloc(Files.Size());
FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size());
CNum folderIndex = 0; CNum folderIndex = 0;
CNum indexInFolder = 0; CNum indexInFolder = 0;
unsigned i; unsigned i;
for (i = 0; i < Files.Size(); i++) for (i = 0; i < Files.Size(); i++)
{ {
bool emptyStream = !Files[i].HasStream; bool emptyStream = !Files[i].HasStream;
@@ -1429,6 +1441,7 @@ void CDbEx::FillLinks()
if (indexInFolder != 0) if (indexInFolder != 0)
ThrowIncorrect(); ThrowIncorrect();
*/ */
for (;;) for (;;)
{ {
if (folderIndex >= NumFolders) if (folderIndex >= NumFolders)

View File

@@ -26,8 +26,8 @@ namespace N7z {
#define _7Z_DECODER_CRYPRO_VARS_DECL #define _7Z_DECODER_CRYPRO_VARS_DECL
#define _7Z_DECODER_CRYPRO_VARS #define _7Z_DECODER_CRYPRO_VARS
#else #else
#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined #define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password
#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined #define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password
#endif #endif
struct CParsedMethods struct CParsedMethods
@@ -39,6 +39,11 @@ struct CParsedMethods
CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {} CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
}; };
struct CFolderEx: public CFolder
{
unsigned UnpackCoder;
};
struct CFolders struct CFolders
{ {
CNum NumPackStreams; CNum NumPackStreams;
@@ -47,10 +52,10 @@ struct CFolders
CObjArray<UInt64> PackPositions; // NumPackStreams + 1 CObjArray<UInt64> PackPositions; // NumPackStreams + 1
// CUInt32DefVector PackCRCs; // we don't use PackCRCs now // CUInt32DefVector PackCRCs; // we don't use PackCRCs now
CUInt32DefVector FolderCRCs; // NumFolders CUInt32DefVector FolderCRCs; // NumFolders
CObjArray<CNum> NumUnpackStreamsVector; // NumFolders CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1 CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1 CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
@@ -61,10 +66,15 @@ struct CFolders
CParsedMethods ParsedMethods; CParsedMethods ParsedMethods;
void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const; void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;
void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const
{
ParseFolderInfo(folderIndex, folder);
folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];
}
unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
{ {
return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]; return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
} }
UInt64 GetFolderUnpackSize(unsigned folderIndex) const UInt64 GetFolderUnpackSize(unsigned folderIndex) const
@@ -77,6 +87,8 @@ struct CFolders
return PackPositions[index + 1] - PackPositions[index]; return PackPositions[index + 1] - PackPositions[index];
} }
CFolders(): NumPackStreams(0), NumFolders(0) {}
void Clear() void Clear()
{ {
NumPackStreams = 0; NumPackStreams = 0;
@@ -103,15 +115,15 @@ struct CDatabase: public CFolders
CUInt64DefVector ATime; CUInt64DefVector ATime;
CUInt64DefVector MTime; CUInt64DefVector MTime;
CUInt64DefVector StartPos; CUInt64DefVector StartPos;
CRecordVector<bool> IsAnti; CBoolVector IsAnti;
/* /*
CRecordVector<bool> IsAux; CBoolVector IsAux;
CByteBuffer SecureBuf; CByteBuffer SecureBuf;
CRecordVector<UInt32> SecureIDs; CRecordVector<UInt32> SecureIDs;
*/ */
CByteBuffer NamesBuf; CByteBuffer NamesBuf;
CObjArray<size_t> NameOffsets; // numFiles + 1, conatins offsets of UINt16 symbols. CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols
/* /*
void ClearSecure() void ClearSecure()
@@ -148,14 +160,16 @@ struct CDatabase: public CFolders
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
const wchar_t * GetName(unsigned index) const /*
const void* GetName(unsigned index) const
{ {
if (!NameOffsets || !NamesBuf) if (!NameOffsets || !NamesBuf)
return NULL; return NULL;
return (const wchar_t *)(const Byte *)NamesBuf + NameOffsets[index]; return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
}; };
*/
HRESULT GetPath(unsigned index, PROPVARIANT *path) const; void GetPath(unsigned index, UString &path) const;
HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
}; };
struct CInArchiveInfo struct CInArchiveInfo
@@ -180,8 +194,9 @@ struct CInArchiveInfo
struct CDbEx: public CDatabase struct CDbEx: public CDatabase
{ {
CInArchiveInfo ArcInfo; CInArchiveInfo ArcInfo;
CRecordVector<CNum> FolderStartFileIndex;
CRecordVector<CNum> FileIndexToFolderIndexMap; CObjArray<CNum> FolderStartFileIndex;
CObjArray<CNum> FileIndexToFolderIndexMap;
UInt64 HeadersSize; UInt64 HeadersSize;
UInt64 PhySize; UInt64 PhySize;
@@ -233,8 +248,8 @@ struct CDbEx: public CDatabase
// SecureOffsets.Clear(); // SecureOffsets.Clear();
ArcInfo.Clear(); ArcInfo.Clear();
FolderStartFileIndex.Clear(); FolderStartFileIndex.Free();
FileIndexToFolderIndexMap.Clear(); FileIndexToFolderIndexMap.Free();
HeadersSize = 0; HeadersSize = 0;
PhySize = 0; PhySize = 0;
@@ -242,22 +257,22 @@ struct CDbEx: public CDatabase
void FillLinks(); void FillLinks();
UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
{ {
return ArcInfo.DataStartPosition + return ArcInfo.DataStartPosition +
PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
} }
UInt64 GetFolderFullPackSize(unsigned folderIndex) const UInt64 GetFolderFullPackSize(CNum folderIndex) const
{ {
return return
PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
PackPositions[FoStartPackStreamIndex[folderIndex]]; PackPositions[FoStartPackStreamIndex[folderIndex]];
} }
UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
{ {
unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex; size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
return PackPositions[i + 1] - PackPositions[i]; return PackPositions[i + 1] - PackPositions[i];
} }
@@ -326,6 +341,8 @@ class CInArchive
UInt64 HeadersSize; UInt64 HeadersSize;
bool _useMixerMT;
void AddByteStream(const Byte *buffer, size_t size); void AddByteStream(const Byte *buffer, size_t size);
void DeleteByteStream(bool needUpdatePos) void DeleteByteStream(bool needUpdatePos)
@@ -339,7 +356,6 @@ class CInArchive
} }
} }
private:
HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
@@ -395,7 +411,11 @@ private:
_7Z_DECODER_CRYPRO_VARS_DECL _7Z_DECODER_CRYPRO_VARS_DECL
); );
public: public:
CInArchive(): _numInByteBufs(0) { } CInArchive(bool useMixerMT):
_numInByteBufs(0),
_useMixerMT(useMixerMT)
{}
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
void Close(); void Close();

View File

@@ -13,8 +13,6 @@
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
const UInt64 k_AES = 0x06F10701;
typedef UInt32 CNum; typedef UInt32 CNum;
const CNum kNumMax = 0x7FFFFFFF; const CNum kNumMax = 0x7FFFFFFF;
const CNum kNumNoIndex = 0xFFFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF;
@@ -23,71 +21,70 @@ struct CCoderInfo
{ {
CMethodId MethodID; CMethodId MethodID;
CByteBuffer Props; CByteBuffer Props;
CNum NumInStreams; UInt32 NumStreams;
CNum NumOutStreams;
bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } bool IsSimpleCoder() const { return NumStreams == 1; }
}; };
struct CBindPair struct CBond
{ {
CNum InIndex; UInt32 PackIndex;
CNum OutIndex; UInt32 UnpackIndex;
}; };
struct CFolder struct CFolder
{ {
CLASS_NO_COPY(CFolder)
public:
CObjArray2<CCoderInfo> Coders; CObjArray2<CCoderInfo> Coders;
CObjArray2<CBindPair> BindPairs; CObjArray2<CBond> Bonds;
CObjArray2<CNum> PackStreams; CObjArray2<UInt32> PackStreams;
CNum GetNumOutStreams() const CFolder() {}
{
CNum result = 0;
FOR_VECTOR(i, Coders)
result += Coders[i].NumOutStreams;
return result;
}
int FindBindPairForInStream(CNum inStreamIndex) const bool IsDecodingSupported() const { return Coders.Size() <= 32; }
{
FOR_VECTOR(i, BindPairs) int Find_in_PackStreams(UInt32 packStream) const
if (BindPairs[i].InIndex == inStreamIndex)
return i;
return -1;
}
int FindBindPairForOutStream(CNum outStreamIndex) const
{
FOR_VECTOR(i, BindPairs)
if (BindPairs[i].OutIndex == outStreamIndex)
return i;
return -1;
}
int FindPackStreamArrayIndex(CNum inStreamIndex) const
{ {
FOR_VECTOR(i, PackStreams) FOR_VECTOR(i, PackStreams)
if (PackStreams[i] == inStreamIndex) if (PackStreams[i] == packStream)
return i; return i;
return -1; return -1;
} }
int GetIndexOfMainOutStream() const int FindBond_for_PackStream(UInt32 packStream) const
{ {
for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--) FOR_VECTOR(i, Bonds)
if (FindBindPairForOutStream(i) < 0) if (Bonds[i].PackIndex == packStream)
return i; return i;
throw 1; return -1;
} }
/*
int FindBond_for_UnpackStream(UInt32 unpackStream) const
{
FOR_VECTOR(i, Bonds)
if (Bonds[i].UnpackIndex == unpackStream)
return i;
return -1;
}
int FindOutCoder() const
{
for (int i = (int)Coders.Size() - 1; i >= 0; i--)
if (FindBond_for_UnpackStream(i) < 0)
return i;
return -1;
}
*/
bool IsEncrypted() const bool IsEncrypted() const
{ {
for (int i = Coders.Size() - 1; i >= 0; i--) FOR_VECTOR(i, Coders)
if (Coders[i].MethodID == k_AES) if (Coders[i].MethodID == k_AES)
return true; return true;
return false; return false;
} }
bool CheckStructure(unsigned numUnpackSizes) const;
}; };
struct CUInt32DefVector struct CUInt32DefVector

View File

@@ -199,7 +199,7 @@ void COutArchive::WriteNumber(UInt64 value)
mask >>= 1; mask >>= 1;
} }
WriteByte(firstByte); WriteByte(firstByte);
for (;i > 0; i--) for (; i > 0; i--)
{ {
WriteByte((Byte)value); WriteByte((Byte)value);
value >>= 8; value >>= 8;
@@ -254,31 +254,33 @@ void COutArchive::WriteFolder(const CFolder &folder)
{ {
WriteNumber(folder.Coders.Size()); WriteNumber(folder.Coders.Size());
unsigned i; unsigned i;
for (i = 0; i < folder.Coders.Size(); i++) for (i = 0; i < folder.Coders.Size(); i++)
{ {
const CCoderInfo &coder = folder.Coders[i]; const CCoderInfo &coder = folder.Coders[i];
{ {
size_t propsSize = coder.Props.Size();
UInt64 id = coder.MethodID; UInt64 id = coder.MethodID;
int idSize; unsigned idSize;
for (idSize = 1; idSize < sizeof(id); idSize++) for (idSize = 1; idSize < sizeof(id); idSize++)
if ((id >> (8 * idSize)) == 0) if ((id >> (8 * idSize)) == 0)
break; break;
Byte longID[15]; idSize &= 0xF;
for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) Byte temp[16];
longID[t] = (Byte)(id & 0xFF); for (unsigned t = idSize; t != 0; t--, id >>= 8)
Byte b; temp[t] = (Byte)(id & 0xFF);
b = (Byte)(idSize & 0xF);
Byte b = (Byte)(idSize);
bool isComplex = !coder.IsSimpleCoder(); bool isComplex = !coder.IsSimpleCoder();
b |= (isComplex ? 0x10 : 0); b |= (isComplex ? 0x10 : 0);
b |= ((propsSize != 0) ? 0x20 : 0 );
WriteByte(b); size_t propsSize = coder.Props.Size();
WriteBytes(longID, idSize); b |= ((propsSize != 0) ? 0x20 : 0);
temp[0] = b;
WriteBytes(temp, idSize + 1);
if (isComplex) if (isComplex)
{ {
WriteNumber(coder.NumInStreams); WriteNumber(coder.NumStreams);
WriteNumber(coder.NumOutStreams); WriteNumber(1); // NumOutStreams;
} }
if (propsSize == 0) if (propsSize == 0)
continue; continue;
@@ -286,17 +288,17 @@ void COutArchive::WriteFolder(const CFolder &folder)
WriteBytes(coder.Props, propsSize); WriteBytes(coder.Props, propsSize);
} }
} }
for (i = 0; i < folder.BindPairs.Size(); i++)
for (i = 0; i < folder.Bonds.Size(); i++)
{ {
const CBindPair &bindPair = folder.BindPairs[i]; const CBond &bond = folder.Bonds[i];
WriteNumber(bindPair.InIndex); WriteNumber(bond.PackIndex);
WriteNumber(bindPair.OutIndex); WriteNumber(bond.UnpackIndex);
} }
if (folder.PackStreams.Size() > 1) if (folder.PackStreams.Size() > 1)
for (i = 0; i < folder.PackStreams.Size(); i++) for (i = 0; i < folder.PackStreams.Size(); i++)
{
WriteNumber(folder.PackStreams[i]); WriteNumber(folder.PackStreams[i]);
}
} }
void COutArchive::WriteBoolVector(const CBoolVector &boolVector) void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
@@ -521,7 +523,10 @@ HRESULT COutArchive::EncodeStream(
UInt64 unpackSize; UInt64 unpackSize;
RINOK(encoder.Encode( RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS
stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL)) stream,
// NULL,
&dataSize64,
folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
return S_OK; return S_OK;
} }

View File

@@ -29,6 +29,8 @@ public:
} }
void WriteBytes(const void *data, size_t size) void WriteBytes(const void *data, size_t size)
{ {
if (size == 0)
return;
if (size > _size - _pos) if (size > _size - _pos)
throw 1; throw 1;
memcpy(_data + _pos, data, size); memcpy(_data + _pos, data, size);
@@ -92,7 +94,7 @@ struct COutFolders
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
CRecordVector<CNum> NumUnpackStreamsVector; CRecordVector<CNum> NumUnpackStreamsVector;
CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
void OutFoldersClear() void OutFoldersClear()
{ {

Some files were not shown because too many files have changed in this diff Show More