mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 13:15:04 -06:00
Update to 7-Zip Version 18.05
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#define MY_VER_MAJOR 17
|
||||
#define MY_VER_MINOR 01
|
||||
#define MY_VER_MAJOR 18
|
||||
#define MY_VER_MINOR 05
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION_NUMBERS "17.01 ZS v1.3.2 R1"
|
||||
#define MY_VERSION_NUMBERS "18.05 ZS v1.3.6 R1"
|
||||
#define MY_VERSION MY_VERSION_NUMBERS
|
||||
|
||||
#ifdef MY_CPU_NAME
|
||||
@@ -10,12 +10,12 @@
|
||||
#define MY_VERSION_CPU MY_VERSION
|
||||
#endif
|
||||
|
||||
#define MY_DATE "2017-10-31"
|
||||
#define MY_DATE "2018-10-21"
|
||||
#undef MY_COPYRIGHT
|
||||
#undef MY_VERSION_COPYRIGHT_DATE
|
||||
#define MY_AUTHOR_NAME "Igor Pavlov, Tino Reichardt"
|
||||
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2017 Igor Pavlov"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov"
|
||||
|
||||
#ifdef USE_COPYRIGHT_CR
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_CR
|
||||
|
||||
354
C/Alloc.c
354
C/Alloc.c
@@ -1,8 +1,10 @@
|
||||
/* Alloc.c -- Memory allocation functions
|
||||
2017-06-15 : Igor Pavlov : Public domain */
|
||||
2018-04-27 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
@@ -14,12 +16,119 @@
|
||||
|
||||
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
int g_allocCount = 0;
|
||||
int g_allocCountMid = 0;
|
||||
int g_allocCountBig = 0;
|
||||
|
||||
|
||||
#define CONVERT_INT_TO_STR(charType, tempSize) \
|
||||
unsigned char temp[tempSize]; unsigned i = 0; \
|
||||
while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \
|
||||
*s++ = (charType)('0' + (unsigned)val); \
|
||||
while (i != 0) { i--; *s++ = temp[i]; } \
|
||||
*s = 0;
|
||||
|
||||
static void ConvertUInt64ToString(UInt64 val, char *s)
|
||||
{
|
||||
CONVERT_INT_TO_STR(char, 24);
|
||||
}
|
||||
|
||||
#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
|
||||
|
||||
static void ConvertUInt64ToHex(UInt64 val, char *s)
|
||||
{
|
||||
UInt64 v = val;
|
||||
unsigned i;
|
||||
for (i = 1;; i++)
|
||||
{
|
||||
v >>= 4;
|
||||
if (v == 0)
|
||||
break;
|
||||
}
|
||||
s[i] = 0;
|
||||
do
|
||||
{
|
||||
unsigned t = (unsigned)(val & 0xF);
|
||||
val >>= 4;
|
||||
s[--i] = GET_HEX_CHAR(t);
|
||||
}
|
||||
while (i);
|
||||
}
|
||||
|
||||
#define DEBUG_OUT_STREAM stderr
|
||||
|
||||
static void Print(const char *s)
|
||||
{
|
||||
fputs(s, DEBUG_OUT_STREAM);
|
||||
}
|
||||
|
||||
static void PrintAligned(const char *s, size_t align)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
for(;;)
|
||||
{
|
||||
fputc(' ', DEBUG_OUT_STREAM);
|
||||
if (len >= align)
|
||||
break;
|
||||
++len;
|
||||
}
|
||||
Print(s);
|
||||
}
|
||||
|
||||
static void PrintLn()
|
||||
{
|
||||
Print("\n");
|
||||
}
|
||||
|
||||
static void PrintHex(UInt64 v, size_t align)
|
||||
{
|
||||
char s[32];
|
||||
ConvertUInt64ToHex(v, s);
|
||||
PrintAligned(s, align);
|
||||
}
|
||||
|
||||
static void PrintDec(UInt64 v, size_t align)
|
||||
{
|
||||
char s[32];
|
||||
ConvertUInt64ToString(v, s);
|
||||
PrintAligned(s, align);
|
||||
}
|
||||
|
||||
static void PrintAddr(void *p)
|
||||
{
|
||||
PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12);
|
||||
}
|
||||
|
||||
|
||||
#define PRINT_ALLOC(name, cnt, size, ptr) \
|
||||
Print(name " "); \
|
||||
PrintDec(cnt++, 10); \
|
||||
PrintHex(size, 10); \
|
||||
PrintAddr(ptr); \
|
||||
PrintLn();
|
||||
|
||||
#define PRINT_FREE(name, cnt, ptr) if (ptr) { \
|
||||
Print(name " "); \
|
||||
PrintDec(--cnt, 10); \
|
||||
PrintAddr(ptr); \
|
||||
PrintLn(); }
|
||||
|
||||
#else
|
||||
|
||||
#define PRINT_ALLOC(name, cnt, size, ptr)
|
||||
#define PRINT_FREE(name, cnt, ptr)
|
||||
#define Print(s)
|
||||
#define PrintLn()
|
||||
#define PrintHex(v, align)
|
||||
#define PrintDec(v, align)
|
||||
#define PrintAddr(p)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *MyAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
@@ -27,7 +136,7 @@ void *MyAlloc(size_t size)
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
{
|
||||
void *p = malloc(size);
|
||||
fprintf(stderr, "\nAlloc %10u bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p);
|
||||
PRINT_ALLOC("Alloc ", g_allocCount, size, p);
|
||||
return p;
|
||||
}
|
||||
#else
|
||||
@@ -37,10 +146,8 @@ void *MyAlloc(size_t size)
|
||||
|
||||
void MyFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address)
|
||||
fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address);
|
||||
#endif
|
||||
PRINT_FREE("Free ", g_allocCount, address);
|
||||
|
||||
free(address);
|
||||
}
|
||||
|
||||
@@ -50,18 +157,16 @@ void *MidAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
|
||||
#endif
|
||||
|
||||
PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL);
|
||||
|
||||
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void MidFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address)
|
||||
fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
|
||||
#endif
|
||||
PRINT_FREE("Free-Mid", g_allocCountMid, address);
|
||||
|
||||
if (!address)
|
||||
return;
|
||||
VirtualFree(address, 0, MEM_RELEASE);
|
||||
@@ -96,9 +201,8 @@ void *BigAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc_Big %10u bytes; count = %10d", size, g_allocCountBig++);
|
||||
#endif
|
||||
|
||||
PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL);
|
||||
|
||||
#ifdef _7ZIP_LARGE_PAGES
|
||||
{
|
||||
@@ -123,10 +227,7 @@ void *BigAlloc(size_t size)
|
||||
|
||||
void BigFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address)
|
||||
fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
|
||||
#endif
|
||||
PRINT_FREE("Free-Big", g_allocCountBig, address);
|
||||
|
||||
if (!address)
|
||||
return;
|
||||
@@ -138,8 +239,217 @@ void BigFree(void *address)
|
||||
|
||||
static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
|
||||
static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); }
|
||||
ISzAlloc const g_Alloc = { SzAlloc, SzFree };
|
||||
const ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); }
|
||||
static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); }
|
||||
const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
|
||||
|
||||
static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }
|
||||
static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); }
|
||||
ISzAlloc const g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
|
||||
|
||||
/*
|
||||
uintptr_t : <stdint.h> C99 (optional)
|
||||
: unsupported in VS6
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef UINT_PTR UIntPtr;
|
||||
#else
|
||||
/*
|
||||
typedef uintptr_t UIntPtr;
|
||||
*/
|
||||
typedef ptrdiff_t UIntPtr;
|
||||
#endif
|
||||
|
||||
|
||||
#define ADJUST_ALLOC_SIZE 0
|
||||
/*
|
||||
#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1)
|
||||
*/
|
||||
/*
|
||||
Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if
|
||||
MyAlloc() can return address that is NOT multiple of sizeof(void *).
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1))))
|
||||
*/
|
||||
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1))))
|
||||
|
||||
#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align)
|
||||
|
||||
|
||||
#if (_POSIX_C_SOURCE >= 200112L) && !defined(_WIN32)
|
||||
#define USE_posix_memalign
|
||||
#endif
|
||||
|
||||
/*
|
||||
This posix_memalign() is for test purposes only.
|
||||
We also need special Free() function instead of free(),
|
||||
if this posix_memalign() is used.
|
||||
*/
|
||||
|
||||
/*
|
||||
static int posix_memalign(void **ptr, size_t align, size_t size)
|
||||
{
|
||||
size_t newSize = size + align;
|
||||
void *p;
|
||||
void *pAligned;
|
||||
*ptr = NULL;
|
||||
if (newSize < size)
|
||||
return 12; // ENOMEM
|
||||
p = MyAlloc(newSize);
|
||||
if (!p)
|
||||
return 12; // ENOMEM
|
||||
pAligned = MY_ALIGN_PTR_UP_PLUS(p, align);
|
||||
((void **)pAligned)[-1] = p;
|
||||
*ptr = pAligned;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
ALLOC_ALIGN_SIZE >= sizeof(void *)
|
||||
ALLOC_ALIGN_SIZE >= cache_line_size
|
||||
*/
|
||||
|
||||
#define ALLOC_ALIGN_SIZE ((size_t)1 << 7)
|
||||
|
||||
static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
|
||||
{
|
||||
#ifndef USE_posix_memalign
|
||||
|
||||
void *p;
|
||||
void *pAligned;
|
||||
size_t newSize;
|
||||
UNUSED_VAR(pp);
|
||||
|
||||
/* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
|
||||
block to prevent cache line sharing with another allocated blocks */
|
||||
|
||||
newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE;
|
||||
if (newSize < size)
|
||||
return NULL;
|
||||
|
||||
p = MyAlloc(newSize);
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE);
|
||||
|
||||
Print(" size="); PrintHex(size, 8);
|
||||
Print(" a_size="); PrintHex(newSize, 8);
|
||||
Print(" ptr="); PrintAddr(p);
|
||||
Print(" a_ptr="); PrintAddr(pAligned);
|
||||
PrintLn();
|
||||
|
||||
((void **)pAligned)[-1] = p;
|
||||
|
||||
return pAligned;
|
||||
|
||||
#else
|
||||
|
||||
void *p;
|
||||
UNUSED_VAR(pp);
|
||||
if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size))
|
||||
return NULL;
|
||||
|
||||
Print(" posix_memalign="); PrintAddr(p);
|
||||
PrintLn();
|
||||
|
||||
return p;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void SzAlignedFree(ISzAllocPtr pp, void *address)
|
||||
{
|
||||
UNUSED_VAR(pp);
|
||||
#ifndef USE_posix_memalign
|
||||
if (address)
|
||||
MyFree(((void **)address)[-1]);
|
||||
#else
|
||||
free(address);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };
|
||||
|
||||
|
||||
|
||||
#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *))
|
||||
|
||||
/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */
|
||||
#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1]
|
||||
/*
|
||||
#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1]
|
||||
*/
|
||||
|
||||
static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
|
||||
{
|
||||
CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);
|
||||
void *adr;
|
||||
void *pAligned;
|
||||
size_t newSize;
|
||||
size_t extra;
|
||||
size_t alignSize = (size_t)1 << p->numAlignBits;
|
||||
|
||||
if (alignSize < sizeof(void *))
|
||||
alignSize = sizeof(void *);
|
||||
|
||||
if (p->offset >= alignSize)
|
||||
return NULL;
|
||||
|
||||
/* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
|
||||
block to prevent cache line sharing with another allocated blocks */
|
||||
extra = p->offset & (sizeof(void *) - 1);
|
||||
newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE;
|
||||
if (newSize < size)
|
||||
return NULL;
|
||||
|
||||
adr = ISzAlloc_Alloc(p->baseAlloc, newSize);
|
||||
|
||||
if (!adr)
|
||||
return NULL;
|
||||
|
||||
pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr +
|
||||
alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset;
|
||||
|
||||
PrintLn();
|
||||
Print("- Aligned: ");
|
||||
Print(" size="); PrintHex(size, 8);
|
||||
Print(" a_size="); PrintHex(newSize, 8);
|
||||
Print(" ptr="); PrintAddr(adr);
|
||||
Print(" a_ptr="); PrintAddr(pAligned);
|
||||
PrintLn();
|
||||
|
||||
REAL_BLOCK_PTR_VAR(pAligned) = adr;
|
||||
|
||||
return pAligned;
|
||||
}
|
||||
|
||||
|
||||
static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)
|
||||
{
|
||||
if (address)
|
||||
{
|
||||
CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt);
|
||||
PrintLn();
|
||||
Print("- Aligned Free: ");
|
||||
PrintLn();
|
||||
ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p)
|
||||
{
|
||||
p->vt.Alloc = AlignOffsetAlloc_Alloc;
|
||||
p->vt.Free = AlignOffsetAlloc_Free;
|
||||
}
|
||||
|
||||
16
C/Alloc.h
16
C/Alloc.h
@@ -1,5 +1,5 @@
|
||||
/* Alloc.h -- Memory allocation functions
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2018-02-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __COMMON_ALLOC_H
|
||||
#define __COMMON_ALLOC_H
|
||||
@@ -31,6 +31,20 @@ void BigFree(void *address);
|
||||
|
||||
extern const ISzAlloc g_Alloc;
|
||||
extern const ISzAlloc g_BigAlloc;
|
||||
extern const ISzAlloc g_MidAlloc;
|
||||
extern const ISzAlloc g_AlignedAlloc;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISzAlloc vt;
|
||||
ISzAllocPtr baseAlloc;
|
||||
unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */
|
||||
size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */
|
||||
} CAlignOffsetAlloc;
|
||||
|
||||
void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p);
|
||||
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
|
||||
10
C/Bcj2.c
10
C/Bcj2.c
@@ -1,5 +1,5 @@
|
||||
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2018-04-28 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -232,10 +232,10 @@ SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
||||
|
||||
if (rem < 4)
|
||||
{
|
||||
SizeT i;
|
||||
SetUi32(p->temp, val);
|
||||
for (i = 0; i < rem; i++)
|
||||
dest[i] = p->temp[i];
|
||||
p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8;
|
||||
p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8;
|
||||
p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8;
|
||||
p->temp[3] = (Byte)val;
|
||||
p->dest = dest + rem;
|
||||
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
|
||||
break;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2017-04-28 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#define PRF(x)
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Bcj2.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* CpuArch.h -- CPU specific code
|
||||
2017-06-30 : Igor Pavlov : Public domain */
|
||||
2017-09-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __CPU_ARCH_H
|
||||
#define __CPU_ARCH_H
|
||||
@@ -174,7 +174,7 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
||||
#ifndef MY_CPU_NAME
|
||||
#ifdef MY_CPU_LE
|
||||
#define MY_CPU_NAME "LE"
|
||||
#elif MY_CPU_BE
|
||||
#elif defined(MY_CPU_BE)
|
||||
#define MY_CPU_NAME "BE"
|
||||
#else
|
||||
/*
|
||||
|
||||
206
C/Lzma2Dec.c
206
C/Lzma2Dec.c
@@ -1,5 +1,5 @@
|
||||
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2018-02-19 : Igor Pavlov : Public domain */
|
||||
|
||||
/* #define SHOW_DEBUG_INFO */
|
||||
|
||||
@@ -14,28 +14,22 @@
|
||||
#include "Lzma2Dec.h"
|
||||
|
||||
/*
|
||||
00000000 - EOS
|
||||
00000001 U U - Uncompressed Reset Dic
|
||||
00000010 U U - Uncompressed No Reset
|
||||
100uuuuu U U P P - LZMA no reset
|
||||
101uuuuu U U P P - LZMA reset state
|
||||
110uuuuu U U P P S - LZMA reset state + new prop
|
||||
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
|
||||
00000000 - End of data
|
||||
00000001 U U - Uncompressed, reset dic, need reset state and set new prop
|
||||
00000010 U U - Uncompressed, no reset
|
||||
100uuuuu U U P P - LZMA, no reset
|
||||
101uuuuu U U P P - LZMA, reset state
|
||||
110uuuuu U U P P S - LZMA, reset state + set new prop
|
||||
111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
|
||||
|
||||
u, U - Unpack Size
|
||||
P - Pack Size
|
||||
S - Props
|
||||
*/
|
||||
|
||||
#define LZMA2_CONTROL_LZMA (1 << 7)
|
||||
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
||||
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||
#define LZMA2_CONTROL_EOF 0
|
||||
|
||||
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
|
||||
|
||||
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
|
||||
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
|
||||
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
|
||||
|
||||
#define LZMA2_LCLP_MAX 4
|
||||
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||
@@ -91,9 +85,11 @@ SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
|
||||
void Lzma2Dec_Init(CLzma2Dec *p)
|
||||
{
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
p->needInitDic = True;
|
||||
p->needInitState = True;
|
||||
p->needInitProp = True;
|
||||
p->needInitLevel = 0xE0;
|
||||
p->isExtraMode = False;
|
||||
p->unpackSize = 0;
|
||||
|
||||
// p->decoder.dicPos = 0; // we can use it instead of full init
|
||||
LzmaDec_Init(&p->decoder);
|
||||
}
|
||||
|
||||
@@ -102,19 +98,26 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
switch (p->state)
|
||||
{
|
||||
case LZMA2_STATE_CONTROL:
|
||||
p->isExtraMode = False;
|
||||
p->control = b;
|
||||
PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos));
|
||||
PRF(printf(" %2X", (unsigned)b));
|
||||
PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
|
||||
PRF(printf(" %02X", (unsigned)b));
|
||||
if (b == 0)
|
||||
return LZMA2_STATE_FINISHED;
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (b > 2)
|
||||
if (b == LZMA2_CONTROL_COPY_RESET_DIC)
|
||||
p->needInitLevel = 0xC0;
|
||||
else if (b > 2 || p->needInitLevel == 0xE0)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->unpackSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b < p->needInitLevel)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->needInitLevel = 0;
|
||||
p->unpackSize = (UInt32)(b & 0x1F) << 16;
|
||||
}
|
||||
return LZMA2_STATE_UNPACK0;
|
||||
|
||||
case LZMA2_STATE_UNPACK0:
|
||||
@@ -124,8 +127,8 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
case LZMA2_STATE_UNPACK1:
|
||||
p->unpackSize |= (UInt32)b;
|
||||
p->unpackSize++;
|
||||
PRF(printf(" %8u", (unsigned)p->unpackSize));
|
||||
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||
PRF(printf(" %7u", (unsigned)p->unpackSize));
|
||||
return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||
|
||||
case LZMA2_STATE_PACK0:
|
||||
p->packSize = (UInt32)b << 8;
|
||||
@@ -134,9 +137,9 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
case LZMA2_STATE_PACK1:
|
||||
p->packSize |= (UInt32)b;
|
||||
p->packSize++;
|
||||
PRF(printf(" %8u", (unsigned)p->packSize));
|
||||
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
|
||||
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
||||
// if (p->packSize < 5) return LZMA2_STATE_ERROR;
|
||||
PRF(printf(" %5u", (unsigned)p->packSize));
|
||||
return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
|
||||
|
||||
case LZMA2_STATE_PROP:
|
||||
{
|
||||
@@ -145,13 +148,12 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
return LZMA2_STATE_ERROR;
|
||||
lc = b % 9;
|
||||
b /= 9;
|
||||
p->decoder.prop.pb = b / 5;
|
||||
p->decoder.prop.pb = (Byte)(b / 5);
|
||||
lp = b % 5;
|
||||
if (lc + lp > LZMA2_LCLP_MAX)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->decoder.prop.lc = lc;
|
||||
p->decoder.prop.lp = lp;
|
||||
p->needInitProp = False;
|
||||
p->decoder.prop.lc = (Byte)lc;
|
||||
p->decoder.prop.lp = (Byte)lp;
|
||||
return LZMA2_STATE_DATA;
|
||||
}
|
||||
}
|
||||
@@ -231,11 +233,6 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||
if (initDic)
|
||||
p->needInitProp = p->needInitState = True;
|
||||
else if (p->needInitDic)
|
||||
break;
|
||||
p->needInitDic = False;
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||
}
|
||||
|
||||
@@ -257,23 +254,17 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
unsigned mode = LZMA2_GET_LZMA_MODE(p);
|
||||
Bool initDic = (mode == 3);
|
||||
Bool initState = (mode != 0);
|
||||
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
|
||||
break;
|
||||
|
||||
Bool initDic = (p->control >= 0xE0);
|
||||
Bool initState = (p->control >= 0xA0);
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||
p->needInitDic = False;
|
||||
p->needInitState = False;
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
|
||||
if (inCur > p->packSize)
|
||||
inCur = (SizeT)p->packSize;
|
||||
|
||||
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||
|
||||
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->packSize -= (UInt32)inCur;
|
||||
@@ -310,6 +301,129 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||
SizeT outSize,
|
||||
const Byte *src, SizeT *srcLen,
|
||||
int checkFinishBlock)
|
||||
{
|
||||
SizeT inSize = *srcLen;
|
||||
*srcLen = 0;
|
||||
|
||||
while (p->state != LZMA2_STATE_ERROR)
|
||||
{
|
||||
if (p->state == LZMA2_STATE_FINISHED)
|
||||
return LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
|
||||
if (outSize == 0 && !checkFinishBlock)
|
||||
return LZMA_STATUS_NOT_FINISHED;
|
||||
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
return LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
(*srcLen)++;
|
||||
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
|
||||
if (p->state == LZMA2_STATE_UNPACK0)
|
||||
{
|
||||
// if (p->decoder.dicPos != 0)
|
||||
if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
|
||||
return LZMA2_PARSE_STATUS_NEW_BLOCK;
|
||||
// if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
|
||||
}
|
||||
|
||||
// The following code can be commented.
|
||||
// It's not big problem, if we read additional input bytes.
|
||||
// It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
|
||||
|
||||
if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
|
||||
{
|
||||
// checkFinishBlock is true. So we expect that block must be finished,
|
||||
// We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
|
||||
// break;
|
||||
return LZMA_STATUS_NOT_FINISHED;
|
||||
}
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
return LZMA2_PARSE_STATUS_NEW_CHUNK;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outSize == 0)
|
||||
return LZMA_STATUS_NOT_FINISHED;
|
||||
|
||||
{
|
||||
SizeT inCur = inSize - *srcLen;
|
||||
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (inCur == 0)
|
||||
return LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
if (inCur > p->unpackSize)
|
||||
inCur = p->unpackSize;
|
||||
if (inCur > outSize)
|
||||
inCur = outSize;
|
||||
p->decoder.dicPos += inCur;
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
outSize -= inCur;
|
||||
p->unpackSize -= (UInt32)inCur;
|
||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->isExtraMode = True;
|
||||
|
||||
if (inCur == 0)
|
||||
{
|
||||
if (p->packSize != 0)
|
||||
return LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
}
|
||||
else if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
if (*src != 0)
|
||||
{
|
||||
// first byte of lzma chunk must be Zero
|
||||
*srcLen += 1;
|
||||
p->packSize--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inCur > p->packSize)
|
||||
inCur = (SizeT)p->packSize;
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->packSize -= (UInt32)inCur;
|
||||
|
||||
if (p->packSize == 0)
|
||||
{
|
||||
SizeT rem = outSize;
|
||||
if (rem > p->unpackSize)
|
||||
rem = p->unpackSize;
|
||||
p->decoder.dicPos += rem;
|
||||
p->unpackSize -= (UInt32)rem;
|
||||
outSize -= rem;
|
||||
if (p->unpackSize == 0)
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return LZMA_STATUS_NOT_SPECIFIED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT outSize = *destLen, inSize = *srcLen;
|
||||
|
||||
60
C/Lzma2Dec.h
60
C/Lzma2Dec.h
@@ -1,5 +1,5 @@
|
||||
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2018-02-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA2_DEC_H
|
||||
#define __LZMA2_DEC_H
|
||||
@@ -12,25 +12,24 @@ EXTERN_C_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaDec decoder;
|
||||
UInt32 packSize;
|
||||
UInt32 unpackSize;
|
||||
unsigned state;
|
||||
Byte control;
|
||||
Bool needInitDic;
|
||||
Bool needInitState;
|
||||
Bool needInitProp;
|
||||
Byte needInitLevel;
|
||||
Byte isExtraMode;
|
||||
Byte _pad_;
|
||||
UInt32 packSize;
|
||||
UInt32 unpackSize;
|
||||
CLzmaDec decoder;
|
||||
} CLzma2Dec;
|
||||
|
||||
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
|
||||
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
|
||||
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
|
||||
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc)
|
||||
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc)
|
||||
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||
void Lzma2Dec_Init(CLzma2Dec *p);
|
||||
|
||||
|
||||
/*
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
|
||||
@@ -53,6 +52,47 @@ SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- LZMA2 block and chunk parsing ---------- */
|
||||
|
||||
/*
|
||||
Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.
|
||||
It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:
|
||||
- LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.
|
||||
- LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.
|
||||
CLzma2Dec::unpackSize contains unpack size of that chunk
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/*
|
||||
LZMA_STATUS_NOT_SPECIFIED // data error
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED //
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused
|
||||
*/
|
||||
LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,
|
||||
LZMA2_PARSE_STATUS_NEW_CHUNK
|
||||
} ELzma2ParseStatus;
|
||||
|
||||
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||
SizeT outSize, // output size
|
||||
const Byte *src, SizeT *srcLen,
|
||||
int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position.
|
||||
);
|
||||
|
||||
/*
|
||||
LZMA2 parser doesn't decode LZMA chunks, so we must read
|
||||
full input LZMA chunk to decode some part of LZMA chunk.
|
||||
|
||||
Lzma2Dec_GetUnpackExtra() returns the value that shows
|
||||
max possible number of output bytes that can be output by decoder
|
||||
at current input positon.
|
||||
*/
|
||||
|
||||
#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/*
|
||||
|
||||
1082
C/Lzma2DecMt.c
Normal file
1082
C/Lzma2DecMt.c
Normal file
File diff suppressed because it is too large
Load Diff
79
C/Lzma2DecMt.h
Normal file
79
C/Lzma2DecMt.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread
|
||||
2018-02-17 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA2_DEC_MT_H
|
||||
#define __LZMA2_DEC_MT_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t inBufSize_ST;
|
||||
size_t outStep_ST;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
unsigned numThreads;
|
||||
size_t inBufSize_MT;
|
||||
size_t outBlockMax;
|
||||
size_t inBlockMax;
|
||||
#endif
|
||||
} CLzma2DecMtProps;
|
||||
|
||||
/* init to single-thread mode */
|
||||
void Lzma2DecMtProps_Init(CLzma2DecMtProps *p);
|
||||
|
||||
|
||||
/* ---------- CLzma2DecMtHandle Interface ---------- */
|
||||
|
||||
/* Lzma2DecMt_ * functions can return the following exit codes:
|
||||
SRes:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||
SZ_ERROR_WRITE - ISeqOutStream write callback error
|
||||
// SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
|
||||
SZ_ERROR_PROGRESS - some break from progress callback
|
||||
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
typedef void * CLzma2DecMtHandle;
|
||||
|
||||
CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);
|
||||
void Lzma2DecMt_Destroy(CLzma2DecMtHandle p);
|
||||
|
||||
SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p,
|
||||
Byte prop,
|
||||
const CLzma2DecMtProps *props,
|
||||
ISeqOutStream *outStream,
|
||||
const UInt64 *outDataSize, // NULL means undefined
|
||||
int finishMode, // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished
|
||||
// Byte *outBuf, size_t *outBufSize,
|
||||
ISeqInStream *inStream,
|
||||
// const Byte *inData, size_t inDataSize,
|
||||
|
||||
// out variables:
|
||||
UInt64 *inProcessed,
|
||||
int *isMT, /* out: (*isMT == 0), if single thread decoding was used */
|
||||
|
||||
// UInt64 *outProcessed,
|
||||
ICompressProgress *progress);
|
||||
|
||||
|
||||
/* ---------- Read from CLzma2DecMtHandle Interface ---------- */
|
||||
|
||||
SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
|
||||
Byte prop,
|
||||
const CLzma2DecMtProps *props,
|
||||
const UInt64 *outDataSize, int finishMode,
|
||||
ISeqInStream *inStream);
|
||||
|
||||
SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
|
||||
Byte *data, size_t *outSize,
|
||||
UInt64 *inStreamProcessed);
|
||||
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
23
C/Lzma2Enc.c
23
C/Lzma2Enc.c
@@ -1,5 +1,5 @@
|
||||
/* Lzma2Enc.c -- LZMA2 Encoder
|
||||
2017-08-28 : Igor Pavlov : Public domain */
|
||||
2018-04-27 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -369,7 +369,9 @@ typedef struct
|
||||
|
||||
ISeqOutStream *outStream;
|
||||
Byte *outBuf;
|
||||
size_t outBufSize;
|
||||
size_t outBuf_Rem; /* remainder in outBuf */
|
||||
|
||||
size_t outBufSize; /* size of allocated outBufs[i] */
|
||||
size_t outBufsDataSizes[MTCODER__BLOCKS_MAX];
|
||||
Bool mtCoder_WasConstructed;
|
||||
CMtCoder mtCoder;
|
||||
@@ -666,7 +668,7 @@ static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned out
|
||||
|
||||
if (!dest)
|
||||
{
|
||||
dest = ISzAlloc_Alloc(me->alloc, me->outBufSize);
|
||||
dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
|
||||
if (!dest)
|
||||
return SZ_ERROR_MEM;
|
||||
me->outBufs[outBufIndex] = dest;
|
||||
@@ -674,7 +676,8 @@ static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned out
|
||||
|
||||
MtProgressThunk_CreateVTable(&progressThunk);
|
||||
progressThunk.mtProgress = &me->mtCoder.mtProgress;
|
||||
progressThunk.index = coderIndex;
|
||||
progressThunk.inSize = 0;
|
||||
progressThunk.outSize = 0;
|
||||
|
||||
res = Lzma2Enc_EncodeMt1(me,
|
||||
&me->coders[coderIndex],
|
||||
@@ -698,10 +701,10 @@ static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex)
|
||||
if (me->outStream)
|
||||
return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE;
|
||||
|
||||
if (size > me->outBufSize)
|
||||
if (size > me->outBuf_Rem)
|
||||
return SZ_ERROR_OUTPUT_EOF;
|
||||
memcpy(me->outBuf, data, size);
|
||||
me->outBufSize -= size;
|
||||
me->outBuf_Rem -= size;
|
||||
me->outBuf += size;
|
||||
return SZ_OK;
|
||||
}
|
||||
@@ -720,10 +723,10 @@ SRes Lzma2Enc_Encode2(CLzma2EncHandle pp,
|
||||
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||
|
||||
if (inStream && inData)
|
||||
return E_INVALIDARG;
|
||||
return SZ_ERROR_PARAM;
|
||||
|
||||
if (outStream && outBuf)
|
||||
return E_INVALIDARG;
|
||||
return SZ_ERROR_PARAM;
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
@@ -748,11 +751,11 @@ SRes Lzma2Enc_Encode2(CLzma2EncHandle pp,
|
||||
|
||||
p->outStream = outStream;
|
||||
p->outBuf = NULL;
|
||||
p->outBufSize = 0;
|
||||
p->outBuf_Rem = 0;
|
||||
if (!outStream)
|
||||
{
|
||||
p->outBuf = outBuf;
|
||||
p->outBufSize = *outBufSize;
|
||||
p->outBuf_Rem = *outBufSize;
|
||||
*outBufSize = 0;
|
||||
}
|
||||
|
||||
|
||||
379
C/LzmaDec.c
379
C/LzmaDec.c
@@ -1,8 +1,9 @@
|
||||
/* LzmaDec.c -- LZMA Decoder
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2018-02-28 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
/* #include "CpuArch.h" */
|
||||
#include "LzmaDec.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -24,9 +25,16 @@
|
||||
#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
|
||||
{ UPDATE_0(p); i = (i + i); A0; } else \
|
||||
{ UPDATE_1(p); i = (i + i) + 1; A1; }
|
||||
#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
|
||||
|
||||
#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
|
||||
#define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); }
|
||||
|
||||
#define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \
|
||||
{ UPDATE_0(p + i); A0; } else \
|
||||
{ UPDATE_1(p + i); A1; }
|
||||
#define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; )
|
||||
#define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; )
|
||||
#define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; )
|
||||
|
||||
#define TREE_DECODE(probs, limit, i) \
|
||||
{ i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
|
||||
|
||||
@@ -46,12 +54,15 @@
|
||||
i -= 0x40; }
|
||||
#endif
|
||||
|
||||
#define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol)
|
||||
#define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol)
|
||||
#define MATCHED_LITER_DEC \
|
||||
matchByte <<= 1; \
|
||||
bit = (matchByte & offs); \
|
||||
probLit = prob + offs + bit + symbol; \
|
||||
GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
|
||||
matchByte += matchByte; \
|
||||
bit = offs; \
|
||||
offs &= matchByte; \
|
||||
probLit = prob + (offs + bit + symbol); \
|
||||
GET_BIT2(probLit, symbol, offs ^= bit; , ;)
|
||||
|
||||
|
||||
|
||||
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
|
||||
|
||||
@@ -66,25 +77,28 @@
|
||||
{ i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
|
||||
|
||||
|
||||
#define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \
|
||||
{ UPDATE_0_CHECK; i += m; m += m; } else \
|
||||
{ UPDATE_1_CHECK; m += m; i += m; }
|
||||
|
||||
|
||||
#define kNumPosBitsMax 4
|
||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
||||
|
||||
#define kLenNumLowBits 3
|
||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
||||
#define kLenNumMidBits 3
|
||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
||||
#define kLenNumHighBits 8
|
||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
||||
|
||||
#define LenChoice 0
|
||||
#define LenChoice2 (LenChoice + 1)
|
||||
#define LenLow (LenChoice2 + 1)
|
||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
||||
#define LenLow 0
|
||||
#define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits))
|
||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
||||
|
||||
#define LenChoice LenLow
|
||||
#define LenChoice2 (LenLow + (1 << kLenNumLowBits))
|
||||
|
||||
#define kNumStates 12
|
||||
#define kNumStates2 16
|
||||
#define kNumLitStates 7
|
||||
|
||||
#define kStartPosModelIndex 4
|
||||
@@ -98,54 +112,117 @@
|
||||
#define kAlignTableSize (1 << kNumAlignBits)
|
||||
|
||||
#define kMatchMinLen 2
|
||||
#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
|
||||
#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols)
|
||||
|
||||
#define IsMatch 0
|
||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
||||
/* 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 */
|
||||
/*
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
*/
|
||||
#define kStartOffset 1664
|
||||
#define GET_PROBS p->probs_1664
|
||||
/*
|
||||
#define GET_PROBS p->probs + kStartOffset
|
||||
#else
|
||||
#define kStartOffset 0
|
||||
#define GET_PROBS p->probs
|
||||
#endif
|
||||
*/
|
||||
|
||||
#define SpecPos (-kStartOffset)
|
||||
#define IsRep0Long (SpecPos + kNumFullDistances)
|
||||
#define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax))
|
||||
#define LenCoder (RepLenCoder + kNumLenProbs)
|
||||
#define IsMatch (LenCoder + kNumLenProbs)
|
||||
#define Align (IsMatch + (kNumStates2 << kNumPosBitsMax))
|
||||
#define IsRep (Align + kAlignTableSize)
|
||||
#define IsRepG0 (IsRep + kNumStates)
|
||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
||||
#define LenCoder (Align + kAlignTableSize)
|
||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
||||
#define Literal (RepLenCoder + kNumLenProbs)
|
||||
#define PosSlot (IsRepG2 + kNumStates)
|
||||
#define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
||||
#define NUM_BASE_PROBS (Literal + kStartOffset)
|
||||
|
||||
#define LZMA_BASE_SIZE 1846
|
||||
#define LZMA_LIT_SIZE 0x300
|
||||
|
||||
#if Literal != LZMA_BASE_SIZE
|
||||
StopCompilingDueBUG
|
||||
#if Align != 0 && kStartOffset != 0
|
||||
#error Stop_Compiling_Bad_LZMA_kAlign
|
||||
#endif
|
||||
|
||||
#define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
|
||||
#if NUM_BASE_PROBS != 1984
|
||||
#error Stop_Compiling_Bad_LZMA_PROBS
|
||||
#endif
|
||||
|
||||
|
||||
#define LZMA_LIT_SIZE 0x300
|
||||
|
||||
#define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
|
||||
|
||||
|
||||
#define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4)
|
||||
#define COMBINED_PS_STATE (posState + state)
|
||||
#define GET_LEN_STATE (posState)
|
||||
|
||||
#define LZMA_DIC_MIN (1 << 12)
|
||||
|
||||
/* First LZMA-symbol is always decoded.
|
||||
And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
|
||||
/*
|
||||
p->remainLen : shows status of LZMA decoder:
|
||||
< kMatchSpecLenStart : normal remain
|
||||
= kMatchSpecLenStart : finished
|
||||
= kMatchSpecLenStart + 1 : need init range coder
|
||||
= kMatchSpecLenStart + 2 : need init range coder and state
|
||||
*/
|
||||
|
||||
/* ---------- LZMA_DECODE_REAL ---------- */
|
||||
/*
|
||||
LzmaDec_DecodeReal_3() can be implemented in external ASM file.
|
||||
3 - is the code compatibility version of that function for check at link time.
|
||||
*/
|
||||
|
||||
#define LZMA_DECODE_REAL LzmaDec_DecodeReal_3
|
||||
|
||||
/*
|
||||
LZMA_DECODE_REAL()
|
||||
In:
|
||||
RangeCoder is normalized
|
||||
if (p->dicPos == limit)
|
||||
{
|
||||
LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases.
|
||||
So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol
|
||||
is not END_OF_PAYALOAD_MARKER, then function returns error code.
|
||||
}
|
||||
|
||||
Processing:
|
||||
first LZMA symbol will be decoded in any case
|
||||
All checks for limits are at the end of main loop,
|
||||
It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit),
|
||||
RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked.
|
||||
|
||||
Out:
|
||||
RangeCoder is normalized
|
||||
Result:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_DATA - Error
|
||||
p->remainLen:
|
||||
< kMatchSpecLenStart : normal remain
|
||||
= kMatchSpecLenStart : finished
|
||||
= kMatchSpecLenStart + 1 : Flush marker (unused now)
|
||||
= kMatchSpecLenStart + 2 : State Init Marker (unused now)
|
||||
*/
|
||||
|
||||
static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
|
||||
{
|
||||
CLzmaProb *probs = p->probs;
|
||||
|
||||
unsigned state = p->state;
|
||||
#ifdef _LZMA_DEC_OPT
|
||||
|
||||
int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit);
|
||||
|
||||
#else
|
||||
|
||||
static
|
||||
int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
|
||||
{
|
||||
CLzmaProb *probs = GET_PROBS;
|
||||
unsigned state = (unsigned)p->state;
|
||||
UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
|
||||
unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
|
||||
unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
|
||||
unsigned lc = p->prop.lc;
|
||||
unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc);
|
||||
|
||||
Byte *dic = p->dic;
|
||||
SizeT dicBufSize = p->dicBufSize;
|
||||
@@ -164,17 +241,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
CLzmaProb *prob;
|
||||
UInt32 bound;
|
||||
unsigned ttt;
|
||||
unsigned posState = processedPos & pbMask;
|
||||
unsigned posState = CALC_POS_STATE(processedPos, pbMask);
|
||||
|
||||
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
|
||||
prob = probs + IsMatch + COMBINED_PS_STATE;
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
unsigned symbol;
|
||||
UPDATE_0(prob);
|
||||
prob = probs + Literal;
|
||||
if (processedPos != 0 || checkDicSize != 0)
|
||||
prob += ((UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
|
||||
(dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
|
||||
prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc);
|
||||
processedPos++;
|
||||
|
||||
if (state < kNumLitStates)
|
||||
@@ -240,13 +316,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
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)
|
||||
{
|
||||
UPDATE_0(prob);
|
||||
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
||||
prob = probs + IsRep0Long + COMBINED_PS_STATE;
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob);
|
||||
@@ -299,7 +378,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
IF_BIT_0(probLen)
|
||||
{
|
||||
UPDATE_0(probLen);
|
||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
||||
probLen = prob + LenLow + GET_LEN_STATE;
|
||||
offset = 0;
|
||||
lim = (1 << kLenNumLowBits);
|
||||
}
|
||||
@@ -310,15 +389,15 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
IF_BIT_0(probLen)
|
||||
{
|
||||
UPDATE_0(probLen);
|
||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
||||
probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
|
||||
offset = kLenNumLowSymbols;
|
||||
lim = (1 << kLenNumMidBits);
|
||||
lim = (1 << kLenNumLowBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1(probLen);
|
||||
probLen = prob + LenHigh;
|
||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
||||
offset = kLenNumLowSymbols * 2;
|
||||
lim = (1 << kLenNumHighBits);
|
||||
}
|
||||
}
|
||||
@@ -331,7 +410,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
IF_BIT_0(probLen)
|
||||
{
|
||||
UPDATE_0(probLen);
|
||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
||||
probLen = prob + LenLow + GET_LEN_STATE;
|
||||
len = 1;
|
||||
TREE_GET_BIT(probLen, len);
|
||||
TREE_GET_BIT(probLen, len);
|
||||
@@ -345,7 +424,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
IF_BIT_0(probLen)
|
||||
{
|
||||
UPDATE_0(probLen);
|
||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
||||
probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
|
||||
len = 1;
|
||||
TREE_GET_BIT(probLen, len);
|
||||
TREE_GET_BIT(probLen, len);
|
||||
@@ -356,7 +435,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
UPDATE_1(probLen);
|
||||
probLen = prob + LenHigh;
|
||||
TREE_DECODE(probLen, (1 << kLenNumHighBits), len);
|
||||
len += kLenNumLowSymbols + kLenNumMidSymbols;
|
||||
len += kLenNumLowSymbols * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,16 +455,16 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
if (posSlot < kEndPosModelIndex)
|
||||
{
|
||||
distance <<= numDirectBits;
|
||||
prob = probs + SpecPos + distance - posSlot - 1;
|
||||
prob = probs + SpecPos;
|
||||
{
|
||||
UInt32 mask = 1;
|
||||
unsigned i = 1;
|
||||
UInt32 m = 1;
|
||||
distance++;
|
||||
do
|
||||
{
|
||||
GET_BIT2(prob + i, i, ; , distance |= mask);
|
||||
mask <<= 1;
|
||||
REV_BIT_VAR(prob, distance, m);
|
||||
}
|
||||
while (--numDirectBits != 0);
|
||||
while (--numDirectBits);
|
||||
distance -= m;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -412,19 +491,20 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
}
|
||||
*/
|
||||
}
|
||||
while (--numDirectBits != 0);
|
||||
while (--numDirectBits);
|
||||
prob = probs + Align;
|
||||
distance <<= kNumAlignBits;
|
||||
{
|
||||
unsigned i = 1;
|
||||
GET_BIT2(prob + i, i, ; , distance |= 1);
|
||||
GET_BIT2(prob + i, i, ; , distance |= 2);
|
||||
GET_BIT2(prob + i, i, ; , distance |= 4);
|
||||
GET_BIT2(prob + i, i, ; , distance |= 8);
|
||||
REV_BIT_CONST(prob, i, 1);
|
||||
REV_BIT_CONST(prob, i, 2);
|
||||
REV_BIT_CONST(prob, i, 4);
|
||||
REV_BIT_LAST (prob, i, 8);
|
||||
distance |= i;
|
||||
}
|
||||
if (distance == (UInt32)0xFFFFFFFF)
|
||||
{
|
||||
len += kMatchSpecLenStart;
|
||||
len = kMatchSpecLenStart;
|
||||
state -= kNumStates;
|
||||
break;
|
||||
}
|
||||
@@ -435,20 +515,12 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
rep2 = rep1;
|
||||
rep1 = rep0;
|
||||
rep0 = distance + 1;
|
||||
if (checkDicSize == 0)
|
||||
{
|
||||
if (distance >= processedPos)
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
else if (distance >= checkDicSize)
|
||||
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
|
||||
if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize))
|
||||
{
|
||||
p->dicPos = dicPos;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
|
||||
}
|
||||
|
||||
len += kMatchMinLen;
|
||||
@@ -511,6 +583,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
|
||||
{
|
||||
@@ -519,7 +592,7 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
|
||||
Byte *dic = p->dic;
|
||||
SizeT dicPos = p->dicPos;
|
||||
SizeT dicBufSize = p->dicBufSize;
|
||||
unsigned len = p->remainLen;
|
||||
unsigned len = (unsigned)p->remainLen;
|
||||
SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
|
||||
SizeT rem = limit - dicPos;
|
||||
if (rem < len)
|
||||
@@ -540,6 +613,14 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define kRange0 0xFFFFFFFF
|
||||
#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))
|
||||
#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)))
|
||||
#if kBadRepCode != (0xC0000000 - 0x400)
|
||||
#error Stop_Compiling_Bad_LZMA_Check
|
||||
#endif
|
||||
|
||||
static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
|
||||
{
|
||||
do
|
||||
@@ -550,9 +631,13 @@ static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte
|
||||
UInt32 rem = p->prop.dicSize - p->processedPos;
|
||||
if (limit - p->dicPos > rem)
|
||||
limit2 = p->dicPos + rem;
|
||||
|
||||
if (p->processedPos == 0)
|
||||
if (p->code >= kBadRepCode)
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
|
||||
|
||||
RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit));
|
||||
|
||||
if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
@@ -561,9 +646,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte
|
||||
}
|
||||
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
|
||||
|
||||
if (p->remainLen > kMatchSpecLenStart)
|
||||
p->remainLen = kMatchSpecLenStart;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -580,17 +662,17 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
||||
UInt32 range = p->range;
|
||||
UInt32 code = p->code;
|
||||
const Byte *bufLimit = buf + inSize;
|
||||
const CLzmaProb *probs = p->probs;
|
||||
unsigned state = p->state;
|
||||
const CLzmaProb *probs = GET_PROBS;
|
||||
unsigned state = (unsigned)p->state;
|
||||
ELzmaDummy res;
|
||||
|
||||
{
|
||||
const CLzmaProb *prob;
|
||||
UInt32 bound;
|
||||
unsigned ttt;
|
||||
unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
|
||||
unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1);
|
||||
|
||||
prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
|
||||
prob = probs + IsMatch + COMBINED_PS_STATE;
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK
|
||||
@@ -618,10 +700,11 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
||||
{
|
||||
unsigned bit;
|
||||
const CLzmaProb *probLit;
|
||||
matchByte <<= 1;
|
||||
bit = (matchByte & offs);
|
||||
probLit = prob + offs + bit + symbol;
|
||||
GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
|
||||
matchByte += matchByte;
|
||||
bit = offs;
|
||||
offs &= matchByte;
|
||||
probLit = prob + (offs + bit + symbol);
|
||||
GET_BIT2_CHECK(probLit, symbol, offs ^= bit; , ; )
|
||||
}
|
||||
while (symbol < 0x100);
|
||||
}
|
||||
@@ -648,7 +731,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
||||
prob = probs + IsRep0Long + COMBINED_PS_STATE;
|
||||
IF_BIT_0_CHECK(prob)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
@@ -691,7 +774,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
||||
IF_BIT_0_CHECK(probLen)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
||||
probLen = prob + LenLow + GET_LEN_STATE;
|
||||
offset = 0;
|
||||
limit = 1 << kLenNumLowBits;
|
||||
}
|
||||
@@ -702,15 +785,15 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
||||
IF_BIT_0_CHECK(probLen)
|
||||
{
|
||||
UPDATE_0_CHECK;
|
||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
||||
probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);
|
||||
offset = kLenNumLowSymbols;
|
||||
limit = 1 << kLenNumMidBits;
|
||||
limit = 1 << kLenNumLowBits;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPDATE_1_CHECK;
|
||||
probLen = prob + LenHigh;
|
||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
||||
offset = kLenNumLowSymbols * 2;
|
||||
limit = 1 << kLenNumHighBits;
|
||||
}
|
||||
}
|
||||
@@ -722,7 +805,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
||||
{
|
||||
unsigned posSlot;
|
||||
prob = probs + PosSlot +
|
||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
||||
((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) <<
|
||||
kNumPosSlotBits);
|
||||
TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
|
||||
if (posSlot >= kStartPosModelIndex)
|
||||
@@ -733,7 +816,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
||||
|
||||
if (posSlot < kEndPosModelIndex)
|
||||
{
|
||||
prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
|
||||
prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -745,17 +828,18 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
||||
code -= range & (((code - range) >> 31) - 1);
|
||||
/* if (code >= range) code -= range; */
|
||||
}
|
||||
while (--numDirectBits != 0);
|
||||
while (--numDirectBits);
|
||||
prob = probs + Align;
|
||||
numDirectBits = kNumAlignBits;
|
||||
}
|
||||
{
|
||||
unsigned i = 1;
|
||||
unsigned m = 1;
|
||||
do
|
||||
{
|
||||
GET_BIT_CHECK(prob + i, i);
|
||||
REV_BIT_CHECK(prob, i, m);
|
||||
}
|
||||
while (--numDirectBits != 0);
|
||||
while (--numDirectBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -768,18 +852,17 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
|
||||
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
|
||||
{
|
||||
p->needFlush = 1;
|
||||
p->remainLen = 0;
|
||||
p->remainLen = kMatchSpecLenStart + 1;
|
||||
p->tempBufSize = 0;
|
||||
|
||||
if (initDic)
|
||||
{
|
||||
p->processedPos = 0;
|
||||
p->checkDicSize = 0;
|
||||
p->needInitState = 1;
|
||||
p->remainLen = kMatchSpecLenStart + 2;
|
||||
}
|
||||
if (initState)
|
||||
p->needInitState = 1;
|
||||
p->remainLen = kMatchSpecLenStart + 2;
|
||||
}
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p)
|
||||
@@ -788,53 +871,54 @@ void LzmaDec_Init(CLzmaDec *p)
|
||||
LzmaDec_InitDicAndState(p, True, True);
|
||||
}
|
||||
|
||||
static void LzmaDec_InitStateReal(CLzmaDec *p)
|
||||
{
|
||||
SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
|
||||
SizeT i;
|
||||
CLzmaProb *probs = p->probs;
|
||||
for (i = 0; i < numProbs; i++)
|
||||
probs[i] = kBitModelTotal >> 1;
|
||||
p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
|
||||
p->state = 0;
|
||||
p->needInitState = 0;
|
||||
}
|
||||
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
|
||||
ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT inSize = *srcLen;
|
||||
(*srcLen) = 0;
|
||||
LzmaDec_WriteRem(p, dicLimit);
|
||||
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
if (p->remainLen > kMatchSpecLenStart)
|
||||
{
|
||||
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
|
||||
p->tempBuf[p->tempBufSize++] = *src++;
|
||||
if (p->tempBufSize != 0 && p->tempBuf[0] != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
if (p->tempBufSize < RC_INIT_SIZE)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
p->code =
|
||||
((UInt32)p->tempBuf[1] << 24)
|
||||
| ((UInt32)p->tempBuf[2] << 16)
|
||||
| ((UInt32)p->tempBuf[3] << 8)
|
||||
| ((UInt32)p->tempBuf[4]);
|
||||
p->range = 0xFFFFFFFF;
|
||||
p->tempBufSize = 0;
|
||||
|
||||
if (p->remainLen > kMatchSpecLenStart + 1)
|
||||
{
|
||||
SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
|
||||
SizeT i;
|
||||
CLzmaProb *probs = p->probs;
|
||||
for (i = 0; i < numProbs; i++)
|
||||
probs[i] = kBitModelTotal >> 1;
|
||||
p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
|
||||
p->state = 0;
|
||||
}
|
||||
|
||||
p->remainLen = 0;
|
||||
}
|
||||
|
||||
LzmaDec_WriteRem(p, dicLimit);
|
||||
|
||||
while (p->remainLen != kMatchSpecLenStart)
|
||||
{
|
||||
int checkEndMarkNow;
|
||||
int checkEndMarkNow = 0;
|
||||
|
||||
if (p->needFlush)
|
||||
{
|
||||
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
|
||||
p->tempBuf[p->tempBufSize++] = *src++;
|
||||
if (p->tempBufSize < RC_INIT_SIZE)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (p->tempBuf[0] != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
p->code =
|
||||
((UInt32)p->tempBuf[1] << 24)
|
||||
| ((UInt32)p->tempBuf[2] << 16)
|
||||
| ((UInt32)p->tempBuf[3] << 8)
|
||||
| ((UInt32)p->tempBuf[4]);
|
||||
p->range = 0xFFFFFFFF;
|
||||
p->needFlush = 0;
|
||||
p->tempBufSize = 0;
|
||||
}
|
||||
|
||||
checkEndMarkNow = 0;
|
||||
if (p->dicPos >= dicLimit)
|
||||
{
|
||||
if (p->remainLen == 0 && p->code == 0)
|
||||
@@ -855,9 +939,6 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
|
||||
checkEndMarkNow = 1;
|
||||
}
|
||||
|
||||
if (p->needInitState)
|
||||
LzmaDec_InitStateReal(p);
|
||||
|
||||
if (p->tempBufSize == 0)
|
||||
{
|
||||
SizeT processed;
|
||||
@@ -930,11 +1011,14 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
|
||||
p->tempBufSize = 0;
|
||||
}
|
||||
}
|
||||
if (p->code == 0)
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
|
||||
|
||||
if (p->code != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT outSize = *destLen;
|
||||
@@ -1011,10 +1095,10 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
|
||||
if (d >= (9 * 5 * 5))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
p->lc = d % 9;
|
||||
p->lc = (Byte)(d % 9);
|
||||
d /= 9;
|
||||
p->pb = d / 5;
|
||||
p->lp = d % 5;
|
||||
p->pb = (Byte)(d / 5);
|
||||
p->lp = (Byte)(d % 5);
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
@@ -1026,9 +1110,10 @@ static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAl
|
||||
{
|
||||
LzmaDec_FreeProbs(p, alloc);
|
||||
p->probs = (CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb));
|
||||
p->numProbs = numProbs;
|
||||
if (!p->probs)
|
||||
return SZ_ERROR_MEM;
|
||||
p->probs_1664 = p->probs + 1664;
|
||||
p->numProbs = numProbs;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
41
C/LzmaDec.h
41
C/LzmaDec.h
@@ -1,5 +1,5 @@
|
||||
/* LzmaDec.h -- LZMA Decoder
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
2018-04-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_DEC_H
|
||||
#define __LZMA_DEC_H
|
||||
@@ -12,11 +12,13 @@ EXTERN_C_BEGIN
|
||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||
|
||||
typedef
|
||||
#ifdef _LZMA_PROB32
|
||||
#define CLzmaProb UInt32
|
||||
UInt32
|
||||
#else
|
||||
#define CLzmaProb UInt16
|
||||
UInt16
|
||||
#endif
|
||||
CLzmaProb;
|
||||
|
||||
|
||||
/* ---------- LZMA Properties ---------- */
|
||||
@@ -25,7 +27,10 @@ EXTERN_C_BEGIN
|
||||
|
||||
typedef struct _CLzmaProps
|
||||
{
|
||||
unsigned lc, lp, pb;
|
||||
Byte lc;
|
||||
Byte lp;
|
||||
Byte pb;
|
||||
Byte _pad_;
|
||||
UInt32 dicSize;
|
||||
} CLzmaProps;
|
||||
|
||||
@@ -47,32 +52,34 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Don't change this structure. ASM code can use it. */
|
||||
CLzmaProps prop;
|
||||
CLzmaProb *probs;
|
||||
CLzmaProb *probs_1664;
|
||||
Byte *dic;
|
||||
const Byte *buf;
|
||||
UInt32 range, code;
|
||||
SizeT dicPos;
|
||||
SizeT dicBufSize;
|
||||
SizeT dicPos;
|
||||
const Byte *buf;
|
||||
UInt32 range;
|
||||
UInt32 code;
|
||||
UInt32 processedPos;
|
||||
UInt32 checkDicSize;
|
||||
unsigned state;
|
||||
UInt32 reps[4];
|
||||
unsigned remainLen;
|
||||
int needFlush;
|
||||
int needInitState;
|
||||
UInt32 state;
|
||||
UInt32 remainLen;
|
||||
|
||||
UInt32 numProbs;
|
||||
unsigned tempBufSize;
|
||||
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||
} CLzmaDec;
|
||||
|
||||
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
||||
#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p);
|
||||
|
||||
/* There are two types of LZMA streams:
|
||||
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
- Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
- Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -132,8 +139,8 @@ LzmaDec_Allocate* can return:
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAllocPtr alloc);
|
||||
void LzmaDec_Free(CLzmaDec *state, ISzAllocPtr alloc);
|
||||
SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||
void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
|
||||
|
||||
/* ---------- Dictionary Interface ---------- */
|
||||
|
||||
@@ -142,7 +149,7 @@ void LzmaDec_Free(CLzmaDec *state, ISzAllocPtr alloc);
|
||||
You must work with CLzmaDec variables directly in this interface.
|
||||
|
||||
STEPS:
|
||||
LzmaDec_Constr()
|
||||
LzmaDec_Construct()
|
||||
LzmaDec_Allocate()
|
||||
for (each new stream)
|
||||
{
|
||||
|
||||
2251
C/LzmaEnc.c
2251
C/LzmaEnc.c
File diff suppressed because it is too large
Load Diff
89
C/MtCoder.c
89
C/MtCoder.c
@@ -1,85 +1,28 @@
|
||||
/* MtCoder.c -- Multi-thread Coder
|
||||
2017-07-17 : Igor Pavlov : Public domain */
|
||||
2018-02-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "MtCoder.h"
|
||||
|
||||
static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
|
||||
{
|
||||
unsigned i;
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
p->progress = progress;
|
||||
p->res = SZ_OK;
|
||||
p->totalInSize = 0;
|
||||
p->totalOutSize = 0;
|
||||
|
||||
for (i = 0; i < MTCODER__THREADS_MAX; i++)
|
||||
SRes MtProgressThunk_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize)
|
||||
{
|
||||
CMtProgressThunk *thunk = CONTAINER_FROM_VTBL(pp, CMtProgressThunk, vt);
|
||||
UInt64 inSize2 = 0;
|
||||
UInt64 outSize2 = 0;
|
||||
if (inSize != (UInt64)(Int64)-1)
|
||||
{
|
||||
CMtProgressSizes *pair = &p->sizes[i];
|
||||
pair->inSize = 0;
|
||||
pair->outSize = 0;
|
||||
inSize2 = inSize - thunk->inSize;
|
||||
thunk->inSize = inSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void MtProgress_Reinit(CMtProgress *p, unsigned index)
|
||||
{
|
||||
CMtProgressSizes *pair = &p->sizes[index];
|
||||
pair->inSize = 0;
|
||||
pair->outSize = 0;
|
||||
}
|
||||
|
||||
|
||||
#define UPDATE_PROGRESS(size, prev, total) \
|
||||
if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }
|
||||
|
||||
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)
|
||||
{
|
||||
SRes res;
|
||||
CMtProgressSizes *pair;
|
||||
|
||||
CriticalSection_Enter(&p->cs);
|
||||
|
||||
pair = &p->sizes[index];
|
||||
UPDATE_PROGRESS(inSize, pair->inSize, p->totalInSize)
|
||||
UPDATE_PROGRESS(outSize, pair->outSize, p->totalOutSize)
|
||||
if (p->res == SZ_OK && p->progress)
|
||||
if (outSize != (UInt64)(Int64)-1)
|
||||
{
|
||||
if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK)
|
||||
p->res = SZ_ERROR_PROGRESS;
|
||||
outSize2 = outSize - thunk->outSize;
|
||||
thunk->outSize = outSize;
|
||||
}
|
||||
res = p->res;
|
||||
|
||||
CriticalSection_Leave(&p->cs);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static SRes MtProgress_GetError(CMtProgress *p)
|
||||
{
|
||||
SRes res;
|
||||
CriticalSection_Enter(&p->cs);
|
||||
res = p->res;
|
||||
CriticalSection_Leave(&p->cs);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void MtProgress_SetError(CMtProgress *p, SRes res)
|
||||
{
|
||||
CriticalSection_Enter(&p->cs);
|
||||
if (p->res == SZ_OK)
|
||||
p->res = res;
|
||||
CriticalSection_Leave(&p->cs);
|
||||
}
|
||||
|
||||
|
||||
static SRes MtProgressThunk_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize)
|
||||
{
|
||||
CMtProgressThunk *p = CONTAINER_FROM_VTBL(pp, CMtProgressThunk, vt);
|
||||
return MtProgress_Set(p->mtProgress, p->index, inSize, outSize);
|
||||
return MtProgress_ProgressAdd(thunk->mtProgress, inSize2, outSize2);
|
||||
}
|
||||
|
||||
|
||||
@@ -298,7 +241,7 @@ static SRes ThreadFunc2(CMtCoderThread *t)
|
||||
res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex,
|
||||
mtc->inStream ? t->inBuf : inData, size, finished);
|
||||
|
||||
MtProgress_Reinit(&mtc->mtProgress, t->index);
|
||||
// MtProgress_Reinit(&mtc->mtProgress, t->index);
|
||||
|
||||
if (res != SZ_OK)
|
||||
MtProgress_SetError(&mtc->mtProgress, res);
|
||||
@@ -654,3 +597,5 @@ SRes MtCoder_Code(CMtCoder *p)
|
||||
MtCoder_Free(p);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
28
C/MtCoder.h
28
C/MtCoder.h
@@ -1,10 +1,10 @@
|
||||
/* MtCoder.h -- Multi-thread Coder
|
||||
2017-06-18 : Igor Pavlov : Public domain */
|
||||
2018-02-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __MT_CODER_H
|
||||
#define __MT_CODER_H
|
||||
|
||||
#include "Threads.h"
|
||||
#include "MtDec.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
@@ -24,33 +24,20 @@ EXTERN_C_BEGIN
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 inSize;
|
||||
UInt64 outSize;
|
||||
} CMtProgressSizes;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ICompressProgress *progress;
|
||||
SRes res;
|
||||
UInt64 totalInSize;
|
||||
UInt64 totalOutSize;
|
||||
CCriticalSection cs;
|
||||
CMtProgressSizes sizes[MTCODER__THREADS_MAX];
|
||||
} CMtProgress;
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ICompressProgress vt;
|
||||
CMtProgress *mtProgress;
|
||||
unsigned index;
|
||||
UInt64 inSize;
|
||||
UInt64 outSize;
|
||||
} CMtProgressThunk;
|
||||
|
||||
void MtProgressThunk_CreateVTable(CMtProgressThunk *p);
|
||||
|
||||
#define MtProgressThunk_Init(p) { (p)->inSize = 0; (p)->outSize = 0; }
|
||||
|
||||
|
||||
struct _CMtCoder;
|
||||
@@ -146,6 +133,9 @@ void MtCoder_Destruct(CMtCoder *p);
|
||||
SRes MtCoder_Code(CMtCoder *p);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
201
C/MtDec.h
Normal file
201
C/MtDec.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/* MtDec.h -- Multi-thread Decoder
|
||||
2018-03-02 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __MT_DEC_H
|
||||
#define __MT_DEC_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "Threads.h"
|
||||
#endif
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#define MTDEC__THREADS_MAX 32
|
||||
#else
|
||||
#define MTDEC__THREADS_MAX 1
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ICompressProgress *progress;
|
||||
SRes res;
|
||||
UInt64 totalInSize;
|
||||
UInt64 totalOutSize;
|
||||
CCriticalSection cs;
|
||||
} CMtProgress;
|
||||
|
||||
void MtProgress_Init(CMtProgress *p, ICompressProgress *progress);
|
||||
SRes MtProgress_Progress_ST(CMtProgress *p);
|
||||
SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize);
|
||||
SRes MtProgress_GetError(CMtProgress *p);
|
||||
void MtProgress_SetError(CMtProgress *p, SRes res);
|
||||
|
||||
struct _CMtDec;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct _CMtDec *mtDec;
|
||||
unsigned index;
|
||||
void *inBuf;
|
||||
|
||||
size_t inDataSize_Start; // size of input data in start block
|
||||
UInt64 inDataSize; // total size of input data in all blocks
|
||||
|
||||
CThread thread;
|
||||
CAutoResetEvent canRead;
|
||||
CAutoResetEvent canWrite;
|
||||
void *allocaPtr;
|
||||
} CMtDecThread;
|
||||
|
||||
void MtDecThread_FreeInBufs(CMtDecThread *t);
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MTDEC_PARSE_CONTINUE, // continue this block with more input data
|
||||
MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread
|
||||
MTDEC_PARSE_NEW, // new block
|
||||
MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue)
|
||||
} EMtDecParseState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// in
|
||||
int startCall;
|
||||
const Byte *src;
|
||||
size_t srcSize;
|
||||
// in : (srcSize == 0) is allowed
|
||||
// out : it's allowed to return less that actually was used ?
|
||||
int srcFinished;
|
||||
|
||||
// out
|
||||
EMtDecParseState state;
|
||||
Bool canCreateNewThread;
|
||||
UInt64 outPos; // check it (size_t)
|
||||
} CMtDecCallbackInfo;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci);
|
||||
|
||||
// PreCode() and Code():
|
||||
// (SRes_return_result != SZ_OK) means stop decoding, no need another blocks
|
||||
SRes (*PreCode)(void *p, unsigned coderIndex);
|
||||
SRes (*Code)(void *p, unsigned coderIndex,
|
||||
const Byte *src, size_t srcSize, int srcFinished,
|
||||
UInt64 *inCodePos, UInt64 *outCodePos, int *stop);
|
||||
// stop - means stop another Code calls
|
||||
|
||||
|
||||
/* Write() must be called, if Parse() was called
|
||||
set (needWrite) if
|
||||
{
|
||||
&& (was not interrupted by progress)
|
||||
&& (was not interrupted in previous block)
|
||||
}
|
||||
|
||||
out:
|
||||
if (*needContinue), decoder still need to continue decoding with new iteration,
|
||||
even after MTDEC_PARSE_END
|
||||
if (*canRecode), we didn't flush current block data, so we still can decode current block later.
|
||||
*/
|
||||
SRes (*Write)(void *p, unsigned coderIndex,
|
||||
Bool needWriteToStream,
|
||||
const Byte *src, size_t srcSize,
|
||||
// int srcFinished,
|
||||
Bool *needContinue,
|
||||
Bool *canRecode);
|
||||
} IMtDecCallback;
|
||||
|
||||
|
||||
|
||||
typedef struct _CMtDec
|
||||
{
|
||||
/* input variables */
|
||||
|
||||
size_t inBufSize; /* size of input block */
|
||||
unsigned numThreadsMax;
|
||||
// size_t inBlockMax;
|
||||
unsigned numThreadsMax_2;
|
||||
|
||||
ISeqInStream *inStream;
|
||||
// const Byte *inData;
|
||||
// size_t inDataSize;
|
||||
|
||||
ICompressProgress *progress;
|
||||
ISzAllocPtr alloc;
|
||||
|
||||
IMtDecCallback *mtCallback;
|
||||
void *mtCallbackObject;
|
||||
|
||||
|
||||
/* internal variables */
|
||||
|
||||
size_t allocatedBufsSize;
|
||||
|
||||
Bool exitThread;
|
||||
WRes exitThreadWRes;
|
||||
|
||||
UInt64 blockIndex;
|
||||
Bool isAllocError;
|
||||
Bool overflow;
|
||||
SRes threadingErrorSRes;
|
||||
|
||||
Bool needContinue;
|
||||
|
||||
// CAutoResetEvent finishedEvent;
|
||||
|
||||
SRes readRes;
|
||||
SRes codeRes;
|
||||
|
||||
Bool wasInterrupted;
|
||||
|
||||
unsigned numStartedThreads_Limit;
|
||||
unsigned numStartedThreads;
|
||||
|
||||
Byte *crossBlock;
|
||||
size_t crossStart;
|
||||
size_t crossEnd;
|
||||
UInt64 readProcessed;
|
||||
Bool readWasFinished;
|
||||
UInt64 inProcessed;
|
||||
|
||||
unsigned filledThreadStart;
|
||||
unsigned numFilledThreads;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
Bool needInterrupt;
|
||||
UInt64 interruptIndex;
|
||||
CMtProgress mtProgress;
|
||||
CMtDecThread threads[MTDEC__THREADS_MAX];
|
||||
#endif
|
||||
} CMtDec;
|
||||
|
||||
|
||||
void MtDec_Construct(CMtDec *p);
|
||||
void MtDec_Destruct(CMtDec *p);
|
||||
|
||||
/*
|
||||
MtDec_Code() returns:
|
||||
SZ_OK - in most cases
|
||||
MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function
|
||||
*/
|
||||
|
||||
SRes MtDec_Code(CMtDec *p);
|
||||
Byte *MtDec_GetCrossBuff(CMtDec *p);
|
||||
|
||||
int MtDec_PrepareRead(CMtDec *p);
|
||||
const Byte *MtDec_Read(CMtDec *p, size_t *inLim);
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 7zMain.c - Test application for 7z Decoder
|
||||
2017-08-26 : Igor Pavlov : Public domain */
|
||||
2018-04-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -606,6 +606,31 @@ int MY_CDECL main(int numargs, char *args[])
|
||||
res = SZ_ERROR_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
{
|
||||
FILETIME mtime, ctime;
|
||||
FILETIME *mtimePtr = NULL;
|
||||
FILETIME *ctimePtr = NULL;
|
||||
|
||||
if (SzBitWithVals_Check(&db.MTime, i))
|
||||
{
|
||||
const CNtfsFileTime *t = &db.MTime.Vals[i];
|
||||
mtime.dwLowDateTime = (DWORD)(t->Low);
|
||||
mtime.dwHighDateTime = (DWORD)(t->High);
|
||||
mtimePtr = &mtime;
|
||||
}
|
||||
if (SzBitWithVals_Check(&db.CTime, i))
|
||||
{
|
||||
const CNtfsFileTime *t = &db.CTime.Vals[i];
|
||||
ctime.dwLowDateTime = (DWORD)(t->Low);
|
||||
ctime.dwHighDateTime = (DWORD)(t->High);
|
||||
ctimePtr = &ctime;
|
||||
}
|
||||
if (mtimePtr || ctimePtr)
|
||||
SetFileTime(outFile.handle, ctimePtr, NULL, mtimePtr);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (File_Close(&outFile))
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
PROG = 7zipInstall.exe
|
||||
MY_FIXED = 1
|
||||
|
||||
LIBS = $(LIBS) version.lib
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 7zipUninstall.c - 7-Zip Uninstaller
|
||||
2017-04-04 : Igor Pavlov : Public domain */
|
||||
2018-03-01 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -546,7 +546,7 @@ static BOOL RemoveDir()
|
||||
#define k_Lang L"Lang"
|
||||
|
||||
// NUM_LANG_TXT_FILES files are placed before en.ttt
|
||||
#define NUM_LANG_TXT_FILES 87
|
||||
#define NUM_LANG_TXT_FILES 88
|
||||
|
||||
#ifdef _64BIT_INSTALLER
|
||||
#define NUM_EXTRA_FILES_64BIT 1
|
||||
@@ -558,7 +558,7 @@ static BOOL RemoveDir()
|
||||
|
||||
static const char * const k_Names =
|
||||
"af an ar ast az ba be bg bn br ca co cs cy da de el eo es et eu ext"
|
||||
" fa fi fr fur fy ga gl gu he hi hr hu hy id io is it ja ka kaa kk ko ku ku-ckb ky"
|
||||
" fa fi fr fur fy ga gl gu he hi hr hu hy id io is it ja ka kaa kab kk ko ku ku-ckb ky"
|
||||
" lij lt lv mk mn mng mng2 mr ms nb ne nl nn pa-in pl ps pt pt-br ro ru"
|
||||
" sa si sk sl sq sr-spc sr-spl sv ta th tr tt ug uk uz va vi yo zh-cn zh-tw"
|
||||
" en.ttt"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
PROG = 7zipUninstall.exe
|
||||
MY_FIXED = 1
|
||||
|
||||
!IFDEF _64BIT_INSTALLER
|
||||
CFLAGS = $(CFLAGS) -D_64BIT_INSTALLER
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
PROG = 7zS2.sfx
|
||||
MY_FIXED = 1
|
||||
|
||||
C_OBJS = \
|
||||
$O\7zAlloc.obj \
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
PROG = 7zS2con.sfx
|
||||
MY_FIXED = 1
|
||||
CFLAGS = $(CFLAGS) -D_CONSOLE
|
||||
|
||||
C_OBJS = \
|
||||
|
||||
190
C/Xz.h
190
C/Xz.h
@@ -1,5 +1,5 @@
|
||||
/* Xz.h - Xz interface
|
||||
2017-07-27 : Igor Pavlov : Public domain */
|
||||
2018-02-28 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __XZ_H
|
||||
#define __XZ_H
|
||||
@@ -139,6 +139,9 @@ SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICom
|
||||
UInt64 Xzs_GetNumBlocks(const CXzs *p);
|
||||
UInt64 Xzs_GetUnpackSize(const CXzs *p);
|
||||
|
||||
|
||||
// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||
@@ -147,22 +150,31 @@ typedef enum
|
||||
CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */
|
||||
} ECoderStatus;
|
||||
|
||||
|
||||
// ECoderFinishMode values are identical to ELzmaFinishMode
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CODER_FINISH_ANY, /* finish at any point */
|
||||
CODER_FINISH_END /* block must be finished at the end */
|
||||
} ECoderFinishMode;
|
||||
|
||||
|
||||
typedef struct _IStateCoder
|
||||
{
|
||||
void *p;
|
||||
void (*Free)(void *p, ISzAllocPtr alloc);
|
||||
SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAllocPtr alloc);
|
||||
void (*Init)(void *p);
|
||||
SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished);
|
||||
SRes (*Code2)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
int srcWasFinished, ECoderFinishMode finishMode,
|
||||
// int *wasFinished,
|
||||
ECoderStatus *status);
|
||||
SizeT (*Filter)(void *p, Byte *data, SizeT size);
|
||||
} IStateCoder;
|
||||
|
||||
|
||||
|
||||
#define MIXCODER_NUM_FILTERS_MAX 4
|
||||
|
||||
typedef struct
|
||||
@@ -170,20 +182,23 @@ typedef struct
|
||||
ISzAllocPtr alloc;
|
||||
Byte *buf;
|
||||
unsigned numCoders;
|
||||
|
||||
Byte *outBuf;
|
||||
size_t outBufSize;
|
||||
size_t outWritten; // is equal to lzmaDecoder.dicPos (in outBuf mode)
|
||||
Bool wasFinished;
|
||||
SRes res;
|
||||
ECoderStatus status;
|
||||
// Bool SingleBufMode;
|
||||
|
||||
int finished[MIXCODER_NUM_FILTERS_MAX - 1];
|
||||
size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];
|
||||
size_t size[MIXCODER_NUM_FILTERS_MAX - 1];
|
||||
UInt64 ids[MIXCODER_NUM_FILTERS_MAX];
|
||||
SRes results[MIXCODER_NUM_FILTERS_MAX];
|
||||
IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];
|
||||
} CMixCoder;
|
||||
|
||||
void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc);
|
||||
void MixCoder_Free(CMixCoder *p);
|
||||
void MixCoder_Init(CMixCoder *p);
|
||||
SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId);
|
||||
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, int srcWasFinished,
|
||||
ECoderFinishMode finishMode, ECoderStatus *status);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -197,6 +212,7 @@ typedef enum
|
||||
XZ_STATE_BLOCK_FOOTER
|
||||
} EXzState;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EXzState state;
|
||||
@@ -210,7 +226,7 @@ typedef struct
|
||||
UInt64 packSize;
|
||||
UInt64 unpackSize;
|
||||
|
||||
UInt64 numBlocks;
|
||||
UInt64 numBlocks; // number of finished blocks in current stream
|
||||
UInt64 indexSize;
|
||||
UInt64 indexPos;
|
||||
UInt64 padSize;
|
||||
@@ -225,16 +241,64 @@ typedef struct
|
||||
CXzCheck check;
|
||||
CSha256 sha;
|
||||
|
||||
Bool parseMode;
|
||||
Bool headerParsedOk;
|
||||
Bool decodeToStreamSignature;
|
||||
unsigned decodeOnlyOneBlock;
|
||||
|
||||
Byte *outBuf;
|
||||
size_t outBufSize;
|
||||
size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked
|
||||
|
||||
Byte shaDigest[SHA256_DIGEST_SIZE];
|
||||
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
|
||||
} CXzUnpacker;
|
||||
|
||||
/* alloc : aligned for cache line allocation is better */
|
||||
void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc);
|
||||
void XzUnpacker_Init(CXzUnpacker *p);
|
||||
void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize);
|
||||
void XzUnpacker_Free(CXzUnpacker *p);
|
||||
|
||||
/*
|
||||
XzUnpacker
|
||||
The sequence for decoding functions:
|
||||
{
|
||||
XzUnpacker_Construct()
|
||||
[Decoding_Calls]
|
||||
XzUnpacker_Free()
|
||||
}
|
||||
|
||||
[Decoding_Calls]
|
||||
|
||||
There are 3 types of interfaces for [Decoding_Calls] calls:
|
||||
|
||||
Interface-1 : Partial output buffers:
|
||||
{
|
||||
XzUnpacker_Init()
|
||||
for()
|
||||
XzUnpacker_Code();
|
||||
}
|
||||
|
||||
Interface-2 : Direct output buffer:
|
||||
Use it, if you know exact size of decoded data, and you need
|
||||
whole xz unpacked data in one output buffer.
|
||||
xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode.
|
||||
{
|
||||
XzUnpacker_Init()
|
||||
XzUnpacker_SetOutBufMode(); // to set output buffer and size
|
||||
for()
|
||||
XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code()
|
||||
}
|
||||
|
||||
Interface-3 : Direct output buffer : One call full decoding
|
||||
It unpacks whole input buffer to output buffer in one call.
|
||||
It uses Interface-2 internally.
|
||||
{
|
||||
XzUnpacker_CodeFull()
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
@@ -264,15 +328,23 @@ Returns:
|
||||
|
||||
|
||||
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode,
|
||||
ECoderStatus *status);
|
||||
const Byte *src, SizeT *srcLen, int srcFinished,
|
||||
ECoderFinishMode finishMode, ECoderStatus *status);
|
||||
|
||||
SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen,
|
||||
ECoderFinishMode finishMode, ECoderStatus *status);
|
||||
|
||||
Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p);
|
||||
|
||||
/*
|
||||
Call XzUnpacker_GetExtraSize after XzUnpacker_Code function to detect real size of
|
||||
xz stream in two cases:
|
||||
XzUnpacker_Code() returns:
|
||||
XzUnpacker_GetExtraSize() returns then number of uncofirmed bytes,
|
||||
if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state.
|
||||
These bytes can be some bytes after xz archive, or
|
||||
it can be start of new xz stream.
|
||||
|
||||
Call XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of
|
||||
xz stream in two cases, if XzUnpacker_Code() returns:
|
||||
res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT
|
||||
res == SZ_ERROR_NO_ARCHIVE
|
||||
*/
|
||||
@@ -297,6 +369,92 @@ Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p);
|
||||
|
||||
#define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags))
|
||||
|
||||
|
||||
|
||||
/* ---------- Multi Threading Decoding ---------- */
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t inBufSize_ST;
|
||||
size_t outStep_ST;
|
||||
Bool ignoreErrors;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
unsigned numThreads;
|
||||
size_t inBufSize_MT;
|
||||
size_t memUseMax;
|
||||
#endif
|
||||
} CXzDecMtProps;
|
||||
|
||||
void XzDecMtProps_Init(CXzDecMtProps *p);
|
||||
|
||||
|
||||
typedef void * CXzDecMtHandle;
|
||||
|
||||
/*
|
||||
alloc : XzDecMt uses CAlignOffsetAlloc for addresses allocated by (alloc).
|
||||
allocMid : for big allocations, aligned allocation is better
|
||||
*/
|
||||
|
||||
CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);
|
||||
void XzDecMt_Destroy(CXzDecMtHandle p);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte UnpackSize_Defined;
|
||||
Byte NumStreams_Defined;
|
||||
Byte NumBlocks_Defined;
|
||||
|
||||
Byte DataAfterEnd;
|
||||
Byte DecodingTruncated; // Decoding was Truncated, we need only partial output data
|
||||
|
||||
UInt64 InSize; // pack size processed
|
||||
UInt64 OutSize;
|
||||
|
||||
UInt64 NumStreams;
|
||||
UInt64 NumBlocks;
|
||||
|
||||
SRes DecodeRes;
|
||||
SRes ReadRes;
|
||||
SRes ProgressRes;
|
||||
SRes CombinedRes;
|
||||
SRes CombinedRes_Type;
|
||||
|
||||
} CXzStatInfo;
|
||||
|
||||
void XzStatInfo_Clear(CXzStatInfo *p);
|
||||
|
||||
/*
|
||||
XzDecMt_Decode()
|
||||
SRes:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_NO_ARCHIVE - is not xz archive
|
||||
SZ_ERROR_ARCHIVE - Headers error
|
||||
SZ_ERROR_DATA - Data Error
|
||||
SZ_ERROR_CRC - CRC Error
|
||||
SZ_ERROR_INPUT_EOF - it needs more input data
|
||||
SZ_ERROR_WRITE - ISeqOutStream error
|
||||
(SZ_ERROR_READ) - ISeqInStream errors
|
||||
(SZ_ERROR_PROGRESS) - ICompressProgress errors
|
||||
// SZ_ERROR_THREAD - error in multi-threading functions
|
||||
MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function
|
||||
*/
|
||||
|
||||
SRes XzDecMt_Decode(CXzDecMtHandle p,
|
||||
const CXzDecMtProps *props,
|
||||
const UInt64 *outDataSize, // NULL means undefined
|
||||
int finishMode, // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished
|
||||
ISeqOutStream *outStream,
|
||||
// Byte *outBuf, size_t *outBufSize,
|
||||
ISeqInStream *inStream,
|
||||
// const Byte *inData, size_t inDataSize,
|
||||
CXzStatInfo *stat,
|
||||
int *isMT, // 0 means that ST (Single-Thread) version was used
|
||||
ICompressProgress *progress);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
31
C/XzEnc.c
31
C/XzEnc.c
@@ -1,5 +1,5 @@
|
||||
/* XzEnc.c -- Xz Encode
|
||||
2017-08-25 : Igor Pavlov : Public domain */
|
||||
2018-04-28 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -136,7 +136,7 @@ static void XzEncIndex_Free(CXzEncIndex *p, ISzAllocPtr alloc)
|
||||
|
||||
static SRes XzEncIndex_ReAlloc(CXzEncIndex *p, size_t newSize, ISzAllocPtr alloc)
|
||||
{
|
||||
Byte *blocks = ISzAlloc_Alloc(alloc, newSize);
|
||||
Byte *blocks = (Byte *)ISzAlloc_Alloc(alloc, newSize);
|
||||
if (!blocks)
|
||||
return SZ_ERROR_MEM;
|
||||
if (p->size != 0)
|
||||
@@ -329,7 +329,7 @@ static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props, ISzAllocPt
|
||||
{
|
||||
if (!p->buf)
|
||||
{
|
||||
p->buf = ISzAlloc_Alloc(alloc, FILTER_BUF_SIZE);
|
||||
p->buf = (Byte *)ISzAlloc_Alloc(alloc, FILTER_BUF_SIZE);
|
||||
if (!p->buf)
|
||||
return SZ_ERROR_MEM;
|
||||
}
|
||||
@@ -362,13 +362,16 @@ static SRes SeqInFilter_Read(const ISeqInStream *pp, void *data, size_t *size)
|
||||
}
|
||||
{
|
||||
SizeT srcLen = p->endPos - p->curPos;
|
||||
int wasFinished;
|
||||
ECoderStatus status;
|
||||
SRes res;
|
||||
*size = sizeOriginal;
|
||||
res = p->StateCoder.Code(p->StateCoder.p, data, size, p->buf + p->curPos, &srcLen,
|
||||
p->srcWasFinished, CODER_FINISH_ANY, &wasFinished);
|
||||
res = p->StateCoder.Code2(p->StateCoder.p,
|
||||
data, size,
|
||||
p->buf + p->curPos, &srcLen,
|
||||
p->srcWasFinished, CODER_FINISH_ANY,
|
||||
&status);
|
||||
p->curPos += srcLen;
|
||||
if (*size != 0 || srcLen == 0 || res != 0)
|
||||
if (*size != 0 || srcLen == 0 || res != SZ_OK)
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -377,11 +380,17 @@ static SRes SeqInFilter_Read(const ISeqInStream *pp, void *data, size_t *size)
|
||||
static void SeqInFilter_Construct(CSeqInFilter *p)
|
||||
{
|
||||
p->buf = NULL;
|
||||
p->StateCoder.p = NULL;
|
||||
p->p.Read = SeqInFilter_Read;
|
||||
}
|
||||
|
||||
static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc)
|
||||
{
|
||||
if (p->StateCoder.p)
|
||||
{
|
||||
p->StateCoder.Free(p->StateCoder.p, alloc);
|
||||
p->StateCoder.p = NULL;
|
||||
}
|
||||
if (p->buf)
|
||||
{
|
||||
ISzAlloc_Free(alloc, p->buf);
|
||||
@@ -1055,7 +1064,7 @@ static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBuf
|
||||
|
||||
if (!dest)
|
||||
{
|
||||
dest = ISzAlloc_Alloc(me->alloc, me->outBufSize);
|
||||
dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
|
||||
if (!dest)
|
||||
return SZ_ERROR_MEM;
|
||||
me->outBufs[outBufIndex] = dest;
|
||||
@@ -1063,7 +1072,7 @@ static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBuf
|
||||
|
||||
MtProgressThunk_CreateVTable(&progressThunk);
|
||||
progressThunk.mtProgress = &me->mtCoder.mtProgress;
|
||||
progressThunk.index = coderIndex;
|
||||
MtProgressThunk_Init(&progressThunk);
|
||||
|
||||
{
|
||||
CXzEncBlockInfo blockSizes;
|
||||
@@ -1224,7 +1233,7 @@ SRes XzEnc_Encode(CXzEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStr
|
||||
if (!p->outBufs[0] || t2 != p->outBufSize)
|
||||
{
|
||||
XzEnc_FreeOutBufs(p);
|
||||
p->outBufs[0] = ISzAlloc_Alloc(p->alloc, t2);
|
||||
p->outBufs[0] = (Byte *)ISzAlloc_Alloc(p->alloc, t2);
|
||||
if (!p->outBufs[0])
|
||||
return SZ_ERROR_MEM;
|
||||
p->outBufSize = t2;
|
||||
@@ -1245,6 +1254,8 @@ SRes XzEnc_Encode(CXzEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStr
|
||||
&& props->reduceSize >= progress2.inOffset)
|
||||
rem = props->reduceSize - progress2.inOffset;
|
||||
*/
|
||||
|
||||
blockSizes.headerSize = 0; // for GCC
|
||||
|
||||
RINOK(Xz_CompressBlock(
|
||||
&p->lzmaf_Items[0],
|
||||
|
||||
6
C/XzIn.c
6
C/XzIn.c
@@ -1,5 +1,5 @@
|
||||
/* XzIn.c - Xz input
|
||||
2017-05-11 : Igor Pavlov : Public domain */
|
||||
2018-02-02 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -103,7 +103,7 @@ static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAllocPt
|
||||
{
|
||||
size_t i;
|
||||
p->numBlocks = numBlocks;
|
||||
p->blocks = ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
|
||||
p->blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
|
||||
if (!p->blocks)
|
||||
return SZ_ERROR_MEM;
|
||||
for (i = 0; i < numBlocks; i++)
|
||||
@@ -131,7 +131,7 @@ static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize,
|
||||
size = (size_t)indexSize;
|
||||
if (size != indexSize)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
buf = ISzAlloc_Alloc(alloc, size);
|
||||
buf = (Byte *)ISzAlloc_Alloc(alloc, size);
|
||||
if (!buf)
|
||||
return SZ_ERROR_MEM;
|
||||
res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);
|
||||
|
||||
Reference in New Issue
Block a user