mirror of
https://github.com/ZDoom/Raze.git
synced 2025-01-31 04:20:42 +00:00
- lzma and zlib update.
This commit is contained in:
parent
3ec8a96ddf
commit
0c03d3e364
51 changed files with 16851 additions and 2824 deletions
|
@ -1,5 +1,5 @@
|
|||
/* 7z.h -- 7z interface
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2018-07-02 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_H
|
||||
#define __7Z_H
|
||||
|
@ -91,6 +91,8 @@ typedef struct
|
|||
UInt64 *CoderUnpackSizes; // for all coders in all folders
|
||||
|
||||
Byte *CodersData;
|
||||
|
||||
UInt64 RangeLimit;
|
||||
} CSzAr;
|
||||
|
||||
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* 7zArcIn.c -- 7z Input functions
|
||||
2018-12-31 : Igor Pavlov : Public domain */
|
||||
2021-02-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -75,7 +75,7 @@ static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc)
|
|||
return SZ_OK;
|
||||
}
|
||||
|
||||
void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc)
|
||||
static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc)
|
||||
{
|
||||
ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
|
||||
ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
|
||||
|
@ -83,7 +83,7 @@ void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc)
|
|||
|
||||
#define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; }
|
||||
|
||||
void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc)
|
||||
static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc)
|
||||
{
|
||||
ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL;
|
||||
ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL;
|
||||
|
@ -105,6 +105,8 @@ static void SzAr_Init(CSzAr *p)
|
|||
p->CoderUnpackSizes = NULL;
|
||||
|
||||
p->CodersData = NULL;
|
||||
|
||||
p->RangeLimit = 0;
|
||||
}
|
||||
|
||||
static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc)
|
||||
|
@ -502,7 +504,7 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd)
|
|||
return SZ_ERROR_ARCHIVE;
|
||||
if (propsSize >= 0x80)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
coder->PropsOffset = sd->Data - dataStart;
|
||||
coder->PropsOffset = (size_t)(sd->Data - dataStart);
|
||||
coder->PropsSize = (Byte)propsSize;
|
||||
sd->Data += (size_t)propsSize;
|
||||
sd->Size -= (size_t)propsSize;
|
||||
|
@ -677,7 +679,7 @@ static SRes ReadUnpackInfo(CSzAr *p,
|
|||
{
|
||||
UInt32 numCoders, ci, numInStreams = 0;
|
||||
|
||||
p->FoCodersOffsets[fo] = sd.Data - startBufPtr;
|
||||
p->FoCodersOffsets[fo] = (size_t)(sd.Data - startBufPtr);
|
||||
|
||||
RINOK(SzReadNumber32(&sd, &numCoders));
|
||||
if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
|
||||
|
@ -797,7 +799,7 @@ static SRes ReadUnpackInfo(CSzAr *p,
|
|||
p->FoToCoderUnpackSizes[fo] = numCodersOutStreams;
|
||||
|
||||
{
|
||||
size_t dataSize = sd.Data - startBufPtr;
|
||||
const size_t dataSize = (size_t)(sd.Data - startBufPtr);
|
||||
p->FoStartPackStreamIndex[fo] = packStreamIndex;
|
||||
p->FoCodersOffsets[fo] = dataSize;
|
||||
MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc);
|
||||
|
@ -885,7 +887,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
|
|||
if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i))
|
||||
numSubDigests += numStreams;
|
||||
}
|
||||
ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data;
|
||||
ssi->sdNumSubStreams.Size = (size_t)(sd->Data - ssi->sdNumSubStreams.Data);
|
||||
continue;
|
||||
}
|
||||
if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd)
|
||||
|
@ -907,7 +909,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
|
|||
{
|
||||
ssi->sdSizes.Data = sd->Data;
|
||||
RINOK(SkipNumbers(sd, numUnpackSizesInData));
|
||||
ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data;
|
||||
ssi->sdSizes.Size = (size_t)(sd->Data - ssi->sdSizes.Data);
|
||||
RINOK(ReadID(sd, &type));
|
||||
}
|
||||
|
||||
|
@ -919,7 +921,7 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
|
|||
{
|
||||
ssi->sdCRCs.Data = sd->Data;
|
||||
RINOK(SkipBitUi32s(sd, numSubDigests));
|
||||
ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data;
|
||||
ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -947,7 +949,11 @@ static SRes SzReadStreamsInfo(CSzAr *p,
|
|||
if (type == k7zIdPackInfo)
|
||||
{
|
||||
RINOK(ReadNumber(sd, dataOffset));
|
||||
if (*dataOffset > p->RangeLimit)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
RINOK(ReadPackInfo(p, sd, alloc));
|
||||
if (p->PackPositions[p->NumPackStreams] > p->RangeLimit - *dataOffset)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
RINOK(ReadID(sd, &type));
|
||||
}
|
||||
if (type == k7zIdUnpackInfo)
|
||||
|
@ -1028,12 +1034,12 @@ static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size
|
|||
return SZ_ERROR_ARCHIVE;
|
||||
for (p = data + pos;
|
||||
#ifdef _WIN32
|
||||
*(const UInt16 *)p != 0
|
||||
*(const UInt16 *)(const void *)p != 0
|
||||
#else
|
||||
p[0] != 0 || p[1] != 0
|
||||
#endif
|
||||
; p += 2);
|
||||
pos = p - data + 2;
|
||||
pos = (size_t)(p - data) + 2;
|
||||
*offsets++ = (pos >> 1);
|
||||
}
|
||||
while (--numFiles);
|
||||
|
@ -1133,6 +1139,8 @@ static SRes SzReadHeader2(
|
|||
SRes res;
|
||||
|
||||
SzAr_Init(&tempAr);
|
||||
tempAr.RangeLimit = p->db.RangeLimit;
|
||||
|
||||
res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,
|
||||
p->startPosAfterHeader, &tempAr, allocTemp);
|
||||
*numTempBufs = tempAr.NumFolders;
|
||||
|
@ -1526,11 +1534,13 @@ static SRes SzArEx_Open2(
|
|||
nextHeaderSize = GetUi64(header + 20);
|
||||
nextHeaderCRC = GetUi32(header + 28);
|
||||
|
||||
p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
|
||||
p->startPosAfterHeader = (UInt64)startArcPos + k7zStartHeaderSize;
|
||||
|
||||
if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
|
||||
return SZ_ERROR_CRC;
|
||||
|
||||
p->db.RangeLimit = nextHeaderOffset;
|
||||
|
||||
nextHeaderSizeT = (size_t)nextHeaderSize;
|
||||
if (nextHeaderSizeT != nextHeaderSize)
|
||||
return SZ_ERROR_MEM;
|
||||
|
@ -1543,13 +1553,13 @@ static SRes SzArEx_Open2(
|
|||
{
|
||||
Int64 pos = 0;
|
||||
RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END));
|
||||
if ((UInt64)pos < startArcPos + nextHeaderOffset ||
|
||||
(UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
|
||||
(UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
|
||||
if ((UInt64)pos < (UInt64)startArcPos + nextHeaderOffset ||
|
||||
(UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
|
||||
(UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
}
|
||||
|
||||
RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));
|
||||
RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset));
|
||||
|
||||
if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp))
|
||||
return SZ_ERROR_MEM;
|
||||
|
@ -1575,6 +1585,8 @@ static SRes SzArEx_Open2(
|
|||
Buf_Init(&tempBuf);
|
||||
|
||||
SzAr_Init(&tempAr);
|
||||
tempAr.RangeLimit = p->db.RangeLimit;
|
||||
|
||||
res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp);
|
||||
SzAr_Free(&tempAr, allocTemp);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* 7zCrc.c -- CRC32 init
|
||||
2017-06-06 : Igor Pavlov : Public domain */
|
||||
2021-04-01 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -26,8 +26,20 @@
|
|||
|
||||
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
|
||||
extern
|
||||
CRC_FUNC g_CrcUpdateT4;
|
||||
CRC_FUNC g_CrcUpdateT4;
|
||||
extern
|
||||
CRC_FUNC g_CrcUpdateT8;
|
||||
CRC_FUNC g_CrcUpdateT8;
|
||||
extern
|
||||
CRC_FUNC g_CrcUpdateT0_32;
|
||||
CRC_FUNC g_CrcUpdateT0_32;
|
||||
extern
|
||||
CRC_FUNC g_CrcUpdateT0_64;
|
||||
CRC_FUNC g_CrcUpdateT0_64;
|
||||
extern
|
||||
CRC_FUNC g_CrcUpdate;
|
||||
CRC_FUNC g_CrcUpdate;
|
||||
|
||||
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
|
||||
|
@ -44,6 +56,7 @@ UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
|||
|
||||
#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);
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
|
@ -53,6 +66,166 @@ UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const U
|
|||
return v;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- hardware CRC ---------- */
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
|
||||
#if defined(MY_CPU_ARM_OR_ARM64)
|
||||
|
||||
// #pragma message("ARM*")
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(MY_CPU_ARM64)
|
||||
#if (_MSC_VER >= 1910)
|
||||
#define USE_ARM64_CRC
|
||||
#endif
|
||||
#endif
|
||||
#elif (defined(__clang__) && (__clang_major__ >= 3)) \
|
||||
|| (defined(__GNUC__) && (__GNUC__ > 4))
|
||||
#if !defined(__ARM_FEATURE_CRC32)
|
||||
#define __ARM_FEATURE_CRC32 1
|
||||
#if (!defined(__clang__) || (__clang_major__ > 3)) // fix these numbers
|
||||
#define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc")))
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__ARM_FEATURE_CRC32)
|
||||
#define USE_ARM64_CRC
|
||||
#include <arm_acle.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// no hardware CRC
|
||||
|
||||
// #define USE_CRC_EMU
|
||||
|
||||
#ifdef USE_CRC_EMU
|
||||
|
||||
#pragma message("ARM64 CRC emulation")
|
||||
|
||||
MY_FORCE_INLINE
|
||||
UInt32 __crc32b(UInt32 v, UInt32 data)
|
||||
{
|
||||
const UInt32 *table = g_CrcTable;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data);
|
||||
return v;
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
UInt32 __crc32w(UInt32 v, UInt32 data)
|
||||
{
|
||||
const UInt32 *table = g_CrcTable;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
return v;
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
UInt32 __crc32d(UInt32 v, UInt64 data)
|
||||
{
|
||||
const UInt32 *table = g_CrcTable;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif // USE_CRC_EMU
|
||||
|
||||
#endif // defined(MY_CPU_ARM64) && defined(MY_CPU_LE)
|
||||
|
||||
|
||||
|
||||
#if defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)
|
||||
|
||||
#define T0_32_UNROLL_BYTES (4 * 4)
|
||||
#define T0_64_UNROLL_BYTES (4 * 8)
|
||||
|
||||
#ifndef ATTRIB_CRC
|
||||
#define ATTRIB_CRC
|
||||
#endif
|
||||
// #pragma message("USE ARM HW CRC")
|
||||
|
||||
ATTRIB_CRC
|
||||
UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
ATTRIB_CRC
|
||||
UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
UNUSED_VAR(table);
|
||||
|
||||
for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_32_UNROLL_BYTES - 1)) != 0; size--)
|
||||
v = __crc32b(v, *p++);
|
||||
|
||||
if (size >= T0_32_UNROLL_BYTES)
|
||||
{
|
||||
const Byte *lim = p + size;
|
||||
size &= (T0_32_UNROLL_BYTES - 1);
|
||||
lim -= size;
|
||||
do
|
||||
{
|
||||
v = __crc32w(v, *(const UInt32 *)(const void *)(p));
|
||||
v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4;
|
||||
v = __crc32w(v, *(const UInt32 *)(const void *)(p));
|
||||
v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4;
|
||||
}
|
||||
while (p != lim);
|
||||
}
|
||||
|
||||
for (; size != 0; size--)
|
||||
v = __crc32b(v, *p++);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
ATTRIB_CRC
|
||||
UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
ATTRIB_CRC
|
||||
UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
UNUSED_VAR(table);
|
||||
|
||||
for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_64_UNROLL_BYTES - 1)) != 0; size--)
|
||||
v = __crc32b(v, *p++);
|
||||
|
||||
if (size >= T0_64_UNROLL_BYTES)
|
||||
{
|
||||
const Byte *lim = p + size;
|
||||
size &= (T0_64_UNROLL_BYTES - 1);
|
||||
lim -= size;
|
||||
do
|
||||
{
|
||||
v = __crc32d(v, *(const UInt64 *)(const void *)(p));
|
||||
v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
|
||||
v = __crc32d(v, *(const UInt64 *)(const void *)(p));
|
||||
v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
|
||||
}
|
||||
while (p != lim);
|
||||
}
|
||||
|
||||
for (; size != 0; size--)
|
||||
v = __crc32b(v, *p++);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)
|
||||
|
||||
#endif // MY_CPU_LE
|
||||
|
||||
|
||||
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable()
|
||||
{
|
||||
UInt32 i;
|
||||
|
@ -123,6 +296,27 @@ void MY_FAST_CALL CrcGenerateTable()
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
#ifdef USE_ARM64_CRC
|
||||
if (CPU_IsSupported_CRC32())
|
||||
{
|
||||
g_CrcUpdateT0_32 = CrcUpdateT0_32;
|
||||
g_CrcUpdateT0_64 = CrcUpdateT0_64;
|
||||
g_CrcUpdate =
|
||||
#if defined(MY_CPU_ARM)
|
||||
CrcUpdateT0_32;
|
||||
#else
|
||||
CrcUpdateT0_64;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_CRC_EMU
|
||||
g_CrcUpdateT0_32 = CrcUpdateT0_32;
|
||||
g_CrcUpdateT0_64 = CrcUpdateT0_64;
|
||||
g_CrcUpdate = CrcUpdateT0_64;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* 7zCrcOpt.c -- CRC32 calculation
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2021-02-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
|||
|
||||
#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;
|
||||
|
@ -16,7 +17,7 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U
|
|||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const UInt32 *)p;
|
||||
v ^= *(const UInt32 *)(const void *)p;
|
||||
v =
|
||||
(table + 0x300)[((v ) & 0xFF)]
|
||||
^ (table + 0x200)[((v >> 8) & 0xFF)]
|
||||
|
@ -28,6 +29,7 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U
|
|||
return v;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
|
@ -36,13 +38,13 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U
|
|||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
UInt32 d;
|
||||
v ^= *(const UInt32 *)p;
|
||||
v ^= *(const UInt32 *)(const void *)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);
|
||||
d = *((const UInt32 *)(const void *)p + 1);
|
||||
v ^=
|
||||
(table + 0x300)[((d ) & 0xFF)]
|
||||
^ (table + 0x200)[((d >> 8) & 0xFF)]
|
||||
|
@ -72,7 +74,7 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, co
|
|||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const UInt32 *)p;
|
||||
v ^= *(const UInt32 *)(const void *)p;
|
||||
v =
|
||||
(table + 0x000)[((v ) & 0xFF)]
|
||||
^ (table + 0x100)[((v >> 8) & 0xFF)]
|
||||
|
@ -94,13 +96,13 @@ UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, co
|
|||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
UInt32 d;
|
||||
v ^= *(const UInt32 *)p;
|
||||
v ^= *(const UInt32 *)(const void *)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);
|
||||
d = *((const UInt32 *)(const void *)p + 1);
|
||||
v ^=
|
||||
(table + 0x000)[((d ) & 0xFF)]
|
||||
^ (table + 0x100)[((d >> 8) & 0xFF)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* 7zDec.c -- Decoding from 7z folder
|
||||
2019-02-02 : Igor Pavlov : Public domain */
|
||||
2021-02-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -21,17 +21,20 @@
|
|||
#endif
|
||||
|
||||
#define k_Copy 0
|
||||
#define k_Delta 3
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
#define k_LZMA2 0x21
|
||||
#endif
|
||||
#define k_LZMA 0x30101
|
||||
#define k_BCJ 0x3030103
|
||||
#define k_BCJ2 0x303011B
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
#define k_Delta 3
|
||||
#define k_BCJ 0x3030103
|
||||
#define k_PPC 0x3030205
|
||||
#define k_IA64 0x3030401
|
||||
#define k_ARM 0x3030501
|
||||
#define k_ARMT 0x3030701
|
||||
#define k_SPARC 0x3030805
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
|
||||
|
@ -56,7 +59,7 @@ static Byte ReadByte(const IByteIn *pp)
|
|||
return *p->cur++;
|
||||
if (p->res == SZ_OK)
|
||||
{
|
||||
size_t size = p->cur - p->begin;
|
||||
size_t size = (size_t)(p->cur - p->begin);
|
||||
p->processed += size;
|
||||
p->res = ILookInStream_Skip(p->inStream, size);
|
||||
size = (1 << 25);
|
||||
|
@ -101,28 +104,32 @@ static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, c
|
|||
Ppmd7_Init(&ppmd, order);
|
||||
}
|
||||
{
|
||||
CPpmd7z_RangeDec rc;
|
||||
Ppmd7z_RangeDec_CreateVTable(&rc);
|
||||
rc.Stream = &s.vt;
|
||||
if (!Ppmd7z_RangeDec_Init(&rc))
|
||||
ppmd.rc.dec.Stream = &s.vt;
|
||||
if (!Ppmd7z_RangeDec_Init(&ppmd.rc.dec))
|
||||
res = SZ_ERROR_DATA;
|
||||
else if (s.extra)
|
||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||
else
|
||||
else if (!s.extra)
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < outSize; i++)
|
||||
Byte *buf = outBuffer;
|
||||
const Byte *lim = buf + outSize;
|
||||
for (; buf != lim; buf++)
|
||||
{
|
||||
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt);
|
||||
int sym = Ppmd7z_DecodeSymbol(&ppmd);
|
||||
if (s.extra || sym < 0)
|
||||
break;
|
||||
outBuffer[i] = (Byte)sym;
|
||||
*buf = (Byte)sym;
|
||||
}
|
||||
if (i != outSize)
|
||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
|
||||
if (buf != lim)
|
||||
res = SZ_ERROR_DATA;
|
||||
else if (!Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec))
|
||||
{
|
||||
/* if (Ppmd7z_DecodeSymbol(&ppmd) != PPMD7_SYM_END || !Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec)) */
|
||||
res = SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
if (s.extra)
|
||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||
else if (s.processed + (size_t)(s.cur - s.begin) != inSize)
|
||||
res = SZ_ERROR_DATA;
|
||||
}
|
||||
Ppmd7_Free(&ppmd, allocMain);
|
||||
return res;
|
||||
|
@ -365,7 +372,9 @@ static SRes CheckSupportedFolder(const CSzFolder *f)
|
|||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
|
||||
#endif
|
||||
|
||||
static SRes SzFolder_Decode2(const CSzFolder *folder,
|
||||
const Byte *propsData,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* 7zStream.c -- 7z Stream functions
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2021-02-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -37,7 +37,7 @@ SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf)
|
|||
|
||||
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset)
|
||||
{
|
||||
Int64 t = offset;
|
||||
Int64 t = (Int64)offset;
|
||||
return ILookInStream_Seek(stream, &t, SZ_SEEK_SET);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
/* 7zTypes.h -- Basic types
|
||||
2018-08-04 : Igor Pavlov : Public domain */
|
||||
2021-12-25 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_TYPES_H
|
||||
#define __7Z_TYPES_H
|
||||
|
||||
#ifdef _WIN32
|
||||
/* #include <windows.h> */
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
@ -43,18 +45,116 @@ EXTERN_C_BEGIN
|
|||
typedef int SRes;
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER > 1200
|
||||
#define MY_ALIGN(n) __declspec(align(n))
|
||||
#else
|
||||
#define MY_ALIGN(n)
|
||||
#endif
|
||||
#else
|
||||
#define MY_ALIGN(n) __attribute__ ((aligned(n)))
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* typedef DWORD WRes; */
|
||||
typedef unsigned WRes;
|
||||
#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
|
||||
|
||||
#else
|
||||
// #define MY_HRES_ERROR__INTERNAL_ERROR MY_SRes_HRESULT_FROM_WRes(ERROR_INTERNAL_ERROR)
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
// #define ENV_HAVE_LSTAT
|
||||
typedef int WRes;
|
||||
#define MY__FACILITY_WIN32 7
|
||||
#define MY__FACILITY__WRes MY__FACILITY_WIN32
|
||||
#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
|
||||
|
||||
// (FACILITY_ERRNO = 0x800) is 7zip's FACILITY constant to represent (errno) errors in HRESULT
|
||||
#define MY__FACILITY_ERRNO 0x800
|
||||
#define MY__FACILITY_WIN32 7
|
||||
#define MY__FACILITY__WRes MY__FACILITY_ERRNO
|
||||
|
||||
#define MY_HRESULT_FROM_errno_CONST_ERROR(x) ((HRESULT)( \
|
||||
( (HRESULT)(x) & 0x0000FFFF) \
|
||||
| (MY__FACILITY__WRes << 16) \
|
||||
| (HRESULT)0x80000000 ))
|
||||
|
||||
#define MY_SRes_HRESULT_FROM_WRes(x) \
|
||||
((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : MY_HRESULT_FROM_errno_CONST_ERROR(x))
|
||||
|
||||
// we call macro HRESULT_FROM_WIN32 for system errors (WRes) that are (errno)
|
||||
#define HRESULT_FROM_WIN32(x) MY_SRes_HRESULT_FROM_WRes(x)
|
||||
|
||||
/*
|
||||
#define ERROR_FILE_NOT_FOUND 2L
|
||||
#define ERROR_ACCESS_DENIED 5L
|
||||
#define ERROR_NO_MORE_FILES 18L
|
||||
#define ERROR_LOCK_VIOLATION 33L
|
||||
#define ERROR_FILE_EXISTS 80L
|
||||
#define ERROR_DISK_FULL 112L
|
||||
#define ERROR_NEGATIVE_SEEK 131L
|
||||
#define ERROR_ALREADY_EXISTS 183L
|
||||
#define ERROR_DIRECTORY 267L
|
||||
#define ERROR_TOO_MANY_POSTS 298L
|
||||
|
||||
#define ERROR_INTERNAL_ERROR 1359L
|
||||
#define ERROR_INVALID_REPARSE_DATA 4392L
|
||||
#define ERROR_REPARSE_TAG_INVALID 4393L
|
||||
#define ERROR_REPARSE_TAG_MISMATCH 4394L
|
||||
*/
|
||||
|
||||
// we use errno equivalents for some WIN32 errors:
|
||||
|
||||
#define ERROR_INVALID_PARAMETER EINVAL
|
||||
#define ERROR_INVALID_FUNCTION EINVAL
|
||||
#define ERROR_ALREADY_EXISTS EEXIST
|
||||
#define ERROR_FILE_EXISTS EEXIST
|
||||
#define ERROR_PATH_NOT_FOUND ENOENT
|
||||
#define ERROR_FILE_NOT_FOUND ENOENT
|
||||
#define ERROR_DISK_FULL ENOSPC
|
||||
// #define ERROR_INVALID_HANDLE EBADF
|
||||
|
||||
// we use FACILITY_WIN32 for errors that has no errno equivalent
|
||||
// Too many posts were made to a semaphore.
|
||||
#define ERROR_TOO_MANY_POSTS ((HRESULT)0x8007012AL)
|
||||
#define ERROR_INVALID_REPARSE_DATA ((HRESULT)0x80071128L)
|
||||
#define ERROR_REPARSE_TAG_INVALID ((HRESULT)0x80071129L)
|
||||
|
||||
// if (MY__FACILITY__WRes != FACILITY_WIN32),
|
||||
// we use FACILITY_WIN32 for COM errors:
|
||||
#define E_OUTOFMEMORY ((HRESULT)0x8007000EL)
|
||||
#define E_INVALIDARG ((HRESULT)0x80070057L)
|
||||
#define MY__E_ERROR_NEGATIVE_SEEK ((HRESULT)0x80070083L)
|
||||
|
||||
/*
|
||||
// we can use FACILITY_ERRNO for some COM errors, that have errno equivalents:
|
||||
#define E_OUTOFMEMORY MY_HRESULT_FROM_errno_CONST_ERROR(ENOMEM)
|
||||
#define E_INVALIDARG MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL)
|
||||
#define MY__E_ERROR_NEGATIVE_SEEK MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL)
|
||||
*/
|
||||
|
||||
// gcc / clang : (sizeof(long) == sizeof(void*)) in 32/64 bits
|
||||
typedef long INT_PTR;
|
||||
typedef unsigned long UINT_PTR;
|
||||
|
||||
#define TEXT(quote) quote
|
||||
|
||||
#define FILE_ATTRIBUTE_READONLY 0x0001
|
||||
#define FILE_ATTRIBUTE_HIDDEN 0x0002
|
||||
#define FILE_ATTRIBUTE_SYSTEM 0x0004
|
||||
#define FILE_ATTRIBUTE_DIRECTORY 0x0010
|
||||
#define FILE_ATTRIBUTE_ARCHIVE 0x0020
|
||||
#define FILE_ATTRIBUTE_DEVICE 0x0040
|
||||
#define FILE_ATTRIBUTE_NORMAL 0x0080
|
||||
#define FILE_ATTRIBUTE_TEMPORARY 0x0100
|
||||
#define FILE_ATTRIBUTE_SPARSE_FILE 0x0200
|
||||
#define FILE_ATTRIBUTE_REPARSE_POINT 0x0400
|
||||
#define FILE_ATTRIBUTE_COMPRESSED 0x0800
|
||||
#define FILE_ATTRIBUTE_OFFLINE 0x1000
|
||||
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x2000
|
||||
#define FILE_ATTRIBUTE_ENCRYPTED 0x4000
|
||||
|
||||
#define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000 /* trick for Unix */
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -63,6 +163,10 @@ typedef int WRes;
|
|||
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
|
||||
#endif
|
||||
|
||||
#ifndef RINOK_WRes
|
||||
#define RINOK_WRes(x) { WRes __result__ = (x); if (__result__ != 0) return __result__; }
|
||||
#endif
|
||||
|
||||
typedef unsigned char Byte;
|
||||
typedef short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
|
@ -75,6 +179,40 @@ typedef int Int32;
|
|||
typedef unsigned int UInt32;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
typedef int INT;
|
||||
typedef Int32 INT32;
|
||||
typedef unsigned int UINT;
|
||||
typedef UInt32 UINT32;
|
||||
typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit for _WIN32 compatibility
|
||||
typedef UINT32 ULONG;
|
||||
|
||||
#undef DWORD
|
||||
typedef UINT32 DWORD;
|
||||
|
||||
#define VOID void
|
||||
|
||||
#define HRESULT LONG
|
||||
|
||||
typedef void *LPVOID;
|
||||
// typedef void VOID;
|
||||
// typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
|
||||
// gcc / clang on Unix : sizeof(long==sizeof(void*) in 32 or 64 bits)
|
||||
typedef long INT_PTR;
|
||||
typedef unsigned long UINT_PTR;
|
||||
typedef long LONG_PTR;
|
||||
typedef unsigned long DWORD_PTR;
|
||||
|
||||
typedef size_t SIZE_T;
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
#define MY_HRES_ERROR__INTERNAL_ERROR ((HRESULT)0x8007054FL)
|
||||
|
||||
|
||||
#ifdef _SZ_NO_INT_64
|
||||
|
||||
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||
|
@ -128,25 +266,37 @@ typedef int BoolInt;
|
|||
#define MY_CDECL __cdecl
|
||||
#define MY_FAST_CALL __fastcall
|
||||
|
||||
#else
|
||||
#else // _MSC_VER
|
||||
|
||||
#define MY_NO_INLINE
|
||||
#define MY_FORCE_INLINE
|
||||
#define MY_CDECL
|
||||
#define MY_FAST_CALL
|
||||
|
||||
/* inline keyword : for C++ / C99 */
|
||||
|
||||
/* GCC, clang: */
|
||||
/*
|
||||
#if defined (__GNUC__) && (__GNUC__ >= 4)
|
||||
#define MY_FORCE_INLINE __attribute__((always_inline))
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) \
|
||||
|| (defined(__clang__) && (__clang_major__ >= 4)) \
|
||||
|| defined(__INTEL_COMPILER) \
|
||||
|| defined(__xlC__)
|
||||
#define MY_NO_INLINE __attribute__((noinline))
|
||||
// #define MY_FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#else
|
||||
#define MY_NO_INLINE
|
||||
#endif
|
||||
*/
|
||||
|
||||
#define MY_FORCE_INLINE
|
||||
|
||||
|
||||
#define MY_CDECL
|
||||
|
||||
#if defined(_M_IX86) \
|
||||
|| defined(__i386__)
|
||||
// #define MY_FAST_CALL __attribute__((fastcall))
|
||||
// #define MY_FAST_CALL __attribute__((cdecl))
|
||||
#define MY_FAST_CALL
|
||||
#elif defined(MY_CPU_AMD64)
|
||||
// #define MY_FAST_CALL __attribute__((ms_abi))
|
||||
#define MY_FAST_CALL
|
||||
#else
|
||||
#define MY_FAST_CALL
|
||||
#endif
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
/* The following interfaces use first parameter as pointer to structure */
|
||||
|
||||
|
@ -335,12 +485,11 @@ struct ISzAlloc
|
|||
GCC 4.8.1 : classes with non-public variable members"
|
||||
*/
|
||||
|
||||
#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
|
||||
|
||||
#define MY_container_of(ptr, type, m) ((type *)(void *)((char *)(void *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
|
||||
|
||||
#endif
|
||||
|
||||
#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr))
|
||||
#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(void *)(ptr))
|
||||
|
||||
/*
|
||||
#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
|
||||
|
@ -353,6 +502,7 @@ struct ISzAlloc
|
|||
*/
|
||||
|
||||
|
||||
#define MY_memset_0_ARRAY(a) memset((a), 0, sizeof(a))
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
||||
2018-04-28 : Igor Pavlov : Public domain */
|
||||
2021-02-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -123,7 +123,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
|||
const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
|
||||
const Byte *srcLim;
|
||||
Byte *dest;
|
||||
SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
|
||||
SizeT num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src);
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
|
@ -134,7 +134,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
|||
dest = p->dest;
|
||||
if (num > (SizeT)(p->destLim - dest))
|
||||
{
|
||||
num = p->destLim - dest;
|
||||
num = (SizeT)(p->destLim - dest);
|
||||
if (num == 0)
|
||||
{
|
||||
p->state = BCJ2_DEC_STATE_ORIG;
|
||||
|
@ -168,7 +168,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
|||
break;
|
||||
}
|
||||
|
||||
num = src - p->bufs[BCJ2_STREAM_MAIN];
|
||||
num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]);
|
||||
|
||||
if (src == srcLim)
|
||||
{
|
||||
|
@ -228,7 +228,7 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
|||
p->ip += 4;
|
||||
val -= p->ip;
|
||||
dest = p->dest;
|
||||
rem = p->destLim - dest;
|
||||
rem = (SizeT)(p->destLim - dest);
|
||||
|
||||
if (rem < 4)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Bra.c -- Converters for RISC code
|
||||
2017-04-04 : Igor Pavlov : Public domain */
|
||||
2021-02-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -22,7 +22,7 @@ SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
|||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
return (SizeT)(p - data);
|
||||
p += 4;
|
||||
if (p[-1] == 0xEB)
|
||||
break;
|
||||
|
@ -43,7 +43,7 @@ SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
|||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
return (SizeT)(p - data);
|
||||
p += 4;
|
||||
if (p[-1] == 0xEB)
|
||||
break;
|
||||
|
@ -78,7 +78,7 @@ SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
|||
{
|
||||
UInt32 b3;
|
||||
if (p > lim)
|
||||
return p - data;
|
||||
return (SizeT)(p - data);
|
||||
b1 = p[1];
|
||||
b3 = p[3];
|
||||
p += 2;
|
||||
|
@ -113,7 +113,7 @@ SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
|||
{
|
||||
UInt32 b3;
|
||||
if (p > lim)
|
||||
return p - data;
|
||||
return (SizeT)(p - data);
|
||||
b1 = p[1];
|
||||
b3 = p[3];
|
||||
p += 2;
|
||||
|
@ -162,7 +162,7 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
|||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
return (SizeT)(p - data);
|
||||
p += 4;
|
||||
/* if ((v & 0xFC000003) == 0x48000001) */
|
||||
if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1)
|
||||
|
@ -196,7 +196,7 @@ SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
|||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
return (SizeT)(p - data);
|
||||
/*
|
||||
v = GetBe32(p);
|
||||
p += 4;
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
/* Compiler.h
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2021-01-05 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_COMPILER_H
|
||||
#define __7Z_COMPILER_H
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifdef UNDER_CE
|
||||
|
@ -25,6 +29,12 @@
|
|||
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#pragma clang diagnostic ignored "-Wmicrosoft-exception-spec"
|
||||
// #pragma clang diagnostic ignored "-Wreserved-id-macro"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define UNUSED_VAR(x) (void)x;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* CpuArch.c -- CPU specific code
|
||||
2018-02-18: Igor Pavlov : Public domain */
|
||||
2021-07-13 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -55,6 +55,47 @@ static UInt32 CheckFlag(UInt32 flag)
|
|||
#define CHECK_CPUID_IS_SUPPORTED
|
||||
#endif
|
||||
|
||||
#ifndef USE_ASM
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER >= 1600
|
||||
#define MY__cpuidex __cpuidex
|
||||
#else
|
||||
|
||||
/*
|
||||
__cpuid (function == 4) requires subfunction number in ECX.
|
||||
MSDN: The __cpuid intrinsic clears the ECX register before calling the cpuid instruction.
|
||||
__cpuid() in new MSVC clears ECX.
|
||||
__cpuid() in old MSVC (14.00) doesn't clear ECX
|
||||
We still can use __cpuid for low (function) values that don't require ECX,
|
||||
but __cpuid() in old MSVC will be incorrect for some function values: (function == 4).
|
||||
So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction,
|
||||
where ECX value is first parameter for FAST_CALL / NO_INLINE function,
|
||||
So the caller of MY__cpuidex_HACK() sets ECX as subFunction, and
|
||||
old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value.
|
||||
|
||||
DON'T remove MY_NO_INLINE and MY_FAST_CALL for MY__cpuidex_HACK() !!!
|
||||
*/
|
||||
|
||||
static
|
||||
MY_NO_INLINE
|
||||
void MY_FAST_CALL MY__cpuidex_HACK(UInt32 subFunction, int *CPUInfo, UInt32 function)
|
||||
{
|
||||
UNUSED_VAR(subFunction);
|
||||
__cpuid(CPUInfo, function);
|
||||
}
|
||||
|
||||
#define MY__cpuidex(info, func, func2) MY__cpuidex_HACK(func2, info, func)
|
||||
#pragma message("======== MY__cpuidex_HACK WAS USED ========")
|
||||
#endif
|
||||
#else
|
||||
#define MY__cpuidex(info, func, func2) __cpuid(info, func)
|
||||
#pragma message("======== (INCORRECT ?) cpuid WAS USED ========")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
||||
{
|
||||
#ifdef USE_ASM
|
||||
|
@ -99,18 +140,20 @@ void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
|||
#endif
|
||||
"=c" (*c) ,
|
||||
"=d" (*d)
|
||||
: "0" (function)) ;
|
||||
: "0" (function), "c"(0) ) ;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, function);
|
||||
*a = CPUInfo[0];
|
||||
*b = CPUInfo[1];
|
||||
*c = CPUInfo[2];
|
||||
*d = CPUInfo[3];
|
||||
|
||||
MY__cpuidex(CPUInfo, (int)function, 0);
|
||||
|
||||
*a = (UInt32)CPUInfo[0];
|
||||
*b = (UInt32)CPUInfo[1];
|
||||
*c = (UInt32)CPUInfo[2];
|
||||
*d = (UInt32)CPUInfo[3];
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -174,7 +217,7 @@ BoolInt CPU_Is_InOrder()
|
|||
}
|
||||
|
||||
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <Windows.h>
|
||||
static BoolInt CPU_Sys_Is_SSE_Supported()
|
||||
{
|
||||
OSVERSIONINFO vi;
|
||||
|
@ -188,13 +231,101 @@ static BoolInt CPU_Sys_Is_SSE_Supported()
|
|||
#define CHECK_SYS_SSE_SUPPORT
|
||||
#endif
|
||||
|
||||
BoolInt CPU_Is_Aes_Supported()
|
||||
|
||||
static UInt32 X86_CPUID_ECX_Get_Flags()
|
||||
{
|
||||
Cx86cpuid p;
|
||||
CHECK_SYS_SSE_SUPPORT
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return 0;
|
||||
return p.c;
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_AES()
|
||||
{
|
||||
return (X86_CPUID_ECX_Get_Flags() >> 25) & 1;
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_SSSE3()
|
||||
{
|
||||
return (X86_CPUID_ECX_Get_Flags() >> 9) & 1;
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_SSE41()
|
||||
{
|
||||
return (X86_CPUID_ECX_Get_Flags() >> 19) & 1;
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_SHA()
|
||||
{
|
||||
Cx86cpuid p;
|
||||
CHECK_SYS_SSE_SUPPORT
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return False;
|
||||
return (p.c >> 25) & 1;
|
||||
|
||||
if (p.maxFunc < 7)
|
||||
return False;
|
||||
{
|
||||
UInt32 d[4] = { 0 };
|
||||
MyCPUID(7, &d[0], &d[1], &d[2], &d[3]);
|
||||
return (d[1] >> 29) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
BoolInt CPU_IsSupported_AVX2()
|
||||
{
|
||||
Cx86cpuid p;
|
||||
CHECK_SYS_SSE_SUPPORT
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MY__PF_XSAVE_ENABLED 17
|
||||
if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED))
|
||||
return False;
|
||||
#endif
|
||||
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return False;
|
||||
if (p.maxFunc < 7)
|
||||
return False;
|
||||
{
|
||||
UInt32 d[4] = { 0 };
|
||||
MyCPUID(7, &d[0], &d[1], &d[2], &d[3]);
|
||||
// printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
|
||||
return 1
|
||||
& (d[1] >> 5); // avx2
|
||||
}
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_VAES_AVX2()
|
||||
{
|
||||
Cx86cpuid p;
|
||||
CHECK_SYS_SSE_SUPPORT
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MY__PF_XSAVE_ENABLED 17
|
||||
if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED))
|
||||
return False;
|
||||
#endif
|
||||
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return False;
|
||||
if (p.maxFunc < 7)
|
||||
return False;
|
||||
{
|
||||
UInt32 d[4] = { 0 };
|
||||
MyCPUID(7, &d[0], &d[1], &d[2], &d[3]);
|
||||
// printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
|
||||
return 1
|
||||
& (d[1] >> 5) // avx2
|
||||
// & (d[1] >> 31) // avx512vl
|
||||
& (d[2] >> 9); // vaes // VEX-256/EVEX
|
||||
}
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_PageGB()
|
||||
|
@ -215,4 +346,133 @@ BoolInt CPU_IsSupported_PageGB()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined(MY_CPU_ARM_OR_ARM64)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
BoolInt CPU_IsSupported_CRC32() { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
|
||||
BoolInt CPU_IsSupported_CRYPTO() { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
|
||||
BoolInt CPU_IsSupported_NEON() { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
|
||||
|
||||
#else
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
/*
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
static void Print_sysctlbyname(const char *name)
|
||||
{
|
||||
size_t bufSize = 256;
|
||||
char buf[256];
|
||||
int res = sysctlbyname(name, &buf, &bufSize, NULL, 0);
|
||||
{
|
||||
int i;
|
||||
printf("\nres = %d : %s : '%s' : bufSize = %d, numeric", res, name, buf, (unsigned)bufSize);
|
||||
for (i = 0; i < 20; i++)
|
||||
printf(" %2x", (unsigned)(Byte)buf[i]);
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static BoolInt My_sysctlbyname_Get_BoolInt(const char *name)
|
||||
{
|
||||
UInt32 val = 0;
|
||||
if (My_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Print_sysctlbyname("hw.pagesize");
|
||||
Print_sysctlbyname("machdep.cpu.brand_string");
|
||||
*/
|
||||
|
||||
BoolInt CPU_IsSupported_CRC32(void)
|
||||
{
|
||||
return My_sysctlbyname_Get_BoolInt("hw.optional.armv8_crc32");
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_NEON(void)
|
||||
{
|
||||
return My_sysctlbyname_Get_BoolInt("hw.optional.neon");
|
||||
}
|
||||
|
||||
#ifdef MY_CPU_ARM64
|
||||
#define APPLE_CRYPTO_SUPPORT_VAL 1
|
||||
#else
|
||||
#define APPLE_CRYPTO_SUPPORT_VAL 0
|
||||
#endif
|
||||
|
||||
BoolInt CPU_IsSupported_SHA1(void) { return APPLE_CRYPTO_SUPPORT_VAL; }
|
||||
BoolInt CPU_IsSupported_SHA2(void) { return APPLE_CRYPTO_SUPPORT_VAL; }
|
||||
BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
|
||||
|
||||
|
||||
#else // __APPLE__
|
||||
|
||||
#include <sys/auxv.h>
|
||||
|
||||
#define USE_HWCAP
|
||||
|
||||
#ifdef USE_HWCAP
|
||||
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
#define MY_HWCAP_CHECK_FUNC_2(name1, name2) \
|
||||
BoolInt CPU_IsSupported_ ## name1() { return (getauxval(AT_HWCAP) & (HWCAP_ ## name2)) ? 1 : 0; }
|
||||
|
||||
#ifdef MY_CPU_ARM64
|
||||
#define MY_HWCAP_CHECK_FUNC(name) \
|
||||
MY_HWCAP_CHECK_FUNC_2(name, name)
|
||||
MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD)
|
||||
// MY_HWCAP_CHECK_FUNC (ASIMD)
|
||||
#elif defined(MY_CPU_ARM)
|
||||
#define MY_HWCAP_CHECK_FUNC(name) \
|
||||
BoolInt CPU_IsSupported_ ## name() { return (getauxval(AT_HWCAP2) & (HWCAP2_ ## name)) ? 1 : 0; }
|
||||
MY_HWCAP_CHECK_FUNC_2(NEON, NEON)
|
||||
#endif
|
||||
|
||||
#else // USE_HWCAP
|
||||
|
||||
#define MY_HWCAP_CHECK_FUNC(name) \
|
||||
BoolInt CPU_IsSupported_ ## name() { return 0; }
|
||||
MY_HWCAP_CHECK_FUNC(NEON)
|
||||
|
||||
#endif // USE_HWCAP
|
||||
|
||||
MY_HWCAP_CHECK_FUNC (CRC32)
|
||||
MY_HWCAP_CHECK_FUNC (SHA1)
|
||||
MY_HWCAP_CHECK_FUNC (SHA2)
|
||||
MY_HWCAP_CHECK_FUNC (AES)
|
||||
|
||||
#endif // __APPLE__
|
||||
#endif // _WIN32
|
||||
|
||||
#endif // MY_CPU_ARM_OR_ARM64
|
||||
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize)
|
||||
{
|
||||
return sysctlbyname(name, buf, bufSize, NULL, 0);
|
||||
}
|
||||
|
||||
int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val)
|
||||
{
|
||||
size_t bufSize = sizeof(*val);
|
||||
int res = My_sysctlbyname_Get(name, val, &bufSize);
|
||||
if (res == 0 && bufSize != sizeof(*val))
|
||||
return EFAULT;
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* CpuArch.h -- CPU specific code
|
||||
2018-02-18 : Igor Pavlov : Public domain */
|
||||
2021-07-13 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __CPU_ARCH_H
|
||||
#define __CPU_ARCH_H
|
||||
|
@ -14,6 +14,10 @@ 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_64BIT means that processor can work with 64-bit registers.
|
||||
MY_CPU_64BIT can be used to select fast code branch
|
||||
MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8)
|
||||
*/
|
||||
|
||||
#if defined(_M_X64) \
|
||||
|
@ -24,8 +28,10 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
#define MY_CPU_AMD64
|
||||
#ifdef __ILP32__
|
||||
#define MY_CPU_NAME "x32"
|
||||
#define MY_CPU_SIZEOF_POINTER 4
|
||||
#else
|
||||
#define MY_CPU_NAME "x64"
|
||||
#define MY_CPU_SIZEOF_POINTER 8
|
||||
#endif
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
@ -35,7 +41,8 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
|| defined(__i386__)
|
||||
#define MY_CPU_X86
|
||||
#define MY_CPU_NAME "x86"
|
||||
#define MY_CPU_32BIT
|
||||
/* #define MY_CPU_32BIT */
|
||||
#define MY_CPU_SIZEOF_POINTER 4
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -59,8 +66,14 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
|| defined(__THUMBEL__) \
|
||||
|| defined(__THUMBEB__)
|
||||
#define MY_CPU_ARM
|
||||
#define MY_CPU_NAME "arm"
|
||||
#define MY_CPU_32BIT
|
||||
|
||||
#if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT)
|
||||
#define MY_CPU_NAME "armt"
|
||||
#else
|
||||
#define MY_CPU_NAME "arm"
|
||||
#endif
|
||||
/* #define MY_CPU_32BIT */
|
||||
#define MY_CPU_SIZEOF_POINTER 4
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -84,17 +97,29 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
|
||||
|
||||
#if defined(__ppc64__) \
|
||||
|| defined(__powerpc64__)
|
||||
|| defined(__powerpc64__) \
|
||||
|| defined(__ppc__) \
|
||||
|| defined(__powerpc__) \
|
||||
|| defined(__PPC__) \
|
||||
|| defined(_POWER)
|
||||
|
||||
#if defined(__ppc64__) \
|
||||
|| defined(__powerpc64__) \
|
||||
|| defined(_LP64) \
|
||||
|| defined(__64BIT__)
|
||||
#ifdef __ILP32__
|
||||
#define MY_CPU_NAME "ppc64-32"
|
||||
#define MY_CPU_SIZEOF_POINTER 4
|
||||
#else
|
||||
#define MY_CPU_NAME "ppc64"
|
||||
#define MY_CPU_SIZEOF_POINTER 8
|
||||
#endif
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__ppc__) \
|
||||
|| defined(__powerpc__)
|
||||
#else
|
||||
#define MY_CPU_NAME "ppc"
|
||||
#define MY_CPU_32BIT
|
||||
#define MY_CPU_SIZEOF_POINTER 4
|
||||
/* #define MY_CPU_32BIT */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -111,6 +136,10 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
#define MY_CPU_X86_OR_AMD64
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64)
|
||||
#define MY_CPU_ARM_OR_ARM64
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
@ -170,6 +199,40 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
#error Stop_Compiling_Bad_32_64_BIT
|
||||
#endif
|
||||
|
||||
#ifdef __SIZEOF_POINTER__
|
||||
#ifdef MY_CPU_SIZEOF_POINTER
|
||||
#if MY_CPU_SIZEOF_POINTER != __SIZEOF_POINTER__
|
||||
#error Stop_Compiling_Bad_MY_CPU_PTR_SIZE
|
||||
#endif
|
||||
#else
|
||||
#define MY_CPU_SIZEOF_POINTER __SIZEOF_POINTER__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
|
||||
#if defined (_LP64)
|
||||
#error Stop_Compiling_Bad_MY_CPU_PTR_SIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER >= 1300
|
||||
#define MY_CPU_pragma_pack_push_1 __pragma(pack(push, 1))
|
||||
#define MY_CPU_pragma_pop __pragma(pack(pop))
|
||||
#else
|
||||
#define MY_CPU_pragma_pack_push_1
|
||||
#define MY_CPU_pragma_pop
|
||||
#endif
|
||||
#else
|
||||
#ifdef __xlC__
|
||||
#define MY_CPU_pragma_pack_push_1 _Pragma("pack(1)")
|
||||
#define MY_CPU_pragma_pop _Pragma("pack()")
|
||||
#else
|
||||
#define MY_CPU_pragma_pack_push_1 _Pragma("pack(push, 1)")
|
||||
#define MY_CPU_pragma_pop _Pragma("pack(pop)")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MY_CPU_NAME
|
||||
#ifdef MY_CPU_LE
|
||||
|
@ -189,8 +252,12 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
|
||||
#ifdef MY_CPU_LE
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM64) \
|
||||
|| defined(__ARM_FEATURE_UNALIGNED)
|
||||
|| defined(MY_CPU_ARM64)
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#define MY_CPU_LE_UNALIGN_64
|
||||
#elif defined(__ARM_FEATURE_UNALIGNED)
|
||||
/* gcc9 for 32-bit arm can use LDRD instruction that requires 32-bit alignment.
|
||||
So we can't use unaligned 64-bit operations. */
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#endif
|
||||
#endif
|
||||
|
@ -200,11 +267,15 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
|
||||
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
|
||||
#ifdef MY_CPU_LE_UNALIGN_64
|
||||
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
|
||||
#endif
|
||||
|
||||
#define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
|
||||
#define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
|
||||
#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
|
||||
#define SetUi16(p, v) { *(UInt16 *)(void *)(p) = (v); }
|
||||
#define SetUi32(p, v) { *(UInt32 *)(void *)(p) = (v); }
|
||||
#ifdef MY_CPU_LE_UNALIGN_64
|
||||
#define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); }
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
|
@ -218,8 +289,6 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
((UInt32)((const Byte *)(p))[2] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[3] << 24))
|
||||
|
||||
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||
|
||||
#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)_vvv_; \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 8); }
|
||||
|
@ -230,19 +299,29 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
_ppp_[2] = (Byte)(_vvv_ >> 16); \
|
||||
_ppp_[3] = (Byte)(_vvv_ >> 24); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MY_CPU_LE_UNALIGN_64
|
||||
|
||||
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||
|
||||
#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
|
||||
SetUi32(_ppp2_ , (UInt32)_vvv2_); \
|
||||
SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __has_builtin
|
||||
#define MY__has_builtin(x) __has_builtin(x)
|
||||
#else
|
||||
#define MY__has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
|
||||
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
|
||||
/* Note: we use bswap instruction, that is unsupported in 386 cpu */
|
||||
|
||||
|
@ -253,8 +332,8 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
#pragma intrinsic(_byteswap_uint64)
|
||||
|
||||
/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */
|
||||
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
|
||||
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
|
||||
#define GetBe32(p) _byteswap_ulong (*(const UInt32 *)(const void *)(p))
|
||||
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const void *)(p))
|
||||
|
||||
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
|
||||
|
||||
|
@ -262,9 +341,9 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
|||
(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
|
||||
|| (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) )
|
||||
|
||||
/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */
|
||||
#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
|
||||
#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
|
||||
/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const void *)(p)) */
|
||||
#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const void *)(p))
|
||||
#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const void *)(p))
|
||||
|
||||
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
|
||||
|
||||
|
@ -325,10 +404,37 @@ int x86cpuid_GetFirm(const Cx86cpuid *p);
|
|||
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
|
||||
#define x86cpuid_GetStepping(ver) (ver & 0xF)
|
||||
|
||||
BoolInt CPU_Is_InOrder();
|
||||
BoolInt CPU_Is_Aes_Supported();
|
||||
BoolInt CPU_IsSupported_PageGB();
|
||||
BoolInt CPU_Is_InOrder(void);
|
||||
|
||||
BoolInt CPU_IsSupported_AES(void);
|
||||
BoolInt CPU_IsSupported_AVX2(void);
|
||||
BoolInt CPU_IsSupported_VAES_AVX2(void);
|
||||
BoolInt CPU_IsSupported_SSSE3(void);
|
||||
BoolInt CPU_IsSupported_SSE41(void);
|
||||
BoolInt CPU_IsSupported_SHA(void);
|
||||
BoolInt CPU_IsSupported_PageGB(void);
|
||||
|
||||
#elif defined(MY_CPU_ARM_OR_ARM64)
|
||||
|
||||
BoolInt CPU_IsSupported_CRC32(void);
|
||||
BoolInt CPU_IsSupported_NEON(void);
|
||||
|
||||
#if defined(_WIN32)
|
||||
BoolInt CPU_IsSupported_CRYPTO(void);
|
||||
#define CPU_IsSupported_SHA1 CPU_IsSupported_CRYPTO
|
||||
#define CPU_IsSupported_SHA2 CPU_IsSupported_CRYPTO
|
||||
#define CPU_IsSupported_AES CPU_IsSupported_CRYPTO
|
||||
#else
|
||||
BoolInt CPU_IsSupported_SHA1(void);
|
||||
BoolInt CPU_IsSupported_SHA2(void);
|
||||
BoolInt CPU_IsSupported_AES(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize);
|
||||
int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val);
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Delta.c -- Delta converter
|
||||
2009-05-26 : Igor Pavlov : Public domain */
|
||||
2021-02-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -12,53 +12,158 @@ void Delta_Init(Byte *state)
|
|||
state[i] = 0;
|
||||
}
|
||||
|
||||
static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < size; i++)
|
||||
dest[i] = src[i];
|
||||
}
|
||||
|
||||
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||
{
|
||||
Byte buf[DELTA_STATE_SIZE];
|
||||
unsigned j = 0;
|
||||
MyMemCpy(buf, state, delta);
|
||||
Byte temp[DELTA_STATE_SIZE];
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < size;)
|
||||
unsigned i = 0;
|
||||
do
|
||||
temp[i] = state[i];
|
||||
while (++i != delta);
|
||||
}
|
||||
|
||||
if (size <= delta)
|
||||
{
|
||||
unsigned i = 0, k;
|
||||
do
|
||||
{
|
||||
for (j = 0; j < delta && i < size; i++, j++)
|
||||
Byte b = *data;
|
||||
*data++ = (Byte)(b - temp[i]);
|
||||
temp[i] = b;
|
||||
}
|
||||
while (++i != size);
|
||||
|
||||
k = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (i == delta)
|
||||
i = 0;
|
||||
state[k] = temp[i++];
|
||||
}
|
||||
while (++k != delta);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
Byte *p = data + size - delta;
|
||||
{
|
||||
unsigned i = 0;
|
||||
do
|
||||
state[i] = *p++;
|
||||
while (++i != delta);
|
||||
}
|
||||
{
|
||||
const Byte *lim = data + delta;
|
||||
ptrdiff_t dif = -(ptrdiff_t)delta;
|
||||
|
||||
if (((ptrdiff_t)size + dif) & 1)
|
||||
{
|
||||
Byte b = data[i];
|
||||
data[i] = (Byte)(b - buf[j]);
|
||||
buf[j] = b;
|
||||
--p; *p = (Byte)(*p - p[dif]);
|
||||
}
|
||||
|
||||
while (p != lim)
|
||||
{
|
||||
--p; *p = (Byte)(*p - p[dif]);
|
||||
--p; *p = (Byte)(*p - p[dif]);
|
||||
}
|
||||
|
||||
dif = -dif;
|
||||
|
||||
do
|
||||
{
|
||||
--p; *p = (Byte)(*p - temp[--dif]);
|
||||
}
|
||||
while (dif != 0);
|
||||
}
|
||||
}
|
||||
if (j == delta)
|
||||
j = 0;
|
||||
MyMemCpy(state, buf + j, delta - j);
|
||||
MyMemCpy(state + delta - j, buf, j);
|
||||
}
|
||||
|
||||
|
||||
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||
{
|
||||
Byte buf[DELTA_STATE_SIZE];
|
||||
unsigned j = 0;
|
||||
MyMemCpy(buf, state, delta);
|
||||
unsigned i;
|
||||
const Byte *lim;
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
i = 0;
|
||||
lim = data + size;
|
||||
|
||||
if (size <= delta)
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < size;)
|
||||
do
|
||||
*data = (Byte)(*data + state[i++]);
|
||||
while (++data != lim);
|
||||
|
||||
for (; delta != i; state++, delta--)
|
||||
*state = state[i];
|
||||
data -= i;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
#define B(n) b ## n
|
||||
#define I(n) Byte B(n) = state[n];
|
||||
#define U(n) { B(n) = (Byte)((B(n)) + *data++); data[-1] = (B(n)); }
|
||||
#define F(n) if (data != lim) { U(n) }
|
||||
|
||||
if (delta == 1)
|
||||
{
|
||||
for (j = 0; j < delta && i < size; i++, j++)
|
||||
I(0)
|
||||
if ((lim - data) & 1) { U(0) }
|
||||
while (data != lim) { U(0) U(0) }
|
||||
data -= 1;
|
||||
}
|
||||
else if (delta == 2)
|
||||
{
|
||||
I(0) I(1)
|
||||
lim -= 1; while (data < lim) { U(0) U(1) }
|
||||
lim += 1; F(0)
|
||||
data -= 2;
|
||||
}
|
||||
else if (delta == 3)
|
||||
{
|
||||
I(0) I(1) I(2)
|
||||
lim -= 2; while (data < lim) { U(0) U(1) U(2) }
|
||||
lim += 2; F(0) F(1)
|
||||
data -= 3;
|
||||
}
|
||||
else if (delta == 4)
|
||||
{
|
||||
I(0) I(1) I(2) I(3)
|
||||
lim -= 3; while (data < lim) { U(0) U(1) U(2) U(3) }
|
||||
lim += 3; F(0) F(1) F(2)
|
||||
data -= 4;
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
do
|
||||
{
|
||||
buf[j] = data[i] = (Byte)(buf[j] + data[i]);
|
||||
*data = (Byte)(*data + state[i++]);
|
||||
data++;
|
||||
}
|
||||
while (i != delta);
|
||||
|
||||
{
|
||||
ptrdiff_t dif = -(ptrdiff_t)delta;
|
||||
do
|
||||
*data = (Byte)(*data + data[dif]);
|
||||
while (++data != lim);
|
||||
data += dif;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == delta)
|
||||
j = 0;
|
||||
MyMemCpy(state, buf + j, delta - j);
|
||||
MyMemCpy(state + delta - j, buf, j);
|
||||
|
||||
do
|
||||
*state++ = *data;
|
||||
while (++data != lim);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/* LzFind.h -- Match finder for LZ algorithms
|
||||
2017-06-10 : Igor Pavlov : Public domain */
|
||||
2021-07-13 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_FIND_H
|
||||
#define __LZ_FIND_H
|
||||
|
@ -15,7 +15,7 @@ typedef struct _CMatchFinder
|
|||
Byte *buffer;
|
||||
UInt32 pos;
|
||||
UInt32 posLimit;
|
||||
UInt32 streamPos;
|
||||
UInt32 streamPos; /* wrap over Zero is allowed (streamPos < pos). Use (UInt32)(streamPos - pos) */
|
||||
UInt32 lenLimit;
|
||||
|
||||
UInt32 cyclicBufferPos;
|
||||
|
@ -51,17 +51,19 @@ typedef struct _CMatchFinder
|
|||
UInt64 expectedDataSize;
|
||||
} CMatchFinder;
|
||||
|
||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((const Byte *)(p)->buffer)
|
||||
|
||||
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
||||
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((UInt32)((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);
|
||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||
/* Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); */
|
||||
void MatchFinder_MoveBlock(CMatchFinder *p);
|
||||
void MatchFinder_ReadIfRequired(CMatchFinder *p);
|
||||
|
||||
|
@ -76,10 +78,21 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
|||
ISzAllocPtr alloc);
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
|
||||
// void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
|
||||
|
||||
/*
|
||||
#define Inline_MatchFinder_InitPos(p, val) \
|
||||
(p)->pos = (val); \
|
||||
(p)->streamPos = (val);
|
||||
*/
|
||||
|
||||
#define Inline_MatchFinder_ReduceOffsets(p, subValue) \
|
||||
(p)->pos -= (subValue); \
|
||||
(p)->streamPos -= (subValue);
|
||||
|
||||
|
||||
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||
size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||
UInt32 *distances, UInt32 maxLen);
|
||||
|
||||
/*
|
||||
|
@ -91,7 +104,7 @@ Conditions:
|
|||
typedef void (*Mf_Init_Func)(void *object);
|
||||
typedef UInt32 (*Mf_GetNumAvailableBytes_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);
|
||||
typedef void (*Mf_Skip_Func)(void *object, UInt32);
|
||||
|
||||
typedef struct _IMatchFinder
|
||||
|
@ -101,21 +114,23 @@ typedef struct _IMatchFinder
|
|||
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
|
||||
Mf_GetMatches_Func GetMatches;
|
||||
Mf_Skip_Func Skip;
|
||||
} IMatchFinder;
|
||||
} IMatchFinder2;
|
||||
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable);
|
||||
|
||||
void MatchFinder_Init_LowHash(CMatchFinder *p);
|
||||
void MatchFinder_Init_HighHash(CMatchFinder *p);
|
||||
void MatchFinder_Init_3(CMatchFinder *p, int readData);
|
||||
void MatchFinder_Init_4(CMatchFinder *p);
|
||||
void MatchFinder_Init(CMatchFinder *p);
|
||||
|
||||
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
|
||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
|
||||
void LzFindPrepare(void);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
2021-07-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_FIND_MT_H
|
||||
#define __LZ_FIND_MT_H
|
||||
|
@ -9,31 +9,26 @@
|
|||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define kMtHashBlockSize (1 << 13)
|
||||
#define kMtHashNumBlocks (1 << 3)
|
||||
#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)
|
||||
|
||||
#define kMtBtBlockSize (1 << 14)
|
||||
#define kMtBtNumBlocks (1 << 6)
|
||||
#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)
|
||||
|
||||
typedef struct _CMtSync
|
||||
{
|
||||
UInt32 numProcessedBlocks;
|
||||
CThread thread;
|
||||
UInt64 affinity;
|
||||
|
||||
BoolInt wasCreated;
|
||||
BoolInt needStart;
|
||||
BoolInt csWasInitialized;
|
||||
BoolInt csWasEntered;
|
||||
|
||||
BoolInt exit;
|
||||
BoolInt stopWriting;
|
||||
|
||||
CThread thread;
|
||||
CAutoResetEvent canStart;
|
||||
CAutoResetEvent wasStarted;
|
||||
CAutoResetEvent wasStopped;
|
||||
CSemaphore freeSemaphore;
|
||||
CSemaphore filledSemaphore;
|
||||
BoolInt csWasInitialized;
|
||||
BoolInt csWasEntered;
|
||||
CCriticalSection cs;
|
||||
UInt32 numProcessedBlocks;
|
||||
// UInt32 numBlocks_Sent;
|
||||
} CMtSync;
|
||||
|
||||
typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
|
||||
|
@ -49,18 +44,23 @@ typedef struct _CMatchFinderMt
|
|||
/* LZ */
|
||||
const Byte *pointerToCurPos;
|
||||
UInt32 *btBuf;
|
||||
UInt32 btBufPos;
|
||||
UInt32 btBufPosLimit;
|
||||
const UInt32 *btBufPos;
|
||||
const UInt32 *btBufPosLimit;
|
||||
UInt32 lzPos;
|
||||
UInt32 btNumAvailBytes;
|
||||
|
||||
UInt32 *hash;
|
||||
UInt32 fixedHashSize;
|
||||
// UInt32 hash4Mask;
|
||||
UInt32 historySize;
|
||||
const UInt32 *crc;
|
||||
|
||||
Mf_Mix_Matches MixMatchesFunc;
|
||||
|
||||
UInt32 failure_LZ_BT; // failure in BT transfered to LZ
|
||||
// UInt32 failure_LZ_LZ; // failure in LZ tables
|
||||
UInt32 failureBuf[1];
|
||||
// UInt32 crc[256];
|
||||
|
||||
/* LZ + BT */
|
||||
CMtSync btSync;
|
||||
Byte btDummy[kMtCacheLineDummy];
|
||||
|
@ -70,6 +70,8 @@ typedef struct _CMatchFinderMt
|
|||
UInt32 hashBufPos;
|
||||
UInt32 hashBufPosLimit;
|
||||
UInt32 hashNumAvail;
|
||||
UInt32 failure_BT;
|
||||
|
||||
|
||||
CLzRef *son;
|
||||
UInt32 matchMaxLen;
|
||||
|
@ -77,7 +79,7 @@ typedef struct _CMatchFinderMt
|
|||
UInt32 pos;
|
||||
const Byte *buffer;
|
||||
UInt32 cyclicBufferPos;
|
||||
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
|
||||
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||
UInt32 cutValue;
|
||||
|
||||
/* BT + Hash */
|
||||
|
@ -87,13 +89,19 @@ typedef struct _CMatchFinderMt
|
|||
/* Hash */
|
||||
Mf_GetHeads GetHeadsFunc;
|
||||
CMatchFinder *MatchFinder;
|
||||
// CMatchFinder MatchFinder;
|
||||
} CMatchFinderMt;
|
||||
|
||||
// only for Mt part
|
||||
void MatchFinderMt_Construct(CMatchFinderMt *p);
|
||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc);
|
||||
|
||||
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
|
||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc);
|
||||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
|
||||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable);
|
||||
|
||||
/* call MatchFinderMt_InitMt() before IMatchFinder::Init() */
|
||||
SRes MatchFinderMt_InitMt(CMatchFinderMt *p);
|
||||
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
|
||||
|
||||
EXTERN_C_END
|
||||
|
|
578
libraries/lzma/C/LzFindOpt.c
Normal file
578
libraries/lzma/C/LzFindOpt.c
Normal file
|
@ -0,0 +1,578 @@
|
|||
/* LzFindOpt.c -- multithreaded Match finder for LZ algorithms
|
||||
2021-07-13 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
#include "LzFind.h"
|
||||
|
||||
// #include "LzFindMt.h"
|
||||
|
||||
// #define LOG_ITERS
|
||||
|
||||
// #define LOG_THREAD
|
||||
|
||||
#ifdef LOG_THREAD
|
||||
#include <stdio.h>
|
||||
#define PRF(x) x
|
||||
#else
|
||||
// #define PRF(x)
|
||||
#endif
|
||||
|
||||
#ifdef LOG_ITERS
|
||||
#include <stdio.h>
|
||||
UInt64 g_NumIters_Tree;
|
||||
UInt64 g_NumIters_Loop;
|
||||
UInt64 g_NumIters_Bytes;
|
||||
#define LOG_ITER(x) x
|
||||
#else
|
||||
#define LOG_ITER(x)
|
||||
#endif
|
||||
|
||||
// ---------- BT THREAD ----------
|
||||
|
||||
#define USE_SON_PREFETCH
|
||||
#define USE_LONG_MATCH_OPT
|
||||
|
||||
#define kEmptyHashValue 0
|
||||
|
||||
// #define CYC_TO_POS_OFFSET 0
|
||||
|
||||
// #define CYC_TO_POS_OFFSET 1 // for debug
|
||||
|
||||
/*
|
||||
MY_NO_INLINE
|
||||
UInt32 * MY_FAST_CALL GetMatchesSpecN_1(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, UInt32 *posRes)
|
||||
{
|
||||
do
|
||||
{
|
||||
UInt32 delta;
|
||||
if (hash == size)
|
||||
break;
|
||||
delta = *hash++;
|
||||
|
||||
if (delta == 0 || delta > (UInt32)pos)
|
||||
return NULL;
|
||||
|
||||
lenLimit++;
|
||||
|
||||
if (delta == (UInt32)pos)
|
||||
{
|
||||
CLzRef *ptr1 = son + ((size_t)pos << 1) - CYC_TO_POS_OFFSET * 2;
|
||||
*d++ = 0;
|
||||
ptr1[0] = kEmptyHashValue;
|
||||
ptr1[1] = kEmptyHashValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 *_distances = ++d;
|
||||
|
||||
CLzRef *ptr0 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2 + 1;
|
||||
CLzRef *ptr1 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;
|
||||
|
||||
const Byte *len0 = cur, *len1 = cur;
|
||||
UInt32 cutValue = _cutValue;
|
||||
const Byte *maxLen = cur + _maxLen;
|
||||
|
||||
for (LOG_ITER(g_NumIters_Tree++);;)
|
||||
{
|
||||
LOG_ITER(g_NumIters_Loop++);
|
||||
{
|
||||
const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
|
||||
CLzRef *pair = son + ((size_t)(((ptrdiff_t)pos - CYC_TO_POS_OFFSET) + diff) << 1);
|
||||
const Byte *len = (len0 < len1 ? len0 : len1);
|
||||
|
||||
#ifdef USE_SON_PREFETCH
|
||||
const UInt32 pair0 = *pair;
|
||||
#endif
|
||||
|
||||
if (len[diff] == len[0])
|
||||
{
|
||||
if (++len != lenLimit && len[diff] == len[0])
|
||||
while (++len != lenLimit)
|
||||
{
|
||||
LOG_ITER(g_NumIters_Bytes++);
|
||||
if (len[diff] != len[0])
|
||||
break;
|
||||
}
|
||||
if (maxLen < len)
|
||||
{
|
||||
maxLen = len;
|
||||
*d++ = (UInt32)(len - cur);
|
||||
*d++ = delta - 1;
|
||||
|
||||
if (len == lenLimit)
|
||||
{
|
||||
const UInt32 pair1 = pair[1];
|
||||
*ptr1 =
|
||||
#ifdef USE_SON_PREFETCH
|
||||
pair0;
|
||||
#else
|
||||
pair[0];
|
||||
#endif
|
||||
*ptr0 = pair1;
|
||||
|
||||
_distances[-1] = (UInt32)(d - _distances);
|
||||
|
||||
#ifdef USE_LONG_MATCH_OPT
|
||||
|
||||
if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
|
||||
break;
|
||||
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
hash++;
|
||||
pos++;
|
||||
cur++;
|
||||
lenLimit++;
|
||||
{
|
||||
CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;
|
||||
#if 0
|
||||
*(UInt64 *)(void *)ptr = ((const UInt64 *)(const void *)ptr)[diff];
|
||||
#else
|
||||
const UInt32 p0 = ptr[0 + (diff * 2)];
|
||||
const UInt32 p1 = ptr[1 + (diff * 2)];
|
||||
ptr[0] = p0;
|
||||
ptr[1] = p1;
|
||||
// ptr[0] = ptr[0 + (diff * 2)];
|
||||
// ptr[1] = ptr[1 + (diff * 2)];
|
||||
#endif
|
||||
}
|
||||
// PrintSon(son + 2, pos - 1);
|
||||
// printf("\npos = %x delta = %x\n", pos, delta);
|
||||
len++;
|
||||
*d++ = 2;
|
||||
*d++ = (UInt32)(len - cur);
|
||||
*d++ = delta - 1;
|
||||
if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff);
|
||||
if (len[diff] < len[0])
|
||||
{
|
||||
delta = pair[1];
|
||||
if (delta >= curMatch)
|
||||
return NULL;
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
len1 = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = *pair;
|
||||
if (delta >= curMatch)
|
||||
return NULL;
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
len0 = len;
|
||||
}
|
||||
|
||||
delta = (UInt32)pos - delta;
|
||||
|
||||
if (--cutValue == 0 || delta >= pos)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
_distances[-1] = (UInt32)(d - _distances);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for (tree iterations)
|
||||
}
|
||||
pos++;
|
||||
cur++;
|
||||
}
|
||||
while (d < limit);
|
||||
*posRes = (UInt32)pos;
|
||||
return d;
|
||||
}
|
||||
*/
|
||||
|
||||
/* define cbs if you use 2 functions.
|
||||
GetMatchesSpecN_1() : (pos < _cyclicBufferSize)
|
||||
GetMatchesSpecN_2() : (pos >= _cyclicBufferSize)
|
||||
|
||||
do not define cbs if you use 1 function:
|
||||
GetMatchesSpecN_2()
|
||||
*/
|
||||
|
||||
// #define cbs _cyclicBufferSize
|
||||
|
||||
/*
|
||||
we use size_t for (pos) and (_cyclicBufferPos_ instead of UInt32
|
||||
to eliminate "movsx" BUG in old MSVC x64 compiler.
|
||||
*/
|
||||
|
||||
UInt32 * MY_FAST_CALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,
|
||||
size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,
|
||||
UInt32 *posRes);
|
||||
|
||||
MY_NO_INLINE
|
||||
UInt32 * MY_FAST_CALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,
|
||||
size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,
|
||||
UInt32 *posRes)
|
||||
{
|
||||
do // while (hash != size)
|
||||
{
|
||||
UInt32 delta;
|
||||
|
||||
#ifndef cbs
|
||||
UInt32 cbs;
|
||||
#endif
|
||||
|
||||
if (hash == size)
|
||||
break;
|
||||
|
||||
delta = *hash++;
|
||||
|
||||
if (delta == 0)
|
||||
return NULL;
|
||||
|
||||
lenLimit++;
|
||||
|
||||
#ifndef cbs
|
||||
cbs = _cyclicBufferSize;
|
||||
if ((UInt32)pos < cbs)
|
||||
{
|
||||
if (delta > (UInt32)pos)
|
||||
return NULL;
|
||||
cbs = (UInt32)pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (delta >= cbs)
|
||||
{
|
||||
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
|
||||
*d++ = 0;
|
||||
ptr1[0] = kEmptyHashValue;
|
||||
ptr1[1] = kEmptyHashValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 *_distances = ++d;
|
||||
|
||||
CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
|
||||
|
||||
UInt32 cutValue = _cutValue;
|
||||
const Byte *len0 = cur, *len1 = cur;
|
||||
const Byte *maxLen = cur + _maxLen;
|
||||
|
||||
// if (cutValue == 0) { *ptr0 = *ptr1 = kEmptyHashValue; } else
|
||||
for (LOG_ITER(g_NumIters_Tree++);;)
|
||||
{
|
||||
LOG_ITER(g_NumIters_Loop++);
|
||||
{
|
||||
// SPEC code
|
||||
CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - (ptrdiff_t)delta
|
||||
+ (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)
|
||||
) << 1);
|
||||
|
||||
const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
|
||||
const Byte *len = (len0 < len1 ? len0 : len1);
|
||||
|
||||
#ifdef USE_SON_PREFETCH
|
||||
const UInt32 pair0 = *pair;
|
||||
#endif
|
||||
|
||||
if (len[diff] == len[0])
|
||||
{
|
||||
if (++len != lenLimit && len[diff] == len[0])
|
||||
while (++len != lenLimit)
|
||||
{
|
||||
LOG_ITER(g_NumIters_Bytes++);
|
||||
if (len[diff] != len[0])
|
||||
break;
|
||||
}
|
||||
if (maxLen < len)
|
||||
{
|
||||
maxLen = len;
|
||||
*d++ = (UInt32)(len - cur);
|
||||
*d++ = delta - 1;
|
||||
|
||||
if (len == lenLimit)
|
||||
{
|
||||
const UInt32 pair1 = pair[1];
|
||||
*ptr1 =
|
||||
#ifdef USE_SON_PREFETCH
|
||||
pair0;
|
||||
#else
|
||||
pair[0];
|
||||
#endif
|
||||
*ptr0 = pair1;
|
||||
|
||||
_distances[-1] = (UInt32)(d - _distances);
|
||||
|
||||
#ifdef USE_LONG_MATCH_OPT
|
||||
|
||||
if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
|
||||
break;
|
||||
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
*d++ = 2;
|
||||
*d++ = (UInt32)(lenLimit - cur);
|
||||
*d++ = delta - 1;
|
||||
cur++;
|
||||
lenLimit++;
|
||||
// SPEC
|
||||
_cyclicBufferPos++;
|
||||
{
|
||||
// SPEC code
|
||||
CLzRef *dest = son + ((size_t)(_cyclicBufferPos) << 1);
|
||||
const CLzRef *src = dest + ((diff
|
||||
+ (ptrdiff_t)(UInt32)((_cyclicBufferPos < delta) ? cbs : 0)) << 1);
|
||||
// CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;
|
||||
#if 0
|
||||
*(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src);
|
||||
#else
|
||||
const UInt32 p0 = src[0];
|
||||
const UInt32 p1 = src[1];
|
||||
dest[0] = p0;
|
||||
dest[1] = p1;
|
||||
#endif
|
||||
}
|
||||
pos++;
|
||||
hash++;
|
||||
if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
|
||||
break;
|
||||
} // for() end for long matches
|
||||
}
|
||||
#endif
|
||||
|
||||
break; // break from TREE iterations
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff);
|
||||
if (len[diff] < len[0])
|
||||
{
|
||||
delta = pair[1];
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
len1 = len;
|
||||
if (delta >= curMatch)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = *pair;
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
len0 = len;
|
||||
if (delta >= curMatch)
|
||||
return NULL;
|
||||
}
|
||||
delta = (UInt32)pos - delta;
|
||||
|
||||
if (--cutValue == 0 || delta >= cbs)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
_distances[-1] = (UInt32)(d - _distances);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for (tree iterations)
|
||||
}
|
||||
pos++;
|
||||
_cyclicBufferPos++;
|
||||
cur++;
|
||||
}
|
||||
while (d < limit);
|
||||
*posRes = (UInt32)pos;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
typedef UInt32 uint32plus; // size_t
|
||||
|
||||
UInt32 * MY_FAST_CALL GetMatchesSpecN_3(uint32plus lenLimit, size_t pos, const Byte *cur, CLzRef *son,
|
||||
UInt32 _cutValue, UInt32 *d, uint32plus _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,
|
||||
size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,
|
||||
UInt32 *posRes)
|
||||
{
|
||||
do // while (hash != size)
|
||||
{
|
||||
UInt32 delta;
|
||||
|
||||
#ifndef cbs
|
||||
UInt32 cbs;
|
||||
#endif
|
||||
|
||||
if (hash == size)
|
||||
break;
|
||||
|
||||
delta = *hash++;
|
||||
|
||||
if (delta == 0)
|
||||
return NULL;
|
||||
|
||||
#ifndef cbs
|
||||
cbs = _cyclicBufferSize;
|
||||
if ((UInt32)pos < cbs)
|
||||
{
|
||||
if (delta > (UInt32)pos)
|
||||
return NULL;
|
||||
cbs = (UInt32)pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (delta >= cbs)
|
||||
{
|
||||
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
|
||||
*d++ = 0;
|
||||
ptr1[0] = kEmptyHashValue;
|
||||
ptr1[1] = kEmptyHashValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
|
||||
UInt32 *_distances = ++d;
|
||||
uint32plus len0 = 0, len1 = 0;
|
||||
UInt32 cutValue = _cutValue;
|
||||
uint32plus maxLen = _maxLen;
|
||||
// lenLimit++; // const Byte *lenLimit = cur + _lenLimit;
|
||||
|
||||
for (LOG_ITER(g_NumIters_Tree++);;)
|
||||
{
|
||||
LOG_ITER(g_NumIters_Loop++);
|
||||
{
|
||||
// const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
|
||||
CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - delta
|
||||
+ (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)
|
||||
) << 1);
|
||||
const Byte *pb = cur - delta;
|
||||
uint32plus len = (len0 < len1 ? len0 : len1);
|
||||
|
||||
#ifdef USE_SON_PREFETCH
|
||||
const UInt32 pair0 = *pair;
|
||||
#endif
|
||||
|
||||
if (pb[len] == cur[len])
|
||||
{
|
||||
if (++len != lenLimit && pb[len] == cur[len])
|
||||
while (++len != lenLimit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
if (maxLen < len)
|
||||
{
|
||||
maxLen = len;
|
||||
*d++ = (UInt32)len;
|
||||
*d++ = delta - 1;
|
||||
if (len == lenLimit)
|
||||
{
|
||||
{
|
||||
const UInt32 pair1 = pair[1];
|
||||
*ptr0 = pair1;
|
||||
*ptr1 =
|
||||
#ifdef USE_SON_PREFETCH
|
||||
pair0;
|
||||
#else
|
||||
pair[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
_distances[-1] = (UInt32)(d - _distances);
|
||||
|
||||
#ifdef USE_LONG_MATCH_OPT
|
||||
|
||||
if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit)
|
||||
break;
|
||||
|
||||
{
|
||||
const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
|
||||
for (;;)
|
||||
{
|
||||
*d++ = 2;
|
||||
*d++ = (UInt32)lenLimit;
|
||||
*d++ = delta - 1;
|
||||
_cyclicBufferPos++;
|
||||
{
|
||||
CLzRef *dest = son + ((size_t)_cyclicBufferPos << 1);
|
||||
const CLzRef *src = dest + ((diff +
|
||||
(ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)) << 1);
|
||||
#if 0
|
||||
*(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src);
|
||||
#else
|
||||
const UInt32 p0 = src[0];
|
||||
const UInt32 p1 = src[1];
|
||||
dest[0] = p0;
|
||||
dest[1] = p1;
|
||||
#endif
|
||||
}
|
||||
hash++;
|
||||
pos++;
|
||||
cur++;
|
||||
pb++;
|
||||
if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const UInt32 curMatch = (UInt32)pos - delta;
|
||||
if (pb[len] < cur[len])
|
||||
{
|
||||
delta = pair[1];
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
len1 = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = *pair;
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
len0 = len;
|
||||
}
|
||||
|
||||
{
|
||||
if (delta >= curMatch)
|
||||
return NULL;
|
||||
delta = (UInt32)pos - delta;
|
||||
if (delta >= cbs
|
||||
// delta >= _cyclicBufferSize || delta >= pos
|
||||
|| --cutValue == 0)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
_distances[-1] = (UInt32)(d - _distances);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for (tree iterations)
|
||||
}
|
||||
pos++;
|
||||
_cyclicBufferPos++;
|
||||
cur++;
|
||||
}
|
||||
while (d < limit);
|
||||
*posRes = (UInt32)pos;
|
||||
return d;
|
||||
}
|
||||
*/
|
|
@ -1,57 +1,34 @@
|
|||
/* LzHash.h -- HASH functions for LZ algorithms
|
||||
2015-04-12 : Igor Pavlov : Public domain */
|
||||
2019-10-30 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_HASH_H
|
||||
#define __LZ_HASH_H
|
||||
|
||||
/*
|
||||
(kHash2Size >= (1 << 8)) : Required
|
||||
(kHash3Size >= (1 << 16)) : Required
|
||||
*/
|
||||
|
||||
#define kHash2Size (1 << 10)
|
||||
#define kHash3Size (1 << 16)
|
||||
#define kHash4Size (1 << 20)
|
||||
// #define kHash4Size (1 << 20)
|
||||
|
||||
#define kFix3HashSize (kHash2Size)
|
||||
#define kFix4HashSize (kHash2Size + kHash3Size)
|
||||
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||
// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||
|
||||
#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
|
||||
/*
|
||||
We use up to 3 crc values for hash:
|
||||
crc0
|
||||
crc1 << Shift_1
|
||||
crc2 << Shift_2
|
||||
(Shift_1 = 5) and (Shift_2 = 10) is good tradeoff.
|
||||
Small values for Shift are not good for collision rate.
|
||||
Big value for Shift_2 increases the minimum size
|
||||
of hash table, that will be slow for small files.
|
||||
*/
|
||||
|
||||
#define HASH3_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||
|
||||
#define HASH4_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
|
||||
|
||||
#define HASH5_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
temp ^= (p->crc[cur[3]] << 5); \
|
||||
h4 = temp & (kHash4Size - 1); \
|
||||
hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
|
||||
|
||||
/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||
#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||
|
||||
|
||||
#define MT_HASH2_CALC \
|
||||
h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||
|
||||
#define MT_HASH3_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||
|
||||
#define MT_HASH4_CALC { \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||
#define kLzHash_CrcShift_1 5
|
||||
#define kLzHash_CrcShift_2 10
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||
2019-02-02 : Igor Pavlov : Public domain */
|
||||
2021-02-09 : Igor Pavlov : Public domain */
|
||||
|
||||
/* #define SHOW_DEBUG_INFO */
|
||||
|
||||
|
@ -93,7 +93,8 @@ void Lzma2Dec_Init(CLzma2Dec *p)
|
|||
LzmaDec_Init(&p->decoder);
|
||||
}
|
||||
|
||||
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
// ELzma2State
|
||||
static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
{
|
||||
switch (p->state)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* LzmaDec.c -- LZMA Decoder
|
||||
2018-07-04 : Igor Pavlov : Public domain */
|
||||
2021-04-01 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -13,10 +13,12 @@
|
|||
|
||||
#define kNumBitModelTotalBits 11
|
||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
#define RC_INIT_SIZE 5
|
||||
|
||||
#ifndef _LZMA_DEC_OPT
|
||||
|
||||
#define kNumMoveBits 5
|
||||
#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
|
||||
|
||||
#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
|
||||
|
@ -62,9 +64,10 @@
|
|||
probLit = prob + (offs + bit + symbol); \
|
||||
GET_BIT2(probLit, symbol, offs ^= bit; , ;)
|
||||
|
||||
#endif // _LZMA_DEC_OPT
|
||||
|
||||
|
||||
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
|
||||
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_INPUT_EOF; range <<= 8; code = (code << 8) | (*buf++); }
|
||||
|
||||
#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
|
||||
#define UPDATE_0_CHECK range = bound;
|
||||
|
@ -114,6 +117,9 @@
|
|||
#define kMatchMinLen 2
|
||||
#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols)
|
||||
|
||||
#define kMatchSpecLen_Error_Data (1 << 9)
|
||||
#define kMatchSpecLen_Error_Fail (kMatchSpecLen_Error_Data - 1)
|
||||
|
||||
/* External ASM code needs same CLzmaProb array layout. So don't change it. */
|
||||
|
||||
/* (probs_1664) is faster and better for code size at some platforms */
|
||||
|
@ -166,10 +172,12 @@
|
|||
|
||||
/*
|
||||
p->remainLen : shows status of LZMA decoder:
|
||||
< kMatchSpecLenStart : normal remain
|
||||
= kMatchSpecLenStart : finished
|
||||
= kMatchSpecLenStart + 1 : need init range coder
|
||||
= kMatchSpecLenStart + 2 : need init range coder and state
|
||||
< kMatchSpecLenStart : the number of bytes to be copied with (p->rep0) offset
|
||||
= kMatchSpecLenStart : the LZMA stream was finished with end mark
|
||||
= kMatchSpecLenStart + 1 : need init range coder
|
||||
= kMatchSpecLenStart + 2 : need init range coder and state
|
||||
= kMatchSpecLen_Error_Fail : Internal Code Failure
|
||||
= kMatchSpecLen_Error_Data + [0 ... 273] : LZMA Data Error
|
||||
*/
|
||||
|
||||
/* ---------- LZMA_DECODE_REAL ---------- */
|
||||
|
@ -188,23 +196,31 @@ In:
|
|||
{
|
||||
LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases.
|
||||
So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol
|
||||
is not END_OF_PAYALOAD_MARKER, then function returns error code.
|
||||
is not END_OF_PAYALOAD_MARKER, then the function doesn't write any byte to dictionary,
|
||||
the function returns SZ_OK, and the caller can use (p->remainLen) and (p->reps[0]) later.
|
||||
}
|
||||
|
||||
Processing:
|
||||
first LZMA symbol will be decoded in any case
|
||||
All checks for limits are at the end of main loop,
|
||||
It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit),
|
||||
The first LZMA symbol will be decoded in any case.
|
||||
All main checks for limits are at the end of main loop,
|
||||
It decodes additional LZMA-symbols while (p->buf < bufLimit && dicPos < limit),
|
||||
RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked.
|
||||
But if (p->buf < bufLimit), the caller provided at least (LZMA_REQUIRED_INPUT_MAX + 1) bytes for
|
||||
next iteration before limit (bufLimit + LZMA_REQUIRED_INPUT_MAX),
|
||||
that is enough for worst case LZMA symbol with one additional RangeCoder normalization for one bit.
|
||||
So that function never reads bufLimit [LZMA_REQUIRED_INPUT_MAX] byte.
|
||||
|
||||
Out:
|
||||
RangeCoder is normalized
|
||||
Result:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_DATA - Error
|
||||
p->remainLen:
|
||||
< kMatchSpecLenStart : normal remain
|
||||
= kMatchSpecLenStart : finished
|
||||
p->remainLen:
|
||||
< kMatchSpecLenStart : the number of bytes to be copied with (p->reps[0]) offset
|
||||
= kMatchSpecLenStart : the LZMA stream was finished with end mark
|
||||
|
||||
SZ_ERROR_DATA - error, when the MATCH-Symbol refers out of dictionary
|
||||
p->remainLen : undefined
|
||||
p->reps[*] : undefined
|
||||
*/
|
||||
|
||||
|
||||
|
@ -316,11 +332,6 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
|
|||
else
|
||||
{
|
||||
UPDATE_1(prob);
|
||||
/*
|
||||
// that case was checked before with kBadRepCode
|
||||
if (checkDicSize == 0 && processedPos == 0)
|
||||
return SZ_ERROR_DATA;
|
||||
*/
|
||||
prob = probs + IsRepG0 + state;
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
|
@ -329,6 +340,13 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
|
|||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob);
|
||||
|
||||
// that case was checked before with kBadRepCode
|
||||
// if (checkDicSize == 0 && processedPos == 0) { len = kMatchSpecLen_Error_Data + 1; break; }
|
||||
// The caller doesn't allow (dicPos == limit) case here
|
||||
// so we don't need the following check:
|
||||
// if (dicPos == limit) { state = state < kNumLitStates ? 9 : 11; len = 1; break; }
|
||||
|
||||
dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
|
||||
dicPos++;
|
||||
processedPos++;
|
||||
|
@ -518,8 +536,10 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
|
|||
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
|
||||
if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize))
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
len += kMatchSpecLen_Error_Data + kMatchMinLen;
|
||||
// len = kMatchSpecLen_Error_Data;
|
||||
// len += kMatchMinLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -532,8 +552,13 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
|
|||
|
||||
if ((rem = limit - dicPos) == 0)
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
/*
|
||||
We stop decoding and return SZ_OK, and we can resume decoding later.
|
||||
Any error conditions can be tested later in caller code.
|
||||
For more strict mode we can stop decoding with error
|
||||
// len += kMatchSpecLen_Error_Data;
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
curLen = ((rem < len) ? (unsigned)rem : len);
|
||||
|
@ -572,7 +597,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
|
|||
p->buf = buf;
|
||||
p->range = range;
|
||||
p->code = code;
|
||||
p->remainLen = (UInt32)len;
|
||||
p->remainLen = (UInt32)len; // & (kMatchSpecLen_Error_Data - 1); // we can write real length for error matches too.
|
||||
p->dicPos = dicPos;
|
||||
p->processedPos = processedPos;
|
||||
p->reps[0] = rep0;
|
||||
|
@ -580,40 +605,61 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
|
|||
p->reps[2] = rep2;
|
||||
p->reps[3] = rep3;
|
||||
p->state = (UInt32)state;
|
||||
|
||||
if (len >= kMatchSpecLen_Error_Data)
|
||||
return SZ_ERROR_DATA;
|
||||
return SZ_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
|
||||
{
|
||||
if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
|
||||
unsigned len = (unsigned)p->remainLen;
|
||||
if (len == 0 /* || len >= kMatchSpecLenStart */)
|
||||
return;
|
||||
{
|
||||
Byte *dic = p->dic;
|
||||
SizeT dicPos = p->dicPos;
|
||||
SizeT dicBufSize = p->dicBufSize;
|
||||
unsigned len = (unsigned)p->remainLen;
|
||||
SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
|
||||
SizeT rem = limit - dicPos;
|
||||
if (rem < len)
|
||||
len = (unsigned)(rem);
|
||||
Byte *dic;
|
||||
SizeT dicBufSize;
|
||||
SizeT rep0; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
|
||||
{
|
||||
SizeT rem = limit - dicPos;
|
||||
if (rem < len)
|
||||
{
|
||||
len = (unsigned)(rem);
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
|
||||
p->processedPos += (UInt32)len;
|
||||
p->remainLen -= (UInt32)len;
|
||||
while (len != 0)
|
||||
dic = p->dic;
|
||||
rep0 = p->reps[0];
|
||||
dicBufSize = p->dicBufSize;
|
||||
do
|
||||
{
|
||||
len--;
|
||||
dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
|
||||
dicPos++;
|
||||
}
|
||||
while (--len);
|
||||
p->dicPos = dicPos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
At staring of new stream we have one of the following symbols:
|
||||
- Literal - is allowed
|
||||
- Non-Rep-Match - is allowed only if it's end marker symbol
|
||||
- Rep-Match - is not allowed
|
||||
We use early check of (RangeCoder:Code) over kBadRepCode to simplify main decoding code
|
||||
*/
|
||||
|
||||
#define kRange0 0xFFFFFFFF
|
||||
#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))
|
||||
#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)))
|
||||
|
@ -621,69 +667,77 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
|
|||
#error Stop_Compiling_Bad_LZMA_Check
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
LzmaDec_DecodeReal2():
|
||||
It calls LZMA_DECODE_REAL() and it adjusts limit according (p->checkDicSize).
|
||||
|
||||
We correct (p->checkDicSize) after LZMA_DECODE_REAL() and in LzmaDec_WriteRem(),
|
||||
and we support the following state of (p->checkDicSize):
|
||||
if (total_processed < p->prop.dicSize) then
|
||||
{
|
||||
(total_processed == p->processedPos)
|
||||
(p->checkDicSize == 0)
|
||||
}
|
||||
else
|
||||
(p->checkDicSize == p->prop.dicSize)
|
||||
*/
|
||||
|
||||
static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
|
||||
{
|
||||
do
|
||||
if (p->checkDicSize == 0)
|
||||
{
|
||||
SizeT limit2 = limit;
|
||||
if (p->checkDicSize == 0)
|
||||
{
|
||||
UInt32 rem = p->prop.dicSize - p->processedPos;
|
||||
if (limit - p->dicPos > rem)
|
||||
limit2 = p->dicPos + rem;
|
||||
|
||||
if (p->processedPos == 0)
|
||||
if (p->code >= kBadRepCode)
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit));
|
||||
|
||||
UInt32 rem = p->prop.dicSize - p->processedPos;
|
||||
if (limit - p->dicPos > rem)
|
||||
limit = p->dicPos + rem;
|
||||
}
|
||||
{
|
||||
int res = LZMA_DECODE_REAL(p, limit, bufLimit);
|
||||
if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
|
||||
LzmaDec_WriteRem(p, limit);
|
||||
return res;
|
||||
}
|
||||
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DUMMY_ERROR, /* unexpected end of input stream */
|
||||
DUMMY_INPUT_EOF, /* need more input data */
|
||||
DUMMY_LIT,
|
||||
DUMMY_MATCH,
|
||||
DUMMY_REP
|
||||
} ELzmaDummy;
|
||||
|
||||
static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
|
||||
|
||||
#define IS_DUMMY_END_MARKER_POSSIBLE(dummyRes) ((dummyRes) == DUMMY_MATCH)
|
||||
|
||||
static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byte **bufOut)
|
||||
{
|
||||
UInt32 range = p->range;
|
||||
UInt32 code = p->code;
|
||||
const Byte *bufLimit = buf + inSize;
|
||||
const Byte *bufLimit = *bufOut;
|
||||
const CLzmaProb *probs = GET_PROBS;
|
||||
unsigned state = (unsigned)p->state;
|
||||
ELzmaDummy res;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const CLzmaProb *prob;
|
||||
UInt32 bound;
|
||||
unsigned ttt;
|
||||
unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1);
|
||||
unsigned posState = CALC_POS_STATE(p->processedPos, ((unsigned)1 << p->prop.pb) - 1);
|
||||
|
||||
prob = probs + IsMatch + COMBINED_PS_STATE;
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK
|
||||
|
||||
/* if (bufLimit - buf >= 7) return DUMMY_LIT; */
|
||||
|
||||
prob = probs + Literal;
|
||||
if (p->checkDicSize != 0 || p->processedPos != 0)
|
||||
prob += ((UInt32)LZMA_LIT_SIZE *
|
||||
((((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->processedPos) & (((unsigned)1 << (p->prop.lp)) - 1)) << p->prop.lc) +
|
||||
((unsigned)p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
|
||||
|
||||
if (state < kNumLitStates)
|
||||
{
|
||||
|
@ -735,8 +789,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
|||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
NORMALIZE_CHECK;
|
||||
return DUMMY_REP;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -812,8 +865,6 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
|||
{
|
||||
unsigned numDirectBits = ((posSlot >> 1) - 1);
|
||||
|
||||
/* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
|
||||
|
||||
if (posSlot < kEndPosModelIndex)
|
||||
{
|
||||
prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits);
|
||||
|
@ -844,12 +895,15 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
|||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
NORMALIZE_CHECK;
|
||||
|
||||
*bufOut = buf;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState)
|
||||
{
|
||||
p->remainLen = kMatchSpecLenStart + 1;
|
||||
|
@ -872,16 +926,41 @@ void LzmaDec_Init(CLzmaDec *p)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
LZMA supports optional end_marker.
|
||||
So the decoder can lookahead for one additional LZMA-Symbol to check end_marker.
|
||||
That additional LZMA-Symbol can require up to LZMA_REQUIRED_INPUT_MAX bytes in input stream.
|
||||
When the decoder reaches dicLimit, it looks (finishMode) parameter:
|
||||
if (finishMode == LZMA_FINISH_ANY), the decoder doesn't lookahead
|
||||
if (finishMode != LZMA_FINISH_ANY), the decoder lookahead, if end_marker is possible for current position
|
||||
|
||||
When the decoder lookahead, and the lookahead symbol is not end_marker, we have two ways:
|
||||
1) Strict mode (default) : the decoder returns SZ_ERROR_DATA.
|
||||
2) The relaxed mode (alternative mode) : we could return SZ_OK, and the caller
|
||||
must check (status) value. The caller can show the error,
|
||||
if the end of stream is expected, and the (status) is noit
|
||||
LZMA_STATUS_FINISHED_WITH_MARK or LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK.
|
||||
*/
|
||||
|
||||
|
||||
#define RETURN__NOT_FINISHED__FOR_FINISH \
|
||||
*status = LZMA_STATUS_NOT_FINISHED; \
|
||||
return SZ_ERROR_DATA; // for strict mode
|
||||
// return SZ_OK; // for relaxed mode
|
||||
|
||||
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
|
||||
ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT inSize = *srcLen;
|
||||
(*srcLen) = 0;
|
||||
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
if (p->remainLen > kMatchSpecLenStart)
|
||||
{
|
||||
if (p->remainLen > kMatchSpecLenStart + 2)
|
||||
return p->remainLen == kMatchSpecLen_Error_Fail ? SZ_ERROR_FAIL : SZ_ERROR_DATA;
|
||||
|
||||
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
|
||||
p->tempBuf[p->tempBufSize++] = *src++;
|
||||
if (p->tempBufSize != 0 && p->tempBuf[0] != 0)
|
||||
|
@ -896,6 +975,12 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
|
|||
| ((UInt32)p->tempBuf[2] << 16)
|
||||
| ((UInt32)p->tempBuf[3] << 8)
|
||||
| ((UInt32)p->tempBuf[4]);
|
||||
|
||||
if (p->checkDicSize == 0
|
||||
&& p->processedPos == 0
|
||||
&& p->code >= kBadRepCode)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
p->range = 0xFFFFFFFF;
|
||||
p->tempBufSize = 0;
|
||||
|
||||
|
@ -913,10 +998,21 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
|
|||
p->remainLen = 0;
|
||||
}
|
||||
|
||||
LzmaDec_WriteRem(p, dicLimit);
|
||||
|
||||
while (p->remainLen != kMatchSpecLenStart)
|
||||
for (;;)
|
||||
{
|
||||
if (p->remainLen == kMatchSpecLenStart)
|
||||
{
|
||||
if (p->code != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
LzmaDec_WriteRem(p, dicLimit);
|
||||
|
||||
{
|
||||
// (p->remainLen == 0 || p->dicPos == dicLimit)
|
||||
|
||||
int checkEndMarkNow = 0;
|
||||
|
||||
if (p->dicPos >= dicLimit)
|
||||
|
@ -933,92 +1029,174 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
|
|||
}
|
||||
if (p->remainLen != 0)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_ERROR_DATA;
|
||||
RETURN__NOT_FINISHED__FOR_FINISH;
|
||||
}
|
||||
checkEndMarkNow = 1;
|
||||
}
|
||||
|
||||
// (p->remainLen == 0)
|
||||
|
||||
if (p->tempBufSize == 0)
|
||||
{
|
||||
SizeT processed;
|
||||
const Byte *bufLimit;
|
||||
int dummyProcessed = -1;
|
||||
|
||||
if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
|
||||
{
|
||||
int dummyRes = LzmaDec_TryDummy(p, src, inSize);
|
||||
if (dummyRes == DUMMY_ERROR)
|
||||
const Byte *bufOut = src + inSize;
|
||||
|
||||
ELzmaDummy dummyRes = LzmaDec_TryDummy(p, src, &bufOut);
|
||||
|
||||
if (dummyRes == DUMMY_INPUT_EOF)
|
||||
{
|
||||
memcpy(p->tempBuf, src, inSize);
|
||||
p->tempBufSize = (unsigned)inSize;
|
||||
size_t i;
|
||||
if (inSize >= LZMA_REQUIRED_INPUT_MAX)
|
||||
break;
|
||||
(*srcLen) += inSize;
|
||||
p->tempBufSize = (unsigned)inSize;
|
||||
for (i = 0; i < inSize; i++)
|
||||
p->tempBuf[i] = src[i];
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
|
||||
|
||||
dummyProcessed = (int)(bufOut - src);
|
||||
if ((unsigned)dummyProcessed > LZMA_REQUIRED_INPUT_MAX)
|
||||
break;
|
||||
|
||||
if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes))
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_ERROR_DATA;
|
||||
unsigned i;
|
||||
(*srcLen) += (unsigned)dummyProcessed;
|
||||
p->tempBufSize = (unsigned)dummyProcessed;
|
||||
for (i = 0; i < (unsigned)dummyProcessed; i++)
|
||||
p->tempBuf[i] = src[i];
|
||||
// p->remainLen = kMatchSpecLen_Error_Data;
|
||||
RETURN__NOT_FINISHED__FOR_FINISH;
|
||||
}
|
||||
|
||||
bufLimit = src;
|
||||
// we will decode only one iteration
|
||||
}
|
||||
else
|
||||
bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
|
||||
|
||||
p->buf = src;
|
||||
if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
processed = (SizeT)(p->buf - src);
|
||||
(*srcLen) += processed;
|
||||
src += processed;
|
||||
inSize -= processed;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned rem = p->tempBufSize, lookAhead = 0;
|
||||
while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
|
||||
p->tempBuf[rem++] = src[lookAhead++];
|
||||
p->tempBufSize = rem;
|
||||
if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
|
||||
|
||||
{
|
||||
int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT)rem);
|
||||
if (dummyRes == DUMMY_ERROR)
|
||||
int res = LzmaDec_DecodeReal2(p, dicLimit, bufLimit);
|
||||
|
||||
SizeT processed = (SizeT)(p->buf - src);
|
||||
|
||||
if (dummyProcessed < 0)
|
||||
{
|
||||
(*srcLen) += (SizeT)lookAhead;
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
if (processed > inSize)
|
||||
break;
|
||||
}
|
||||
if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
|
||||
else if ((unsigned)dummyProcessed != processed)
|
||||
break;
|
||||
|
||||
src += processed;
|
||||
inSize -= processed;
|
||||
(*srcLen) += processed;
|
||||
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
p->remainLen = kMatchSpecLen_Error_Data;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
// we have some data in (p->tempBuf)
|
||||
// in strict mode: tempBufSize is not enough for one Symbol decoding.
|
||||
// in relaxed mode: tempBufSize not larger than required for one Symbol decoding.
|
||||
|
||||
unsigned rem = p->tempBufSize;
|
||||
unsigned ahead = 0;
|
||||
int dummyProcessed = -1;
|
||||
|
||||
while (rem < LZMA_REQUIRED_INPUT_MAX && ahead < inSize)
|
||||
p->tempBuf[rem++] = src[ahead++];
|
||||
|
||||
// ahead - the size of new data copied from (src) to (p->tempBuf)
|
||||
// rem - the size of temp buffer including new data from (src)
|
||||
|
||||
if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
|
||||
{
|
||||
const Byte *bufOut = p->tempBuf + rem;
|
||||
|
||||
ELzmaDummy dummyRes = LzmaDec_TryDummy(p, p->tempBuf, &bufOut);
|
||||
|
||||
if (dummyRes == DUMMY_INPUT_EOF)
|
||||
{
|
||||
if (rem >= LZMA_REQUIRED_INPUT_MAX)
|
||||
break;
|
||||
p->tempBufSize = rem;
|
||||
(*srcLen) += (SizeT)ahead;
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
dummyProcessed = (int)(bufOut - p->tempBuf);
|
||||
|
||||
if ((unsigned)dummyProcessed < p->tempBufSize)
|
||||
break;
|
||||
|
||||
if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes))
|
||||
{
|
||||
(*srcLen) += (unsigned)dummyProcessed - p->tempBufSize;
|
||||
p->tempBufSize = (unsigned)dummyProcessed;
|
||||
// p->remainLen = kMatchSpecLen_Error_Data;
|
||||
RETURN__NOT_FINISHED__FOR_FINISH;
|
||||
}
|
||||
}
|
||||
|
||||
p->buf = p->tempBuf;
|
||||
if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
{
|
||||
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;
|
||||
// we decode one symbol from (p->tempBuf) here, so the (bufLimit) is equal to (p->buf)
|
||||
int res = LzmaDec_DecodeReal2(p, dicLimit, p->buf);
|
||||
|
||||
SizeT processed = (SizeT)(p->buf - p->tempBuf);
|
||||
rem = p->tempBufSize;
|
||||
|
||||
if (dummyProcessed < 0)
|
||||
{
|
||||
if (processed > LZMA_REQUIRED_INPUT_MAX)
|
||||
break;
|
||||
if (processed < rem)
|
||||
break;
|
||||
}
|
||||
else if ((unsigned)dummyProcessed != processed)
|
||||
break;
|
||||
|
||||
processed -= rem;
|
||||
|
||||
src += processed;
|
||||
inSize -= processed;
|
||||
(*srcLen) += processed;
|
||||
p->tempBufSize = 0;
|
||||
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
p->remainLen = kMatchSpecLen_Error_Data;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
(*srcLen) += (SizeT)lookAhead;
|
||||
src += lookAhead;
|
||||
inSize -= (SizeT)lookAhead;
|
||||
p->tempBufSize = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p->code != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return SZ_OK;
|
||||
|
||||
/* Some unexpected error: internal error of code, memory corruption or hardware failure */
|
||||
p->remainLen = kMatchSpecLen_Error_Fail;
|
||||
return SZ_ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT outSize = *destLen;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* LzmaDec.h -- LZMA Decoder
|
||||
2018-04-21 : Igor Pavlov : Public domain */
|
||||
2020-03-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_DEC_H
|
||||
#define __LZMA_DEC_H
|
||||
|
@ -181,6 +181,7 @@ Returns:
|
|||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
||||
|
@ -223,6 +224,7 @@ Returns:
|
|||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure
|
||||
*/
|
||||
|
||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* LzmaEnc.c -- LZMA Encoder
|
||||
2019-01-10: Igor Pavlov : Public domain */
|
||||
2021-11-18: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
|||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "CpuArch.h"
|
||||
#include "LzmaEnc.h"
|
||||
|
||||
#include "LzFind.h"
|
||||
|
@ -19,12 +20,25 @@
|
|||
#include "LzFindMt.h"
|
||||
#endif
|
||||
|
||||
/* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */
|
||||
|
||||
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
|
||||
ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
||||
UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
|
||||
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
|
||||
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
|
||||
void LzmaEnc_Finish(CLzmaEncHandle pp);
|
||||
void LzmaEnc_SaveState(CLzmaEncHandle pp);
|
||||
void LzmaEnc_RestoreState(CLzmaEncHandle pp);
|
||||
|
||||
#ifdef SHOW_STAT
|
||||
static unsigned g_STAT_OFFSET = 0;
|
||||
#endif
|
||||
|
||||
#define kLzmaMaxHistorySize ((UInt32)3 << 29)
|
||||
/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */
|
||||
/* for good normalization speed we still reserve 256 MB before 4 GB range */
|
||||
#define kLzmaMaxHistorySize ((UInt32)15 << 28)
|
||||
|
||||
#define kNumTopBits 24
|
||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
||||
|
@ -36,7 +50,7 @@ static unsigned g_STAT_OFFSET = 0;
|
|||
|
||||
#define kNumMoveReducingBits 4
|
||||
#define kNumBitPriceShiftBits 4
|
||||
#define kBitPrice (1 << kNumBitPriceShiftBits)
|
||||
// #define kBitPrice (1 << kNumBitPriceShiftBits)
|
||||
|
||||
#define REP_LEN_COUNT 64
|
||||
|
||||
|
@ -47,6 +61,7 @@ void LzmaEncProps_Init(CLzmaEncProps *p)
|
|||
p->reduceSize = (UInt64)(Int64)-1;
|
||||
p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
|
||||
p->writeEndMark = 0;
|
||||
p->affinity = 0;
|
||||
}
|
||||
|
||||
void LzmaEncProps_Normalize(CLzmaEncProps *p)
|
||||
|
@ -55,16 +70,21 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
|
|||
if (level < 0) level = 5;
|
||||
p->level = level;
|
||||
|
||||
if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26)));
|
||||
if (p->dictSize == 0)
|
||||
p->dictSize =
|
||||
( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
|
||||
( level <= 6 ? ((UInt32)1 << (level + 19)) :
|
||||
( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
|
||||
)));
|
||||
|
||||
if (p->dictSize > p->reduceSize)
|
||||
{
|
||||
unsigned i;
|
||||
UInt32 reduceSize = (UInt32)p->reduceSize;
|
||||
for (i = 11; i <= 30; i++)
|
||||
{
|
||||
if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
|
||||
if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
|
||||
}
|
||||
UInt32 v = (UInt32)p->reduceSize;
|
||||
const UInt32 kReduceMin = ((UInt32)1 << 12);
|
||||
if (v < kReduceMin)
|
||||
v = kReduceMin;
|
||||
if (p->dictSize > v)
|
||||
p->dictSize = v;
|
||||
}
|
||||
|
||||
if (p->lc < 0) p->lc = 3;
|
||||
|
@ -74,8 +94,8 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
|
|||
if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
|
||||
if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
|
||||
if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
|
||||
if (p->numHashBytes < 0) p->numHashBytes = 4;
|
||||
if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
|
||||
if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5);
|
||||
if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1);
|
||||
|
||||
if (p->numThreads < 0)
|
||||
p->numThreads =
|
||||
|
@ -93,18 +113,85 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
|
|||
return props.dictSize;
|
||||
}
|
||||
|
||||
#if (_MSC_VER >= 1400)
|
||||
/* BSR code is fast for some new CPUs */
|
||||
/* #define LZMA_LOG_BSR */
|
||||
|
||||
/*
|
||||
x86/x64:
|
||||
|
||||
BSR:
|
||||
IF (SRC == 0) ZF = 1, DEST is undefined;
|
||||
AMD : DEST is unchanged;
|
||||
IF (SRC != 0) ZF = 0; DEST is index of top non-zero bit
|
||||
BSR is slow in some processors
|
||||
|
||||
LZCNT:
|
||||
IF (SRC == 0) CF = 1, DEST is size_in_bits_of_register(src) (32 or 64)
|
||||
IF (SRC != 0) CF = 0, DEST = num_lead_zero_bits
|
||||
IF (DEST == 0) ZF = 1;
|
||||
|
||||
LZCNT works only in new processors starting from Haswell.
|
||||
if LZCNT is not supported by processor, then it's executed as BSR.
|
||||
LZCNT can be faster than BSR, if supported.
|
||||
*/
|
||||
|
||||
// #define LZMA_LOG_BSR
|
||||
|
||||
#if defined(MY_CPU_ARM_OR_ARM64) /* || defined(MY_CPU_X86_OR_AMD64) */
|
||||
|
||||
#if (defined(__clang__) && (__clang_major__ >= 6)) \
|
||||
|| (defined(__GNUC__) && (__GNUC__ >= 6))
|
||||
#define LZMA_LOG_BSR
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
// #if defined(MY_CPU_ARM_OR_ARM64)
|
||||
#define LZMA_LOG_BSR
|
||||
// #endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// #include <intrin.h>
|
||||
|
||||
#ifdef LZMA_LOG_BSR
|
||||
|
||||
#define kDicLogSizeMaxCompress 32
|
||||
#if defined(__clang__) \
|
||||
|| defined(__GNUC__)
|
||||
|
||||
#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); }
|
||||
/*
|
||||
C code: : (30 - __builtin_clz(x))
|
||||
gcc9/gcc10 for x64 /x86 : 30 - (bsr(x) xor 31)
|
||||
clang10 for x64 : 31 + (bsr(x) xor -32)
|
||||
*/
|
||||
|
||||
static unsigned GetPosSlot1(UInt32 pos)
|
||||
#define MY_clz(x) ((unsigned)__builtin_clz(x))
|
||||
// __lzcnt32
|
||||
// __builtin_ia32_lzcnt_u32
|
||||
|
||||
#else // #if defined(_MSC_VER)
|
||||
|
||||
#ifdef MY_CPU_ARM_OR_ARM64
|
||||
|
||||
#define MY_clz _CountLeadingZeros
|
||||
|
||||
#else // if defined(MY_CPU_X86_OR_AMD64)
|
||||
|
||||
// #define MY_clz __lzcnt // we can use lzcnt (unsupported by old CPU)
|
||||
// _BitScanReverse code is not optimal for some MSVC compilers
|
||||
#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); zz--; \
|
||||
res = (zz + zz) + (pos >> zz); }
|
||||
|
||||
#endif // MY_CPU_X86_OR_AMD64
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
#ifndef BSR2_RET
|
||||
|
||||
#define BSR2_RET(pos, res) { unsigned zz = 30 - MY_clz(pos); \
|
||||
res = (zz + zz) + (pos >> zz); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
unsigned GetPosSlot1(UInt32 pos);
|
||||
unsigned GetPosSlot1(UInt32 pos)
|
||||
{
|
||||
unsigned res;
|
||||
BSR2_RET(pos, res);
|
||||
|
@ -113,10 +200,10 @@ static unsigned GetPosSlot1(UInt32 pos)
|
|||
#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
|
||||
#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
|
||||
|
||||
#else
|
||||
|
||||
#define kNumLogBits (9 + sizeof(size_t) / 2)
|
||||
/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */
|
||||
#else // ! LZMA_LOG_BSR
|
||||
|
||||
#define kNumLogBits (11 + sizeof(size_t) / 8 * 3)
|
||||
|
||||
#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
|
||||
|
||||
|
@ -163,7 +250,7 @@ static void LzmaEnc_FastPosInit(Byte *g_FastPos)
|
|||
#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
|
||||
#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }
|
||||
|
||||
#endif
|
||||
#endif // LZMA_LOG_BSR
|
||||
|
||||
|
||||
#define LZMA_NUM_REPS 4
|
||||
|
@ -193,7 +280,7 @@ typedef struct
|
|||
|
||||
#define kNumLenToPosStates 4
|
||||
#define kNumPosSlotBits 6
|
||||
#define kDicLogSizeMin 0
|
||||
// #define kDicLogSizeMin 0
|
||||
#define kDicLogSizeMax 32
|
||||
#define kDistTableSizeMax (kDicLogSizeMax * 2)
|
||||
|
||||
|
@ -299,7 +386,7 @@ typedef UInt32 CProbPrice;
|
|||
typedef struct
|
||||
{
|
||||
void *matchFinderObj;
|
||||
IMatchFinder matchFinder;
|
||||
IMatchFinder2 matchFinder;
|
||||
|
||||
unsigned optCur;
|
||||
unsigned optEnd;
|
||||
|
@ -344,10 +431,14 @@ typedef struct
|
|||
// begin of CMatchFinderMt is used in LZ thread
|
||||
CMatchFinderMt matchFinderMt;
|
||||
// end of CMatchFinderMt is used in BT and HASH threads
|
||||
// #else
|
||||
// CMatchFinder matchFinderBase;
|
||||
#endif
|
||||
|
||||
CMatchFinder matchFinderBase;
|
||||
|
||||
|
||||
// we suppose that we have 8-bytes alignment after CMatchFinder
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
Byte pad[128];
|
||||
#endif
|
||||
|
@ -355,8 +446,10 @@ typedef struct
|
|||
// LZ thread
|
||||
CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
|
||||
|
||||
UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
|
||||
// we want {len , dist} pairs to be 8-bytes aligned in matches array
|
||||
UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2];
|
||||
|
||||
// we want 8-bytes alignment here
|
||||
UInt32 alignPrices[kAlignTableSize];
|
||||
UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
|
||||
UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
|
||||
|
@ -385,12 +478,19 @@ typedef struct
|
|||
|
||||
CSaveState saveState;
|
||||
|
||||
// BoolInt mf_Failure;
|
||||
#ifndef _7ZIP_ST
|
||||
Byte pad2[128];
|
||||
#endif
|
||||
} CLzmaEnc;
|
||||
|
||||
|
||||
#define MFB (p->matchFinderBase)
|
||||
/*
|
||||
#ifndef _7ZIP_ST
|
||||
#define MFB (p->matchFinderMt.MatchFinder)
|
||||
#endif
|
||||
*/
|
||||
|
||||
#define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr));
|
||||
|
||||
|
@ -455,41 +555,51 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
|
|||
|
||||
if (props.lc > LZMA_LC_MAX
|
||||
|| props.lp > LZMA_LP_MAX
|
||||
|| props.pb > LZMA_PB_MAX
|
||||
|| props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)
|
||||
|| props.dictSize > kLzmaMaxHistorySize)
|
||||
|| props.pb > LZMA_PB_MAX)
|
||||
return SZ_ERROR_PARAM;
|
||||
|
||||
|
||||
if (props.dictSize > kLzmaMaxHistorySize)
|
||||
props.dictSize = kLzmaMaxHistorySize;
|
||||
|
||||
#ifndef LZMA_LOG_BSR
|
||||
{
|
||||
const UInt64 dict64 = props.dictSize;
|
||||
if (dict64 > ((UInt64)1 << kDicLogSizeMaxCompress))
|
||||
return SZ_ERROR_PARAM;
|
||||
}
|
||||
#endif
|
||||
|
||||
p->dictSize = props.dictSize;
|
||||
{
|
||||
unsigned fb = props.fb;
|
||||
unsigned fb = (unsigned)props.fb;
|
||||
if (fb < 5)
|
||||
fb = 5;
|
||||
if (fb > LZMA_MATCH_LEN_MAX)
|
||||
fb = LZMA_MATCH_LEN_MAX;
|
||||
p->numFastBytes = fb;
|
||||
}
|
||||
p->lc = props.lc;
|
||||
p->lp = props.lp;
|
||||
p->pb = props.pb;
|
||||
p->lc = (unsigned)props.lc;
|
||||
p->lp = (unsigned)props.lp;
|
||||
p->pb = (unsigned)props.pb;
|
||||
p->fastMode = (props.algo == 0);
|
||||
// p->_maxMode = True;
|
||||
p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);
|
||||
MFB.btMode = (Byte)(props.btMode ? 1 : 0);
|
||||
{
|
||||
unsigned numHashBytes = 4;
|
||||
if (props.btMode)
|
||||
{
|
||||
if (props.numHashBytes < 2)
|
||||
numHashBytes = 2;
|
||||
else if (props.numHashBytes < 4)
|
||||
numHashBytes = props.numHashBytes;
|
||||
if (props.numHashBytes < 2) numHashBytes = 2;
|
||||
else if (props.numHashBytes < 4) numHashBytes = (unsigned)props.numHashBytes;
|
||||
}
|
||||
p->matchFinderBase.numHashBytes = numHashBytes;
|
||||
if (props.numHashBytes >= 5) numHashBytes = 5;
|
||||
|
||||
MFB.numHashBytes = numHashBytes;
|
||||
}
|
||||
|
||||
p->matchFinderBase.cutValue = props.mc;
|
||||
MFB.cutValue = props.mc;
|
||||
|
||||
p->writeEndMark = props.writeEndMark;
|
||||
p->writeEndMark = (BoolInt)props.writeEndMark;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
/*
|
||||
|
@ -500,6 +610,8 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
|
|||
}
|
||||
*/
|
||||
p->multiThread = (props.numThreads > 1);
|
||||
p->matchFinderMt.btSync.affinity =
|
||||
p->matchFinderMt.hashSync.affinity = props.affinity;
|
||||
#endif
|
||||
|
||||
return SZ_OK;
|
||||
|
@ -509,7 +621,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
|
|||
void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
|
||||
{
|
||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||
p->matchFinderBase.expectedDataSize = expectedDataSiize;
|
||||
MFB.expectedDataSize = expectedDataSiize;
|
||||
}
|
||||
|
||||
|
||||
|
@ -536,8 +648,8 @@ static void RangeEnc_Construct(CRangeEnc *p)
|
|||
p->bufBase = NULL;
|
||||
}
|
||||
|
||||
#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
|
||||
#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
|
||||
#define RangeEnc_GetProcessed(p) ( (p)->processed + (size_t)((p)->buf - (p)->bufBase) + (p)->cacheSize)
|
||||
#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + (size_t)((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
|
||||
|
||||
#define RC_BUF_SIZE (1 << 16)
|
||||
|
||||
|
@ -556,12 +668,11 @@ static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)
|
|||
static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)
|
||||
{
|
||||
ISzAlloc_Free(alloc, p->bufBase);
|
||||
p->bufBase = 0;
|
||||
p->bufBase = NULL;
|
||||
}
|
||||
|
||||
static void RangeEnc_Init(CRangeEnc *p)
|
||||
{
|
||||
/* Stream.Init(); */
|
||||
p->range = 0xFFFFFFFF;
|
||||
p->cache = 0;
|
||||
p->low = 0;
|
||||
|
@ -575,12 +686,12 @@ static void RangeEnc_Init(CRangeEnc *p)
|
|||
|
||||
MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)
|
||||
{
|
||||
size_t num;
|
||||
if (p->res != SZ_OK)
|
||||
return;
|
||||
num = p->buf - p->bufBase;
|
||||
if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
|
||||
p->res = SZ_ERROR_WRITE;
|
||||
const size_t num = (size_t)(p->buf - p->bufBase);
|
||||
if (p->res == SZ_OK)
|
||||
{
|
||||
if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
|
||||
p->res = SZ_ERROR_WRITE;
|
||||
}
|
||||
p->processed += num;
|
||||
p->buf = p->bufBase;
|
||||
}
|
||||
|
@ -656,7 +767,7 @@ static void RangeEnc_FlushData(CRangeEnc *p)
|
|||
range += newBound & mask; \
|
||||
mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
|
||||
mask += ((1 << kNumMoveBits) - 1); \
|
||||
ttt += (Int32)(mask - ttt) >> kNumMoveBits; \
|
||||
ttt += (UInt32)((Int32)(mask - ttt) >> kNumMoveBits); \
|
||||
*(prob) = (CLzmaProb)ttt; \
|
||||
RC_NORM(p) \
|
||||
}
|
||||
|
@ -749,7 +860,7 @@ static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
|
|||
bitCount++;
|
||||
}
|
||||
}
|
||||
ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
|
||||
ProbPrices[i] = (CProbPrice)(((unsigned)kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
|
||||
// printf("\n%3d: %5d", i, ProbPrices[i]);
|
||||
}
|
||||
}
|
||||
|
@ -985,7 +1096,11 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
|
|||
|
||||
p->additionalOffset++;
|
||||
p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
|
||||
numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
|
||||
{
|
||||
const UInt32 *d = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
|
||||
// if (!d) { p->mf_Failure = True; *numPairsRes = 0; return 0; }
|
||||
numPairs = (unsigned)(d - p->matches);
|
||||
}
|
||||
*numPairsRes = numPairs;
|
||||
|
||||
#ifdef SHOW_STAT
|
||||
|
@ -1001,7 +1116,7 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
|
|||
if (numPairs == 0)
|
||||
return 0;
|
||||
{
|
||||
unsigned len = p->matches[(size_t)numPairs - 2];
|
||||
const unsigned len = p->matches[(size_t)numPairs - 2];
|
||||
if (len != p->numFastBytes)
|
||||
return len;
|
||||
{
|
||||
|
@ -1011,7 +1126,7 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
|
|||
{
|
||||
const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
|
||||
const Byte *p2 = p1 + len;
|
||||
ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1];
|
||||
const ptrdiff_t dif = (ptrdiff_t)-1 - (ptrdiff_t)p->matches[(size_t)numPairs - 1];
|
||||
const Byte *lim = p1 + numAvail;
|
||||
for (; p2 != lim && *p2 == p2[dif]; p2++)
|
||||
{}
|
||||
|
@ -1167,6 +1282,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
|
|||
repLens[i] = len;
|
||||
if (len > repLens[repMaxIndex])
|
||||
repMaxIndex = i;
|
||||
if (len == LZMA_MATCH_LEN_MAX) // 21.03 : optimization
|
||||
break;
|
||||
}
|
||||
|
||||
if (repLens[repMaxIndex] >= p->numFastBytes)
|
||||
|
@ -1179,10 +1296,12 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
|
|||
}
|
||||
|
||||
matches = p->matches;
|
||||
#define MATCHES matches
|
||||
// #define MATCHES p->matches
|
||||
|
||||
if (mainLen >= p->numFastBytes)
|
||||
{
|
||||
p->backRes = matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
|
||||
p->backRes = MATCHES[(size_t)numPairs - 1] + LZMA_NUM_REPS;
|
||||
MOVE_POS(p, mainLen - 1)
|
||||
return mainLen;
|
||||
}
|
||||
|
@ -1276,13 +1395,13 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
|
|||
if (len < 2)
|
||||
len = 2;
|
||||
else
|
||||
while (len > matches[offs])
|
||||
while (len > MATCHES[offs])
|
||||
offs += 2;
|
||||
|
||||
for (; ; len++)
|
||||
{
|
||||
COptimal *opt;
|
||||
UInt32 dist = matches[(size_t)offs + 1];
|
||||
UInt32 dist = MATCHES[(size_t)offs + 1];
|
||||
UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
|
||||
unsigned lenToPosState = GetLenToPosState(len);
|
||||
|
||||
|
@ -1306,7 +1425,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
|
|||
opt->extra = 0;
|
||||
}
|
||||
|
||||
if (len == matches[offs])
|
||||
if (len == MATCHES[offs])
|
||||
{
|
||||
offs += 2;
|
||||
if (offs == numPairs)
|
||||
|
@ -1727,8 +1846,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
|
|||
if (newLen > numAvail)
|
||||
{
|
||||
newLen = numAvail;
|
||||
for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
|
||||
matches[numPairs] = (UInt32)newLen;
|
||||
for (numPairs = 0; newLen > MATCHES[numPairs]; numPairs += 2);
|
||||
MATCHES[numPairs] = (UInt32)newLen;
|
||||
numPairs += 2;
|
||||
}
|
||||
|
||||
|
@ -1747,9 +1866,9 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
|
|||
}
|
||||
|
||||
offs = 0;
|
||||
while (startLen > matches[offs])
|
||||
while (startLen > MATCHES[offs])
|
||||
offs += 2;
|
||||
dist = matches[(size_t)offs + 1];
|
||||
dist = MATCHES[(size_t)offs + 1];
|
||||
|
||||
// if (dist >= kNumFullDistances)
|
||||
GetPosSlot2(dist, posSlot);
|
||||
|
@ -1776,7 +1895,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
|
|||
}
|
||||
}
|
||||
|
||||
if (len == matches[offs])
|
||||
if (len == MATCHES[offs])
|
||||
{
|
||||
// if (p->_maxMode) {
|
||||
// MATCH : LIT : REP_0
|
||||
|
@ -1841,7 +1960,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
|
|||
offs += 2;
|
||||
if (offs == numPairs)
|
||||
break;
|
||||
dist = matches[(size_t)offs + 1];
|
||||
dist = MATCHES[(size_t)offs + 1];
|
||||
// if (dist >= kNumFullDistances)
|
||||
GetPosSlot2(dist, posSlot);
|
||||
}
|
||||
|
@ -2059,8 +2178,23 @@ static SRes CheckErrors(CLzmaEnc *p)
|
|||
return p->result;
|
||||
if (p->rc.res != SZ_OK)
|
||||
p->result = SZ_ERROR_WRITE;
|
||||
if (p->matchFinderBase.result != SZ_OK)
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
if (
|
||||
// p->mf_Failure ||
|
||||
(p->mtMode &&
|
||||
( // p->matchFinderMt.failure_LZ_LZ ||
|
||||
p->matchFinderMt.failure_LZ_BT))
|
||||
)
|
||||
{
|
||||
p->result = MY_HRES_ERROR__INTERNAL_ERROR;
|
||||
// printf("\nCheckErrors p->matchFinderMt.failureLZ\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (MFB.result != SZ_OK)
|
||||
p->result = SZ_ERROR_READ;
|
||||
|
||||
if (p->result != SZ_OK)
|
||||
p->finished = True;
|
||||
return p->result;
|
||||
|
@ -2198,14 +2332,14 @@ MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p)
|
|||
|
||||
|
||||
|
||||
void LzmaEnc_Construct(CLzmaEnc *p)
|
||||
static void LzmaEnc_Construct(CLzmaEnc *p)
|
||||
{
|
||||
RangeEnc_Construct(&p->rc);
|
||||
MatchFinder_Construct(&p->matchFinderBase);
|
||||
MatchFinder_Construct(&MFB);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
p->matchFinderMt.MatchFinder = &MFB;
|
||||
MatchFinderMt_Construct(&p->matchFinderMt);
|
||||
p->matchFinderMt.MatchFinder = &p->matchFinderBase;
|
||||
#endif
|
||||
|
||||
{
|
||||
|
@ -2221,7 +2355,6 @@ void LzmaEnc_Construct(CLzmaEnc *p)
|
|||
LzmaEnc_InitPriceTables(p->ProbPrices);
|
||||
p->litProbs = NULL;
|
||||
p->saveState.litProbs = NULL;
|
||||
|
||||
}
|
||||
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
|
||||
|
@ -2233,7 +2366,7 @@ CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
|
|||
return p;
|
||||
}
|
||||
|
||||
void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
|
||||
static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
|
||||
{
|
||||
ISzAlloc_Free(alloc, p->litProbs);
|
||||
ISzAlloc_Free(alloc, p->saveState.litProbs);
|
||||
|
@ -2241,13 +2374,13 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
|
|||
p->saveState.litProbs = NULL;
|
||||
}
|
||||
|
||||
void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
|
||||
static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
|
||||
#endif
|
||||
|
||||
MatchFinder_Free(&p->matchFinderBase, allocBig);
|
||||
MatchFinder_Free(&MFB, allocBig);
|
||||
LzmaEnc_FreeLits(p, alloc);
|
||||
RangeEnc_Free(&p->rc, alloc);
|
||||
}
|
||||
|
@ -2259,11 +2392,18 @@ void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
|
|||
}
|
||||
|
||||
|
||||
MY_NO_INLINE
|
||||
static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)
|
||||
{
|
||||
UInt32 nowPos32, startPos32;
|
||||
if (p->needInit)
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
if (p->mtMode)
|
||||
{
|
||||
RINOK(MatchFinderMt_InitMt(&p->matchFinderMt));
|
||||
}
|
||||
#endif
|
||||
p->matchFinder.Init(p->matchFinderObj);
|
||||
p->needInit = 0;
|
||||
}
|
||||
|
@ -2521,12 +2661,12 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa
|
|||
// { int y; for (y = 0; y < 100; y++) {
|
||||
FillDistancesPrices(p);
|
||||
// }}
|
||||
LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
|
||||
LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);
|
||||
}
|
||||
if (p->repLenEncCounter <= 0)
|
||||
{
|
||||
p->repLenEncCounter = REP_LEN_COUNT;
|
||||
LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
|
||||
LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2559,11 +2699,13 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa
|
|||
static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
|
||||
{
|
||||
UInt32 beforeSize = kNumOpts;
|
||||
UInt32 dictSize;
|
||||
|
||||
if (!RangeEnc_Alloc(&p->rc, alloc))
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));
|
||||
p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0));
|
||||
#endif
|
||||
|
||||
{
|
||||
|
@ -2582,36 +2724,56 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc,
|
|||
}
|
||||
}
|
||||
|
||||
p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
|
||||
MFB.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
|
||||
|
||||
if (beforeSize + p->dictSize < keepWindowSize)
|
||||
beforeSize = keepWindowSize - p->dictSize;
|
||||
|
||||
dictSize = p->dictSize;
|
||||
if (dictSize == ((UInt32)2 << 30) ||
|
||||
dictSize == ((UInt32)3 << 30))
|
||||
{
|
||||
/* 21.03 : here we reduce the dictionary for 2 reasons:
|
||||
1) we don't want 32-bit back_distance matches in decoder for 2 GB dictionary.
|
||||
2) we want to elimate useless last MatchFinder_Normalize3() for corner cases,
|
||||
where data size is aligned for 1 GB: 5/6/8 GB.
|
||||
That reducing must be >= 1 for such corner cases. */
|
||||
dictSize -= 1;
|
||||
}
|
||||
|
||||
if (beforeSize + dictSize < keepWindowSize)
|
||||
beforeSize = keepWindowSize - dictSize;
|
||||
|
||||
/* in worst case we can look ahead for
|
||||
max(LZMA_MATCH_LEN_MAX, numFastBytes + 1 + numFastBytes) bytes.
|
||||
we send larger value for (keepAfter) to MantchFinder_Create():
|
||||
(numFastBytes + LZMA_MATCH_LEN_MAX + 1)
|
||||
*/
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
if (p->mtMode)
|
||||
{
|
||||
RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes,
|
||||
LZMA_MATCH_LEN_MAX
|
||||
+ 1 /* 18.04 */
|
||||
RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize,
|
||||
p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */
|
||||
, allocBig));
|
||||
p->matchFinderObj = &p->matchFinderMt;
|
||||
p->matchFinderBase.bigHash = (Byte)(
|
||||
(p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0);
|
||||
MFB.bigHash = (Byte)(
|
||||
(p->dictSize > kBigHashDicLimit && MFB.hashMask >= 0xFFFFFF) ? 1 : 0);
|
||||
MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
|
||||
if (!MatchFinder_Create(&MFB, dictSize, beforeSize,
|
||||
p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 21.03 */
|
||||
, allocBig))
|
||||
return SZ_ERROR_MEM;
|
||||
p->matchFinderObj = &p->matchFinderBase;
|
||||
MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
|
||||
p->matchFinderObj = &MFB;
|
||||
MatchFinder_CreateVTable(&MFB, &p->matchFinder);
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
void LzmaEnc_Init(CLzmaEnc *p)
|
||||
static void LzmaEnc_Init(CLzmaEnc *p)
|
||||
{
|
||||
unsigned i;
|
||||
p->state = 0;
|
||||
|
@ -2675,12 +2837,14 @@ void LzmaEnc_Init(CLzmaEnc *p)
|
|||
|
||||
p->additionalOffset = 0;
|
||||
|
||||
p->pbMask = (1 << p->pb) - 1;
|
||||
p->pbMask = ((unsigned)1 << p->pb) - 1;
|
||||
p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);
|
||||
|
||||
// p->mf_Failure = False;
|
||||
}
|
||||
|
||||
|
||||
void LzmaEnc_InitPrices(CLzmaEnc *p)
|
||||
static void LzmaEnc_InitPrices(CLzmaEnc *p)
|
||||
{
|
||||
if (!p->fastMode)
|
||||
{
|
||||
|
@ -2694,8 +2858,8 @@ void LzmaEnc_InitPrices(CLzmaEnc *p)
|
|||
|
||||
p->repLenEncCounter = REP_LEN_COUNT;
|
||||
|
||||
LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
|
||||
LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
|
||||
LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);
|
||||
LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);
|
||||
}
|
||||
|
||||
static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
|
||||
|
@ -2719,7 +2883,7 @@ static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInS
|
|||
ISzAllocPtr alloc, ISzAllocPtr allocBig)
|
||||
{
|
||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||
p->matchFinderBase.stream = inStream;
|
||||
MFB.stream = inStream;
|
||||
p->needInit = 1;
|
||||
p->rc.outStream = outStream;
|
||||
return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
|
||||
|
@ -2730,16 +2894,16 @@ SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
|
|||
ISzAllocPtr alloc, ISzAllocPtr allocBig)
|
||||
{
|
||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||
p->matchFinderBase.stream = inStream;
|
||||
MFB.stream = inStream;
|
||||
p->needInit = 1;
|
||||
return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
|
||||
}
|
||||
|
||||
static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
|
||||
{
|
||||
p->matchFinderBase.directInput = 1;
|
||||
p->matchFinderBase.bufferBase = (Byte *)src;
|
||||
p->matchFinderBase.directInputRem = srcLen;
|
||||
MFB.directInput = 1;
|
||||
MFB.bufferBase = (Byte *)src;
|
||||
MFB.directInputRem = srcLen;
|
||||
}
|
||||
|
||||
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
||||
|
@ -2781,19 +2945,23 @@ static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, s
|
|||
size = p->rem;
|
||||
p->overflow = True;
|
||||
}
|
||||
memcpy(p->data, data, size);
|
||||
p->rem -= size;
|
||||
p->data += size;
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(p->data, data, size);
|
||||
p->rem -= size;
|
||||
p->data += size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
|
||||
{
|
||||
const CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||
return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
|
||||
{
|
||||
|
@ -2841,6 +3009,7 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
|
|||
}
|
||||
|
||||
|
||||
MY_NO_INLINE
|
||||
static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
|
@ -2870,7 +3039,7 @@ static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
|
|||
LzmaEnc_Finish(p);
|
||||
|
||||
/*
|
||||
if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
|
||||
if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB))
|
||||
res = SZ_ERROR_FAIL;
|
||||
}
|
||||
*/
|
||||
|
@ -2889,35 +3058,43 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
|
|||
|
||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
|
||||
{
|
||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||
unsigned i;
|
||||
UInt32 dictSize = p->dictSize;
|
||||
if (*size < LZMA_PROPS_SIZE)
|
||||
return SZ_ERROR_PARAM;
|
||||
*size = LZMA_PROPS_SIZE;
|
||||
props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
|
||||
|
||||
if (dictSize >= ((UInt32)1 << 22))
|
||||
{
|
||||
UInt32 kDictMask = ((UInt32)1 << 20) - 1;
|
||||
if (dictSize < (UInt32)0xFFFFFFFF - kDictMask)
|
||||
dictSize = (dictSize + kDictMask) & ~kDictMask;
|
||||
}
|
||||
else for (i = 11; i <= 30; i++)
|
||||
{
|
||||
if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; }
|
||||
if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; }
|
||||
}
|
||||
const CLzmaEnc *p = (const CLzmaEnc *)pp;
|
||||
const UInt32 dictSize = p->dictSize;
|
||||
UInt32 v;
|
||||
props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
|
||||
|
||||
// we write aligned dictionary value to properties for lzma decoder
|
||||
if (dictSize >= ((UInt32)1 << 21))
|
||||
{
|
||||
const UInt32 kDictMask = ((UInt32)1 << 20) - 1;
|
||||
v = (dictSize + kDictMask) & ~kDictMask;
|
||||
if (v < dictSize)
|
||||
v = dictSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i = 11 * 2;
|
||||
do
|
||||
{
|
||||
v = (UInt32)(2 + (i & 1)) << (i >> 1);
|
||||
i++;
|
||||
}
|
||||
while (v < dictSize);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
props[1 + i] = (Byte)(dictSize >> (8 * i));
|
||||
return SZ_OK;
|
||||
SetUi32(props + 1, v);
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)
|
||||
{
|
||||
return ((CLzmaEnc *)pp)->writeEndMark;
|
||||
return (unsigned)((CLzmaEnc *)pp)->writeEndMark;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2974,3 +3151,15 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
|||
LzmaEnc_Destroy(p, alloc, allocBig);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
#ifndef _7ZIP_ST
|
||||
void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2])
|
||||
{
|
||||
const CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||
lz_threads[0] = p->matchFinderMt.hashSync.thread;
|
||||
lz_threads[1] = p->matchFinderMt.btSync.thread;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* LzmaEnc.h -- LZMA Encoder
|
||||
2017-07-27 : Igor Pavlov : Public domain */
|
||||
2019-10-30 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_ENC_H
|
||||
#define __LZMA_ENC_H
|
||||
|
@ -29,6 +29,8 @@ typedef struct _CLzmaEncProps
|
|||
|
||||
UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.
|
||||
Encoder uses this value to reduce dictionary size */
|
||||
|
||||
UInt64 affinity;
|
||||
} CLzmaEncProps;
|
||||
|
||||
void LzmaEncProps_Init(CLzmaEncProps *p);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Ppmd.h -- PPMD codec common code
|
||||
2017-04-03 : Igor Pavlov : Public domain
|
||||
2021-04-13 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
#ifndef __PPMD_H
|
||||
|
@ -9,7 +9,16 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
|||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#ifdef MY_CPU_32BIT
|
||||
#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
|
||||
/*
|
||||
PPMD code always uses 32-bit internal fields in PPMD structures to store internal references in main block.
|
||||
if (PPMD_32BIT is defined), the PPMD code stores internal pointers to 32-bit reference fields.
|
||||
if (PPMD_32BIT is NOT defined), the PPMD code stores internal UInt32 offsets to reference fields.
|
||||
if (pointer size is 64-bit), then (PPMD_32BIT) mode is not allowed,
|
||||
if (pointer size is 32-bit), then (PPMD_32BIT) mode is optional,
|
||||
and it's allowed to disable PPMD_32BIT mode even if pointer is 32-bit.
|
||||
PPMD code works slightly faster in (PPMD_32BIT) mode.
|
||||
*/
|
||||
#define PPMD_32BIT
|
||||
#endif
|
||||
|
||||
|
@ -28,7 +37,7 @@ EXTERN_C_BEGIN
|
|||
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
|
||||
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
MY_CPU_pragma_pack_push_1
|
||||
/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */
|
||||
|
||||
/* SEE-contexts for PPM-contexts with masked symbols */
|
||||
|
@ -40,41 +49,114 @@ typedef struct
|
|||
} CPpmd_See;
|
||||
|
||||
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
|
||||
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
|
||||
{ (p)->Summ = (UInt16)((p)->Summ << 1); (p)->Count = (Byte)(3 << (p)->Shift++); }
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte Symbol;
|
||||
Byte Freq;
|
||||
UInt16 SuccessorLow;
|
||||
UInt16 SuccessorHigh;
|
||||
UInt16 Successor_0;
|
||||
UInt16 Successor_1;
|
||||
} CPpmd_State;
|
||||
|
||||
#pragma pack(pop)
|
||||
typedef struct CPpmd_State2_
|
||||
{
|
||||
Byte Symbol;
|
||||
Byte Freq;
|
||||
} CPpmd_State2;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
CPpmd_State *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_State_Ref;
|
||||
typedef struct CPpmd_State4_
|
||||
{
|
||||
UInt16 Successor_0;
|
||||
UInt16 Successor_1;
|
||||
} CPpmd_State4;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
void *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_Void_Ref;
|
||||
MY_CPU_pragma_pop
|
||||
|
||||
/*
|
||||
PPMD code can write full CPpmd_State structure data to CPpmd*_Context
|
||||
at (byte offset = 2) instead of some fields of original CPpmd*_Context structure.
|
||||
|
||||
If we use pointers to different types, but that point to shared
|
||||
memory space, we can have aliasing problem (strict aliasing).
|
||||
|
||||
XLC compiler in -O2 mode can change the order of memory write instructions
|
||||
in relation to read instructions, if we have use pointers to different types.
|
||||
|
||||
To solve that aliasing problem we use combined CPpmd*_Context structure
|
||||
with unions that contain the fields from both structures:
|
||||
the original CPpmd*_Context and CPpmd_State.
|
||||
So we can access the fields from both structures via one pointer,
|
||||
and the compiler doesn't change the order of write instructions
|
||||
in relation to read instructions.
|
||||
|
||||
If we don't use memory write instructions to shared memory in
|
||||
some local code, and we use only reading instructions (read only),
|
||||
then probably it's safe to use pointers to different types for reading.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef PPMD_32BIT
|
||||
|
||||
#define Ppmd_Ref_Type(type) type *
|
||||
#define Ppmd_GetRef(p, ptr) (ptr)
|
||||
#define Ppmd_GetPtr(p, ptr) (ptr)
|
||||
#define Ppmd_GetPtr_Type(p, ptr, note_type) (ptr)
|
||||
|
||||
#else
|
||||
|
||||
#define Ppmd_Ref_Type(type) UInt32
|
||||
#define Ppmd_GetRef(p, ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
|
||||
#define Ppmd_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
|
||||
#define Ppmd_GetPtr_Type(p, offs, type) ((type *)Ppmd_GetPtr(p, offs))
|
||||
|
||||
#endif // PPMD_32BIT
|
||||
|
||||
|
||||
typedef Ppmd_Ref_Type(CPpmd_State) CPpmd_State_Ref;
|
||||
typedef Ppmd_Ref_Type(void) CPpmd_Void_Ref;
|
||||
typedef Ppmd_Ref_Type(Byte) CPpmd_Byte_Ref;
|
||||
|
||||
|
||||
/*
|
||||
#ifdef MY_CPU_LE_UNALIGN
|
||||
// the unaligned 32-bit access latency can be too large, if the data is not in L1 cache.
|
||||
#define Ppmd_GET_SUCCESSOR(p) ((CPpmd_Void_Ref)*(const UInt32 *)(const void *)&(p)->Successor_0)
|
||||
#define Ppmd_SET_SUCCESSOR(p, v) *(UInt32 *)(void *)(void *)&(p)->Successor_0 = (UInt32)(v)
|
||||
|
||||
#else
|
||||
*/
|
||||
|
||||
/*
|
||||
We can write 16-bit halves to 32-bit (Successor) field in any selected order.
|
||||
But the native order is more consistent way.
|
||||
So we use the native order, if LE/BE order can be detected here at compile time.
|
||||
*/
|
||||
|
||||
#ifdef MY_CPU_BE
|
||||
|
||||
#define Ppmd_GET_SUCCESSOR(p) \
|
||||
( (CPpmd_Void_Ref) (((UInt32)(p)->Successor_0 << 16) | (p)->Successor_1) )
|
||||
|
||||
#define Ppmd_SET_SUCCESSOR(p, v) { \
|
||||
(p)->Successor_0 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); \
|
||||
(p)->Successor_1 = (UInt16)((UInt32)(v) /* & 0xFFFF */); }
|
||||
|
||||
#else
|
||||
|
||||
#define Ppmd_GET_SUCCESSOR(p) \
|
||||
( (CPpmd_Void_Ref) ((p)->Successor_0 | ((UInt32)(p)->Successor_1 << 16)) )
|
||||
|
||||
#define Ppmd_SET_SUCCESSOR(p, v) { \
|
||||
(p)->Successor_0 = (UInt16)((UInt32)(v) /* & 0xFFFF */); \
|
||||
(p)->Successor_1 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); }
|
||||
|
||||
#endif
|
||||
|
||||
// #endif
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
Byte *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_Byte_Ref;
|
||||
|
||||
#define PPMD_SetAllBitsIn256Bytes(p) \
|
||||
{ size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,8 @@
|
|||
/* Ppmd7.h -- PPMdH compression codec
|
||||
2018-07-04 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
/* This code supports virtual RangeDecoder and includes the implementation
|
||||
of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
|
||||
If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
|
||||
/* Ppmd7.h -- Ppmd7 (PPMdH) compression codec
|
||||
2021-04-13 : Igor Pavlov : Public domain
|
||||
This code is based on:
|
||||
PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
|
||||
#ifndef __PPMD7_H
|
||||
#define __PPMD7_H
|
||||
|
@ -21,23 +19,56 @@ EXTERN_C_BEGIN
|
|||
|
||||
struct CPpmd7_Context_;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
struct CPpmd7_Context_ *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd7_Context_Ref;
|
||||
typedef Ppmd_Ref_Type(struct CPpmd7_Context_) CPpmd7_Context_Ref;
|
||||
|
||||
// MY_CPU_pragma_pack_push_1
|
||||
|
||||
typedef struct CPpmd7_Context_
|
||||
{
|
||||
UInt16 NumStats;
|
||||
UInt16 SummFreq;
|
||||
CPpmd_State_Ref Stats;
|
||||
|
||||
|
||||
union
|
||||
{
|
||||
UInt16 SummFreq;
|
||||
CPpmd_State2 State2;
|
||||
} Union2;
|
||||
|
||||
union
|
||||
{
|
||||
CPpmd_State_Ref Stats;
|
||||
CPpmd_State4 State4;
|
||||
} Union4;
|
||||
|
||||
CPpmd7_Context_Ref Suffix;
|
||||
} CPpmd7_Context;
|
||||
|
||||
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
|
||||
// MY_CPU_pragma_pop
|
||||
|
||||
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->Union2)
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 Range;
|
||||
UInt32 Code;
|
||||
UInt32 Low;
|
||||
IByteIn *Stream;
|
||||
} CPpmd7_RangeDec;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 Range;
|
||||
Byte Cache;
|
||||
// Byte _dummy_[3];
|
||||
UInt64 Low;
|
||||
UInt64 CacheSize;
|
||||
IByteOut *Stream;
|
||||
} CPpmd7z_RangeEnc;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -48,17 +79,30 @@ typedef struct
|
|||
|
||||
UInt32 Size;
|
||||
UInt32 GlueCount;
|
||||
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
|
||||
UInt32 AlignOffset;
|
||||
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
|
||||
|
||||
Byte Indx2Units[PPMD_NUM_INDEXES];
|
||||
|
||||
|
||||
|
||||
union
|
||||
{
|
||||
CPpmd7_RangeDec dec;
|
||||
CPpmd7z_RangeEnc enc;
|
||||
} rc;
|
||||
|
||||
Byte Indx2Units[PPMD_NUM_INDEXES + 2]; // +2 for alignment
|
||||
Byte Units2Indx[128];
|
||||
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
|
||||
Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
|
||||
|
||||
Byte NS2BSIndx[256], NS2Indx[256];
|
||||
Byte ExpEscape[16];
|
||||
CPpmd_See DummySee, See[25][16];
|
||||
UInt16 BinSumm[128][64];
|
||||
// int LastSymbol;
|
||||
} CPpmd7;
|
||||
|
||||
|
||||
void Ppmd7_Construct(CPpmd7 *p);
|
||||
BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc);
|
||||
void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc);
|
||||
|
@ -68,74 +112,69 @@ void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
|
|||
|
||||
/* ---------- Internal Functions ---------- */
|
||||
|
||||
extern const Byte PPMD7_kExpEscape[16];
|
||||
|
||||
#ifdef PPMD_32BIT
|
||||
#define Ppmd7_GetPtr(p, ptr) (ptr)
|
||||
#define Ppmd7_GetContext(p, ptr) (ptr)
|
||||
#define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
|
||||
#else
|
||||
#define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
|
||||
#define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
|
||||
#define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
|
||||
#endif
|
||||
#define Ppmd7_GetPtr(p, ptr) Ppmd_GetPtr(p, ptr)
|
||||
#define Ppmd7_GetContext(p, ptr) Ppmd_GetPtr_Type(p, ptr, CPpmd7_Context)
|
||||
#define Ppmd7_GetStats(p, ctx) Ppmd_GetPtr_Type(p, (ctx)->Union4.Stats, CPpmd_State)
|
||||
|
||||
void Ppmd7_Update1(CPpmd7 *p);
|
||||
void Ppmd7_Update1_0(CPpmd7 *p);
|
||||
void Ppmd7_Update2(CPpmd7 *p);
|
||||
void Ppmd7_UpdateBin(CPpmd7 *p);
|
||||
|
||||
#define PPMD7_HiBitsFlag_3(sym) ((((unsigned)sym + 0xC0) >> (8 - 3)) & (1 << 3))
|
||||
#define PPMD7_HiBitsFlag_4(sym) ((((unsigned)sym + 0xC0) >> (8 - 4)) & (1 << 4))
|
||||
// #define PPMD7_HiBitsFlag_3(sym) ((sym) < 0x40 ? 0 : (1 << 3))
|
||||
// #define PPMD7_HiBitsFlag_4(sym) ((sym) < 0x40 ? 0 : (1 << 4))
|
||||
|
||||
#define Ppmd7_GetBinSumm(p) \
|
||||
&p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
|
||||
p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
|
||||
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
|
||||
2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \
|
||||
((p->RunLength >> 26) & 0x20)]
|
||||
&p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1] \
|
||||
[ p->PrevSuccess + ((p->RunLength >> 26) & 0x20) \
|
||||
+ p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] \
|
||||
+ PPMD7_HiBitsFlag_4(Ppmd7Context_OneState(p->MinContext)->Symbol) \
|
||||
+ (p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol)) ]
|
||||
|
||||
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
|
||||
|
||||
|
||||
/*
|
||||
We support two versions of Ppmd7 (PPMdH) methods that use same CPpmd7 structure:
|
||||
1) Ppmd7a_*: original PPMdH
|
||||
2) Ppmd7z_*: modified PPMdH with 7z Range Coder
|
||||
Ppmd7_*: the structures and functions that are common for both versions of PPMd7 (PPMdH)
|
||||
*/
|
||||
|
||||
/* ---------- Decode ---------- */
|
||||
|
||||
typedef struct IPpmd7_RangeDec IPpmd7_RangeDec;
|
||||
#define PPMD7_SYM_END (-1)
|
||||
#define PPMD7_SYM_ERROR (-2)
|
||||
|
||||
struct IPpmd7_RangeDec
|
||||
{
|
||||
UInt32 (*GetThreshold)(const IPpmd7_RangeDec *p, UInt32 total);
|
||||
void (*Decode)(const IPpmd7_RangeDec *p, UInt32 start, UInt32 size);
|
||||
UInt32 (*DecodeBit)(const IPpmd7_RangeDec *p, UInt32 size0);
|
||||
};
|
||||
/*
|
||||
You must set (CPpmd7::rc.dec.Stream) before Ppmd7*_RangeDec_Init()
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IPpmd7_RangeDec vt;
|
||||
UInt32 Range;
|
||||
UInt32 Code;
|
||||
IByteIn *Stream;
|
||||
} CPpmd7z_RangeDec;
|
||||
Ppmd7*_DecodeSymbol()
|
||||
out:
|
||||
>= 0 : decoded byte
|
||||
-1 : PPMD7_SYM_END : End of payload marker
|
||||
-2 : PPMD7_SYM_ERROR : Data error
|
||||
*/
|
||||
|
||||
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
|
||||
BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
|
||||
/* Ppmd7a_* : original PPMdH */
|
||||
BoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p);
|
||||
#define Ppmd7a_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
||||
int Ppmd7a_DecodeSymbol(CPpmd7 *p);
|
||||
|
||||
/* Ppmd7z_* : modified PPMdH with 7z Range Coder */
|
||||
BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p);
|
||||
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
||||
|
||||
int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc);
|
||||
int Ppmd7z_DecodeSymbol(CPpmd7 *p);
|
||||
// Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim);
|
||||
|
||||
|
||||
/* ---------- Encode ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 Low;
|
||||
UInt32 Range;
|
||||
Byte Cache;
|
||||
UInt64 CacheSize;
|
||||
IByteOut *Stream;
|
||||
} CPpmd7z_RangeEnc;
|
||||
|
||||
void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p);
|
||||
void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p);
|
||||
|
||||
void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
|
||||
void Ppmd7z_Init_RangeEnc(CPpmd7 *p);
|
||||
void Ppmd7z_Flush_RangeEnc(CPpmd7 *p);
|
||||
// void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol);
|
||||
void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* Ppmd7Dec.c -- PPMdH Decoder
|
||||
2018-07-04 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder
|
||||
2021-04-13 : Igor Pavlov : Public domain
|
||||
This code is based on:
|
||||
PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
|
@ -8,184 +10,288 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
|||
|
||||
#define kTopValue (1 << 24)
|
||||
|
||||
BoolInt Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
|
||||
|
||||
#define READ_BYTE(p) IByteIn_Read((p)->Stream)
|
||||
|
||||
BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p)
|
||||
{
|
||||
unsigned i;
|
||||
p->Code = 0;
|
||||
p->Range = 0xFFFFFFFF;
|
||||
if (IByteIn_Read(p->Stream) != 0)
|
||||
if (READ_BYTE(p) != 0)
|
||||
return False;
|
||||
for (i = 0; i < 4; i++)
|
||||
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
|
||||
p->Code = (p->Code << 8) | READ_BYTE(p);
|
||||
return (p->Code < 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
#define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt);
|
||||
|
||||
static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total)
|
||||
#define RC_NORM_BASE(p) if ((p)->Range < kTopValue) \
|
||||
{ (p)->Code = ((p)->Code << 8) | READ_BYTE(p); (p)->Range <<= 8;
|
||||
|
||||
#define RC_NORM_1(p) RC_NORM_BASE(p) }
|
||||
#define RC_NORM(p) RC_NORM_BASE(p) RC_NORM_BASE(p) }}
|
||||
|
||||
// we must use only one type of Normalization from two: LOCAL or REMOTE
|
||||
#define RC_NORM_LOCAL(p) // RC_NORM(p)
|
||||
#define RC_NORM_REMOTE(p) RC_NORM(p)
|
||||
|
||||
#define R (&p->rc.dec)
|
||||
|
||||
MY_FORCE_INLINE
|
||||
// MY_NO_INLINE
|
||||
static void RangeDec_Decode(CPpmd7 *p, UInt32 start, UInt32 size)
|
||||
{
|
||||
GET_Ppmd7z_RangeDec
|
||||
return p->Code / (p->Range /= total);
|
||||
|
||||
|
||||
R->Code -= start * R->Range;
|
||||
R->Range *= size;
|
||||
RC_NORM_LOCAL(R)
|
||||
}
|
||||
|
||||
static void Range_Normalize(CPpmd7z_RangeDec *p)
|
||||
{
|
||||
if (p->Range < kTopValue)
|
||||
{
|
||||
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
|
||||
p->Range <<= 8;
|
||||
if (p->Range < kTopValue)
|
||||
{
|
||||
p->Code = (p->Code << 8) | IByteIn_Read(p->Stream);
|
||||
p->Range <<= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size)
|
||||
{
|
||||
GET_Ppmd7z_RangeDec
|
||||
p->Code -= start * p->Range;
|
||||
p->Range *= size;
|
||||
Range_Normalize(p);
|
||||
}
|
||||
|
||||
static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0)
|
||||
{
|
||||
GET_Ppmd7z_RangeDec
|
||||
UInt32 newBound = (p->Range >> 14) * size0;
|
||||
UInt32 symbol;
|
||||
if (p->Code < newBound)
|
||||
{
|
||||
symbol = 0;
|
||||
p->Range = newBound;
|
||||
}
|
||||
else
|
||||
{
|
||||
symbol = 1;
|
||||
p->Code -= newBound;
|
||||
p->Range -= newBound;
|
||||
}
|
||||
Range_Normalize(p);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
|
||||
{
|
||||
p->vt.GetThreshold = Range_GetThreshold;
|
||||
p->vt.Decode = Range_Decode;
|
||||
p->vt.DecodeBit = Range_DecodeBit;
|
||||
}
|
||||
#define RC_Decode(start, size) RangeDec_Decode(p, start, size);
|
||||
#define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R)
|
||||
#define RC_GetThreshold(total) (R->Code / (R->Range /= (total)))
|
||||
|
||||
|
||||
#define MASK(sym) ((signed char *)charMask)[sym]
|
||||
#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
|
||||
typedef CPpmd7_Context * CTX_PTR;
|
||||
#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
|
||||
void Ppmd7_UpdateModel(CPpmd7 *p);
|
||||
|
||||
int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc)
|
||||
#define MASK(sym) ((unsigned char *)charMask)[sym]
|
||||
// MY_FORCE_INLINE
|
||||
// static
|
||||
int Ppmd7z_DecodeSymbol(CPpmd7 *p)
|
||||
{
|
||||
size_t charMask[256 / sizeof(size_t)];
|
||||
|
||||
if (p->MinContext->NumStats != 1)
|
||||
{
|
||||
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
|
||||
unsigned i;
|
||||
UInt32 count, hiCnt;
|
||||
if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
|
||||
UInt32 summFreq = p->MinContext->Union2.SummFreq;
|
||||
|
||||
|
||||
|
||||
|
||||
count = RC_GetThreshold(summFreq);
|
||||
hiCnt = count;
|
||||
|
||||
if ((Int32)(count -= s->Freq) < 0)
|
||||
{
|
||||
Byte symbol;
|
||||
rc->Decode(rc, 0, s->Freq);
|
||||
Byte sym;
|
||||
RC_DecodeFinal(0, s->Freq);
|
||||
p->FoundState = s;
|
||||
symbol = s->Symbol;
|
||||
sym = s->Symbol;
|
||||
Ppmd7_Update1_0(p);
|
||||
return symbol;
|
||||
return sym;
|
||||
}
|
||||
|
||||
p->PrevSuccess = 0;
|
||||
i = p->MinContext->NumStats - 1;
|
||||
i = (unsigned)p->MinContext->NumStats - 1;
|
||||
|
||||
do
|
||||
{
|
||||
if ((hiCnt += (++s)->Freq) > count)
|
||||
if ((Int32)(count -= (++s)->Freq) < 0)
|
||||
{
|
||||
Byte symbol;
|
||||
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
|
||||
Byte sym;
|
||||
RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq);
|
||||
p->FoundState = s;
|
||||
symbol = s->Symbol;
|
||||
sym = s->Symbol;
|
||||
Ppmd7_Update1(p);
|
||||
return symbol;
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
while (--i);
|
||||
if (count >= p->MinContext->SummFreq)
|
||||
return -2;
|
||||
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
|
||||
rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
|
||||
|
||||
if (hiCnt >= summFreq)
|
||||
return PPMD7_SYM_ERROR;
|
||||
|
||||
hiCnt -= count;
|
||||
RC_Decode(hiCnt, summFreq - hiCnt);
|
||||
|
||||
p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol);
|
||||
PPMD_SetAllBitsIn256Bytes(charMask);
|
||||
MASK(s->Symbol) = 0;
|
||||
i = p->MinContext->NumStats - 1;
|
||||
do { MASK((--s)->Symbol) = 0; } while (--i);
|
||||
// i = p->MinContext->NumStats - 1;
|
||||
// do { MASK((--s)->Symbol) = 0; } while (--i);
|
||||
{
|
||||
CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext);
|
||||
MASK(s->Symbol) = 0;
|
||||
do
|
||||
{
|
||||
unsigned sym0 = s2[0].Symbol;
|
||||
unsigned sym1 = s2[1].Symbol;
|
||||
s2 += 2;
|
||||
MASK(sym0) = 0;
|
||||
MASK(sym1) = 0;
|
||||
}
|
||||
while (s2 < s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
|
||||
UInt16 *prob = Ppmd7_GetBinSumm(p);
|
||||
if (rc->DecodeBit(rc, *prob) == 0)
|
||||
UInt32 pr = *prob;
|
||||
UInt32 size0 = (R->Range >> 14) * pr;
|
||||
pr = PPMD_UPDATE_PROB_1(pr);
|
||||
|
||||
if (R->Code < size0)
|
||||
{
|
||||
Byte symbol;
|
||||
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
|
||||
symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
|
||||
Ppmd7_UpdateBin(p);
|
||||
return symbol;
|
||||
Byte sym;
|
||||
*prob = (UInt16)(pr + (1 << PPMD_INT_BITS));
|
||||
|
||||
// RangeDec_DecodeBit0(size0);
|
||||
R->Range = size0;
|
||||
RC_NORM_1(R)
|
||||
/* we can use single byte normalization here because of
|
||||
(min(BinSumm[][]) = 95) > (1 << (14 - 8)) */
|
||||
|
||||
// sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
|
||||
// Ppmd7_UpdateBin(p);
|
||||
{
|
||||
unsigned freq = s->Freq;
|
||||
CTX_PTR c = CTX(SUCCESSOR(s));
|
||||
sym = s->Symbol;
|
||||
p->FoundState = s;
|
||||
p->PrevSuccess = 1;
|
||||
p->RunLength++;
|
||||
s->Freq = (Byte)(freq + (freq < 128));
|
||||
// NextContext(p);
|
||||
if (p->OrderFall == 0 && (const Byte *)c > p->Text)
|
||||
p->MaxContext = p->MinContext = c;
|
||||
else
|
||||
Ppmd7_UpdateModel(p);
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
|
||||
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
|
||||
|
||||
*prob = (UInt16)pr;
|
||||
p->InitEsc = p->ExpEscape[pr >> 10];
|
||||
|
||||
// RangeDec_DecodeBit1(size0);
|
||||
|
||||
R->Code -= size0;
|
||||
R->Range -= size0;
|
||||
RC_NORM_LOCAL(R)
|
||||
|
||||
PPMD_SetAllBitsIn256Bytes(charMask);
|
||||
MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
|
||||
p->PrevSuccess = 0;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
CPpmd_State *ps[256], *s;
|
||||
CPpmd_State *s, *s2;
|
||||
UInt32 freqSum, count, hiCnt;
|
||||
|
||||
CPpmd_See *see;
|
||||
unsigned i, num, numMasked = p->MinContext->NumStats;
|
||||
CPpmd7_Context *mc;
|
||||
unsigned numMasked;
|
||||
RC_NORM_REMOTE(R)
|
||||
mc = p->MinContext;
|
||||
numMasked = mc->NumStats;
|
||||
|
||||
do
|
||||
{
|
||||
p->OrderFall++;
|
||||
if (!p->MinContext->Suffix)
|
||||
return -1;
|
||||
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
|
||||
if (!mc->Suffix)
|
||||
return PPMD7_SYM_END;
|
||||
mc = Ppmd7_GetContext(p, mc->Suffix);
|
||||
}
|
||||
while (p->MinContext->NumStats == numMasked);
|
||||
hiCnt = 0;
|
||||
s = Ppmd7_GetStats(p, p->MinContext);
|
||||
i = 0;
|
||||
num = p->MinContext->NumStats - numMasked;
|
||||
do
|
||||
{
|
||||
int k = (int)(MASK(s->Symbol));
|
||||
hiCnt += (s->Freq & k);
|
||||
ps[i] = s++;
|
||||
i -= k;
|
||||
}
|
||||
while (i != num);
|
||||
while (mc->NumStats == numMasked);
|
||||
|
||||
s = Ppmd7_GetStats(p, mc);
|
||||
|
||||
{
|
||||
unsigned num = mc->NumStats;
|
||||
unsigned num2 = num / 2;
|
||||
|
||||
num &= 1;
|
||||
hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num);
|
||||
s += num;
|
||||
p->MinContext = mc;
|
||||
|
||||
do
|
||||
{
|
||||
unsigned sym0 = s[0].Symbol;
|
||||
unsigned sym1 = s[1].Symbol;
|
||||
s += 2;
|
||||
hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0)));
|
||||
hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1)));
|
||||
}
|
||||
while (--num2);
|
||||
}
|
||||
|
||||
see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
|
||||
freqSum += hiCnt;
|
||||
count = rc->GetThreshold(rc, freqSum);
|
||||
|
||||
|
||||
|
||||
|
||||
count = RC_GetThreshold(freqSum);
|
||||
|
||||
if (count < hiCnt)
|
||||
{
|
||||
Byte symbol;
|
||||
CPpmd_State **pps = ps;
|
||||
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
|
||||
s = *pps;
|
||||
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
|
||||
Byte sym;
|
||||
|
||||
s = Ppmd7_GetStats(p, p->MinContext);
|
||||
hiCnt = count;
|
||||
// count -= s->Freq & (unsigned)(MASK(s->Symbol));
|
||||
// if ((Int32)count >= 0)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
|
||||
// count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
|
||||
};
|
||||
}
|
||||
s--;
|
||||
RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq);
|
||||
|
||||
// new (see->Summ) value can overflow over 16-bits in some rare cases
|
||||
Ppmd_See_Update(see);
|
||||
p->FoundState = s;
|
||||
symbol = s->Symbol;
|
||||
sym = s->Symbol;
|
||||
Ppmd7_Update2(p);
|
||||
return symbol;
|
||||
return sym;
|
||||
}
|
||||
|
||||
if (count >= freqSum)
|
||||
return -2;
|
||||
rc->Decode(rc, hiCnt, freqSum - hiCnt);
|
||||
return PPMD7_SYM_ERROR;
|
||||
|
||||
RC_Decode(hiCnt, freqSum - hiCnt);
|
||||
|
||||
// We increase (see->Summ) for sum of Freqs of all non_Masked symbols.
|
||||
// new (see->Summ) value can overflow over 16-bits in some rare cases
|
||||
see->Summ = (UInt16)(see->Summ + freqSum);
|
||||
do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
|
||||
|
||||
s = Ppmd7_GetStats(p, p->MinContext);
|
||||
s2 = s + p->MinContext->NumStats;
|
||||
do
|
||||
{
|
||||
MASK(s->Symbol) = 0;
|
||||
s++;
|
||||
}
|
||||
while (s != s2);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim)
|
||||
{
|
||||
int sym = 0;
|
||||
if (buf != lim)
|
||||
do
|
||||
{
|
||||
sym = Ppmd7z_DecodeSymbol(p);
|
||||
if (sym < 0)
|
||||
break;
|
||||
*buf = (Byte)sym;
|
||||
}
|
||||
while (++buf < lim);
|
||||
p->LastSymbol = sym;
|
||||
return buf;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
/* Threads.c -- multithreading library
|
||||
2017-06-26 : Igor Pavlov : Public domain */
|
||||
2021-12-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef USE_THREADS_CreateThread
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
|
@ -29,28 +31,103 @@ WRes HandlePtr_Close(HANDLE *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }
|
||||
WRes Handle_WaitObject(HANDLE h)
|
||||
{
|
||||
DWORD dw = WaitForSingleObject(h, INFINITE);
|
||||
/*
|
||||
(dw) result:
|
||||
WAIT_OBJECT_0 // 0
|
||||
WAIT_ABANDONED // 0x00000080 : is not compatible with Win32 Error space
|
||||
WAIT_TIMEOUT // 0x00000102 : is compatible with Win32 Error space
|
||||
WAIT_FAILED // 0xFFFFFFFF
|
||||
*/
|
||||
if (dw == WAIT_FAILED)
|
||||
{
|
||||
dw = GetLastError();
|
||||
if (dw == 0)
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
return (WRes)dw;
|
||||
}
|
||||
|
||||
#define Thread_Wait(p) Handle_WaitObject(*(p))
|
||||
|
||||
WRes Thread_Wait_Close(CThread *p)
|
||||
{
|
||||
WRes res = Thread_Wait(p);
|
||||
WRes res2 = Thread_Close(p);
|
||||
return (res != 0 ? res : res2);
|
||||
}
|
||||
|
||||
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||
{
|
||||
/* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||
|
||||
#ifdef UNDER_CE
|
||||
|
||||
|
||||
#ifdef USE_THREADS_CreateThread
|
||||
|
||||
DWORD threadId;
|
||||
*p = CreateThread(0, 0, func, param, 0, &threadId);
|
||||
|
||||
*p = CreateThread(NULL, 0, func, param, 0, &threadId);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
unsigned threadId;
|
||||
*p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
|
||||
|
||||
*p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId));
|
||||
|
||||
#endif
|
||||
|
||||
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
||||
return HandleToWRes(*p);
|
||||
}
|
||||
|
||||
|
||||
WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity)
|
||||
{
|
||||
#ifdef USE_THREADS_CreateThread
|
||||
|
||||
UNUSED_VAR(affinity)
|
||||
return Thread_Create(p, func, param);
|
||||
|
||||
#else
|
||||
|
||||
/* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||
HANDLE h;
|
||||
WRes wres;
|
||||
unsigned threadId;
|
||||
h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId));
|
||||
*p = h;
|
||||
wres = HandleToWRes(h);
|
||||
if (h)
|
||||
{
|
||||
{
|
||||
// DWORD_PTR prevMask =
|
||||
SetThreadAffinityMask(h, (DWORD_PTR)affinity);
|
||||
/*
|
||||
if (prevMask == 0)
|
||||
{
|
||||
// affinity change is non-critical error, so we can ignore it
|
||||
// wres = GetError();
|
||||
}
|
||||
*/
|
||||
}
|
||||
{
|
||||
DWORD prevSuspendCount = ResumeThread(h);
|
||||
/* ResumeThread() returns:
|
||||
0 : was_not_suspended
|
||||
1 : was_resumed
|
||||
-1 : error
|
||||
*/
|
||||
if (prevSuspendCount == (DWORD)-1)
|
||||
wres = GetError();
|
||||
}
|
||||
}
|
||||
|
||||
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
||||
return wres;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
|
||||
{
|
||||
*p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
|
||||
|
@ -68,10 +145,22 @@ WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEven
|
|||
|
||||
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
|
||||
{
|
||||
// negative ((LONG)maxCount) is not supported in WIN32::CreateSemaphore()
|
||||
*p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
|
||||
return HandleToWRes(*p);
|
||||
}
|
||||
|
||||
WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
|
||||
{
|
||||
// if (Semaphore_IsCreated(p))
|
||||
{
|
||||
WRes wres = Semaphore_Close(p);
|
||||
if (wres != 0)
|
||||
return wres;
|
||||
}
|
||||
return Semaphore_Create(p, initCount, maxCount);
|
||||
}
|
||||
|
||||
static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
|
||||
{ return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
|
||||
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
|
||||
|
@ -80,7 +169,9 @@ WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
|
|||
|
||||
WRes CriticalSection_Init(CCriticalSection *p)
|
||||
{
|
||||
/* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
|
||||
/* InitializeCriticalSection() can raise exception:
|
||||
Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception
|
||||
Windows Vista+ : no exceptions */
|
||||
#ifdef _MSC_VER
|
||||
__try
|
||||
#endif
|
||||
|
@ -89,7 +180,361 @@ WRes CriticalSection_Init(CCriticalSection *p)
|
|||
/* InitializeCriticalSectionAndSpinCount(p, 0); */
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; }
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
// ---------- POSIX ----------
|
||||
|
||||
#ifndef __APPLE__
|
||||
#ifndef _7ZIP_AFFINITY_DISABLE
|
||||
// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "Threads.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _7ZIP_AFFINITY_SUPPORTED
|
||||
// #include <sched.h>
|
||||
#endif
|
||||
|
||||
|
||||
// #include <stdio.h>
|
||||
// #define PRF(p) p
|
||||
#define PRF(p)
|
||||
|
||||
#define Print(s) PRF(printf("\n%s\n", s))
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet)
|
||||
{
|
||||
// new thread in Posix probably inherits affinity from parrent thread
|
||||
Print("Thread_Create_With_CpuSet");
|
||||
|
||||
pthread_attr_t attr;
|
||||
int ret;
|
||||
// int ret2;
|
||||
|
||||
p->_created = 0;
|
||||
|
||||
RINOK(pthread_attr_init(&attr));
|
||||
|
||||
ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
if (cpuSet)
|
||||
{
|
||||
#ifdef _7ZIP_AFFINITY_SUPPORTED
|
||||
|
||||
/*
|
||||
printf("\n affinity :");
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof(*cpuSet) && i < 8; i++)
|
||||
{
|
||||
Byte b = *((const Byte *)cpuSet + i);
|
||||
char temp[32];
|
||||
#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
|
||||
temp[0] = GET_HEX_CHAR((b & 0xF));
|
||||
temp[1] = GET_HEX_CHAR((b >> 4));
|
||||
// temp[0] = GET_HEX_CHAR((b >> 4)); // big-endian
|
||||
// temp[1] = GET_HEX_CHAR((b & 0xF)); // big-endian
|
||||
temp[2] = 0;
|
||||
printf("%s", temp);
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
// ret2 =
|
||||
pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet);
|
||||
// if (ret2) ret = ret2;
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = pthread_create(&p->_tid, &attr, func, param);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
p->_created = 1;
|
||||
/*
|
||||
if (cpuSet)
|
||||
{
|
||||
// ret2 =
|
||||
pthread_setaffinity_np(p->_tid, sizeof(*cpuSet), cpuSet);
|
||||
// if (ret2) ret = ret2;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
// ret2 =
|
||||
pthread_attr_destroy(&attr);
|
||||
// if (ret2 != 0) ret = ret2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||
{
|
||||
return Thread_Create_With_CpuSet(p, func, param, NULL);
|
||||
}
|
||||
|
||||
|
||||
WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity)
|
||||
{
|
||||
Print("Thread_Create_WithAffinity");
|
||||
CCpuSet cs;
|
||||
unsigned i;
|
||||
CpuSet_Zero(&cs);
|
||||
for (i = 0; i < sizeof(affinity) * 8; i++)
|
||||
{
|
||||
if (affinity == 0)
|
||||
break;
|
||||
if (affinity & 1)
|
||||
{
|
||||
CpuSet_Set(&cs, i);
|
||||
}
|
||||
affinity >>= 1;
|
||||
}
|
||||
return Thread_Create_With_CpuSet(p, func, param, &cs);
|
||||
}
|
||||
|
||||
|
||||
WRes Thread_Close(CThread *p)
|
||||
{
|
||||
// Print("Thread_Close");
|
||||
int ret;
|
||||
if (!p->_created)
|
||||
return 0;
|
||||
|
||||
ret = pthread_detach(p->_tid);
|
||||
p->_tid = 0;
|
||||
p->_created = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
WRes Thread_Wait_Close(CThread *p)
|
||||
{
|
||||
// Print("Thread_Wait_Close");
|
||||
void *thread_return;
|
||||
int ret;
|
||||
if (!p->_created)
|
||||
return EINVAL;
|
||||
|
||||
ret = pthread_join(p->_tid, &thread_return);
|
||||
// probably we can't use that (_tid) after pthread_join(), so we close thread here
|
||||
p->_created = 0;
|
||||
p->_tid = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static WRes Event_Create(CEvent *p, int manualReset, int signaled)
|
||||
{
|
||||
RINOK(pthread_mutex_init(&p->_mutex, NULL));
|
||||
RINOK(pthread_cond_init(&p->_cond, NULL));
|
||||
p->_manual_reset = manualReset;
|
||||
p->_state = (signaled ? True : False);
|
||||
p->_created = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled)
|
||||
{ return Event_Create(p, True, signaled); }
|
||||
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p)
|
||||
{ return ManualResetEvent_Create(p, 0); }
|
||||
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled)
|
||||
{ return Event_Create(p, False, signaled); }
|
||||
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p)
|
||||
{ return AutoResetEvent_Create(p, 0); }
|
||||
|
||||
|
||||
WRes Event_Set(CEvent *p)
|
||||
{
|
||||
RINOK(pthread_mutex_lock(&p->_mutex));
|
||||
p->_state = True;
|
||||
int res1 = pthread_cond_broadcast(&p->_cond);
|
||||
int res2 = pthread_mutex_unlock(&p->_mutex);
|
||||
return (res2 ? res2 : res1);
|
||||
}
|
||||
|
||||
WRes Event_Reset(CEvent *p)
|
||||
{
|
||||
RINOK(pthread_mutex_lock(&p->_mutex));
|
||||
p->_state = False;
|
||||
return pthread_mutex_unlock(&p->_mutex);
|
||||
}
|
||||
|
||||
WRes Event_Wait(CEvent *p)
|
||||
{
|
||||
RINOK(pthread_mutex_lock(&p->_mutex));
|
||||
while (p->_state == False)
|
||||
{
|
||||
// ETIMEDOUT
|
||||
// ret =
|
||||
pthread_cond_wait(&p->_cond, &p->_mutex);
|
||||
// if (ret != 0) break;
|
||||
}
|
||||
if (p->_manual_reset == False)
|
||||
{
|
||||
p->_state = False;
|
||||
}
|
||||
return pthread_mutex_unlock(&p->_mutex);
|
||||
}
|
||||
|
||||
WRes Event_Close(CEvent *p)
|
||||
{
|
||||
if (!p->_created)
|
||||
return 0;
|
||||
p->_created = 0;
|
||||
{
|
||||
int res1 = pthread_mutex_destroy(&p->_mutex);
|
||||
int res2 = pthread_cond_destroy(&p->_cond);
|
||||
return (res1 ? res1 : res2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
|
||||
{
|
||||
if (initCount > maxCount || maxCount < 1)
|
||||
return EINVAL;
|
||||
RINOK(pthread_mutex_init(&p->_mutex, NULL));
|
||||
RINOK(pthread_cond_init(&p->_cond, NULL));
|
||||
p->_count = initCount;
|
||||
p->_maxCount = maxCount;
|
||||
p->_created = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
|
||||
{
|
||||
if (Semaphore_IsCreated(p))
|
||||
{
|
||||
/*
|
||||
WRes wres = Semaphore_Close(p);
|
||||
if (wres != 0)
|
||||
return wres;
|
||||
*/
|
||||
if (initCount > maxCount || maxCount < 1)
|
||||
return EINVAL;
|
||||
// return EINVAL; // for debug
|
||||
p->_count = initCount;
|
||||
p->_maxCount = maxCount;
|
||||
return 0;
|
||||
}
|
||||
return Semaphore_Create(p, initCount, maxCount);
|
||||
}
|
||||
|
||||
|
||||
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount)
|
||||
{
|
||||
UInt32 newCount;
|
||||
int ret;
|
||||
|
||||
if (releaseCount < 1)
|
||||
return EINVAL;
|
||||
|
||||
RINOK(pthread_mutex_lock(&p->_mutex));
|
||||
|
||||
newCount = p->_count + releaseCount;
|
||||
if (newCount > p->_maxCount)
|
||||
ret = ERROR_TOO_MANY_POSTS; // EINVAL;
|
||||
else
|
||||
{
|
||||
p->_count = newCount;
|
||||
ret = pthread_cond_broadcast(&p->_cond);
|
||||
}
|
||||
RINOK(pthread_mutex_unlock(&p->_mutex));
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRes Semaphore_Wait(CSemaphore *p)
|
||||
{
|
||||
RINOK(pthread_mutex_lock(&p->_mutex));
|
||||
while (p->_count < 1)
|
||||
{
|
||||
pthread_cond_wait(&p->_cond, &p->_mutex);
|
||||
}
|
||||
p->_count--;
|
||||
return pthread_mutex_unlock(&p->_mutex);
|
||||
}
|
||||
|
||||
WRes Semaphore_Close(CSemaphore *p)
|
||||
{
|
||||
if (!p->_created)
|
||||
return 0;
|
||||
p->_created = 0;
|
||||
{
|
||||
int res1 = pthread_mutex_destroy(&p->_mutex);
|
||||
int res2 = pthread_cond_destroy(&p->_cond);
|
||||
return (res1 ? res1 : res2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
WRes CriticalSection_Init(CCriticalSection *p)
|
||||
{
|
||||
// Print("CriticalSection_Init");
|
||||
if (!p)
|
||||
return EINTR;
|
||||
return pthread_mutex_init(&p->_mutex, NULL);
|
||||
}
|
||||
|
||||
void CriticalSection_Enter(CCriticalSection *p)
|
||||
{
|
||||
// Print("CriticalSection_Enter");
|
||||
if (p)
|
||||
{
|
||||
// int ret =
|
||||
pthread_mutex_lock(&p->_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void CriticalSection_Leave(CCriticalSection *p)
|
||||
{
|
||||
// Print("CriticalSection_Leave");
|
||||
if (p)
|
||||
{
|
||||
// int ret =
|
||||
pthread_mutex_unlock(&p->_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void CriticalSection_Delete(CCriticalSection *p)
|
||||
{
|
||||
// Print("CriticalSection_Delete");
|
||||
if (p)
|
||||
{
|
||||
// int ret =
|
||||
pthread_mutex_destroy(&p->_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
LONG InterlockedIncrement(LONG volatile *addend)
|
||||
{
|
||||
// Print("InterlockedIncrement");
|
||||
#ifdef USE_HACK_UNSAFE_ATOMIC
|
||||
LONG val = *addend + 1;
|
||||
*addend = val;
|
||||
return val;
|
||||
#else
|
||||
return __sync_add_and_fetch(addend, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
|
|
@ -1,38 +1,139 @@
|
|||
/* Threads.h -- multithreading library
|
||||
2017-06-18 : Igor Pavlov : Public domain */
|
||||
2021-12-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_THREADS_H
|
||||
#define __7Z_THREADS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <Windows.h>
|
||||
#else
|
||||
|
||||
#if defined(__linux__)
|
||||
#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
|
||||
#ifndef _7ZIP_AFFINITY_DISABLE
|
||||
#define _7ZIP_AFFINITY_SUPPORTED
|
||||
// #pragma message(" ==== _7ZIP_AFFINITY_SUPPORTED")
|
||||
// #define _GNU_SOURCE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
WRes HandlePtr_Close(HANDLE *h);
|
||||
WRes Handle_WaitObject(HANDLE h);
|
||||
|
||||
typedef HANDLE CThread;
|
||||
#define Thread_Construct(p) *(p) = NULL
|
||||
|
||||
#define Thread_Construct(p) { *(p) = NULL; }
|
||||
#define Thread_WasCreated(p) (*(p) != NULL)
|
||||
#define Thread_Close(p) HandlePtr_Close(p)
|
||||
#define Thread_Wait(p) Handle_WaitObject(*(p))
|
||||
// #define Thread_Wait(p) Handle_WaitObject(*(p))
|
||||
|
||||
#ifdef UNDER_CE
|
||||
// if (USE_THREADS_CreateThread is defined), we use _beginthreadex()
|
||||
// if (USE_THREADS_CreateThread is not definned), we use CreateThread()
|
||||
#define USE_THREADS_CreateThread
|
||||
#endif
|
||||
|
||||
typedef
|
||||
#ifdef UNDER_CE
|
||||
DWORD
|
||||
#ifdef USE_THREADS_CreateThread
|
||||
DWORD
|
||||
#else
|
||||
unsigned
|
||||
#endif
|
||||
THREAD_FUNC_RET_TYPE;
|
||||
|
||||
typedef DWORD_PTR CAffinityMask;
|
||||
typedef DWORD_PTR CCpuSet;
|
||||
|
||||
#define CpuSet_Zero(p) { *(p) = 0; }
|
||||
#define CpuSet_Set(p, cpu) { *(p) |= ((DWORD_PTR)1 << (cpu)); }
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
typedef struct _CThread
|
||||
{
|
||||
pthread_t _tid;
|
||||
int _created;
|
||||
} CThread;
|
||||
|
||||
#define Thread_Construct(p) { (p)->_tid = 0; (p)->_created = 0; }
|
||||
#define Thread_WasCreated(p) ((p)->_created != 0)
|
||||
WRes Thread_Close(CThread *p);
|
||||
// #define Thread_Wait Thread_Wait_Close
|
||||
|
||||
typedef void * THREAD_FUNC_RET_TYPE;
|
||||
|
||||
typedef UInt64 CAffinityMask;
|
||||
|
||||
#ifdef _7ZIP_AFFINITY_SUPPORTED
|
||||
|
||||
typedef cpu_set_t CCpuSet;
|
||||
#define CpuSet_Zero(p) CPU_ZERO(p)
|
||||
#define CpuSet_Set(p, cpu) CPU_SET(cpu, p)
|
||||
#define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p)
|
||||
|
||||
#else
|
||||
unsigned
|
||||
|
||||
typedef UInt64 CCpuSet;
|
||||
#define CpuSet_Zero(p) { *(p) = 0; }
|
||||
#define CpuSet_Set(p, cpu) { *(p) |= ((UInt64)1 << (cpu)); }
|
||||
#define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0)
|
||||
|
||||
#endif
|
||||
THREAD_FUNC_RET_TYPE;
|
||||
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
|
||||
#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
|
||||
|
||||
#if defined(_WIN32) && defined(__GNUC__)
|
||||
/* GCC compiler for x86 32-bit uses the rule:
|
||||
the stack is 16-byte aligned before CALL instruction for function calling.
|
||||
But only root function main() contains instructions that
|
||||
set 16-byte alignment for stack pointer. And another functions
|
||||
just keep alignment, if it was set in some parent function.
|
||||
|
||||
The problem:
|
||||
if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(),
|
||||
the root function of thread doesn't set 16-byte alignment.
|
||||
And stack frames in all child functions also will be unaligned in that case.
|
||||
|
||||
Here we set (force_align_arg_pointer) attribute for root function of new thread.
|
||||
Do we need (force_align_arg_pointer) also for another systems? */
|
||||
|
||||
#define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer))
|
||||
// #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions
|
||||
#else
|
||||
#define THREAD_FUNC_ATTRIB_ALIGN_ARG
|
||||
#endif
|
||||
|
||||
#define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
|
||||
|
||||
typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
|
||||
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
|
||||
WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity);
|
||||
WRes Thread_Wait_Close(CThread *p);
|
||||
|
||||
#ifdef _WIN32
|
||||
#define Thread_Create_With_CpuSet(p, func, param, cs) \
|
||||
Thread_Create_With_Affinity(p, func, param, *cs)
|
||||
#else
|
||||
WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
typedef HANDLE CEvent;
|
||||
typedef CEvent CAutoResetEvent;
|
||||
|
@ -54,6 +155,7 @@ typedef HANDLE CSemaphore;
|
|||
#define Semaphore_Close(p) HandlePtr_Close(p)
|
||||
#define Semaphore_Wait(p) Handle_WaitObject(*(p))
|
||||
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
|
||||
WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
|
||||
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
|
||||
WRes Semaphore_Release1(CSemaphore *p);
|
||||
|
||||
|
@ -63,6 +165,68 @@ WRes CriticalSection_Init(CCriticalSection *p);
|
|||
#define CriticalSection_Enter(p) EnterCriticalSection(p)
|
||||
#define CriticalSection_Leave(p) LeaveCriticalSection(p)
|
||||
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
typedef struct _CEvent
|
||||
{
|
||||
int _created;
|
||||
int _manual_reset;
|
||||
int _state;
|
||||
pthread_mutex_t _mutex;
|
||||
pthread_cond_t _cond;
|
||||
} CEvent;
|
||||
|
||||
typedef CEvent CAutoResetEvent;
|
||||
typedef CEvent CManualResetEvent;
|
||||
|
||||
#define Event_Construct(p) (p)->_created = 0
|
||||
#define Event_IsCreated(p) ((p)->_created)
|
||||
|
||||
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
|
||||
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
|
||||
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
|
||||
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
|
||||
WRes Event_Set(CEvent *p);
|
||||
WRes Event_Reset(CEvent *p);
|
||||
WRes Event_Wait(CEvent *p);
|
||||
WRes Event_Close(CEvent *p);
|
||||
|
||||
|
||||
typedef struct _CSemaphore
|
||||
{
|
||||
int _created;
|
||||
UInt32 _count;
|
||||
UInt32 _maxCount;
|
||||
pthread_mutex_t _mutex;
|
||||
pthread_cond_t _cond;
|
||||
} CSemaphore;
|
||||
|
||||
#define Semaphore_Construct(p) (p)->_created = 0
|
||||
#define Semaphore_IsCreated(p) ((p)->_created)
|
||||
|
||||
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
|
||||
WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
|
||||
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
|
||||
#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1)
|
||||
WRes Semaphore_Wait(CSemaphore *p);
|
||||
WRes Semaphore_Close(CSemaphore *p);
|
||||
|
||||
|
||||
typedef struct _CCriticalSection
|
||||
{
|
||||
pthread_mutex_t _mutex;
|
||||
} CCriticalSection;
|
||||
|
||||
WRes CriticalSection_Init(CCriticalSection *p);
|
||||
void CriticalSection_Delete(CCriticalSection *cs);
|
||||
void CriticalSection_Enter(CCriticalSection *cs);
|
||||
void CriticalSection_Leave(CCriticalSection *cs);
|
||||
|
||||
LONG InterlockedIncrement(LONG volatile *addend);
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,7 +4,9 @@ make_release_only()
|
|||
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_PPMD_SUPPPORT" )
|
||||
|
||||
set( LZMA_FILES
|
||||
find_package(Threads)
|
||||
|
||||
add_library( lzma STATIC
|
||||
C/7zArcIn.c
|
||||
C/7zBuf.c
|
||||
C/7zCrc.c
|
||||
|
@ -18,17 +20,13 @@ set( LZMA_FILES
|
|||
C/CpuArch.c
|
||||
C/Delta.c
|
||||
C/LzFind.c
|
||||
C/LzFindMt.c
|
||||
C/LzFindOpt.c
|
||||
C/Lzma2Dec.c
|
||||
C/LzmaDec.c
|
||||
C/LzmaEnc.c
|
||||
C/Ppmd7.c
|
||||
C/Ppmd7Dec.c )
|
||||
|
||||
if( WIN32 )
|
||||
set( LZMA_FILES ${LZMA_FILES} C/LzFindMt.c C/Threads.c )
|
||||
else()
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_ST" )
|
||||
endif()
|
||||
|
||||
add_library( lzma STATIC ${LZMA_FILES} )
|
||||
target_link_libraries( lzma )
|
||||
C/Ppmd7Dec.c
|
||||
C/Threads.c
|
||||
)
|
||||
target_link_libraries( lzma Threads::Threads )
|
||||
|
|
|
@ -1,6 +1,80 @@
|
|||
HISTORY of the LZMA SDK
|
||||
-----------------------
|
||||
|
||||
21.07 2021-12-26
|
||||
-------------------------
|
||||
- New switches: -spm and -im!{file_path} to exclude directories from processing
|
||||
for specified paths that don't contain path separator character at the end of path.
|
||||
- The sorting order of files in archives was slightly changed to be more consistent
|
||||
for cases where the name of some directory is the same as the prefix part of the name
|
||||
of another directory or file.
|
||||
|
||||
|
||||
21.06 2021-11-24
|
||||
-------------------------
|
||||
- Bug in LZMA encoder in file LzmaEnc.c was fixed:
|
||||
LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly,
|
||||
if size value for output buffer is smaller than size required for all compressed data.
|
||||
LzmaEnc_Encode() could work incorrectly,
|
||||
if callback ISeqOutStream::Write() doesn't write all compressed data.
|
||||
NCompress::NLzma::CEncoder::Code() could work incorrectly,
|
||||
if callback ISequentialOutStream::Write() returns error code.
|
||||
- Bug in versions 21.00-21.05 was fixed:
|
||||
7-Zip didn't set attributes of directories during archive extracting.
|
||||
|
||||
|
||||
21.04 beta 2021-11-02
|
||||
-------------------------
|
||||
- 7-Zip now reduces the number of working CPU threads for compression,
|
||||
if RAM size is not enough for compression with big LZMA2 dictionary.
|
||||
- 7-Zip now can create and check "file.sha256" text files that contain the list
|
||||
of file names and SHA-256 checksums in format compatible with sha256sum program.
|
||||
|
||||
|
||||
21.03 beta 2021-07-20
|
||||
-------------------------
|
||||
- The maximum dictionary size for LZMA/LZMA2 compressing was increased to 4 GB (3840 MiB).
|
||||
- Minor speed optimizations in LZMA/LZMA2 compressing.
|
||||
|
||||
|
||||
21.02 alpha 2021-05-06
|
||||
-------------------------
|
||||
- The command line version of 7-Zip for macOS was released.
|
||||
- The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux
|
||||
was increased by 20%-60%.
|
||||
|
||||
|
||||
21.01 alpha 2021-03-09
|
||||
-------------------------
|
||||
- The command line version of 7-Zip for Linux was released.
|
||||
- The improvements for speed of ARM64 version using hardware CPU instructions
|
||||
for AES, CRC-32, SHA-1 and SHA-256.
|
||||
- Some bugs were fixed.
|
||||
|
||||
|
||||
20.02 alpha 2020-08-08
|
||||
-------------------------
|
||||
- The default number of LZMA2 chunks per solid block in 7z archive was increased to 64.
|
||||
It allows to increase the compression speed for big 7z archives, if there is a big number
|
||||
of CPU cores and threads.
|
||||
- The speed of PPMd compressing/decompressing was increased for 7z archives.
|
||||
- The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system
|
||||
to modify "Last Access Time" property of source files for archiving and hashing operations.
|
||||
- Some bugs were fixed.
|
||||
|
||||
|
||||
20.00 alpha 2020-02-06
|
||||
-------------------------
|
||||
- 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5,
|
||||
that can work faster than bt4 and hc4 match finders for the data with big redundancy.
|
||||
- The compression ratio was improved for Fast and Fastest compression levels with the
|
||||
following default settings:
|
||||
- Fastest level (-mx1) : hc5 match finder with 256 KB dictionary.
|
||||
- Fast level (-mx3) : hc5 match finder with 4 MB dictionary.
|
||||
- Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra
|
||||
compression levels.
|
||||
|
||||
|
||||
19.00 2019-02-21
|
||||
-------------------------
|
||||
- Encryption strength for 7z archives was increased:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
LZMA SDK 19.00
|
||||
LZMA SDK 21.07
|
||||
--------------
|
||||
|
||||
LZMA SDK provides the documentation, samples, header files,
|
||||
|
@ -62,14 +62,61 @@ LZMA SDK Contents
|
|||
|
||||
UNIX/Linux version
|
||||
------------------
|
||||
To compile C++ version of file->file LZMA encoding, go to directory
|
||||
CPP/7zip/Bundles/LzmaCon
|
||||
and call make to recompile it:
|
||||
make -f makefile.gcc clean all
|
||||
There are several otpions to compile 7-Zip with different compilers: gcc and clang.
|
||||
Also 7-Zip code contains two versions for some critical parts of code: in C and in Assembeler.
|
||||
So if you compile the version with Assembeler code, you will get faster 7-Zip binary.
|
||||
|
||||
7-Zip's assembler code uses the following syntax for different platforms:
|
||||
|
||||
1) x86 and x86-64 (AMD64): MASM syntax.
|
||||
There are 2 programs that supports MASM syntax in Linux.
|
||||
' 'Asmc Macro Assembler and JWasm. But JWasm now doesn't support some
|
||||
cpu instructions used in 7-Zip.
|
||||
So you must install Asmc Macro Assembler in Linux, if you want to compile fastest version
|
||||
of 7-Zip x86 and x86-64:
|
||||
https://github.com/nidud/asmc
|
||||
|
||||
2) arm64: GNU assembler for ARM64 with preprocessor.
|
||||
That systax of that arm64 assembler code in 7-Zip is supported by GCC and CLANG for ARM64.
|
||||
|
||||
There are different binaries that can be compiled from 7-Zip source.
|
||||
There are 2 main files in folder for compiling:
|
||||
makefile - that can be used for compiling Windows version of 7-Zip with nmake command
|
||||
makefile.gcc - that can be used for compiling Linux/macOS versions of 7-Zip with make command
|
||||
|
||||
At first you must change the current folder to folder that contains `makefile.gcc`:
|
||||
|
||||
cd CPP/7zip/Bundles/Alone7z
|
||||
|
||||
Then you can compile `makefile.gcc` with the command:
|
||||
|
||||
make -j -f makefile.gcc
|
||||
|
||||
Also there are additional "*.mak" files in folder "CPP/7zip/" that can be used to compile
|
||||
7-Zip binaries with optimized code and optimzing options.
|
||||
|
||||
To compile with GCC without assembler:
|
||||
cd CPP/7zip/Bundles/Alone7z
|
||||
make -j -f ../../cmpl_gcc.mak
|
||||
|
||||
To compile with CLANG without assembler:
|
||||
make -j -f ../../cmpl_clang.mak
|
||||
|
||||
To compile 7-Zip for x86-64 with asmc assembler:
|
||||
make -j -f ../../cmpl_gcc_x64.mak
|
||||
|
||||
To compile 7-Zip for arm64 with assembler:
|
||||
make -j -f ../../cmpl_gcc_arm64.mak
|
||||
|
||||
To compile 7-Zip for arm64 for macOS:
|
||||
make -j -f ../../cmpl_mac_arm64.mak
|
||||
|
||||
Also you can change some compiler options in the mak files:
|
||||
cmpl_gcc.mak
|
||||
var_gcc.mak
|
||||
warn_gcc.mak
|
||||
|
||||
|
||||
In some UNIX/Linux versions you must compile LZMA with static libraries.
|
||||
To compile with static libraries, you can use
|
||||
LIB = -lm -static
|
||||
|
||||
Also you can use p7zip (port of 7-Zip for POSIX systems like Unix or Linux):
|
||||
|
||||
|
|
|
@ -1,6 +1,69 @@
|
|||
|
||||
ChangeLog file for zlib
|
||||
|
||||
Changes in 1.2.12 (27 Mar 2022)
|
||||
- Cygwin does not have _wopen(), so do not create gzopen_w() there
|
||||
- Permit a deflateParams() parameter change as soon as possible
|
||||
- Limit hash table inserts after switch from stored deflate
|
||||
- Fix bug when window full in deflate_stored()
|
||||
- Fix CLEAR_HASH macro to be usable as a single statement
|
||||
- Avoid a conversion error in gzseek when off_t type too small
|
||||
- Have Makefile return non-zero error code on test failure
|
||||
- Avoid some conversion warnings in gzread.c and gzwrite.c
|
||||
- Update use of errno for newer Windows CE versions
|
||||
- Small speedup to inflate [psumbera]
|
||||
- Return an error if the gzputs string length can't fit in an int
|
||||
- Add address checking in clang to -w option of configure
|
||||
- Don't compute check value for raw inflate if asked to validate
|
||||
- Handle case where inflateSync used when header never processed
|
||||
- Avoid the use of ptrdiff_t
|
||||
- Avoid an undefined behavior of memcpy() in gzappend()
|
||||
- Avoid undefined behaviors of memcpy() in gz*printf()
|
||||
- Avoid an undefined behavior of memcpy() in _tr_stored_block()
|
||||
- Make the names in functions declarations identical to definitions
|
||||
- Remove old assembler code in which bugs have manifested
|
||||
- Fix deflateEnd() to not report an error at start of raw deflate
|
||||
- Add legal disclaimer to README
|
||||
- Emphasize the need to continue decompressing gzip members
|
||||
- Correct the initialization requirements for deflateInit2()
|
||||
- Fix a bug that can crash deflate on some input when using Z_FIXED
|
||||
- Assure that the number of bits for deflatePrime() is valid
|
||||
- Use a structure to make globals in enough.c evident
|
||||
- Use a macro for the printf format of big_t in enough.c
|
||||
- Clean up code style in enough.c, update version
|
||||
- Use inline function instead of macro for index in enough.c
|
||||
- Clarify that prefix codes are counted in enough.c
|
||||
- Show all the codes for the maximum tables size in enough.c
|
||||
- Add gznorm.c example, which normalizes gzip files
|
||||
- Fix the zran.c example to work on a multiple-member gzip file
|
||||
- Add tables for crc32_combine(), to speed it up by a factor of 200
|
||||
- Add crc32_combine_gen() and crc32_combine_op() for fast combines
|
||||
- Speed up software CRC-32 computation by a factor of 1.5 to 3
|
||||
- Use atomic test and set, if available, for dynamic CRC tables
|
||||
- Don't bother computing check value after successful inflateSync()
|
||||
- Correct comment in crc32.c
|
||||
- Add use of the ARMv8 crc32 instructions when requested
|
||||
- Use ARM crc32 instructions if the ARM architecture has them
|
||||
- Explicitly note that the 32-bit check values are 32 bits
|
||||
- Avoid adding empty gzip member after gzflush with Z_FINISH
|
||||
- Fix memory leak on error in gzlog.c
|
||||
- Fix error in comment on the polynomial representation of a byte
|
||||
- Clarify gz* function interfaces, referring to parameter names
|
||||
- Change macro name in inflate.c to avoid collision in VxWorks
|
||||
- Correct typo in blast.c
|
||||
- Improve portability of contrib/minizip
|
||||
- Fix indentation in minizip's zip.c
|
||||
- Replace black/white with allow/block. (theresa-m)
|
||||
- minizip warning fix if MAXU32 already defined. (gvollant)
|
||||
- Fix unztell64() in minizip to work past 4GB. (Daniël Hörchner)
|
||||
- Clean up minizip to reduce warnings for testing
|
||||
- Add fallthrough comments for gcc
|
||||
- Eliminate use of ULL constants
|
||||
- Separate out address sanitizing from warnings in configure
|
||||
- Remove destructive aspects of make distclean
|
||||
- Check for cc masquerading as gcc or clang in configure
|
||||
- Fix crc32.c to compile local functions only if used
|
||||
|
||||
Changes in 1.2.11 (15 Jan 2017)
|
||||
- Fix deflate stored bug when pulling last block from window
|
||||
- Permit immediate deflateParams changes before any deflate input
|
||||
|
@ -511,7 +574,7 @@ Changes in 1.2.3.5 (8 Jan 2010)
|
|||
- Don't use _vsnprintf on later versions of MSVC [Lowman]
|
||||
- Add CMake build script and input file [Lowman]
|
||||
- Update contrib/minizip to 1.1 [Svensson, Vollant]
|
||||
- Moved nintendods directory from contrib to .
|
||||
- Moved nintendods directory from contrib to root
|
||||
- Replace gzio.c with a new set of routines with the same functionality
|
||||
- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above
|
||||
- Update contrib/minizip to 1.1b
|
||||
|
@ -685,7 +748,7 @@ Changes in 1.2.2.4 (11 July 2005)
|
|||
- Be more strict on incomplete code sets in inflate_table() and increase
|
||||
ENOUGH and MAXD -- this repairs a possible security vulnerability for
|
||||
invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
|
||||
discovering the vulnerability and providing test cases.
|
||||
discovering the vulnerability and providing test cases
|
||||
- Add ia64 support to configure for HP-UX [Smith]
|
||||
- Add error return to gzread() for format or i/o error [Levin]
|
||||
- Use malloc.h for OS/2 [Necasek]
|
||||
|
@ -721,7 +784,7 @@ Changes in 1.2.2.2 (30 December 2004)
|
|||
- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
|
||||
- Add updated make_vms.com [Coghlan], update README
|
||||
- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
|
||||
fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
|
||||
fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html
|
||||
- Add FAQ entry and comments in deflate.c on uninitialized memory access
|
||||
- Add Solaris 9 make options in configure [Gilbert]
|
||||
- Allow strerror() usage in gzio.c for STDC
|
||||
|
@ -792,7 +855,7 @@ Changes in 1.2.1.1 (9 January 2004)
|
|||
- Fix a big fat bug in inftrees.c that prevented decoding valid
|
||||
dynamic blocks with only literals and no distance codes --
|
||||
Thanks to "Hot Emu" for the bug report and sample file
|
||||
- Add a note to puff.c on no distance codes case.
|
||||
- Add a note to puff.c on no distance codes case
|
||||
|
||||
Changes in 1.2.1 (17 November 2003)
|
||||
- Remove a tab in contrib/gzappend/gzappend.c
|
||||
|
@ -1036,14 +1099,14 @@ Changes in 1.2.0 (9 March 2003)
|
|||
- Add contrib/puff/ simple inflate for deflate format description
|
||||
|
||||
Changes in 1.1.4 (11 March 2002)
|
||||
- ZFREE was repeated on same allocation on some error conditions.
|
||||
- ZFREE was repeated on same allocation on some error conditions
|
||||
This creates a security problem described in
|
||||
http://www.zlib.org/advisory-2002-03-11.txt
|
||||
- Returned incorrect error (Z_MEM_ERROR) on some invalid data
|
||||
- Avoid accesses before window for invalid distances with inflate window
|
||||
less than 32K.
|
||||
less than 32K
|
||||
- force windowBits > 8 to avoid a bug in the encoder for a window size
|
||||
of 256 bytes. (A complete fix will be available in 1.1.5).
|
||||
of 256 bytes. (A complete fix will be available in 1.1.5)
|
||||
|
||||
Changes in 1.1.3 (9 July 1998)
|
||||
- fix "an inflate input buffer bug that shows up on rare but persistent
|
||||
|
@ -1117,7 +1180,7 @@ Changes in 1.1.1 (27 Feb 98)
|
|||
- remove block truncation heuristic which had very marginal effect for zlib
|
||||
(smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
|
||||
compression ratio on some files. This also allows inlining _tr_tally for
|
||||
matches in deflate_slow.
|
||||
matches in deflate_slow
|
||||
- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
|
||||
|
||||
Changes in 1.1.0 (24 Feb 98)
|
||||
|
@ -1162,7 +1225,7 @@ Changes in 1.0.8 (27 Jan 1998)
|
|||
- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
|
||||
- use constant arrays for the static trees in trees.c instead of computing
|
||||
them at run time (thanks to Ken Raeburn for this suggestion). To create
|
||||
trees.h, compile with GEN_TREES_H and run "make test".
|
||||
trees.h, compile with GEN_TREES_H and run "make test"
|
||||
- check return code of example in "make test" and display result
|
||||
- pass minigzip command line options to file_compress
|
||||
- simplifying code of inflateSync to avoid gcc 2.8 bug
|
||||
|
@ -1201,12 +1264,12 @@ Changes in 1.0.6 (19 Jan 1998)
|
|||
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
|
||||
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
|
||||
- Fix a deflate bug occurring only with compression level 0 (thanks to
|
||||
Andy Buckler for finding this one).
|
||||
- In minigzip, pass transparently also the first byte for .Z files.
|
||||
Andy Buckler for finding this one)
|
||||
- In minigzip, pass transparently also the first byte for .Z files
|
||||
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
|
||||
- check Z_FINISH in inflate (thanks to Marc Schluper)
|
||||
- Implement deflateCopy (thanks to Adam Costello)
|
||||
- make static libraries by default in configure, add --shared option.
|
||||
- make static libraries by default in configure, add --shared option
|
||||
- move MSDOS or Windows specific files to directory msdos
|
||||
- suppress the notion of partial flush to simplify the interface
|
||||
(but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
|
||||
|
@ -1218,7 +1281,7 @@ Changes in 1.0.6 (19 Jan 1998)
|
|||
- added Makefile.nt (thanks to Stephen Williams)
|
||||
- added the unsupported "contrib" directory:
|
||||
contrib/asm386/ by Gilles Vollant <info@winimage.com>
|
||||
386 asm code replacing longest_match().
|
||||
386 asm code replacing longest_match()
|
||||
contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
A C++ I/O streams interface to the zlib gz* functions
|
||||
contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||
|
@ -1226,7 +1289,7 @@ Changes in 1.0.6 (19 Jan 1998)
|
|||
contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
|
||||
A very simple tar.gz file extractor using zlib
|
||||
contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
|
||||
How to use compress(), uncompress() and the gz* functions from VB.
|
||||
How to use compress(), uncompress() and the gz* functions from VB
|
||||
- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
|
||||
level) in minigzip (thanks to Tom Lane)
|
||||
|
||||
|
@ -1235,8 +1298,8 @@ Changes in 1.0.6 (19 Jan 1998)
|
|||
- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
|
||||
- add undocumented function zError to convert error code to string
|
||||
(for Tim Smithers)
|
||||
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
|
||||
- Use default memcpy for Symantec MSDOS compiler.
|
||||
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code
|
||||
- Use default memcpy for Symantec MSDOS compiler
|
||||
- Add EXPORT keyword for check_func (needed for Windows DLL)
|
||||
- add current directory to LD_LIBRARY_PATH for "make test"
|
||||
- create also a link for libz.so.1
|
||||
|
@ -1249,7 +1312,7 @@ Changes in 1.0.6 (19 Jan 1998)
|
|||
- allow compilation with ANSI keywords only enabled for TurboC in large model
|
||||
- avoid "versionString"[0] (Borland bug)
|
||||
- add NEED_DUMMY_RETURN for Borland
|
||||
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
|
||||
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch)
|
||||
- allow compilation with CC
|
||||
- defined STDC for OS/2 (David Charlap)
|
||||
- limit external names to 8 chars for MVS (Thomas Lund)
|
||||
|
@ -1259,7 +1322,7 @@ Changes in 1.0.6 (19 Jan 1998)
|
|||
- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
|
||||
- added makelcc.bat for lcc-win32 (Tom St Denis)
|
||||
- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
|
||||
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
|
||||
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion
|
||||
- check for unistd.h in configure (for off_t)
|
||||
- remove useless check parameter in inflate_blocks_free
|
||||
- avoid useless assignment of s->check to itself in inflate_blocks_new
|
||||
|
@ -1280,7 +1343,7 @@ Changes in 1.0.5 (3 Jan 98)
|
|||
Changes in 1.0.4 (24 Jul 96)
|
||||
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
|
||||
bit, so the decompressor could decompress all the correct data but went
|
||||
on to attempt decompressing extra garbage data. This affected minigzip too.
|
||||
on to attempt decompressing extra garbage data. This affected minigzip too
|
||||
- zlibVersion and gzerror return const char* (needed for DLL)
|
||||
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
|
||||
- use z_error only for DEBUG (avoid problem with DLLs)
|
||||
|
@ -1310,7 +1373,7 @@ Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
|
|||
- fix array overlay in deflate.c which sometimes caused bad compressed data
|
||||
- fix inflate bug with empty stored block
|
||||
- fix MSDOS medium model which was broken in 0.99
|
||||
- fix deflateParams() which could generate bad compressed data.
|
||||
- fix deflateParams() which could generate bad compressed data
|
||||
- Bytef is define'd instead of typedef'ed (work around Borland bug)
|
||||
- added an INDEX file
|
||||
- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
|
||||
|
@ -1331,7 +1394,7 @@ Changes in 0.99 (27 Jan 96)
|
|||
- allow preset dictionary shared between compressor and decompressor
|
||||
- allow compression level 0 (no compression)
|
||||
- add deflateParams in zlib.h: allow dynamic change of compression level
|
||||
and compression strategy.
|
||||
and compression strategy
|
||||
- test large buffers and deflateParams in example.c
|
||||
- add optional "configure" to build zlib as a shared library
|
||||
- suppress Makefile.qnx, use configure instead
|
||||
|
@ -1373,30 +1436,30 @@ Changes in 0.99 (27 Jan 96)
|
|||
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
|
||||
- use Z_BINARY instead of BINARY
|
||||
- document that gzclose after gzdopen will close the file
|
||||
- allow "a" as mode in gzopen.
|
||||
- allow "a" as mode in gzopen
|
||||
- fix error checking in gzread
|
||||
- allow skipping .gz extra-field on pipes
|
||||
- added reference to Perl interface in README
|
||||
- put the crc table in FAR data (I dislike more and more the medium model :)
|
||||
- added get_crc_table
|
||||
- added a dimension to all arrays (Borland C can't count).
|
||||
- added a dimension to all arrays (Borland C can't count)
|
||||
- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
|
||||
- guard against multiple inclusion of *.h (for precompiled header on Mac)
|
||||
- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
|
||||
- Watcom C pretends to be Microsoft C small model even in 32 bit mode
|
||||
- don't use unsized arrays to avoid silly warnings by Visual C++:
|
||||
warning C4746: 'inflate_mask' : unsized array treated as '__far'
|
||||
(what's wrong with far data in far model?).
|
||||
(what's wrong with far data in far model?)
|
||||
- define enum out of inflate_blocks_state to allow compilation with C++
|
||||
|
||||
Changes in 0.95 (16 Aug 95)
|
||||
- fix MSDOS small and medium model (now easier to adapt to any compiler)
|
||||
- inlined send_bits
|
||||
- fix the final (:-) bug for deflate with flush (output was correct but
|
||||
not completely flushed in rare occasions).
|
||||
not completely flushed in rare occasions)
|
||||
- default window size is same for compression and decompression
|
||||
(it's now sufficient to set MAX_WBITS in zconf.h).
|
||||
(it's now sufficient to set MAX_WBITS in zconf.h)
|
||||
- voidp -> voidpf and voidnp -> voidp (for consistency with other
|
||||
typedefs and because voidnp was not near in large model).
|
||||
typedefs and because voidnp was not near in large model)
|
||||
|
||||
Changes in 0.94 (13 Aug 95)
|
||||
- support MSDOS medium model
|
||||
|
@ -1405,12 +1468,12 @@ Changes in 0.94 (13 Aug 95)
|
|||
- added support for VMS
|
||||
- allow a compression level in gzopen()
|
||||
- gzflush now calls fflush
|
||||
- For deflate with flush, flush even if no more input is provided.
|
||||
- For deflate with flush, flush even if no more input is provided
|
||||
- rename libgz.a as libz.a
|
||||
- avoid complex expression in infcodes.c triggering Turbo C bug
|
||||
- work around a problem with gcc on Alpha (in INSERT_STRING)
|
||||
- don't use inline functions (problem with some gcc versions)
|
||||
- allow renaming of Byte, uInt, etc... with #define.
|
||||
- allow renaming of Byte, uInt, etc... with #define
|
||||
- avoid warning about (unused) pointer before start of array in deflate.c
|
||||
- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
|
||||
- avoid reserved word 'new' in trees.c
|
||||
|
@ -1429,7 +1492,7 @@ Changes in 0.92 (3 May 95)
|
|||
- no memcpy on Pyramid
|
||||
- suppressed inftest.c
|
||||
- optimized fill_window, put longest_match inline for gcc
|
||||
- optimized inflate on stored blocks.
|
||||
- optimized inflate on stored blocks
|
||||
- untabify all sources to simplify patches
|
||||
|
||||
Changes in 0.91 (2 May 95)
|
||||
|
@ -1447,7 +1510,7 @@ Changes in 0.9 (1 May 95)
|
|||
- let again gzread copy uncompressed data unchanged (was working in 0.71)
|
||||
- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
|
||||
- added a test of inflateSync in example.c
|
||||
- moved MAX_WBITS to zconf.h because users might want to change that.
|
||||
- moved MAX_WBITS to zconf.h because users might want to change that
|
||||
- document explicitly that zalloc(64K) on MSDOS must return a normalized
|
||||
pointer (zero offset)
|
||||
- added Makefiles for Microsoft C, Turbo C, Borland C++
|
||||
|
@ -1456,7 +1519,7 @@ Changes in 0.9 (1 May 95)
|
|||
Changes in 0.8 (29 April 95)
|
||||
- added fast inflate (inffast.c)
|
||||
- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
|
||||
is incompatible with previous versions of zlib which returned Z_OK.
|
||||
is incompatible with previous versions of zlib which returned Z_OK
|
||||
- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
|
||||
(actually that was not a compiler bug, see 0.81 above)
|
||||
- gzread no longer reads one extra byte in certain cases
|
||||
|
@ -1466,50 +1529,50 @@ Changes in 0.8 (29 April 95)
|
|||
|
||||
Changes in 0.71 (14 April 95)
|
||||
- Fixed more MSDOS compilation problems :( There is still a bug with
|
||||
TurboC large model.
|
||||
TurboC large model
|
||||
|
||||
Changes in 0.7 (14 April 95)
|
||||
- Added full inflate support.
|
||||
- Added full inflate support
|
||||
- Simplified the crc32() interface. The pre- and post-conditioning
|
||||
(one's complement) is now done inside crc32(). WARNING: this is
|
||||
incompatible with previous versions; see zlib.h for the new usage.
|
||||
incompatible with previous versions; see zlib.h for the new usage
|
||||
|
||||
Changes in 0.61 (12 April 95)
|
||||
- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
|
||||
- workaround for a bug in TurboC. example and minigzip now work on MSDOS
|
||||
|
||||
Changes in 0.6 (11 April 95)
|
||||
- added minigzip.c
|
||||
- added gzdopen to reopen a file descriptor as gzFile
|
||||
- added transparent reading of non-gziped files in gzread.
|
||||
- added transparent reading of non-gziped files in gzread
|
||||
- fixed bug in gzread (don't read crc as data)
|
||||
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
|
||||
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose)
|
||||
- don't allocate big arrays in the stack (for MSDOS)
|
||||
- fix some MSDOS compilation problems
|
||||
|
||||
Changes in 0.5:
|
||||
- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
|
||||
not yet Z_FULL_FLUSH.
|
||||
not yet Z_FULL_FLUSH
|
||||
- support decompression but only in a single step (forced Z_FINISH)
|
||||
- added opaque object for zalloc and zfree.
|
||||
- added opaque object for zalloc and zfree
|
||||
- added deflateReset and inflateReset
|
||||
- added a variable zlib_version for consistency checking.
|
||||
- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
|
||||
Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
|
||||
- added a variable zlib_version for consistency checking
|
||||
- renamed the 'filter' parameter of deflateInit2 as 'strategy'
|
||||
Added Z_FILTERED and Z_HUFFMAN_ONLY constants
|
||||
|
||||
Changes in 0.4:
|
||||
- avoid "zip" everywhere, use zlib instead of ziplib.
|
||||
- avoid "zip" everywhere, use zlib instead of ziplib
|
||||
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
|
||||
if compression method == 8.
|
||||
if compression method == 8
|
||||
- added adler32 and crc32
|
||||
- renamed deflateOptions as deflateInit2, call one or the other but not both
|
||||
- added the method parameter for deflateInit2.
|
||||
- added the method parameter for deflateInit2
|
||||
- added inflateInit2
|
||||
- simplied considerably deflateInit and inflateInit by not supporting
|
||||
user-provided history buffer. This is supported only in deflateInit2
|
||||
and inflateInit2.
|
||||
and inflateInit2
|
||||
|
||||
Changes in 0.3:
|
||||
- prefix all macro names with Z_
|
||||
- use Z_FINISH instead of deflateEnd to finish compression.
|
||||
- use Z_FINISH instead of deflateEnd to finish compression
|
||||
- added Z_HUFFMAN_ONLY
|
||||
- added gzerror()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.11 is a general purpose data compression library. All the code is
|
||||
zlib 1.2.12 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
|
||||
|
@ -31,7 +31,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
|||
issue of Dr. Dobb's Journal; a copy of the article is available at
|
||||
http://marknelson.us/1997/01/01/zlib-engine/ .
|
||||
|
||||
The changes made in version 1.2.11 are documented in the file ChangeLog.
|
||||
The changes made in version 1.2.12 are documented in the file ChangeLog.
|
||||
|
||||
Unsupported third party contributions are provided in directory contrib/ .
|
||||
|
||||
|
@ -84,7 +84,7 @@ Acknowledgments:
|
|||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
(C) 1995-2022 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -108,7 +108,10 @@ Copyright notice:
|
|||
If you use the zlib library in a product, we would appreciate *not* receiving
|
||||
lengthy legal documents to sign. The sources are provided for free but without
|
||||
warranty of any kind. The library has been entirely written by Jean-loup
|
||||
Gailly and Mark Adler; it does not include third-party code.
|
||||
Gailly and Mark Adler; it does not include third-party code. We make all
|
||||
contributions to and distributions of this project solely in our personal
|
||||
capacity, and are not conveying any rights to any intellectual property of
|
||||
any third parties.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include in
|
||||
the file ChangeLog history information documenting your changes. Please read
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/* deflate.c -- compress data using the deflation algorithm
|
||||
* Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
* Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -52,7 +52,7 @@
|
|||
#include "deflate.h"
|
||||
|
||||
const char deflate_copyright[] =
|
||||
" deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
|
||||
" deflate 1.2.12 Copyright 1995-2022 Jean-loup Gailly and Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
|
@ -190,8 +190,11 @@ local const config configuration_table[10] = {
|
|||
* prev[] will be initialized on the fly.
|
||||
*/
|
||||
#define CLEAR_HASH(s) \
|
||||
s->head[s->hash_size-1] = NIL; \
|
||||
zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
|
||||
do { \
|
||||
s->head[s->hash_size-1] = NIL; \
|
||||
zmemzero((Bytef *)s->head, \
|
||||
(unsigned)(s->hash_size-1)*sizeof(*s->head)); \
|
||||
} while (0)
|
||||
|
||||
/* ===========================================================================
|
||||
* Slide the hash table when sliding the window down (could be avoided with 32
|
||||
|
@ -252,11 +255,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
|||
int wrap = 1;
|
||||
static const char my_version[] = ZLIB_VERSION;
|
||||
|
||||
ushf *overlay;
|
||||
/* We overlay pending_buf and d_buf+l_buf. This works since the average
|
||||
* output size for (length,distance) codes is <= 24 bits.
|
||||
*/
|
||||
|
||||
if (version == Z_NULL || version[0] != my_version[0] ||
|
||||
stream_size != sizeof(z_stream)) {
|
||||
return Z_VERSION_ERROR;
|
||||
|
@ -326,9 +324,47 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
|||
|
||||
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
|
||||
|
||||
overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
|
||||
s->pending_buf = (uchf *) overlay;
|
||||
s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
|
||||
/* We overlay pending_buf and sym_buf. This works since the average size
|
||||
* for length/distance pairs over any compressed block is assured to be 31
|
||||
* bits or less.
|
||||
*
|
||||
* Analysis: The longest fixed codes are a length code of 8 bits plus 5
|
||||
* extra bits, for lengths 131 to 257. The longest fixed distance codes are
|
||||
* 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
|
||||
* possible fixed-codes length/distance pair is then 31 bits total.
|
||||
*
|
||||
* sym_buf starts one-fourth of the way into pending_buf. So there are
|
||||
* three bytes in sym_buf for every four bytes in pending_buf. Each symbol
|
||||
* in sym_buf is three bytes -- two for the distance and one for the
|
||||
* literal/length. As each symbol is consumed, the pointer to the next
|
||||
* sym_buf value to read moves forward three bytes. From that symbol, up to
|
||||
* 31 bits are written to pending_buf. The closest the written pending_buf
|
||||
* bits gets to the next sym_buf symbol to read is just before the last
|
||||
* code is written. At that time, 31*(n-2) bits have been written, just
|
||||
* after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at
|
||||
* 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1
|
||||
* symbols are written.) The closest the writing gets to what is unread is
|
||||
* then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and
|
||||
* can range from 128 to 32768.
|
||||
*
|
||||
* Therefore, at a minimum, there are 142 bits of space between what is
|
||||
* written and what is read in the overlain buffers, so the symbols cannot
|
||||
* be overwritten by the compressed data. That space is actually 139 bits,
|
||||
* due to the three-bit fixed-code block header.
|
||||
*
|
||||
* That covers the case where either Z_FIXED is specified, forcing fixed
|
||||
* codes, or when the use of fixed codes is chosen, because that choice
|
||||
* results in a smaller compressed block than dynamic codes. That latter
|
||||
* condition then assures that the above analysis also covers all dynamic
|
||||
* blocks. A dynamic-code block will only be chosen to be emitted if it has
|
||||
* fewer bits than a fixed-code block would for the same set of symbols.
|
||||
* Therefore its average symbol length is assured to be less than 31. So
|
||||
* the compressed data for a dynamic block also cannot overwrite the
|
||||
* symbols from which it is being constructed.
|
||||
*/
|
||||
|
||||
s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
|
||||
s->pending_buf_size = (ulg)s->lit_bufsize * 4;
|
||||
|
||||
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
|
||||
s->pending_buf == Z_NULL) {
|
||||
|
@ -337,8 +373,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
|||
deflateEnd (strm);
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
|
||||
s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
|
||||
s->sym_buf = s->pending_buf + s->lit_bufsize;
|
||||
s->sym_end = (s->lit_bufsize - 1) * 3;
|
||||
/* We avoid equality with lit_bufsize*3 because of wraparound at 64K
|
||||
* on 16 bit machines and because stored blocks are restricted to
|
||||
* 64K-1 bytes.
|
||||
*/
|
||||
|
||||
s->level = level;
|
||||
s->strategy = strategy;
|
||||
|
@ -488,13 +528,13 @@ int ZEXPORT deflateResetKeep (strm)
|
|||
#ifdef GZIP
|
||||
s->wrap == 2 ? GZIP_STATE :
|
||||
#endif
|
||||
s->wrap ? INIT_STATE : BUSY_STATE;
|
||||
INIT_STATE;
|
||||
strm->adler =
|
||||
#ifdef GZIP
|
||||
s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
|
||||
#endif
|
||||
adler32(0L, Z_NULL, 0);
|
||||
s->last_flush = Z_NO_FLUSH;
|
||||
s->last_flush = -2;
|
||||
|
||||
_tr_init(s);
|
||||
|
||||
|
@ -549,7 +589,8 @@ int ZEXPORT deflatePrime (strm, bits, value)
|
|||
|
||||
if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
s = strm->state;
|
||||
if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
|
||||
if (bits < 0 || bits > 16 ||
|
||||
s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
|
||||
return Z_BUF_ERROR;
|
||||
do {
|
||||
put = Buf_size - s->bi_valid;
|
||||
|
@ -587,12 +628,12 @@ int ZEXPORT deflateParams(strm, level, strategy)
|
|||
func = configuration_table[s->level].func;
|
||||
|
||||
if ((strategy != s->strategy || func != configuration_table[level].func) &&
|
||||
s->high_water) {
|
||||
s->last_flush != -2) {
|
||||
/* Flush the last buffer: */
|
||||
int err = deflate(strm, Z_BLOCK);
|
||||
if (err == Z_STREAM_ERROR)
|
||||
return err;
|
||||
if (strm->avail_out == 0)
|
||||
if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
|
||||
return Z_BUF_ERROR;
|
||||
}
|
||||
if (s->level != level) {
|
||||
|
@ -811,6 +852,8 @@ int ZEXPORT deflate (strm, flush)
|
|||
}
|
||||
|
||||
/* Write the header */
|
||||
if (s->status == INIT_STATE && s->wrap == 0)
|
||||
s->status = BUSY_STATE;
|
||||
if (s->status == INIT_STATE) {
|
||||
/* zlib header */
|
||||
uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
|
||||
|
@ -1108,7 +1151,6 @@ int ZEXPORT deflateCopy (dest, source)
|
|||
#else
|
||||
deflate_state *ds;
|
||||
deflate_state *ss;
|
||||
ushf *overlay;
|
||||
|
||||
|
||||
if (deflateStateCheck(source) || dest == Z_NULL) {
|
||||
|
@ -1128,8 +1170,7 @@ int ZEXPORT deflateCopy (dest, source)
|
|||
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
|
||||
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
|
||||
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
|
||||
overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
|
||||
ds->pending_buf = (uchf *) overlay;
|
||||
ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
|
||||
|
||||
if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
|
||||
ds->pending_buf == Z_NULL) {
|
||||
|
@ -1143,8 +1184,7 @@ int ZEXPORT deflateCopy (dest, source)
|
|||
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
|
||||
|
||||
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
|
||||
ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
|
||||
ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
|
||||
ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
|
||||
|
||||
ds->l_desc.dyn_tree = ds->dyn_ltree;
|
||||
ds->d_desc.dyn_tree = ds->dyn_dtree;
|
||||
|
@ -1513,6 +1553,8 @@ local void fill_window(s)
|
|||
s->match_start -= wsize;
|
||||
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
|
||||
s->block_start -= (long) wsize;
|
||||
if (s->insert > s->strstart)
|
||||
s->insert = s->strstart;
|
||||
slide_hash(s);
|
||||
more += wsize;
|
||||
}
|
||||
|
@ -1742,6 +1784,7 @@ local block_state deflate_stored(s, flush)
|
|||
s->matches = 2; /* clear hash */
|
||||
zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
|
||||
s->strstart = s->w_size;
|
||||
s->insert = s->strstart;
|
||||
}
|
||||
else {
|
||||
if (s->window_size - s->strstart <= used) {
|
||||
|
@ -1750,12 +1793,14 @@ local block_state deflate_stored(s, flush)
|
|||
zmemcpy(s->window, s->window + s->w_size, s->strstart);
|
||||
if (s->matches < 2)
|
||||
s->matches++; /* add a pending slide_hash() */
|
||||
if (s->insert > s->strstart)
|
||||
s->insert = s->strstart;
|
||||
}
|
||||
zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
|
||||
s->strstart += used;
|
||||
s->insert += MIN(used, s->w_size - s->insert);
|
||||
}
|
||||
s->block_start = s->strstart;
|
||||
s->insert += MIN(used, s->w_size - s->insert);
|
||||
}
|
||||
if (s->high_water < s->strstart)
|
||||
s->high_water = s->strstart;
|
||||
|
@ -1770,7 +1815,7 @@ local block_state deflate_stored(s, flush)
|
|||
return block_done;
|
||||
|
||||
/* Fill the window with any remaining input. */
|
||||
have = s->window_size - s->strstart - 1;
|
||||
have = s->window_size - s->strstart;
|
||||
if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
|
||||
/* Slide the window down. */
|
||||
s->block_start -= s->w_size;
|
||||
|
@ -1779,12 +1824,15 @@ local block_state deflate_stored(s, flush)
|
|||
if (s->matches < 2)
|
||||
s->matches++; /* add a pending slide_hash() */
|
||||
have += s->w_size; /* more space now */
|
||||
if (s->insert > s->strstart)
|
||||
s->insert = s->strstart;
|
||||
}
|
||||
if (have > s->strm->avail_in)
|
||||
have = s->strm->avail_in;
|
||||
if (have) {
|
||||
read_buf(s->strm, s->window + s->strstart, have);
|
||||
s->strstart += have;
|
||||
s->insert += MIN(have, s->w_size - s->insert);
|
||||
}
|
||||
if (s->high_water < s->strstart)
|
||||
s->high_water = s->strstart;
|
||||
|
@ -1912,7 +1960,7 @@ local block_state deflate_fast(s, flush)
|
|||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
@ -2043,7 +2091,7 @@ local block_state deflate_slow(s, flush)
|
|||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
@ -2118,7 +2166,7 @@ local block_state deflate_rle(s, flush)
|
|||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
@ -2157,7 +2205,7 @@ local block_state deflate_huff(s, flush)
|
|||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
if (s->sym_next)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2016 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2018 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -217,7 +217,7 @@ typedef struct internal_state {
|
|||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf *l_buf; /* buffer for literals or lengths */
|
||||
uchf *sym_buf; /* buffer for distances and literals/lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
|
@ -239,13 +239,8 @@ typedef struct internal_state {
|
|||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf *d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
uInt sym_next; /* running index in sym_buf */
|
||||
uInt sym_end; /* symbol table full when sym_next reaches this */
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
|
@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
|
|||
|
||||
# define _tr_tally_lit(s, c, flush) \
|
||||
{ uch cc = (c); \
|
||||
s->d_buf[s->last_lit] = 0; \
|
||||
s->l_buf[s->last_lit++] = cc; \
|
||||
s->sym_buf[s->sym_next++] = 0; \
|
||||
s->sym_buf[s->sym_next++] = 0; \
|
||||
s->sym_buf[s->sym_next++] = cc; \
|
||||
s->dyn_ltree[cc].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
flush = (s->sym_next == s->sym_end); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ uch len = (uch)(length); \
|
||||
ush dist = (ush)(distance); \
|
||||
s->d_buf[s->last_lit] = dist; \
|
||||
s->l_buf[s->last_lit++] = len; \
|
||||
s->sym_buf[s->sym_next++] = dist; \
|
||||
s->sym_buf[s->sym_next++] = dist >> 8; \
|
||||
s->sym_buf[s->sym_next++] = len; \
|
||||
dist--; \
|
||||
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
flush = (s->sym_next == s->sym_end); \
|
||||
}
|
||||
#else
|
||||
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
|
||||
* Copyright (C) 2004-2019 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
|||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#if defined(_WIN32)
|
||||
# define WIDECHAR
|
||||
#endif
|
||||
|
||||
|
@ -190,6 +190,7 @@ typedef struct {
|
|||
/* just for writing */
|
||||
int level; /* compression level */
|
||||
int strategy; /* compression strategy */
|
||||
int reset; /* true if a reset is pending after a Z_FINISH */
|
||||
/* seek request */
|
||||
z_off64_t skip; /* amount to skip (already rewound if backwards) */
|
||||
int seek; /* true if seek request pending */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* Copyright (C) 1995-2022 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -477,6 +477,7 @@ void FAR *out_desc;
|
|||
}
|
||||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN;
|
||||
/* fallthrough */
|
||||
|
||||
case LEN:
|
||||
/* use inflate_fast() if we have enough input and output */
|
||||
|
|
|
@ -70,7 +70,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
code const FAR *dcode; /* local strm->distcode */
|
||||
unsigned lmask; /* mask for first level of length codes */
|
||||
unsigned dmask; /* mask for first level of distance codes */
|
||||
code here; /* retrieved table entry */
|
||||
code const *here; /* retrieved table entry */
|
||||
unsigned op; /* code bits, operation, extra bits, or */
|
||||
/* window position, window bytes to copy */
|
||||
unsigned len; /* match length, unused bytes */
|
||||
|
@ -107,20 +107,20 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = lcode[hold & lmask];
|
||||
here = lcode + (hold & lmask);
|
||||
dolen:
|
||||
op = (unsigned)(here.bits);
|
||||
op = (unsigned)(here->bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here.op);
|
||||
op = (unsigned)(here->op);
|
||||
if (op == 0) { /* literal */
|
||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
*out++ = (unsigned char)(here.val);
|
||||
"inflate: literal 0x%02x\n", here->val));
|
||||
*out++ = (unsigned char)(here->val);
|
||||
}
|
||||
else if (op & 16) { /* length base */
|
||||
len = (unsigned)(here.val);
|
||||
len = (unsigned)(here->val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (op) {
|
||||
if (bits < op) {
|
||||
|
@ -138,14 +138,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = dcode[hold & dmask];
|
||||
here = dcode + (hold & dmask);
|
||||
dodist:
|
||||
op = (unsigned)(here.bits);
|
||||
op = (unsigned)(here->bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here.op);
|
||||
op = (unsigned)(here->op);
|
||||
if (op & 16) { /* distance base */
|
||||
dist = (unsigned)(here.val);
|
||||
dist = (unsigned)(here->val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
|
@ -264,7 +264,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level distance code */
|
||||
here = dcode[here.val + (hold & ((1U << op) - 1))];
|
||||
here = dcode + here->val + (hold & ((1U << op) - 1));
|
||||
goto dodist;
|
||||
}
|
||||
else {
|
||||
|
@ -274,7 +274,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level length code */
|
||||
here = lcode[here.val + (hold & ((1U << op) - 1))];
|
||||
here = lcode + here->val + (hold & ((1U << op) - 1));
|
||||
goto dolen;
|
||||
}
|
||||
else if (op & 32) { /* end-of-block */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* inflate.c -- zlib decompression
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* Copyright (C) 1995-2022 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -130,6 +130,7 @@ z_streamp strm;
|
|||
state->mode = HEAD;
|
||||
state->last = 0;
|
||||
state->havedict = 0;
|
||||
state->flags = -1;
|
||||
state->dmax = 32768U;
|
||||
state->head = Z_NULL;
|
||||
state->hold = 0;
|
||||
|
@ -447,10 +448,10 @@ unsigned copy;
|
|||
|
||||
/* check function to use adler32() for zlib or crc32() for gzip */
|
||||
#ifdef GUNZIP
|
||||
# define UPDATE(check, buf, len) \
|
||||
# define UPDATE_CHECK(check, buf, len) \
|
||||
(state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
|
||||
#else
|
||||
# define UPDATE(check, buf, len) adler32(check, buf, len)
|
||||
# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
|
||||
#endif
|
||||
|
||||
/* check macros for header crc */
|
||||
|
@ -670,7 +671,6 @@ int flush;
|
|||
state->mode = FLAGS;
|
||||
break;
|
||||
}
|
||||
state->flags = 0; /* expect zlib header */
|
||||
if (state->head != Z_NULL)
|
||||
state->head->done = -1;
|
||||
if (!(state->wrap & 1) || /* check if zlib header allowed */
|
||||
|
@ -697,6 +697,7 @@ int flush;
|
|||
break;
|
||||
}
|
||||
state->dmax = 1U << len;
|
||||
state->flags = 0; /* indicate zlib header */
|
||||
Tracev((stderr, "inflate: zlib header ok\n"));
|
||||
strm->adler = state->check = adler32(0L, Z_NULL, 0);
|
||||
state->mode = hold & 0x200 ? DICTID : TYPE;
|
||||
|
@ -722,6 +723,7 @@ int flush;
|
|||
CRC2(state->check, hold);
|
||||
INITBITS();
|
||||
state->mode = TIME;
|
||||
/* fallthrough */
|
||||
case TIME:
|
||||
NEEDBITS(32);
|
||||
if (state->head != Z_NULL)
|
||||
|
@ -730,6 +732,7 @@ int flush;
|
|||
CRC4(state->check, hold);
|
||||
INITBITS();
|
||||
state->mode = OS;
|
||||
/* fallthrough */
|
||||
case OS:
|
||||
NEEDBITS(16);
|
||||
if (state->head != Z_NULL) {
|
||||
|
@ -740,6 +743,7 @@ int flush;
|
|||
CRC2(state->check, hold);
|
||||
INITBITS();
|
||||
state->mode = EXLEN;
|
||||
/* fallthrough */
|
||||
case EXLEN:
|
||||
if (state->flags & 0x0400) {
|
||||
NEEDBITS(16);
|
||||
|
@ -753,6 +757,7 @@ int flush;
|
|||
else if (state->head != Z_NULL)
|
||||
state->head->extra = Z_NULL;
|
||||
state->mode = EXTRA;
|
||||
/* fallthrough */
|
||||
case EXTRA:
|
||||
if (state->flags & 0x0400) {
|
||||
copy = state->length;
|
||||
|
@ -775,6 +780,7 @@ int flush;
|
|||
}
|
||||
state->length = 0;
|
||||
state->mode = NAME;
|
||||
/* fallthrough */
|
||||
case NAME:
|
||||
if (state->flags & 0x0800) {
|
||||
if (have == 0) goto inf_leave;
|
||||
|
@ -796,6 +802,7 @@ int flush;
|
|||
state->head->name = Z_NULL;
|
||||
state->length = 0;
|
||||
state->mode = COMMENT;
|
||||
/* fallthrough */
|
||||
case COMMENT:
|
||||
if (state->flags & 0x1000) {
|
||||
if (have == 0) goto inf_leave;
|
||||
|
@ -816,6 +823,7 @@ int flush;
|
|||
else if (state->head != Z_NULL)
|
||||
state->head->comment = Z_NULL;
|
||||
state->mode = HCRC;
|
||||
/* fallthrough */
|
||||
case HCRC:
|
||||
if (state->flags & 0x0200) {
|
||||
NEEDBITS(16);
|
||||
|
@ -839,6 +847,7 @@ int flush;
|
|||
strm->adler = state->check = ZSWAP32(hold);
|
||||
INITBITS();
|
||||
state->mode = DICT;
|
||||
/* fallthrough */
|
||||
case DICT:
|
||||
if (state->havedict == 0) {
|
||||
RESTORE();
|
||||
|
@ -846,8 +855,10 @@ int flush;
|
|||
}
|
||||
strm->adler = state->check = adler32(0L, Z_NULL, 0);
|
||||
state->mode = TYPE;
|
||||
/* fallthrough */
|
||||
case TYPE:
|
||||
if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
|
||||
/* fallthrough */
|
||||
case TYPEDO:
|
||||
if (state->last) {
|
||||
BYTEBITS();
|
||||
|
@ -898,8 +909,10 @@ int flush;
|
|||
INITBITS();
|
||||
state->mode = COPY_;
|
||||
if (flush == Z_TREES) goto inf_leave;
|
||||
/* fallthrough */
|
||||
case COPY_:
|
||||
state->mode = COPY;
|
||||
/* fallthrough */
|
||||
case COPY:
|
||||
copy = state->length;
|
||||
if (copy) {
|
||||
|
@ -935,6 +948,7 @@ int flush;
|
|||
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||
state->have = 0;
|
||||
state->mode = LENLENS;
|
||||
/* fallthrough */
|
||||
case LENLENS:
|
||||
while (state->have < state->ncode) {
|
||||
NEEDBITS(3);
|
||||
|
@ -956,6 +970,7 @@ int flush;
|
|||
Tracev((stderr, "inflate: code lengths ok\n"));
|
||||
state->have = 0;
|
||||
state->mode = CODELENS;
|
||||
/* fallthrough */
|
||||
case CODELENS:
|
||||
while (state->have < state->nlen + state->ndist) {
|
||||
for (;;) {
|
||||
|
@ -1039,8 +1054,10 @@ int flush;
|
|||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN_;
|
||||
if (flush == Z_TREES) goto inf_leave;
|
||||
/* fallthrough */
|
||||
case LEN_:
|
||||
state->mode = LEN;
|
||||
/* fallthrough */
|
||||
case LEN:
|
||||
if (have >= 6 && left >= 258) {
|
||||
RESTORE();
|
||||
|
@ -1090,6 +1107,7 @@ int flush;
|
|||
}
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
state->mode = LENEXT;
|
||||
/* fallthrough */
|
||||
case LENEXT:
|
||||
if (state->extra) {
|
||||
NEEDBITS(state->extra);
|
||||
|
@ -1100,6 +1118,7 @@ int flush;
|
|||
Tracevv((stderr, "inflate: length %u\n", state->length));
|
||||
state->was = state->length;
|
||||
state->mode = DIST;
|
||||
/* fallthrough */
|
||||
case DIST:
|
||||
for (;;) {
|
||||
here = state->distcode[BITS(state->distbits)];
|
||||
|
@ -1127,6 +1146,7 @@ int flush;
|
|||
state->offset = (unsigned)here.val;
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
state->mode = DISTEXT;
|
||||
/* fallthrough */
|
||||
case DISTEXT:
|
||||
if (state->extra) {
|
||||
NEEDBITS(state->extra);
|
||||
|
@ -1143,6 +1163,7 @@ int flush;
|
|||
#endif
|
||||
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
||||
state->mode = MATCH;
|
||||
/* fallthrough */
|
||||
case MATCH:
|
||||
if (left == 0) goto inf_leave;
|
||||
copy = out - left;
|
||||
|
@ -1202,7 +1223,7 @@ int flush;
|
|||
state->total += out;
|
||||
if ((state->wrap & 4) && out)
|
||||
strm->adler = state->check =
|
||||
UPDATE(state->check, put - out, out);
|
||||
UPDATE_CHECK(state->check, put - out, out);
|
||||
out = left;
|
||||
if ((state->wrap & 4) && (
|
||||
#ifdef GUNZIP
|
||||
|
@ -1218,10 +1239,11 @@ int flush;
|
|||
}
|
||||
#ifdef GUNZIP
|
||||
state->mode = LENGTH;
|
||||
/* fallthrough */
|
||||
case LENGTH:
|
||||
if (state->wrap && state->flags) {
|
||||
NEEDBITS(32);
|
||||
if (hold != (state->total & 0xffffffffUL)) {
|
||||
if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
|
||||
strm->msg = (char *)"incorrect length check";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
|
@ -1231,6 +1253,7 @@ int flush;
|
|||
}
|
||||
#endif
|
||||
state->mode = DONE;
|
||||
/* fallthrough */
|
||||
case DONE:
|
||||
ret = Z_STREAM_END;
|
||||
goto inf_leave;
|
||||
|
@ -1240,6 +1263,7 @@ int flush;
|
|||
case MEM:
|
||||
return Z_MEM_ERROR;
|
||||
case SYNC:
|
||||
/* fallthrough */
|
||||
default:
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
|
@ -1265,7 +1289,7 @@ int flush;
|
|||
state->total += out;
|
||||
if ((state->wrap & 4) && out)
|
||||
strm->adler = state->check =
|
||||
UPDATE(state->check, strm->next_out - out, out);
|
||||
UPDATE_CHECK(state->check, strm->next_out - out, out);
|
||||
strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
|
||||
(state->mode == TYPE ? 128 : 0) +
|
||||
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
|
||||
|
@ -1401,6 +1425,7 @@ int ZEXPORT inflateSync(strm)
|
|||
z_streamp strm;
|
||||
{
|
||||
unsigned len; /* number of bytes to look at or looked at */
|
||||
int flags; /* temporary to save header status */
|
||||
unsigned long in, out; /* temporary to save total_in and total_out */
|
||||
unsigned char buf[4]; /* to restore bit buffer to byte string */
|
||||
struct inflate_state FAR *state;
|
||||
|
@ -1433,9 +1458,15 @@ z_streamp strm;
|
|||
|
||||
/* return no joy or set up to restart inflate() on a new block */
|
||||
if (state->have != 4) return Z_DATA_ERROR;
|
||||
if (state->flags == -1)
|
||||
state->wrap = 0; /* if no header yet, treat as raw */
|
||||
else
|
||||
state->wrap &= ~4; /* no point in computing a check value now */
|
||||
flags = state->flags;
|
||||
in = strm->total_in; out = strm->total_out;
|
||||
inflateReset(strm);
|
||||
strm->total_in = in; strm->total_out = out;
|
||||
state->flags = flags;
|
||||
state->mode = TYPE;
|
||||
return Z_OK;
|
||||
}
|
||||
|
@ -1531,7 +1562,7 @@ int check;
|
|||
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
if (check)
|
||||
if (check && state->wrap)
|
||||
state->wrap |= 4;
|
||||
else
|
||||
state->wrap &= ~4;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* inflate.h -- internal inflate state definition
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* Copyright (C) 1995-2019 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -86,7 +86,8 @@ struct inflate_state {
|
|||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
|
||||
bit 2 true to validate check value */
|
||||
int havedict; /* true if dictionary provided */
|
||||
int flags; /* gzip header method and flags (0 if zlib) */
|
||||
int flags; /* gzip header method and flags, 0 if zlib, or
|
||||
-1 if raw or no header yet */
|
||||
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
||||
unsigned long check; /* protected copy of check value */
|
||||
unsigned long total; /* protected copy of output count */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2017 Mark Adler
|
||||
* Copyright (C) 1995-2022 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
|||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
|
||||
" inflate 1.2.12 Copyright 1995-2022 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
|
@ -62,7 +62,7 @@ unsigned short FAR *work;
|
|||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* trees.c -- output deflated data using Huffman coding
|
||||
* Copyright (C) 1995-2017 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2021 Jean-loup Gailly
|
||||
* detect_data_type() function provided freely by Cosmin Truta, 2006
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
@ -149,7 +149,7 @@ local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
|
|||
local void compress_block OF((deflate_state *s, const ct_data *ltree,
|
||||
const ct_data *dtree));
|
||||
local int detect_data_type OF((deflate_state *s));
|
||||
local unsigned bi_reverse OF((unsigned value, int length));
|
||||
local unsigned bi_reverse OF((unsigned code, int len));
|
||||
local void bi_windup OF((deflate_state *s));
|
||||
local void bi_flush OF((deflate_state *s));
|
||||
|
||||
|
@ -416,7 +416,7 @@ local void init_block(s)
|
|||
|
||||
s->dyn_ltree[END_BLOCK].Freq = 1;
|
||||
s->opt_len = s->static_len = 0L;
|
||||
s->last_lit = s->matches = 0;
|
||||
s->sym_next = s->matches = 0;
|
||||
}
|
||||
|
||||
#define SMALLEST 1
|
||||
|
@ -870,7 +870,8 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
|
|||
bi_windup(s); /* align on byte boundary */
|
||||
put_short(s, (ush)stored_len);
|
||||
put_short(s, (ush)~stored_len);
|
||||
zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
|
||||
if (stored_len)
|
||||
zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
|
||||
s->pending += stored_len;
|
||||
#ifdef ZLIB_DEBUG
|
||||
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
|
||||
|
@ -947,7 +948,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
|||
|
||||
Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
|
||||
opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
|
||||
s->last_lit));
|
||||
s->sym_next / 3));
|
||||
|
||||
if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
|
||||
|
||||
|
@ -1016,8 +1017,9 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
|
|||
unsigned dist; /* distance of matched string */
|
||||
unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
|
||||
{
|
||||
s->d_buf[s->last_lit] = (ush)dist;
|
||||
s->l_buf[s->last_lit++] = (uch)lc;
|
||||
s->sym_buf[s->sym_next++] = dist;
|
||||
s->sym_buf[s->sym_next++] = dist >> 8;
|
||||
s->sym_buf[s->sym_next++] = lc;
|
||||
if (dist == 0) {
|
||||
/* lc is the unmatched char */
|
||||
s->dyn_ltree[lc].Freq++;
|
||||
|
@ -1032,30 +1034,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
|
|||
s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
|
||||
s->dyn_dtree[d_code(dist)].Freq++;
|
||||
}
|
||||
|
||||
#ifdef TRUNCATE_BLOCK
|
||||
/* Try to guess if it is profitable to stop the current block here */
|
||||
if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
|
||||
/* Compute an upper bound for the compressed length */
|
||||
ulg out_length = (ulg)s->last_lit*8L;
|
||||
ulg in_length = (ulg)((long)s->strstart - s->block_start);
|
||||
int dcode;
|
||||
for (dcode = 0; dcode < D_CODES; dcode++) {
|
||||
out_length += (ulg)s->dyn_dtree[dcode].Freq *
|
||||
(5L+extra_dbits[dcode]);
|
||||
}
|
||||
out_length >>= 3;
|
||||
Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
|
||||
s->last_lit, in_length, out_length,
|
||||
100L - out_length*100L/in_length));
|
||||
if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
|
||||
}
|
||||
#endif
|
||||
return (s->last_lit == s->lit_bufsize-1);
|
||||
/* We avoid equality with lit_bufsize because of wraparound at 64K
|
||||
* on 16 bit machines and because stored blocks are restricted to
|
||||
* 64K-1 bytes.
|
||||
*/
|
||||
return (s->sym_next == s->sym_end);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
|
@ -1068,13 +1047,14 @@ local void compress_block(s, ltree, dtree)
|
|||
{
|
||||
unsigned dist; /* distance of matched string */
|
||||
int lc; /* match length or unmatched char (if dist == 0) */
|
||||
unsigned lx = 0; /* running index in l_buf */
|
||||
unsigned sx = 0; /* running index in sym_buf */
|
||||
unsigned code; /* the code to send */
|
||||
int extra; /* number of extra bits to send */
|
||||
|
||||
if (s->last_lit != 0) do {
|
||||
dist = s->d_buf[lx];
|
||||
lc = s->l_buf[lx++];
|
||||
if (s->sym_next != 0) do {
|
||||
dist = s->sym_buf[sx++] & 0xff;
|
||||
dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
|
||||
lc = s->sym_buf[sx++];
|
||||
if (dist == 0) {
|
||||
send_code(s, lc, ltree); /* send a literal byte */
|
||||
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
|
||||
|
@ -1099,11 +1079,10 @@ local void compress_block(s, ltree, dtree)
|
|||
}
|
||||
} /* literal or match pair ? */
|
||||
|
||||
/* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
|
||||
Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
|
||||
"pendingBuf overflow");
|
||||
/* Check that the overlay between pending_buf and sym_buf is ok: */
|
||||
Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
|
||||
|
||||
} while (lx < s->last_lit);
|
||||
} while (sx < s->sym_next);
|
||||
|
||||
send_code(s, END_BLOCK, ltree);
|
||||
}
|
||||
|
@ -1112,9 +1091,9 @@ local void compress_block(s, ltree, dtree)
|
|||
* Check if the data type is TEXT or BINARY, using the following algorithm:
|
||||
* - TEXT if the two conditions below are satisfied:
|
||||
* a) There are no non-portable control characters belonging to the
|
||||
* "black list" (0..6, 14..25, 28..31).
|
||||
* "block list" (0..6, 14..25, 28..31).
|
||||
* b) There is at least one printable character belonging to the
|
||||
* "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
|
||||
* "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
|
||||
* - BINARY otherwise.
|
||||
* - The following partially-portable control characters form a
|
||||
* "gray list" that is ignored in this detection algorithm:
|
||||
|
@ -1124,19 +1103,19 @@ local void compress_block(s, ltree, dtree)
|
|||
local int detect_data_type(s)
|
||||
deflate_state *s;
|
||||
{
|
||||
/* black_mask is the bit mask of black-listed bytes
|
||||
/* block_mask is the bit mask of block-listed bytes
|
||||
* set bits 0..6, 14..25, and 28..31
|
||||
* 0xf3ffc07f = binary 11110011111111111100000001111111
|
||||
*/
|
||||
unsigned long black_mask = 0xf3ffc07fUL;
|
||||
unsigned long block_mask = 0xf3ffc07fUL;
|
||||
int n;
|
||||
|
||||
/* Check for non-textual ("black-listed") bytes. */
|
||||
for (n = 0; n <= 31; n++, black_mask >>= 1)
|
||||
if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
|
||||
/* Check for non-textual ("block-listed") bytes. */
|
||||
for (n = 0; n <= 31; n++, block_mask >>= 1)
|
||||
if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
|
||||
return Z_BINARY;
|
||||
|
||||
/* Check for textual ("white-listed") bytes. */
|
||||
/* Check for textual ("allow-listed") bytes. */
|
||||
if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
|
||||
|| s->dyn_ltree[13].Freq != 0)
|
||||
return Z_TEXT;
|
||||
|
@ -1144,7 +1123,7 @@ local int detect_data_type(s)
|
|||
if (s->dyn_ltree[n].Freq != 0)
|
||||
return Z_TEXT;
|
||||
|
||||
/* There are no "black-listed" or "white-listed" bytes:
|
||||
/* There are no "block-listed" or "allow-listed" bytes:
|
||||
* this stream either is empty or has tolerated ("gray-listed") bytes only.
|
||||
*/
|
||||
return Z_BINARY;
|
||||
|
|
|
@ -69,6 +69,7 @@ EXPORTS
|
|||
gzoffset64
|
||||
adler32_combine64
|
||||
crc32_combine64
|
||||
crc32_combine_gen64
|
||||
; checksum functions
|
||||
adler32
|
||||
adler32_z
|
||||
|
@ -76,6 +77,8 @@ EXPORTS
|
|||
crc32_z
|
||||
adler32_combine
|
||||
crc32_combine
|
||||
crc32_combine_gen
|
||||
crc32_combine_op
|
||||
; various hacks, don't look :)
|
||||
deflateInit_
|
||||
deflateInit2_
|
||||
|
|
Binary file not shown.
|
@ -1,7 +1,7 @@
|
|||
/* zlib.h -- interface of the 'zlib' general purpose compression library
|
||||
version 1.2.11, January 15th, 2017
|
||||
version 1.2.12, March 11th, 2022
|
||||
|
||||
Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -37,11 +37,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ZLIB_VERSION "1.2.11"
|
||||
#define ZLIB_VERNUM 0x12b0
|
||||
#define ZLIB_VERSION "1.2.12"
|
||||
#define ZLIB_VERNUM 0x12c0
|
||||
#define ZLIB_VER_MAJOR 1
|
||||
#define ZLIB_VER_MINOR 2
|
||||
#define ZLIB_VER_REVISION 11
|
||||
#define ZLIB_VER_REVISION 12
|
||||
#define ZLIB_VER_SUBREVISION 0
|
||||
|
||||
/*
|
||||
|
@ -543,8 +543,7 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
|
|||
int strategy));
|
||||
|
||||
This is another version of deflateInit with more compression options. The
|
||||
fields next_in, zalloc, zfree and opaque must be initialized before by the
|
||||
caller.
|
||||
fields zalloc, zfree and opaque must be initialized before by the caller.
|
||||
|
||||
The method parameter is the compression method. It must be Z_DEFLATED in
|
||||
this version of the library.
|
||||
|
@ -712,11 +711,12 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
|
|||
used to switch between compression and straight copy of the input data, or
|
||||
to switch to a different kind of input data requiring a different strategy.
|
||||
If the compression approach (which is a function of the level) or the
|
||||
strategy is changed, and if any input has been consumed in a previous
|
||||
deflate() call, then the input available so far is compressed with the old
|
||||
level and strategy using deflate(strm, Z_BLOCK). There are three approaches
|
||||
for the compression levels 0, 1..3, and 4..9 respectively. The new level
|
||||
and strategy will take effect at the next call of deflate().
|
||||
strategy is changed, and if there have been any deflate() calls since the
|
||||
state was initialized or reset, then the input available so far is
|
||||
compressed with the old level and strategy using deflate(strm, Z_BLOCK).
|
||||
There are three approaches for the compression levels 0, 1..3, and 4..9
|
||||
respectively. The new level and strategy will take effect at the next call
|
||||
of deflate().
|
||||
|
||||
If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
|
||||
not have enough output space to complete, then the parameter change will not
|
||||
|
@ -865,9 +865,11 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
|
|||
detection, or add 16 to decode only the gzip format (the zlib format will
|
||||
return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
|
||||
CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
|
||||
below), inflate() will not automatically decode concatenated gzip streams.
|
||||
inflate() will return Z_STREAM_END at the end of the gzip stream. The state
|
||||
would need to be reset to continue decoding a subsequent gzip stream.
|
||||
below), inflate() will *not* automatically decode concatenated gzip members.
|
||||
inflate() will return Z_STREAM_END at the end of the gzip member. The state
|
||||
would need to be reset to continue decoding a subsequent gzip member. This
|
||||
*must* be done if there is more data after a gzip member, in order for the
|
||||
decompression to be compliant with the gzip standard (RFC 1952).
|
||||
|
||||
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
|
||||
|
@ -1302,14 +1304,14 @@ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
|
|||
/*
|
||||
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
|
||||
|
||||
Opens a gzip (.gz) file for reading or writing. The mode parameter is as
|
||||
in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
|
||||
a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
|
||||
compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
|
||||
for fixed code compression as in "wb9F". (See the description of
|
||||
deflateInit2 for more information about the strategy parameter.) 'T' will
|
||||
request transparent writing or appending with no compression and not using
|
||||
the gzip format.
|
||||
Open the gzip (.gz) file at path for reading and decompressing, or
|
||||
compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
|
||||
but can also include a compression level ("wb9") or a strategy: 'f' for
|
||||
filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
|
||||
'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
|
||||
as in "wb9F". (See the description of deflateInit2 for more information
|
||||
about the strategy parameter.) 'T' will request transparent writing or
|
||||
appending with no compression and not using the gzip format.
|
||||
|
||||
"a" can be used instead of "w" to request that the gzip stream that will
|
||||
be written be appended to the file. "+" will result in an error, since
|
||||
|
@ -1339,9 +1341,9 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
|
|||
|
||||
ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
|
||||
/*
|
||||
gzdopen associates a gzFile with the file descriptor fd. File descriptors
|
||||
are obtained from calls like open, dup, creat, pipe or fileno (if the file
|
||||
has been previously opened with fopen). The mode parameter is as in gzopen.
|
||||
Associate a gzFile with the file descriptor fd. File descriptors are
|
||||
obtained from calls like open, dup, creat, pipe or fileno (if the file has
|
||||
been previously opened with fopen). The mode parameter is as in gzopen.
|
||||
|
||||
The next call of gzclose on the returned gzFile will also close the file
|
||||
descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
|
||||
|
@ -1362,13 +1364,13 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
|
|||
|
||||
ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
|
||||
/*
|
||||
Set the internal buffer size used by this library's functions. The
|
||||
default buffer size is 8192 bytes. This function must be called after
|
||||
gzopen() or gzdopen(), and before any other calls that read or write the
|
||||
file. The buffer memory allocation is always deferred to the first read or
|
||||
write. Three times that size in buffer space is allocated. A larger buffer
|
||||
size of, for example, 64K or 128K bytes will noticeably increase the speed
|
||||
of decompression (reading).
|
||||
Set the internal buffer size used by this library's functions for file to
|
||||
size. The default buffer size is 8192 bytes. This function must be called
|
||||
after gzopen() or gzdopen(), and before any other calls that read or write
|
||||
the file. The buffer memory allocation is always deferred to the first read
|
||||
or write. Three times that size in buffer space is allocated. A larger
|
||||
buffer size of, for example, 64K or 128K bytes will noticeably increase the
|
||||
speed of decompression (reading).
|
||||
|
||||
The new buffer size also affects the maximum length for gzprintf().
|
||||
|
||||
|
@ -1378,9 +1380,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
|
|||
|
||||
ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
|
||||
/*
|
||||
Dynamically update the compression level or strategy. See the description
|
||||
of deflateInit2 for the meaning of these parameters. Previously provided
|
||||
data is flushed before the parameter change.
|
||||
Dynamically update the compression level and strategy for file. See the
|
||||
description of deflateInit2 for the meaning of these parameters. Previously
|
||||
provided data is flushed before applying the parameter changes.
|
||||
|
||||
gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
|
||||
opened for writing, Z_ERRNO if there is an error writing the flushed data,
|
||||
|
@ -1389,7 +1391,7 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
|
|||
|
||||
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
|
||||
/*
|
||||
Reads the given number of uncompressed bytes from the compressed file. If
|
||||
Read and decompress up to len uncompressed bytes from file into buf. If
|
||||
the input file is not in gzip format, gzread copies the given number of
|
||||
bytes into the buffer directly from the file.
|
||||
|
||||
|
@ -1420,11 +1422,11 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
|
|||
ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
|
||||
gzFile file));
|
||||
/*
|
||||
Read up to nitems items of size size from file to buf, otherwise operating
|
||||
as gzread() does. This duplicates the interface of stdio's fread(), with
|
||||
size_t request and return types. If the library defines size_t, then
|
||||
z_size_t is identical to size_t. If not, then z_size_t is an unsigned
|
||||
integer type that can contain a pointer.
|
||||
Read and decompress up to nitems items of size size from file into buf,
|
||||
otherwise operating as gzread() does. This duplicates the interface of
|
||||
stdio's fread(), with size_t request and return types. If the library
|
||||
defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
|
||||
is an unsigned integer type that can contain a pointer.
|
||||
|
||||
gzfread() returns the number of full items read of size size, or zero if
|
||||
the end of the file was reached and a full item could not be read, or if
|
||||
|
@ -1443,18 +1445,16 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
|
|||
file, reseting and retrying on end-of-file, when size is not 1.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
|
||||
voidpc buf, unsigned len));
|
||||
ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
|
||||
/*
|
||||
Writes the given number of uncompressed bytes into the compressed file.
|
||||
gzwrite returns the number of uncompressed bytes written or 0 in case of
|
||||
error.
|
||||
Compress and write the len uncompressed bytes at buf to file. gzwrite
|
||||
returns the number of uncompressed bytes written or 0 in case of error.
|
||||
*/
|
||||
|
||||
ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
|
||||
z_size_t nitems, gzFile file));
|
||||
/*
|
||||
gzfwrite() writes nitems items of size size from buf to file, duplicating
|
||||
Compress and write nitems items of size size from buf to file, duplicating
|
||||
the interface of stdio's fwrite(), with size_t request and return types. If
|
||||
the library defines size_t, then z_size_t is identical to size_t. If not,
|
||||
then z_size_t is an unsigned integer type that can contain a pointer.
|
||||
|
@ -1467,22 +1467,22 @@ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
|
|||
|
||||
ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
|
||||
/*
|
||||
Converts, formats, and writes the arguments to the compressed file under
|
||||
control of the format string, as in fprintf. gzprintf returns the number of
|
||||
Convert, format, compress, and write the arguments (...) to file under
|
||||
control of the string format, as in fprintf. gzprintf returns the number of
|
||||
uncompressed bytes actually written, or a negative zlib error code in case
|
||||
of error. The number of uncompressed bytes written is limited to 8191, or
|
||||
one less than the buffer size given to gzbuffer(). The caller should assure
|
||||
that this limit is not exceeded. If it is exceeded, then gzprintf() will
|
||||
return an error (0) with nothing written. In this case, there may also be a
|
||||
buffer overflow with unpredictable consequences, which is possible only if
|
||||
zlib was compiled with the insecure functions sprintf() or vsprintf()
|
||||
zlib was compiled with the insecure functions sprintf() or vsprintf(),
|
||||
because the secure snprintf() or vsnprintf() functions were not available.
|
||||
This can be determined using zlibCompileFlags().
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
|
||||
/*
|
||||
Writes the given null-terminated string to the compressed file, excluding
|
||||
Compress and write the given null-terminated string s to file, excluding
|
||||
the terminating null character.
|
||||
|
||||
gzputs returns the number of characters written, or -1 in case of error.
|
||||
|
@ -1490,11 +1490,12 @@ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
|
|||
|
||||
ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
|
||||
/*
|
||||
Reads bytes from the compressed file until len-1 characters are read, or a
|
||||
newline character is read and transferred to buf, or an end-of-file
|
||||
condition is encountered. If any characters are read or if len == 1, the
|
||||
string is terminated with a null character. If no characters are read due
|
||||
to an end-of-file or len < 1, then the buffer is left untouched.
|
||||
Read and decompress bytes from file into buf, until len-1 characters are
|
||||
read, or until a newline character is read and transferred to buf, or an
|
||||
end-of-file condition is encountered. If any characters are read or if len
|
||||
is one, the string is terminated with a null character. If no characters
|
||||
are read due to an end-of-file or len is less than one, then the buffer is
|
||||
left untouched.
|
||||
|
||||
gzgets returns buf which is a null-terminated string, or it returns NULL
|
||||
for end-of-file or in case of error. If there was an error, the contents at
|
||||
|
@ -1503,13 +1504,13 @@ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
|
|||
|
||||
ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
|
||||
/*
|
||||
Writes c, converted to an unsigned char, into the compressed file. gzputc
|
||||
Compress and write c, converted to an unsigned char, into file. gzputc
|
||||
returns the value that was written, or -1 in case of error.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
|
||||
/*
|
||||
Reads one byte from the compressed file. gzgetc returns this byte or -1
|
||||
Read and decompress one byte from file. gzgetc returns this byte or -1
|
||||
in case of end of file or error. This is implemented as a macro for speed.
|
||||
As such, it does not do all of the checking the other functions do. I.e.
|
||||
it does not check to see if file is NULL, nor whether the structure file
|
||||
|
@ -1518,8 +1519,8 @@ ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
|
|||
|
||||
ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
|
||||
/*
|
||||
Push one character back onto the stream to be read as the first character
|
||||
on the next read. At least one character of push-back is allowed.
|
||||
Push c back onto the stream for file to be read as the first character on
|
||||
the next read. At least one character of push-back is always allowed.
|
||||
gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
|
||||
fail if c is -1, and may fail if a character has been pushed but not read
|
||||
yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
|
||||
|
@ -1530,9 +1531,9 @@ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
|
|||
|
||||
ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
|
||||
/*
|
||||
Flushes all pending output into the compressed file. The parameter flush
|
||||
is as in the deflate() function. The return value is the zlib error number
|
||||
(see function gzerror below). gzflush is only permitted when writing.
|
||||
Flush all pending output to file. The parameter flush is as in the
|
||||
deflate() function. The return value is the zlib error number (see function
|
||||
gzerror below). gzflush is only permitted when writing.
|
||||
|
||||
If the flush parameter is Z_FINISH, the remaining data is written and the
|
||||
gzip stream is completed in the output. If gzwrite() is called again, a new
|
||||
|
@ -1547,8 +1548,8 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
|
|||
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
|
||||
z_off_t offset, int whence));
|
||||
|
||||
Sets the starting position for the next gzread or gzwrite on the given
|
||||
compressed file. The offset represents a number of bytes in the
|
||||
Set the starting position to offset relative to whence for the next gzread
|
||||
or gzwrite on file. The offset represents a number of bytes in the
|
||||
uncompressed data stream. The whence parameter is defined as in lseek(2);
|
||||
the value SEEK_END is not supported.
|
||||
|
||||
|
@ -1565,18 +1566,18 @@ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
|
|||
|
||||
ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
|
||||
/*
|
||||
Rewinds the given file. This function is supported only for reading.
|
||||
Rewind file. This function is supported only for reading.
|
||||
|
||||
gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
|
||||
gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
|
||||
*/
|
||||
|
||||
/*
|
||||
ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
|
||||
|
||||
Returns the starting position for the next gzread or gzwrite on the given
|
||||
compressed file. This position represents a number of bytes in the
|
||||
uncompressed data stream, and is zero when starting, even if appending or
|
||||
reading a gzip stream from the middle of a file using gzdopen().
|
||||
Return the starting position for the next gzread or gzwrite on file.
|
||||
This position represents a number of bytes in the uncompressed data stream,
|
||||
and is zero when starting, even if appending or reading a gzip stream from
|
||||
the middle of a file using gzdopen().
|
||||
|
||||
gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
|
||||
*/
|
||||
|
@ -1584,22 +1585,22 @@ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
|
|||
/*
|
||||
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
|
||||
|
||||
Returns the current offset in the file being read or written. This offset
|
||||
includes the count of bytes that precede the gzip stream, for example when
|
||||
appending or when using gzdopen() for reading. When reading, the offset
|
||||
does not include as yet unused buffered input. This information can be used
|
||||
for a progress indicator. On error, gzoffset() returns -1.
|
||||
Return the current compressed (actual) read or write offset of file. This
|
||||
offset includes the count of bytes that precede the gzip stream, for example
|
||||
when appending or when using gzdopen() for reading. When reading, the
|
||||
offset does not include as yet unused buffered input. This information can
|
||||
be used for a progress indicator. On error, gzoffset() returns -1.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzeof OF((gzFile file));
|
||||
/*
|
||||
Returns true (1) if the end-of-file indicator has been set while reading,
|
||||
false (0) otherwise. Note that the end-of-file indicator is set only if the
|
||||
read tried to go past the end of the input, but came up short. Therefore,
|
||||
just like feof(), gzeof() may return false even if there is no more data to
|
||||
read, in the event that the last read request was for the exact number of
|
||||
bytes remaining in the input file. This will happen if the input file size
|
||||
is an exact multiple of the buffer size.
|
||||
Return true (1) if the end-of-file indicator for file has been set while
|
||||
reading, false (0) otherwise. Note that the end-of-file indicator is set
|
||||
only if the read tried to go past the end of the input, but came up short.
|
||||
Therefore, just like feof(), gzeof() may return false even if there is no
|
||||
more data to read, in the event that the last read request was for the exact
|
||||
number of bytes remaining in the input file. This will happen if the input
|
||||
file size is an exact multiple of the buffer size.
|
||||
|
||||
If gzeof() returns true, then the read functions will return no more data,
|
||||
unless the end-of-file indicator is reset by gzclearerr() and the input file
|
||||
|
@ -1608,7 +1609,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
|
|||
|
||||
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
|
||||
/*
|
||||
Returns true (1) if file is being copied directly while reading, or false
|
||||
Return true (1) if file is being copied directly while reading, or false
|
||||
(0) if file is a gzip stream being decompressed.
|
||||
|
||||
If the input file is empty, gzdirect() will return true, since the input
|
||||
|
@ -1629,8 +1630,8 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
|
|||
|
||||
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
|
||||
/*
|
||||
Flushes all pending output if necessary, closes the compressed file and
|
||||
deallocates the (de)compression state. Note that once file is closed, you
|
||||
Flush all pending output for file, if necessary, close file and
|
||||
deallocate the (de)compression state. Note that once file is closed, you
|
||||
cannot call gzerror with file, since its structures have been deallocated.
|
||||
gzclose must not be called more than once on the same file, just as free
|
||||
must not be called more than once on the same allocation.
|
||||
|
@ -1654,10 +1655,10 @@ ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
|
|||
|
||||
ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
|
||||
/*
|
||||
Returns the error message for the last error which occurred on the given
|
||||
compressed file. errnum is set to zlib error number. If an error occurred
|
||||
in the file system and not in the compression library, errnum is set to
|
||||
Z_ERRNO and the application may consult errno to get the exact error code.
|
||||
Return the error message for the last error which occurred on file.
|
||||
errnum is set to zlib error number. If an error occurred in the file system
|
||||
and not in the compression library, errnum is set to Z_ERRNO and the
|
||||
application may consult errno to get the exact error code.
|
||||
|
||||
The application must not modify the returned string. Future calls to
|
||||
this function may invalidate the previously returned string. If file is
|
||||
|
@ -1670,7 +1671,7 @@ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
|
|||
|
||||
ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
|
||||
/*
|
||||
Clears the error and end-of-file flags for file. This is analogous to the
|
||||
Clear the error and end-of-file flags for file. This is analogous to the
|
||||
clearerr() function in stdio. This is useful for continuing to read a gzip
|
||||
file that is being written concurrently.
|
||||
*/
|
||||
|
@ -1688,8 +1689,9 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
|
|||
ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
|
||||
/*
|
||||
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
|
||||
return the updated checksum. If buf is Z_NULL, this function returns the
|
||||
required initial value for the checksum.
|
||||
return the updated checksum. An Adler-32 value is in the range of a 32-bit
|
||||
unsigned integer. If buf is Z_NULL, this function returns the required
|
||||
initial value for the checksum.
|
||||
|
||||
An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
|
||||
much faster.
|
||||
|
@ -1722,12 +1724,13 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
|
|||
negative, the result has no meaning or utility.
|
||||
*/
|
||||
|
||||
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
|
||||
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
|
||||
/*
|
||||
Update a running CRC-32 with the bytes buf[0..len-1] and return the
|
||||
updated CRC-32. If buf is Z_NULL, this function returns the required
|
||||
initial value for the crc. Pre- and post-conditioning (one's complement) is
|
||||
performed within this function so it shouldn't be done by the application.
|
||||
updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
|
||||
If buf is Z_NULL, this function returns the required initial value for the
|
||||
crc. Pre- and post-conditioning (one's complement) is performed within this
|
||||
function so it shouldn't be done by the application.
|
||||
|
||||
Usage example:
|
||||
|
||||
|
@ -1739,7 +1742,7 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
|
|||
if (crc != original_crc) error();
|
||||
*/
|
||||
|
||||
ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,
|
||||
ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf,
|
||||
z_size_t len));
|
||||
/*
|
||||
Same as crc32(), but with a size_t length.
|
||||
|
@ -1755,6 +1758,20 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
|
|||
len2.
|
||||
*/
|
||||
|
||||
/*
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
|
||||
|
||||
Return the operator corresponding to length len2, to be used with
|
||||
crc32_combine_op().
|
||||
*/
|
||||
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
|
||||
/*
|
||||
Give the same result as crc32_combine(), using op in place of len2. op is
|
||||
is generated from len2 by crc32_combine_gen(). This will be faster than
|
||||
crc32_combine() if the generated op is used more than once.
|
||||
*/
|
||||
|
||||
|
||||
/* various hacks, don't look :) */
|
||||
|
||||
|
@ -1842,6 +1859,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
|||
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t));
|
||||
#endif
|
||||
|
||||
#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
|
||||
|
@ -1852,6 +1870,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
|||
# define z_gzoffset z_gzoffset64
|
||||
# define z_adler32_combine z_adler32_combine64
|
||||
# define z_crc32_combine z_crc32_combine64
|
||||
# define z_crc32_combine_gen z_crc32_combine_gen64
|
||||
# else
|
||||
# define gzopen gzopen64
|
||||
# define gzseek gzseek64
|
||||
|
@ -1859,6 +1878,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
|||
# define gzoffset gzoffset64
|
||||
# define adler32_combine adler32_combine64
|
||||
# define crc32_combine crc32_combine64
|
||||
# define crc32_combine_gen crc32_combine_gen64
|
||||
# endif
|
||||
# ifndef Z_LARGE64
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
|
@ -1867,6 +1887,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
|||
ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
|
||||
# endif
|
||||
#else
|
||||
ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
|
||||
|
@ -1875,12 +1896,14 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
|||
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
|
||||
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
|
||||
#endif
|
||||
|
||||
#else /* Z_SOLO */
|
||||
|
||||
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
|
||||
|
||||
#endif /* !Z_SOLO */
|
||||
|
||||
|
@ -1893,7 +1916,7 @@ ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int));
|
|||
ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp));
|
||||
ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
|
||||
ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
|
||||
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)
|
||||
#if defined(_WIN32) && !defined(Z_SOLO)
|
||||
ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
|
||||
const char *mode));
|
||||
#endif
|
||||
|
|
|
@ -136,8 +136,8 @@ const char * ZEXPORT zError(err)
|
|||
return ERR_MSG(err);
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
/* The Microsoft C Run-Time Library for Windows CE doesn't have
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
/* The older Microsoft C Run-Time Library for Windows CE doesn't have
|
||||
* errno. We define it as a global variable to simplify porting.
|
||||
* Its value is always 0 and should not be used.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* zutil.h -- internal interface and configuration of the compression library
|
||||
* Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
|
||||
* Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -29,10 +29,6 @@
|
|||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef Z_SOLO
|
||||
typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
|
@ -46,6 +42,17 @@ typedef unsigned short ush;
|
|||
typedef ush FAR ushf;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
|
||||
# include <limits.h>
|
||||
# if (ULONG_MAX == 0xffffffffffffffff)
|
||||
# define Z_U8 unsigned long
|
||||
# elif (ULLONG_MAX == 0xffffffffffffffff)
|
||||
# define Z_U8 unsigned long long
|
||||
# elif (UINT_MAX == 0xffffffffffffffff)
|
||||
# define Z_U8 unsigned
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
/* (size given to avoid silly warnings with Visual C++) */
|
||||
|
||||
|
@ -170,10 +177,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
|
||||
# if defined(_WIN32_WCE)
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# ifndef _PTRDIFF_T_DEFINED
|
||||
typedef int ptrdiff_t;
|
||||
# define _PTRDIFF_T_DEFINED
|
||||
# endif
|
||||
# else
|
||||
# define fdopen(fd,type) _fdopen(fd,type)
|
||||
# endif
|
||||
|
|
Loading…
Reference in a new issue