mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 15:14:59 -06:00
Update to 7-Zip Version 18.05
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
; 7zAsm.asm -- ASM macros
|
||||
; 2012-12-30 : Igor Pavlov : Public domain
|
||||
; 2018-02-03 : Igor Pavlov : Public domain
|
||||
|
||||
MY_ASM_START macro
|
||||
ifdef x64
|
||||
@@ -52,6 +52,15 @@ endif
|
||||
x6 equ ESI
|
||||
x7 equ EDI
|
||||
|
||||
x0_W equ AX
|
||||
x1_W equ CX
|
||||
x2_W equ DX
|
||||
x3_W equ BX
|
||||
|
||||
x5_W equ BP
|
||||
x6_W equ SI
|
||||
x7_W equ DI
|
||||
|
||||
x0_L equ AL
|
||||
x1_L equ CL
|
||||
x2_L equ DL
|
||||
@@ -63,6 +72,10 @@ endif
|
||||
x3_H equ BH
|
||||
|
||||
ifdef x64
|
||||
x5_L equ BPL
|
||||
x6_L equ SIL
|
||||
x7_L equ DIL
|
||||
|
||||
r0 equ RAX
|
||||
r1 equ RCX
|
||||
r2 equ RDX
|
||||
@@ -103,3 +116,32 @@ MY_POP_4_REGS macro
|
||||
pop r5
|
||||
pop r3
|
||||
endm
|
||||
|
||||
|
||||
ifdef x64
|
||||
|
||||
; for WIN64-x64 ABI:
|
||||
|
||||
REG_PARAM_0 equ r1
|
||||
REG_PARAM_1 equ r2
|
||||
REG_PARAM_2 equ r8
|
||||
REG_PARAM_3 equ r9
|
||||
|
||||
MY_PUSH_PRESERVED_REGS macro
|
||||
MY_PUSH_4_REGS
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
endm
|
||||
|
||||
|
||||
MY_POP_PRESERVED_REGS macro
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
MY_POP_4_REGS
|
||||
endm
|
||||
|
||||
endif
|
||||
|
||||
1258
Asm/x86/LzmaDecOpt.asm
Normal file
1258
Asm/x86/LzmaDecOpt.asm
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -13,7 +13,9 @@ struct CMethodFull: public CMethodProps
|
||||
{
|
||||
CMethodId Id;
|
||||
UInt32 NumStreams;
|
||||
int CodecIndex;
|
||||
|
||||
CMethodFull(): CodecIndex(-1) {}
|
||||
bool IsSimpleCoder() const { return NumStreams == 1; }
|
||||
};
|
||||
|
||||
|
||||
@@ -236,8 +236,8 @@ HRESULT CDecoder::Decode(
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, bool mtMode, UInt32 numThreads
|
||||
#if !defined(_7ZIP_ST)
|
||||
, bool mtMode, UInt32 numThreads, UInt64 memUsage
|
||||
#endif
|
||||
)
|
||||
{
|
||||
@@ -312,7 +312,7 @@ HRESULT CDecoder::Decode(
|
||||
#endif
|
||||
|
||||
CCreatedCoder cod;
|
||||
RINOK(CreateCoder(
|
||||
RINOK(CreateCoder_Id(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
coderInfo.MethodID, false, cod));
|
||||
|
||||
@@ -355,11 +355,39 @@ HRESULT CDecoder::Decode(
|
||||
|
||||
unsigned i;
|
||||
|
||||
bool mt_wasUsed = false;
|
||||
|
||||
for (i = 0; i < folderInfo.Coders.Size(); i++)
|
||||
{
|
||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
||||
IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
|
||||
|
||||
#if !defined(_7ZIP_ST)
|
||||
if (!mt_wasUsed)
|
||||
{
|
||||
if (mtMode)
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
||||
decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
|
||||
if (setCoderMt)
|
||||
{
|
||||
mt_wasUsed = true;
|
||||
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
|
||||
}
|
||||
}
|
||||
// if (memUsage != 0)
|
||||
{
|
||||
CMyComPtr<ICompressSetMemLimit> setMemLimit;
|
||||
decoder->QueryInterface(IID_ICompressSetMemLimit, (void **)&setMemLimit);
|
||||
if (setMemLimit)
|
||||
{
|
||||
mt_wasUsed = true;
|
||||
RINOK(setMemLimit->SetMemLimit(memUsage));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
|
||||
decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
|
||||
@@ -376,18 +404,6 @@ HRESULT CDecoder::Decode(
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
if (mtMode)
|
||||
{
|
||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
||||
decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
|
||||
if (setCoderMt)
|
||||
{
|
||||
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
{
|
||||
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
|
||||
|
||||
@@ -59,8 +59,8 @@ public:
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, bool mtMode, UInt32 numThreads
|
||||
#if !defined(_7ZIP_ST)
|
||||
, bool mtMode, UInt32 numThreads, UInt64 memUsage
|
||||
#endif
|
||||
);
|
||||
};
|
||||
|
||||
@@ -154,9 +154,18 @@ HRESULT CEncoder::CreateMixerCoder(
|
||||
|
||||
CCreatedCoder cod;
|
||||
|
||||
RINOK(CreateCoder(
|
||||
if (methodFull.CodecIndex >= 0)
|
||||
{
|
||||
RINOK(CreateCoder_Index(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodFull.CodecIndex, true, cod));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(CreateCoder_Id(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodFull.Id, true, cod));
|
||||
}
|
||||
|
||||
if (cod.NumStreams != methodFull.NumStreams)
|
||||
return E_FAIL;
|
||||
|
||||
@@ -152,6 +152,12 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
|
||||
if (_fileIsOpen)
|
||||
{
|
||||
UInt32 cur = (size < _rem ? size : (UInt32)_rem);
|
||||
if (_calcCrc)
|
||||
{
|
||||
const UInt32 k_Step = (UInt32)1 << 20;
|
||||
if (cur > k_Step)
|
||||
cur = k_Step;
|
||||
}
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Write(data, cur, &cur);
|
||||
@@ -363,8 +369,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
, dataAfterEnd_Error
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, true, _numThreads
|
||||
#if !defined(_7ZIP_ST)
|
||||
, true, _numThreads, _memUsage
|
||||
#endif
|
||||
);
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ CHandler::CHandler()
|
||||
_crcSize = 4;
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
_numThreads = NSystem::GetNumberOfProcessors();
|
||||
_useMultiThreadMixer = true;
|
||||
#endif
|
||||
|
||||
@@ -823,8 +822,8 @@ STDMETHODIMP CHandler::Close()
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
|
||||
_numThreads = numProcessors;
|
||||
|
||||
InitCommon();
|
||||
_useMultiThreadMixer = true;
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
@@ -843,13 +842,15 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
|
||||
RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
|
||||
continue;
|
||||
}
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
|
||||
continue;
|
||||
HRESULT hres;
|
||||
if (SetCommonProperty(name, value, hres))
|
||||
{
|
||||
RINOK(hres);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
|
||||
@@ -8,16 +8,6 @@
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
#include "../Common/HandlerOut.h"
|
||||
#endif
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
#include "7zIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
#ifndef __7Z_SET_PROPERTIES
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
@@ -30,6 +20,16 @@ namespace N7z {
|
||||
|
||||
#endif
|
||||
|
||||
// #ifdef __7Z_SET_PROPERTIES
|
||||
#include "../Common/HandlerOut.h"
|
||||
// #endif
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
#include "7zIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
@@ -38,8 +38,6 @@ class COutHandler: public CMultiMethodProps
|
||||
HRESULT SetSolidFromString(const UString &s);
|
||||
HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
|
||||
public:
|
||||
bool _removeSfxBlock;
|
||||
|
||||
UInt64 _numSolidFiles;
|
||||
UInt64 _numSolidBytes;
|
||||
bool _numSolidBytesDefined;
|
||||
@@ -58,6 +56,8 @@ public:
|
||||
|
||||
bool _useMultiThreadMixer;
|
||||
|
||||
bool _removeSfxBlock;
|
||||
|
||||
// bool _volumeMode;
|
||||
|
||||
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
|
||||
@@ -70,9 +70,10 @@ public:
|
||||
_numSolidBytesDefined = false;
|
||||
}
|
||||
|
||||
void InitProps7z();
|
||||
void InitProps();
|
||||
|
||||
COutHandler() { InitProps(); }
|
||||
COutHandler() { InitProps7z(); }
|
||||
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
};
|
||||
@@ -82,16 +83,23 @@ public:
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveGetRawProps,
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
public ISetProperties,
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
public IOutArchive,
|
||||
#endif
|
||||
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
public CMyUnknownImp
|
||||
|
||||
public CMyUnknownImp,
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
, public COutHandler
|
||||
public COutHandler
|
||||
#else
|
||||
public CCommonMethodProps
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
@@ -135,7 +143,6 @@ private:
|
||||
#ifdef EXTRACT_ONLY
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
UInt32 _numThreads;
|
||||
bool _useMultiThreadMixer;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "7zOut.h"
|
||||
#include "7zUpdate.h"
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
namespace NArchive {
|
||||
@@ -41,9 +43,11 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
||||
|
||||
HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)
|
||||
{
|
||||
if (!FindMethod(
|
||||
dest.CodecIndex = FindMethod_Index(
|
||||
EXTERNAL_CODECS_VARS
|
||||
m.MethodName, dest.Id, dest.NumStreams))
|
||||
m.MethodName, true,
|
||||
dest.Id, dest.NumStreams);
|
||||
if (dest.CodecIndex < 0)
|
||||
return E_INVALIDARG;
|
||||
(CProps &)dest = (CProps &)m;
|
||||
return S_OK;
|
||||
@@ -700,10 +704,8 @@ static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void COutHandler::InitProps()
|
||||
void COutHandler::InitProps7z()
|
||||
{
|
||||
CMultiMethodProps::Init();
|
||||
|
||||
_removeSfxBlock = false;
|
||||
_compressHeaders = true;
|
||||
_encryptHeadersSpecified = false;
|
||||
@@ -723,6 +725,14 @@ void COutHandler::InitProps()
|
||||
_useTypeSorting = false;
|
||||
}
|
||||
|
||||
void COutHandler::InitProps()
|
||||
{
|
||||
CMultiMethodProps::Init();
|
||||
InitProps7z();
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT COutHandler::SetSolidFromString(const UString &s)
|
||||
{
|
||||
UString s2 = s;
|
||||
@@ -763,6 +773,10 @@ HRESULT COutHandler::SetSolidFromString(const UString &s)
|
||||
}
|
||||
_numSolidBytes = (v << numBits);
|
||||
_numSolidBytesDefined = true;
|
||||
/*
|
||||
if (_numSolidBytes == 0)
|
||||
_numSolidFiles = 1;
|
||||
*/
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
@@ -811,7 +825,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
|
||||
return E_INVALIDARG;
|
||||
return SetSolidFromString(name);
|
||||
}
|
||||
|
||||
|
||||
UInt32 number;
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
// UString realName = name.Ptr(index);
|
||||
@@ -922,3 +936,5 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1115,11 +1115,11 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
|
||||
, dataAfterEnd_Error
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
#if !defined(_7ZIP_ST)
|
||||
, false // mtMode
|
||||
, 1 // numThreads
|
||||
, 0 // memUsage
|
||||
#endif
|
||||
|
||||
);
|
||||
|
||||
RINOK(result);
|
||||
|
||||
@@ -1507,7 +1507,8 @@ void CThreadDecoder::Execute()
|
||||
|
||||
_7Z_DECODER_CRYPRO_VARS
|
||||
#ifndef _7ZIP_ST
|
||||
, MtMode, NumThreads
|
||||
, MtMode, NumThreads,
|
||||
0 // MemUsage
|
||||
#endif
|
||||
|
||||
);
|
||||
@@ -1696,13 +1697,14 @@ HRESULT Update(
|
||||
|
||||
UInt64 inSizeForReduce = 0;
|
||||
{
|
||||
bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0);
|
||||
FOR_VECTOR (i, updateItems)
|
||||
{
|
||||
const CUpdateItem &ui = updateItems[i];
|
||||
if (ui.NewData)
|
||||
{
|
||||
complexity += ui.Size;
|
||||
if (numSolidFiles != 1)
|
||||
if (isSolid)
|
||||
inSizeForReduce += ui.Size;
|
||||
else if (inSizeForReduce < ui.Size)
|
||||
inSizeForReduce = ui.Size;
|
||||
@@ -2142,8 +2144,8 @@ HRESULT Update(
|
||||
#ifndef _7ZIP_ST
|
||||
, false // mtMode
|
||||
, 1 // numThreads
|
||||
, 0 // memUsage
|
||||
#endif
|
||||
|
||||
);
|
||||
|
||||
RINOK(res);
|
||||
@@ -2293,7 +2295,8 @@ HRESULT Update(
|
||||
continue;
|
||||
CRecordVector<CRefItem> refItems;
|
||||
refItems.ClearAndSetSize(numFiles);
|
||||
bool sortByType = (options.UseTypeSorting && numSolidFiles > 1);
|
||||
// bool sortByType = (options.UseTypeSorting && isSoid); // numSolidFiles > 1
|
||||
bool sortByType = options.UseTypeSorting;
|
||||
|
||||
unsigned i;
|
||||
|
||||
|
||||
@@ -549,9 +549,9 @@ private:
|
||||
|
||||
Byte *TempBuf;
|
||||
UInt32 TempBufSize;
|
||||
UInt32 TempBufWritten;
|
||||
unsigned NumIdenticalFiles;
|
||||
bool TempBufMode;
|
||||
UInt32 m_BufStartFolderOffset;
|
||||
|
||||
unsigned m_StartIndex;
|
||||
unsigned m_CurrentIndex;
|
||||
@@ -575,7 +575,6 @@ private:
|
||||
HRESULT OpenFile();
|
||||
HRESULT CloseFileWithResOp(Int32 resOp);
|
||||
HRESULT CloseFile();
|
||||
HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);
|
||||
public:
|
||||
HRESULT WriteEmptyFiles();
|
||||
|
||||
@@ -672,11 +671,11 @@ HRESULT CFolderOutStream::OpenFile()
|
||||
FreeTempBuf();
|
||||
TempBuf = (Byte *)MyAlloc(item.Size);
|
||||
TempBufSize = item.Size;
|
||||
if (TempBuf == NULL)
|
||||
if (!TempBuf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
TempBufMode = true;
|
||||
m_BufStartFolderOffset = item.Offset;
|
||||
TempBufWritten = 0;
|
||||
}
|
||||
else if (numExtractItems == 1)
|
||||
{
|
||||
@@ -725,8 +724,9 @@ HRESULT CFolderOutStream::WriteEmptyFiles()
|
||||
}
|
||||
|
||||
|
||||
HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
|
||||
HRESULT CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
// (data == NULL) means Error_Data for solid folder flushing
|
||||
COM_TRY_BEGIN
|
||||
|
||||
UInt32 realProcessed = 0;
|
||||
@@ -741,21 +741,34 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
HRESULT res = S_OK;
|
||||
if (numBytesToWrite != 0)
|
||||
{
|
||||
if (!isOK)
|
||||
if (!data)
|
||||
m_IsOk = false;
|
||||
|
||||
if (m_RealOutStream)
|
||||
{
|
||||
UInt32 processedSizeLocal = 0;
|
||||
res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
|
||||
// 18.01 : we don't want ZEROs instead of missing data
|
||||
if (data)
|
||||
res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
|
||||
else
|
||||
processedSizeLocal = numBytesToWrite;
|
||||
numBytesToWrite = processedSizeLocal;
|
||||
}
|
||||
|
||||
if (TempBufMode && TempBuf)
|
||||
memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite);
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
memcpy(TempBuf + TempBufWritten, data, numBytesToWrite);
|
||||
TempBufWritten += numBytesToWrite;
|
||||
}
|
||||
}
|
||||
}
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
if (data)
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
m_RemainFileSize -= numBytesToWrite;
|
||||
m_PosInFolder += numBytesToWrite;
|
||||
@@ -773,7 +786,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
m_FileIsOpen = true;
|
||||
m_CurrentIndex++;
|
||||
if (result == S_OK && m_RealOutStream && TempBuf)
|
||||
result = WriteStream(m_RealOutStream, TempBuf, (size_t)(m_PosInFolder - m_BufStartFolderOffset));
|
||||
result = WriteStream(m_RealOutStream, TempBuf, TempBufWritten);
|
||||
|
||||
if (!TempBuf && TempBufMode && m_RealOutStream)
|
||||
{
|
||||
@@ -822,7 +835,8 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
if (data)
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
m_PosInFolder += numBytesToWrite;
|
||||
}
|
||||
@@ -843,12 +857,6 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write2(data, size, processedSize, true);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CFolderOutStream::FlushCorrupted(unsigned folderIndex)
|
||||
{
|
||||
if (!NeedMoreWrite())
|
||||
@@ -862,19 +870,16 @@ HRESULT CFolderOutStream::FlushCorrupted(unsigned folderIndex)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const unsigned kBufSize = (1 << 12);
|
||||
Byte buf[kBufSize];
|
||||
for (unsigned i = 0; i < kBufSize; i++)
|
||||
buf[i] = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!NeedMoreWrite())
|
||||
return S_OK;
|
||||
UInt64 remain = GetRemain();
|
||||
UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize);
|
||||
UInt32 size = (UInt32)1 << 20;
|
||||
if (size > remain)
|
||||
size = (UInt32)remain;
|
||||
UInt32 processedSizeLocal = 0;
|
||||
RINOK(Write2(buf, size, &processedSizeLocal, false));
|
||||
RINOK(Write(NULL, size, &processedSizeLocal));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,18 +2,92 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "../../../Windows/System.h"
|
||||
#endif
|
||||
#include "../../../Common/StringToInt.h"
|
||||
|
||||
#include "../Common/ParseProperties.h"
|
||||
|
||||
#include "HandlerOut.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res)
|
||||
{
|
||||
if (*s == 0)
|
||||
{
|
||||
switch (prop.vt)
|
||||
{
|
||||
case VT_UI4: res = prop.ulVal; return true;
|
||||
case VT_UI8: res = prop.uhVal.QuadPart; return true;
|
||||
case VT_BSTR:
|
||||
s = prop.bstrVal;
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return false;
|
||||
|
||||
const wchar_t *end;
|
||||
UInt64 v = ConvertStringToUInt64(s, &end);
|
||||
if (s == end)
|
||||
return false;
|
||||
wchar_t c = *end;
|
||||
if (c == 0)
|
||||
{
|
||||
res = v;
|
||||
return true;
|
||||
}
|
||||
if (end[1] != 0)
|
||||
return false;
|
||||
|
||||
if (c == '%')
|
||||
{
|
||||
res = percentsBase / 100 * v;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned numBits;
|
||||
switch (MyCharLower_Ascii(c))
|
||||
{
|
||||
case 'b': numBits = 0; break;
|
||||
case 'k': numBits = 10; break;
|
||||
case 'm': numBits = 20; break;
|
||||
case 'g': numBits = 30; break;
|
||||
case 't': numBits = 40; break;
|
||||
default: return false;
|
||||
}
|
||||
UInt64 val2 = v << numBits;
|
||||
if ((val2 >> numBits) != v)
|
||||
return false;
|
||||
res = val2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres)
|
||||
{
|
||||
hres = S_OK;
|
||||
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
hres = ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
|
||||
{
|
||||
if (!ParseSizeString(name.Ptr(6), value, _memAvail, _memUsage))
|
||||
hres = E_INVALIDARG;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
|
||||
{
|
||||
if (m.FindProp(propID) < 0)
|
||||
@@ -34,21 +108,23 @@ void CMultiMethodProps::SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32
|
||||
}
|
||||
#endif
|
||||
|
||||
void CMultiMethodProps::Init()
|
||||
void CMultiMethodProps::InitMulti()
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
_numProcessors = _numThreads = NSystem::GetNumberOfProcessors();
|
||||
#endif
|
||||
|
||||
_level = (UInt32)(Int32)-1;
|
||||
_analysisLevel = -1;
|
||||
|
||||
_autoFilter = true;
|
||||
_crcSize = 4;
|
||||
_filterMethod.Clear();
|
||||
_methods.Clear();
|
||||
_autoFilter = true;
|
||||
}
|
||||
|
||||
void CMultiMethodProps::Init()
|
||||
{
|
||||
InitCommon();
|
||||
InitMulti();
|
||||
_methods.Clear();
|
||||
_filterMethod.Clear();
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
|
||||
{
|
||||
UString name = nameSpec;
|
||||
@@ -78,20 +154,18 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
|
||||
_crcSize = 4;
|
||||
return ParsePropToUInt32(name, value, _crcSize);
|
||||
}
|
||||
|
||||
{
|
||||
HRESULT hres;
|
||||
if (SetCommonProperty(name, value, hres))
|
||||
return hres;
|
||||
}
|
||||
|
||||
UInt32 number;
|
||||
unsigned index = ParseStringToUInt32(name, number);
|
||||
UString realName = name.Ptr(index);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
|
||||
#endif
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
if (name.IsEqualTo("f"))
|
||||
{
|
||||
HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
|
||||
@@ -110,20 +184,20 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
|
||||
return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CSingleMethodProps::Init()
|
||||
{
|
||||
InitCommon();
|
||||
InitSingle();
|
||||
Clear();
|
||||
_level = (UInt32)(Int32)-1;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
_numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
|
||||
AddProp_NumThreads(_numThreads);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
Init();
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
UString name = names[i];
|
||||
@@ -137,20 +211,22 @@ HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PR
|
||||
RINOK(ParsePropToUInt32(name.Ptr(1), value, a));
|
||||
_level = a;
|
||||
AddProp_Level(a);
|
||||
continue;
|
||||
}
|
||||
else if (name.IsPrefixedBy_Ascii_NoCase("mt"))
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
|
||||
AddProp_NumThreads(_numThreads);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(ParseMethodFromPROPVARIANT(names[i], value));
|
||||
HRESULT hres;
|
||||
if (SetCommonProperty(name, value, hres))
|
||||
{
|
||||
RINOK(hres)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
RINOK(ParseMethodFromPROPVARIANT(names[i], value));
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -3,20 +3,57 @@
|
||||
#ifndef __HANDLER_OUT_H
|
||||
#define __HANDLER_OUT_H
|
||||
|
||||
#include "../../../Windows/System.h"
|
||||
|
||||
#include "../../Common/MethodProps.h"
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
class CMultiMethodProps
|
||||
bool ParseSizeString(const wchar_t *name, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res);
|
||||
|
||||
class CCommonMethodProps
|
||||
{
|
||||
UInt32 _level;
|
||||
int _analysisLevel;
|
||||
protected:
|
||||
void InitCommon()
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
_numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
|
||||
#endif
|
||||
|
||||
UInt64 memAvail = (UInt64)(sizeof(size_t)) << 28;
|
||||
_memAvail = memAvail;
|
||||
_memUsage = memAvail;
|
||||
if (NWindows::NSystem::GetRamSize(memAvail))
|
||||
{
|
||||
_memAvail = memAvail;
|
||||
_memUsage = memAvail / 32 * 17;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
#ifndef _7ZIP_ST
|
||||
UInt32 _numThreads;
|
||||
UInt32 _numProcessors;
|
||||
#endif
|
||||
|
||||
UInt64 _memUsage;
|
||||
UInt64 _memAvail;
|
||||
|
||||
bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres);
|
||||
|
||||
CCommonMethodProps() { InitCommon(); }
|
||||
};
|
||||
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
class CMultiMethodProps: public CCommonMethodProps
|
||||
{
|
||||
UInt32 _level;
|
||||
int _analysisLevel;
|
||||
|
||||
void InitMulti();
|
||||
public:
|
||||
UInt32 _crcSize;
|
||||
CObjectVector<COneMethodInfo> _methods;
|
||||
COneMethodInfo _filterMethod;
|
||||
@@ -43,27 +80,31 @@ public:
|
||||
int GetAnalysisLevel() const { return _analysisLevel; }
|
||||
|
||||
void Init();
|
||||
CMultiMethodProps() { InitMulti(); }
|
||||
|
||||
CMultiMethodProps() { Init(); }
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
};
|
||||
|
||||
class CSingleMethodProps: public COneMethodInfo
|
||||
|
||||
class CSingleMethodProps: public COneMethodInfo, public CCommonMethodProps
|
||||
{
|
||||
UInt32 _level;
|
||||
|
||||
public:
|
||||
#ifndef _7ZIP_ST
|
||||
UInt32 _numThreads;
|
||||
UInt32 _numProcessors;
|
||||
#endif
|
||||
|
||||
void InitSingle()
|
||||
{
|
||||
_level = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
public:
|
||||
void Init();
|
||||
CSingleMethodProps() { Init(); }
|
||||
CSingleMethodProps() { InitSingle(); }
|
||||
|
||||
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
|
||||
HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "../Compress/BZip2Decoder.h"
|
||||
#include "../Compress/CopyCoder.h"
|
||||
#include "../Compress/LzfseDecoder.h"
|
||||
#include "../Compress/ZlibDecoder.h"
|
||||
|
||||
#include "Common/OutStreamWithCRC.h"
|
||||
@@ -121,6 +122,7 @@ enum
|
||||
METHOD_ADC = 0x80000004,
|
||||
METHOD_ZLIB = 0x80000005,
|
||||
METHOD_BZIP2 = 0x80000006,
|
||||
METHOD_LZFSE = 0x80000007,
|
||||
METHOD_COMMENT = 0x7FFFFFFE, // is used to comment "+beg" and "+end" in extra field.
|
||||
METHOD_END = 0xFFFFFFFF
|
||||
};
|
||||
@@ -217,6 +219,7 @@ class CHandler:
|
||||
bool _masterCrcError;
|
||||
bool _headersError;
|
||||
|
||||
UInt32 _dataStartOffset;
|
||||
UInt64 _startPos;
|
||||
UInt64 _phySize;
|
||||
|
||||
@@ -276,6 +279,7 @@ void CMethods::GetString(AString &res) const
|
||||
case METHOD_ADC: s = "ADC"; break;
|
||||
case METHOD_ZLIB: s = "ZLIB"; break;
|
||||
case METHOD_BZIP2: s = "BZip2"; break;
|
||||
case METHOD_LZFSE: s = "LZFSE"; break;
|
||||
default: ConvertUInt32ToString(type, buf); s = buf;
|
||||
}
|
||||
res.Add_OptSpaced(s);
|
||||
@@ -307,6 +311,10 @@ static const CAppleName k_Names[] =
|
||||
{ true, "hfs", "Apple_HFS" },
|
||||
{ true, "hfsx", "Apple_HFSX" },
|
||||
{ true, "ufs", "Apple_UFS" },
|
||||
|
||||
// efi_sys partition is FAT32, but it's not main file. So we use (IsFs = false)
|
||||
{ false, "efi_sys", "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" },
|
||||
|
||||
{ false, "free", "Apple_Free" },
|
||||
{ false, "ddm", "DDM" },
|
||||
{ false, NULL, "Apple_partition_map" },
|
||||
@@ -326,6 +334,7 @@ static const Byte kProps[] =
|
||||
kpidCRC,
|
||||
kpidComment,
|
||||
kpidMethod
|
||||
// kpidOffset
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
@@ -624,17 +633,40 @@ bool CHandler::ParseBlob(const CByteBuffer &data)
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream)
|
||||
{
|
||||
/*
|
||||
- usual dmg contains Koly Header at the end:
|
||||
- rare case dmg contains Koly Header at the start.
|
||||
*/
|
||||
|
||||
_dataStartOffset = 0;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPos));
|
||||
|
||||
UInt64 fileSize = 0;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
|
||||
RINOK(stream->Seek(_startPos, STREAM_SEEK_SET, NULL));
|
||||
|
||||
Byte buf[HEADER_SIZE];
|
||||
RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE));
|
||||
|
||||
UInt64 headerPos;
|
||||
bool startKolyMode = false;
|
||||
|
||||
if (IsKoly(buf))
|
||||
{
|
||||
// it can be normal koly-at-the-end or koly-at-the-start
|
||||
headerPos = _startPos;
|
||||
if (_startPos <= (1 << 8))
|
||||
{
|
||||
// we want to support startKolyMode, even if there is
|
||||
// some data before dmg file, like 128 bytes MacBin header
|
||||
_dataStartOffset = HEADER_SIZE;
|
||||
startKolyMode = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &headerPos));
|
||||
// we check only koly-at-the-end
|
||||
headerPos = fileSize;
|
||||
if (headerPos < HEADER_SIZE)
|
||||
return S_FALSE;
|
||||
headerPos -= HEADER_SIZE;
|
||||
@@ -660,24 +692,35 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
// CChecksum dataForkChecksum;
|
||||
// dataForkChecksum.Parse(buf + 0x50);
|
||||
|
||||
_startPos = 0;
|
||||
|
||||
UInt64 top = 0;
|
||||
if (!dataForkPair.UpdateTop(headerPos, top)) return S_FALSE;
|
||||
if (!xmlPair.UpdateTop(headerPos, top)) return S_FALSE;
|
||||
if (!rsrcPair.UpdateTop(headerPos, top)) return S_FALSE;
|
||||
UInt64 limit = startKolyMode ? fileSize : headerPos;
|
||||
|
||||
if (!dataForkPair.UpdateTop(limit, top)) return S_FALSE;
|
||||
if (!xmlPair.UpdateTop(limit, top)) return S_FALSE;
|
||||
if (!rsrcPair.UpdateTop(limit, top)) return S_FALSE;
|
||||
|
||||
/* Some old dmg files contain garbage data in blobPair field.
|
||||
So we need to ignore such garbage case;
|
||||
And we still need to detect offset of start of archive for "parser" mode. */
|
||||
|
||||
bool useBlob = blobPair.UpdateTop(headerPos, top);
|
||||
bool useBlob = blobPair.UpdateTop(limit, top);
|
||||
|
||||
_startPos = 0;
|
||||
_phySize = headerPos + HEADER_SIZE;
|
||||
|
||||
if (top != headerPos)
|
||||
if (startKolyMode)
|
||||
_phySize = top;
|
||||
else
|
||||
{
|
||||
_phySize = headerPos + HEADER_SIZE;
|
||||
_startPos = 0;
|
||||
if (top != headerPos)
|
||||
{
|
||||
/*
|
||||
if expected absolute offset is not equal to real header offset,
|
||||
2 cases are possible:
|
||||
- additional (unknown) headers
|
||||
- archive with offset.
|
||||
So we try to read XML with absolute offset to select from these two ways.
|
||||
*/
|
||||
CForkPair xmlPair2 = xmlPair;
|
||||
const char *sz = "<?xml version";
|
||||
const unsigned len = (unsigned)strlen(sz);
|
||||
@@ -687,9 +730,11 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
if (ReadData(stream, xmlPair2, buf2) != S_OK
|
||||
|| memcmp(buf2, sz, len) != 0)
|
||||
{
|
||||
// if absolute offset is not OK, probably it's archive with offset
|
||||
_startPos = headerPos - top;
|
||||
_phySize = top + HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Byte reserved[0x78]
|
||||
@@ -1034,6 +1079,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
case kpidOffset:
|
||||
{
|
||||
prop = item.StartPos;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case kpidMethod:
|
||||
{
|
||||
CMethods m;
|
||||
@@ -1247,6 +1300,11 @@ STDMETHODIMP CAdcDecoder::Code(ISequentialInStream *inStream,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
@@ -1292,6 +1350,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
CAdcDecoder *adcCoderSpec = new CAdcDecoder();
|
||||
CMyComPtr<ICompressCoder> adcCoder = adcCoderSpec;
|
||||
|
||||
NCompress::NLzfse::CDecoder *lzfseCoderSpec = new NCompress::NLzfse::CDecoder();
|
||||
CMyComPtr<ICompressCoder> lzfseCoder = lzfseCoderSpec;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
@@ -1369,7 +1430,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
break;
|
||||
}
|
||||
|
||||
RINOK(_inStream->Seek(_startPos + item.StartPos + block.PackPos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_inStream->Seek(_startPos + _dataStartOffset + item.StartPos + block.PackPos, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(block.PackSize);
|
||||
bool realMethod = true;
|
||||
outStreamSpec->Init(block.UnpSize);
|
||||
@@ -1419,6 +1480,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
break;
|
||||
}
|
||||
|
||||
case METHOD_LZFSE:
|
||||
{
|
||||
res = lzfseCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, progress);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
@@ -1490,6 +1557,9 @@ class CInStream:
|
||||
CAdcDecoder *adcCoderSpec;
|
||||
CMyComPtr<ICompressCoder> adcCoder;
|
||||
|
||||
NCompress::NLzfse::CDecoder *lzfseCoderSpec;
|
||||
CMyComPtr<ICompressCoder> lzfseCoder;
|
||||
|
||||
CBufPtrSeqOutStream *outStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
|
||||
@@ -1651,6 +1721,15 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (res == S_OK && bzip2CoderSpec->GetInputProcessedSize() != block.PackSize)
|
||||
res = S_FALSE;
|
||||
break;
|
||||
|
||||
case METHOD_LZFSE:
|
||||
if (!lzfseCoder)
|
||||
{
|
||||
lzfseCoderSpec = new NCompress::NLzfse::CDecoder();
|
||||
lzfseCoder = lzfseCoderSpec;
|
||||
}
|
||||
res = lzfseCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
return E_FAIL;
|
||||
@@ -1738,6 +1817,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
case METHOD_ADC:
|
||||
case METHOD_ZLIB:
|
||||
case METHOD_BZIP2:
|
||||
case METHOD_LZFSE:
|
||||
case METHOD_END:
|
||||
break;
|
||||
default:
|
||||
@@ -1747,7 +1827,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
|
||||
spec->Stream = _inStream;
|
||||
spec->Size = spec->File->Size;
|
||||
RINOK(spec->InitAndSeek(_startPos));
|
||||
RINOK(spec->InitAndSeek(_startPos + _dataStartOffset));
|
||||
*stream = specStream.Detach();
|
||||
return S_OK;
|
||||
|
||||
|
||||
@@ -567,6 +567,7 @@ static const char * const g_Machines[] =
|
||||
|
||||
static const CUInt32PCharPair g_MachinePairs[] =
|
||||
{
|
||||
{ 243, "RISC-V" },
|
||||
{ 47787, "Xilinx MicroBlaze" }
|
||||
// { 0x9026, "Alpha" }
|
||||
};
|
||||
|
||||
@@ -317,11 +317,15 @@ public:
|
||||
// bool CaseSensetive;
|
||||
UString ResFileName;
|
||||
|
||||
UInt64 SpecOffset;
|
||||
UInt64 PhySize;
|
||||
UInt64 PhySize2;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
SpecOffset = 0;
|
||||
PhySize = 0;
|
||||
PhySize2 = 0;
|
||||
HeadersError = false;
|
||||
ThereAreAltStreams = false;
|
||||
// CaseSensetive = false;
|
||||
@@ -444,7 +448,7 @@ HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inSt
|
||||
e.NumBlocks > fork.NumBlocks - curBlock ||
|
||||
e.NumBlocks > Header.NumBlocks - e.Pos)
|
||||
return S_FALSE;
|
||||
RINOK(inStream->Seek((UInt64)e.Pos << Header.BlockSizeLog, STREAM_SEEK_SET, NULL));
|
||||
RINOK(inStream->Seek(SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog), STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(inStream,
|
||||
(Byte *)buf + ((size_t)curBlock << Header.BlockSizeLog),
|
||||
(size_t)e.NumBlocks << Header.BlockSizeLog));
|
||||
@@ -1154,13 +1158,36 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
|
||||
}
|
||||
|
||||
static const unsigned kHeaderPadSize = (1 << 10);
|
||||
static const unsigned kMainHeaderSize = 512;
|
||||
static const unsigned kHfsHeaderSize = kHeaderPadSize + kMainHeaderSize;
|
||||
|
||||
API_FUNC_static_IsArc IsArc_HFS(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < kHfsHeaderSize)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
p += kHeaderPadSize;
|
||||
if (p[0] == 'B' && p[1] == 'D')
|
||||
{
|
||||
if (p[0x7C] != 'H' || p[0x7C + 1] != '+')
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X'))
|
||||
return k_IsArc_Res_NO;
|
||||
UInt32 version = Get16(p + 2);
|
||||
if (version < 4 || version > 5)
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
return k_IsArc_Res_YES;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
|
||||
{
|
||||
Clear();
|
||||
static const unsigned kHeaderSize = kHeaderPadSize + 512;
|
||||
Byte buf[kHeaderSize];
|
||||
RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize));
|
||||
Byte buf[kHfsHeaderSize];
|
||||
RINOK(ReadStream_FALSE(inStream, buf, kHfsHeaderSize));
|
||||
{
|
||||
for (unsigned i = 0; i < kHeaderPadSize; i++)
|
||||
if (buf[i] != 0)
|
||||
@@ -1171,6 +1198,67 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
|
||||
|
||||
h.Header[0] = p[0];
|
||||
h.Header[1] = p[1];
|
||||
|
||||
if (p[0] == 'B' && p[1] == 'D')
|
||||
{
|
||||
/*
|
||||
It's header for old HFS format.
|
||||
We don't support old HFS format, but we support
|
||||
special HFS volume that contains embedded HFS+ volume
|
||||
*/
|
||||
|
||||
if (p[0x7C] != 'H' || p[0x7C + 1] != '+')
|
||||
return S_FALSE;
|
||||
|
||||
/*
|
||||
h.CTime = Get32(p + 0x2);
|
||||
h.MTime = Get32(p + 0x6);
|
||||
|
||||
h.NumFiles = Get32(p + 0x54);
|
||||
h.NumFolders = Get32(p + 0x58);
|
||||
|
||||
if (h.NumFolders > ((UInt32)1 << 29) ||
|
||||
h.NumFiles > ((UInt32)1 << 30))
|
||||
return S_FALSE;
|
||||
if (progress)
|
||||
{
|
||||
UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1;
|
||||
RINOK(progress->SetTotal(&numFiles, NULL));
|
||||
}
|
||||
h.NumFreeBlocks = Get16(p + 0x22);
|
||||
*/
|
||||
|
||||
UInt32 blockSize = Get32(p + 0x14);
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 9; ((UInt32)1 << i) != blockSize; i++)
|
||||
if (i == 31)
|
||||
return S_FALSE;
|
||||
h.BlockSizeLog = i;
|
||||
}
|
||||
|
||||
h.NumBlocks = Get16(p + 0x12);
|
||||
/*
|
||||
we suppose that it has the follwing layout
|
||||
{
|
||||
start block with header
|
||||
[h.NumBlocks]
|
||||
end block with header
|
||||
}
|
||||
*/
|
||||
PhySize2 = ((UInt64)h.NumBlocks + 2) << h.BlockSizeLog;
|
||||
|
||||
UInt32 startBlock = Get16(p + 0x7C + 2);
|
||||
UInt32 blockCount = Get16(p + 0x7C + 4);
|
||||
SpecOffset = (UInt64)(1 + startBlock) << h.BlockSizeLog;
|
||||
UInt64 phy = SpecOffset + ((UInt64)blockCount << h.BlockSizeLog);
|
||||
if (PhySize2 < phy)
|
||||
PhySize2 = phy;
|
||||
RINOK(inStream->Seek(SpecOffset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(inStream, buf, kHfsHeaderSize));
|
||||
}
|
||||
|
||||
if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X'))
|
||||
return S_FALSE;
|
||||
h.Version = Get16(p + 2);
|
||||
@@ -1330,7 +1418,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
case kpidExtension: prop = Header.IsHfsX() ? "hfsx" : "hfs"; break;
|
||||
case kpidMethod: prop = Header.IsHfsX() ? "HFSX" : "HFS+"; break;
|
||||
case kpidPhySize: prop = PhySize; break;
|
||||
case kpidPhySize:
|
||||
{
|
||||
UInt64 v = SpecOffset + PhySize;
|
||||
if (v < PhySize2)
|
||||
v = PhySize2;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
case kpidClusterSize: prop = (UInt32)1 << Header.BlockSizeLog; break;
|
||||
case kpidFreeSpace: prop = (UInt64)Header.GetFreeSize(); break;
|
||||
case kpidMTime: HfsTimeToProp(Header.MTime, prop); break;
|
||||
@@ -1754,7 +1849,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (fork.Size == pos)
|
||||
break;
|
||||
const CExtent &e = fork.Extents[extentIndex];
|
||||
RINOK(_stream->Seek((UInt64)e.Pos << Header.BlockSizeLog, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_stream->Seek(SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog), STREAM_SEEK_SET, NULL));
|
||||
UInt64 extentRem = (UInt64)e.NumBlocks << Header.BlockSizeLog;
|
||||
while (extentRem != 0)
|
||||
{
|
||||
@@ -1865,6 +1960,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
}
|
||||
|
||||
static const Byte k_Signature[] = {
|
||||
2, 'B', 'D',
|
||||
4, 'H', '+', 0, 4,
|
||||
4, 'H', 'X', 0, 5 };
|
||||
|
||||
@@ -1873,6 +1969,6 @@ REGISTER_ARC_I(
|
||||
k_Signature,
|
||||
kHeaderPadSize,
|
||||
NArcInfoFlags::kMultiSignature,
|
||||
NULL)
|
||||
IsArc_HFS)
|
||||
|
||||
}}
|
||||
|
||||
@@ -488,6 +488,16 @@ ARCHIVE_INTERFACE(IOutArchive, 0xA0)
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
ISetProperties::SetProperties()
|
||||
PROPVARIANT values[i].vt:
|
||||
VT_EMPTY
|
||||
VT_BOOL
|
||||
VT_UI4 - if 32-bit number
|
||||
VT_UI8 - if 64-bit number
|
||||
VT_BSTR
|
||||
*/
|
||||
|
||||
ARCHIVE_INTERFACE(ISetProperties, 0x03)
|
||||
{
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE;
|
||||
|
||||
@@ -180,7 +180,7 @@ UInt32 CInArchive::ReadDigits(int numDigits)
|
||||
Byte b = ReadByte();
|
||||
if (b < '0' || b > '9')
|
||||
{
|
||||
if (b == 0) // it's bug in some CD's
|
||||
if (b == 0 || b == ' ') // it's bug in some CD's
|
||||
b = '0';
|
||||
else
|
||||
throw CHeaderErrorException();
|
||||
|
||||
@@ -109,7 +109,8 @@ void CVersion::ToProp(NCOM::CPropVariant &prop)
|
||||
prop = sz;
|
||||
}
|
||||
|
||||
static const unsigned kHeaderSize = 4 + 20;
|
||||
static const unsigned kCoffHeaderSize = 20;
|
||||
static const unsigned kPeHeaderSize = 4 + kCoffHeaderSize;
|
||||
static const unsigned k_OptHeader32_Size_MIN = 96;
|
||||
static const unsigned k_OptHeader64_Size_MIN = 112;
|
||||
|
||||
@@ -125,15 +126,14 @@ struct CHeader
|
||||
UInt16 OptHeaderSize;
|
||||
UInt16 Flags;
|
||||
|
||||
bool Parse(const Byte *p);
|
||||
void ParseBase(const Byte *p);
|
||||
bool ParseCoff(const Byte *p);
|
||||
bool ParsePe(const Byte *p);
|
||||
bool IsDll() const { return (Flags & PE_IMAGE_FILE_DLL) != 0; }
|
||||
};
|
||||
|
||||
bool CHeader::Parse(const Byte *p)
|
||||
void CHeader::ParseBase(const Byte *p)
|
||||
{
|
||||
if (Get32(p) != k_Signature32)
|
||||
return false;
|
||||
p += 4;
|
||||
G16( 0, Machine);
|
||||
G16( 2, NumSections);
|
||||
G32( 4, Time);
|
||||
@@ -141,6 +141,13 @@ bool CHeader::Parse(const Byte *p)
|
||||
G32(12, NumSymbols);
|
||||
G16(16, OptHeaderSize);
|
||||
G16(18, Flags);
|
||||
}
|
||||
|
||||
bool CHeader::ParsePe(const Byte *p)
|
||||
{
|
||||
if (Get32(p) != k_Signature32)
|
||||
return false;
|
||||
ParseBase(p + 4);
|
||||
return OptHeaderSize >= k_OptHeader32_Size_MIN;
|
||||
}
|
||||
|
||||
@@ -380,6 +387,10 @@ void CSection::Parse(const Byte *p)
|
||||
G32(36, Flags);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// IMAGE_FILE_*
|
||||
|
||||
static const CUInt32PCharPair g_HeaderCharacts[] =
|
||||
{
|
||||
{ 1, "Executable" },
|
||||
@@ -399,39 +410,65 @@ static const CUInt32PCharPair g_HeaderCharacts[] =
|
||||
{ 15, "Big-Endian" }
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair g_DllCharacts[] =
|
||||
// IMAGE_DLLCHARACTERISTICS_*
|
||||
|
||||
static const char * const g_DllCharacts[] =
|
||||
{
|
||||
{ 5, "HighEntropyVA" },
|
||||
{ 6, "Relocated" },
|
||||
{ 7, "Integrity" },
|
||||
{ 8, "NX-Compatible" },
|
||||
{ 9, "NoIsolation" },
|
||||
{ 10, "NoSEH" },
|
||||
{ 11, "NoBind" },
|
||||
{ 12, "AppContainer" },
|
||||
{ 13, "WDM" },
|
||||
{ 14, "GuardCF" },
|
||||
{ 15, "TerminalServerAware" }
|
||||
NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, "HighEntropyVA"
|
||||
, "Relocated"
|
||||
, "Integrity"
|
||||
, "NX-Compatible"
|
||||
, "NoIsolation"
|
||||
, "NoSEH"
|
||||
, "NoBind"
|
||||
, "AppContainer"
|
||||
, "WDM"
|
||||
, "GuardCF"
|
||||
, "TerminalServerAware"
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair g_SectFlags[] =
|
||||
|
||||
// IMAGE_SCN_* constants:
|
||||
|
||||
static const char * const g_SectFlags[] =
|
||||
{
|
||||
{ 3, "NoPad" },
|
||||
{ 5, "Code" },
|
||||
{ 6, "InitializedData" },
|
||||
{ 7, "UninitializedData" },
|
||||
{ 9, "Comments" },
|
||||
{ 11, "Remove" },
|
||||
{ 12, "COMDAT" },
|
||||
{ 15, "GP" },
|
||||
{ 24, "ExtendedRelocations" },
|
||||
{ 25, "Discardable" },
|
||||
{ 26, "NotCached" },
|
||||
{ 27, "NotPaged" },
|
||||
{ 28, "Shared" },
|
||||
{ 29, "Execute" },
|
||||
{ 30, "Read" },
|
||||
{ 31, "Write" }
|
||||
NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, "NoPad"
|
||||
, NULL
|
||||
, "Code"
|
||||
, "InitializedData"
|
||||
, "UninitializedData"
|
||||
, "Other"
|
||||
, "Comments"
|
||||
, NULL // OVER
|
||||
, "Remove"
|
||||
, "COMDAT"
|
||||
, NULL
|
||||
, "NO_DEFER_SPEC_EXC"
|
||||
, "GP" // MEM_FARDATA
|
||||
, NULL // SYSHEAP
|
||||
, "PURGEABLE" // 16BIT
|
||||
, "LOCKED"
|
||||
, "PRELOAD"
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, "ExtendedRelocations"
|
||||
, "Discardable"
|
||||
, "NotCached"
|
||||
, "NotPaged"
|
||||
, "Shared"
|
||||
, "Execute"
|
||||
, "Read"
|
||||
, "Write"
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair g_MachinePairs[] =
|
||||
@@ -699,7 +736,6 @@ class CHandler:
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CObjectVector<CSection> _sections;
|
||||
UInt32 _peOffset;
|
||||
CHeader _header;
|
||||
UInt32 _totalSize;
|
||||
Int32 _mainSubfile;
|
||||
@@ -720,9 +756,12 @@ class CHandler:
|
||||
bool _parseResources;
|
||||
bool _checksumError;
|
||||
|
||||
bool IsOpt() const { return _header.OptHeaderSize != 0; }
|
||||
|
||||
COptHeader _optHeader;
|
||||
|
||||
bool _allowTail;
|
||||
bool _coffMode;
|
||||
|
||||
HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection);
|
||||
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
|
||||
@@ -742,7 +781,10 @@ class CHandler:
|
||||
}
|
||||
|
||||
public:
|
||||
CHandler(): _allowTail(false) {}
|
||||
CHandler(bool coffMode = false):
|
||||
_coffMode(coffMode),
|
||||
_allowTail(coffMode)
|
||||
{}
|
||||
|
||||
MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IArchiveAllowTail)
|
||||
INTERFACE_IInArchive(;)
|
||||
@@ -841,6 +883,34 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: prop = _totalSize; break;
|
||||
case kpidComment: if (!_versionFullString.IsEmpty()) prop = _versionFullString; break;
|
||||
case kpidShortComment:
|
||||
if (!_versionShortString.IsEmpty())
|
||||
prop = _versionShortString;
|
||||
else
|
||||
{
|
||||
PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop);
|
||||
}
|
||||
break;
|
||||
|
||||
case kpidName: if (!_originalFilename.IsEmpty()) prop = _originalFilename; break;
|
||||
|
||||
// case kpidIsSelfExe: prop = !_header.IsDll(); break;
|
||||
// case kpidError:
|
||||
case kpidWarning: if (_checksumError) prop = "Checksum error"; break;
|
||||
|
||||
case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;
|
||||
case kpidMTime:
|
||||
case kpidCTime: TimeToProp(_header.Time, prop); break;
|
||||
case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break;
|
||||
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
|
||||
|
||||
default:
|
||||
if (IsOpt())
|
||||
switch (propID)
|
||||
{
|
||||
|
||||
case kpidSectAlign: prop = _optHeader.SectAlign; break;
|
||||
case kpidFileAlign: prop = _optHeader.FileAlign; break;
|
||||
case kpidLinkerVer:
|
||||
@@ -857,37 +927,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidInitDataSize: prop = _optHeader.InitDataSize; break;
|
||||
case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break;
|
||||
case kpidImageSize: prop = _optHeader.ImageSize; break;
|
||||
case kpidPhySize: prop = _totalSize; break;
|
||||
case kpidHeadersSize: prop = _optHeader.HeadersSize; break;
|
||||
case kpidChecksum: prop = _optHeader.CheckSum; break;
|
||||
case kpidComment: if (!_versionFullString.IsEmpty()) prop = _versionFullString; break;
|
||||
case kpidShortComment:
|
||||
if (!_versionShortString.IsEmpty())
|
||||
prop = _versionShortString;
|
||||
else
|
||||
{
|
||||
PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop);
|
||||
}
|
||||
break;
|
||||
|
||||
case kpidName: if (!_originalFilename.IsEmpty()) prop = _originalFilename; break;
|
||||
case kpidExtension:
|
||||
if (_header.IsDll())
|
||||
prop = _optHeader.IsSybSystem_EFI() ? "efi" : "dll";
|
||||
prop = "dll";
|
||||
else if (_optHeader.IsSybSystem_EFI())
|
||||
prop = "efi";
|
||||
break;
|
||||
|
||||
// case kpidIsSelfExe: prop = !_header.IsDll(); break;
|
||||
|
||||
// case kpidError:
|
||||
case kpidWarning: if (_checksumError) prop = "Checksum error"; break;
|
||||
|
||||
case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;
|
||||
case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;
|
||||
case kpidSubSystem: TYPE_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break;
|
||||
|
||||
case kpidMTime:
|
||||
case kpidCTime: TimeToProp(_header.Time, prop); break;
|
||||
case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break;
|
||||
case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break;
|
||||
case kpidStackReserve: prop = _optHeader.StackReserve; break;
|
||||
case kpidStackCommit: prop = _optHeader.StackCommit; break;
|
||||
@@ -898,8 +950,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
// case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
|
||||
// case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;
|
||||
// case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;
|
||||
|
||||
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -1056,7 +1107,24 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidMTime:
|
||||
case kpidCTime:
|
||||
TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break;
|
||||
case kpidCharacts: if (item.IsRealSect) FLAGS_TO_PROP(g_SectFlags, item.Flags, prop); break;
|
||||
case kpidCharacts:
|
||||
if (item.IsRealSect)
|
||||
{
|
||||
UInt32 flags = item.Flags;
|
||||
const UInt32 MY__IMAGE_SCN_ALIGN_MASK = 0x00F00000;
|
||||
AString s = FlagsToString(g_SectFlags, ARRAY_SIZE(g_SectFlags), item.Flags & ~MY__IMAGE_SCN_ALIGN_MASK);
|
||||
const UInt32 align = ((flags >> 20) & 0xF);
|
||||
if (align != 0)
|
||||
{
|
||||
char sz[32];
|
||||
ConvertUInt32ToString(1 << (align - 1), sz);
|
||||
s.Add_Space();
|
||||
s += "align_";
|
||||
s += sz;
|
||||
}
|
||||
prop = s;
|
||||
}
|
||||
break;
|
||||
case kpidZerosTailIsAllowed: if (!item.IsRealSect) prop = true; break;
|
||||
}
|
||||
}
|
||||
@@ -1073,8 +1141,17 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
|
||||
return S_OK;
|
||||
const unsigned kEntrySize = 28;
|
||||
UInt32 numItems = debugLink.Size / kEntrySize;
|
||||
if (numItems * kEntrySize != debugLink.Size || numItems > 16)
|
||||
if (numItems > 16)
|
||||
return S_FALSE;
|
||||
|
||||
// MAC's EFI file: numItems can be incorrect. Only first CDebugEntry entry is correct.
|
||||
// debugLink.Size = kEntrySize + some_data, pointed by entry[0].
|
||||
if (numItems * kEntrySize != debugLink.Size)
|
||||
{
|
||||
// return S_FALSE;
|
||||
if (numItems > 1)
|
||||
numItems = 1;
|
||||
}
|
||||
|
||||
UInt64 pa = 0;
|
||||
unsigned i;
|
||||
@@ -2114,6 +2191,31 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
bool CHeader::ParseCoff(const Byte *p)
|
||||
{
|
||||
ParseBase(p);
|
||||
if (PointerToSymbolTable < kCoffHeaderSize)
|
||||
return false;
|
||||
if (NumSymbols >= (1 << 24))
|
||||
return false;
|
||||
if (OptHeaderSize != 0 && OptHeaderSize < k_OptHeader32_Size_MIN)
|
||||
return false;
|
||||
|
||||
// 18.04: we reduce false detections
|
||||
if (NumSections == 0 && OptHeaderSize == 0)
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(g_MachinePairs); i++)
|
||||
if (Machine == g_MachinePairs[i].Value)
|
||||
return true;
|
||||
if (Machine == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static inline bool CheckPeOffset(UInt32 pe)
|
||||
{
|
||||
// ((pe & 7) == 0) is for most PE files. But there is unusual EFI-PE file that uses unaligned pe value.
|
||||
@@ -2133,10 +2235,10 @@ API_FUNC_static_IsArc IsArc_Pe(const Byte *p, size_t size)
|
||||
UInt32 pe = Get32(p + 0x3C);
|
||||
if (!CheckPeOffset(pe))
|
||||
return k_IsArc_Res_NO;
|
||||
if (pe + kHeaderSize > size)
|
||||
if (pe + kPeHeaderSize > size)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
CHeader header;
|
||||
if (!header.Parse(p + pe))
|
||||
if (!header.ParsePe(p + pe))
|
||||
return k_IsArc_Res_NO;
|
||||
return k_IsArc_Res_YES;
|
||||
}
|
||||
@@ -2144,32 +2246,47 @@ API_FUNC_static_IsArc IsArc_Pe(const Byte *p, size_t size)
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
{
|
||||
UInt32 coffOffset = 0;
|
||||
if (_coffMode)
|
||||
{
|
||||
Byte h[kStartSize];
|
||||
_mainSubfile = -1;
|
||||
RINOK(ReadStream_FALSE(stream, h, kStartSize));
|
||||
if (h[0] != 'M' || h[1] != 'Z')
|
||||
return S_FALSE;
|
||||
/* most of PE files contain 0x0090 at offset 2.
|
||||
But some rare PE files contain another values. So we don't use that check.
|
||||
if (Get16(h + 2) != 0x90) return false; */
|
||||
_peOffset = Get32(h + 0x3C);
|
||||
if (!CheckPeOffset(_peOffset))
|
||||
Byte h[kCoffHeaderSize];
|
||||
RINOK(ReadStream_FALSE(stream, h, kCoffHeaderSize));
|
||||
if (!_header.ParseCoff(h))
|
||||
return S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Byte h[kHeaderSize];
|
||||
RINOK(stream->Seek(_peOffset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(stream, h, kHeaderSize));
|
||||
if (!_header.Parse(h))
|
||||
return S_FALSE;
|
||||
UInt32 _peOffset;
|
||||
{
|
||||
Byte h[kStartSize];
|
||||
RINOK(ReadStream_FALSE(stream, h, kStartSize));
|
||||
if (h[0] != 'M' || h[1] != 'Z')
|
||||
return S_FALSE;
|
||||
/* most of PE files contain 0x0090 at offset 2.
|
||||
But some rare PE files contain another values. So we don't use that check.
|
||||
if (Get16(h + 2) != 0x90) return false; */
|
||||
_peOffset = Get32(h + 0x3C);
|
||||
if (!CheckPeOffset(_peOffset))
|
||||
return S_FALSE;
|
||||
coffOffset = _peOffset + 4;
|
||||
}
|
||||
{
|
||||
Byte h[kPeHeaderSize];
|
||||
RINOK(stream->Seek(_peOffset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(stream, h, kPeHeaderSize));
|
||||
if (!_header.ParsePe(h))
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 bufSize = _header.OptHeaderSize + (UInt32)_header.NumSections * kSectionSize;
|
||||
_totalSize = _peOffset + kHeaderSize + bufSize;
|
||||
const UInt32 optStart = coffOffset + kCoffHeaderSize;
|
||||
const UInt32 bufSize = _header.OptHeaderSize + (UInt32)_header.NumSections * kSectionSize;
|
||||
_totalSize = optStart + bufSize;
|
||||
CByteBuffer buffer(bufSize);
|
||||
|
||||
RINOK(ReadStream_FALSE(stream, buffer, bufSize));
|
||||
|
||||
if (_header.OptHeaderSize != 0)
|
||||
if (!_optHeader.Parse(buffer, _header.OptHeaderSize))
|
||||
return S_FALSE;
|
||||
|
||||
@@ -2207,7 +2324,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
for (i = 0; i < _sections.Size(); i++)
|
||||
_sections[i].UpdateTotalSize(_totalSize);
|
||||
|
||||
bool thereISDebug;
|
||||
bool thereISDebug = false;
|
||||
if (IsOpt())
|
||||
{
|
||||
RINOK(LoadDebugSections(stream, thereISDebug));
|
||||
|
||||
const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate];
|
||||
@@ -2256,8 +2375,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
_totalSize += (UInt32)k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= 512)
|
||||
if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= optStart)
|
||||
{
|
||||
if (_header.NumSymbols >= (1 << 24))
|
||||
return S_FALSE;
|
||||
@@ -2306,11 +2426,12 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
}
|
||||
|
||||
|
||||
if (IsOpt())
|
||||
if (_optHeader.CheckSum != 0)
|
||||
{
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
UInt32 checkSum = 0;
|
||||
RINOK(CalcCheckSum(stream, _totalSize, _peOffset + kHeaderSize + k_CheckSum_Field_Offset, checkSum));
|
||||
RINOK(CalcCheckSum(stream, _totalSize, optStart + k_CheckSum_Field_Offset, checkSum));
|
||||
_checksumError = (checkSum != _optHeader.CheckSum);
|
||||
}
|
||||
|
||||
@@ -2333,6 +2454,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
const CSection § = _sections[i];
|
||||
CMixItem mixItem;
|
||||
mixItem.SectionIndex = i;
|
||||
if (IsOpt())
|
||||
if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty())
|
||||
{
|
||||
const unsigned numMixItems = _mixItems.Size();
|
||||
@@ -2480,6 +2602,8 @@ STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_totalSize = 0;
|
||||
_checksumError = false;
|
||||
_mainSubfile = -1;
|
||||
|
||||
_stream.Release();
|
||||
_sections.Clear();
|
||||
_mixItems.Clear();
|
||||
@@ -2675,10 +2799,41 @@ REGISTER_ARC_I(
|
||||
0,
|
||||
NArcInfoFlags::kPreArc,
|
||||
IsArc_Pe)
|
||||
|
||||
|
||||
}
|
||||
|
||||
namespace NCoff {
|
||||
|
||||
API_FUNC_static_IsArc IsArc_Coff(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < NPe::kCoffHeaderSize)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
NPe::CHeader header;
|
||||
if (!header.ParseCoff(p))
|
||||
return k_IsArc_Res_NO;
|
||||
return k_IsArc_Res_YES;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static const Byte k_Signature[] =
|
||||
{
|
||||
2, 0x4C, 0x01, // x86
|
||||
2, 0x64, 0x86, // x64
|
||||
2, 0x64, 0xAA // ARM64
|
||||
};
|
||||
REGISTER_ARC_I_CLS(
|
||||
*/
|
||||
|
||||
REGISTER_ARC_I_CLS_NO_SIG(
|
||||
NPe::CHandler(true),
|
||||
"COFF", "obj", 0, 0xC6,
|
||||
// k_Signature,
|
||||
0,
|
||||
// NArcInfoFlags::kMultiSignature |
|
||||
NArcInfoFlags::kStartOpen,
|
||||
IsArc_Coff)
|
||||
}
|
||||
|
||||
|
||||
namespace NTe {
|
||||
|
||||
@@ -139,11 +139,10 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val)
|
||||
{
|
||||
*val = 0;
|
||||
|
||||
for (unsigned i = 0; i < maxSize;)
|
||||
for (unsigned i = 0; i < maxSize && i < 10;)
|
||||
{
|
||||
Byte b = p[i];
|
||||
if (i < 10)
|
||||
*val |= (UInt64)(b & 0x7F) << (7 * i);
|
||||
*val |= (UInt64)(b & 0x7F) << (7 * i);
|
||||
i++;
|
||||
if ((b & 0x80) == 0)
|
||||
return i;
|
||||
@@ -1086,7 +1085,7 @@ HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool
|
||||
if (!lzCoder)
|
||||
{
|
||||
const UInt32 methodID = 0x40305;
|
||||
RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodID, false, lzCoder));
|
||||
RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS methodID, false, lzCoder));
|
||||
if (!lzCoder)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
@@ -1363,7 +1362,9 @@ static const Byte kProps[] =
|
||||
kpidCharacts,
|
||||
kpidSymLink,
|
||||
kpidHardLink,
|
||||
kpidCopyLink
|
||||
kpidCopyLink,
|
||||
|
||||
kpidVolumeIndex
|
||||
};
|
||||
|
||||
|
||||
@@ -1794,6 +1795,18 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
case kpidSplitBefore: prop = item.IsSplitBefore(); break;
|
||||
case kpidSplitAfter: prop = lastItem.IsSplitAfter(); break;
|
||||
|
||||
case kpidVolumeIndex:
|
||||
{
|
||||
if (item.VolIndex < _arcs.Size())
|
||||
{
|
||||
const CInArcInfo &arcInfo = _arcs[item.VolIndex].Info;
|
||||
if (arcInfo.IsVolume())
|
||||
prop = (UInt64)arcInfo.GetVolIndex();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidCRC:
|
||||
{
|
||||
const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem);
|
||||
|
||||
@@ -180,7 +180,7 @@ struct CItem
|
||||
|
||||
AString Name;
|
||||
|
||||
int VolIndex;
|
||||
unsigned VolIndex;
|
||||
int NextItem;
|
||||
|
||||
UInt32 UnixMTime;
|
||||
|
||||
@@ -777,7 +777,9 @@ static const Byte kProps[] =
|
||||
kpidCRC,
|
||||
kpidHostOS,
|
||||
kpidMethod,
|
||||
kpidUnpackVer
|
||||
kpidUnpackVer,
|
||||
|
||||
kpidVolumeIndex
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
@@ -995,6 +997,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidCommented: prop = item.IsCommented(); break;
|
||||
case kpidSplitBefore: prop = item.IsSplitBefore(); break;
|
||||
case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break;
|
||||
|
||||
case kpidVolumeIndex:
|
||||
if (_arcInfo.Is_VolNumber_Defined())
|
||||
prop = (UInt32)(_arcInfo.VolNumber + refItem.VolumeIndex);
|
||||
break;
|
||||
|
||||
case kpidCRC:
|
||||
{
|
||||
prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC);
|
||||
@@ -1691,7 +1699,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
methodID += 2;
|
||||
else
|
||||
methodID += 3;
|
||||
RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, false, mi.Coder));
|
||||
RINOK(CreateCoder_Id(EXTERNAL_CODECS_VARS methodID, false, mi.Coder));
|
||||
}
|
||||
|
||||
if (mi.Coder == 0)
|
||||
|
||||
@@ -26,7 +26,7 @@ struct CInArcInfo
|
||||
UInt32 DataCRC;
|
||||
bool EndOfArchive_was_Read;
|
||||
|
||||
CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false) {}
|
||||
CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false), VolNumber(0) {}
|
||||
|
||||
UInt64 GetPhySize() const { return EndPos - StartPos; }
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/7zCrc.h"
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../../C/CpuArch.h"
|
||||
#include "../../../C/Xz.h"
|
||||
@@ -1209,8 +1208,10 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
|
||||
else
|
||||
{
|
||||
ECoderStatus status;
|
||||
XzUnpacker_Init(&_xz);
|
||||
SRes res = XzUnpacker_Code(&_xz, dest, &destLen, _inputBuffer, &srcLen, CODER_FINISH_END, &status);
|
||||
SRes res = XzUnpacker_CodeFull(&_xz,
|
||||
dest, &destLen,
|
||||
_inputBuffer, &srcLen,
|
||||
CODER_FINISH_END, &status);
|
||||
if (res != 0)
|
||||
return SResToHRESULT(res);
|
||||
if (status != CODER_STATUS_NEEDS_MORE_INPUT || !XzUnpacker_IsStreamWasFinished(&_xz))
|
||||
|
||||
@@ -94,7 +94,9 @@ static bool ParseInt64(const char *p, Int64 &val)
|
||||
|
||||
static bool ParseInt64_MTime(const char *p, Int64 &val)
|
||||
{
|
||||
// rare case tar contains spaces instead of MTime
|
||||
// rare case tar : ZEROs in Docker-Windows TARs
|
||||
// rare case tar : spaces
|
||||
if (GetUi32(p) != 0)
|
||||
for (unsigned i = 0; i < 12; i++)
|
||||
if (p[i] != ' ')
|
||||
return ParseInt64(p, val);
|
||||
|
||||
@@ -24,9 +24,7 @@
|
||||
|
||||
#include "IArchive.h"
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
#include "Common/HandlerOut.h"
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
@@ -49,14 +47,22 @@ class CHandler:
|
||||
public IInArchive,
|
||||
public IArchiveOpenSeq,
|
||||
public IInArchiveGetStream,
|
||||
public ISetProperties,
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
public IOutArchive,
|
||||
public ISetProperties,
|
||||
public CMultiMethodProps,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
|
||||
public CMyUnknownImp,
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
public CMultiMethodProps
|
||||
#else
|
||||
public CCommonMethodProps
|
||||
#endif
|
||||
{
|
||||
NCompress::NXz::CStatInfo _stat;
|
||||
CXzStatInfo _stat;
|
||||
SRes MainDecodeSRes;
|
||||
|
||||
bool _isArc;
|
||||
bool _needSeekToStart;
|
||||
@@ -71,34 +77,48 @@ class CHandler:
|
||||
|
||||
UInt64 _numSolidBytes;
|
||||
|
||||
HRESULT SetSolidFromString(const UString &s);
|
||||
HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
|
||||
void InitSolid()
|
||||
void InitXz()
|
||||
{
|
||||
_filterId = 0;
|
||||
_numSolidBytes = XZ_PROPS__BLOCK_SIZE__AUTO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Init()
|
||||
{
|
||||
InitSolid();
|
||||
_filterId = 0;
|
||||
CMultiMethodProps::Init();
|
||||
#ifndef EXTRACT_ONLY
|
||||
InitXz();
|
||||
CMultiMethodProps::Init();
|
||||
#else
|
||||
CCommonMethodProps::InitCommon();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
|
||||
HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);
|
||||
|
||||
HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
|
||||
NCompress::NXz::CDecoder &decoder, ICompressProgressInfo *progress)
|
||||
HRESULT Decode(NCompress::NXz::CDecoder &decoder,
|
||||
ISequentialInStream *seqInStream,
|
||||
ISequentialOutStream *outStream,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
decoder._numThreads = _numThreads;
|
||||
#endif
|
||||
decoder._memUsage = _memUsage;
|
||||
|
||||
MainDecodeSRes = SZ_OK;
|
||||
|
||||
RINOK(decoder.Decode(seqInStream, outStream,
|
||||
NULL, // *outSizeLimit
|
||||
true, // finishStream
|
||||
progress));
|
||||
_stat = decoder;
|
||||
|
||||
_stat = decoder.Stat;
|
||||
MainDecodeSRes = decoder.MainDecodeSRes;
|
||||
|
||||
_phySize_Defined = true;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -107,9 +127,9 @@ public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)
|
||||
MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ISetProperties)
|
||||
#ifndef EXTRACT_ONLY
|
||||
MY_QUERYINTERFACE_ENTRY(IOutArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(ISetProperties)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
@@ -117,10 +137,10 @@ public:
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
INTERFACE_IOutArchive(;)
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
#endif
|
||||
|
||||
size_t _blocksArraySize;
|
||||
@@ -146,7 +166,7 @@ CHandler::CHandler():
|
||||
_blocksArraySize(0)
|
||||
{
|
||||
#ifndef EXTRACT_ONLY
|
||||
Init();
|
||||
InitXz();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -307,7 +327,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: if (_phySize_Defined) prop = _stat.PhySize; break;
|
||||
case kpidPhySize: if (_phySize_Defined) prop = _stat.InSize; break;
|
||||
case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break;
|
||||
case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break;
|
||||
case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;
|
||||
@@ -330,19 +350,22 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
SRes sres = MainDecodeSRes; // _stat.DecodeRes2; //
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (_stat.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (/*_stat.UnexpectedEnd */ sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
|
||||
if (_stat.HeadersError) v |= kpv_ErrorFlags_HeadersError;
|
||||
if (_stat.Unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
|
||||
if (_stat.DataError) v |= kpv_ErrorFlags_DataError;
|
||||
if (_stat.CrcError) v |= kpv_ErrorFlags_CrcError;
|
||||
prop = v;
|
||||
if (/* _stat.HeadersError */ sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError;
|
||||
if (/* _stat.Unsupported */ sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod;
|
||||
if (/* _stat.DataError */ sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError;
|
||||
if (/* _stat.CrcError */ sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError;
|
||||
if (v != 0)
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidMainSubfile:
|
||||
{
|
||||
// debug only, comment it:
|
||||
// if (_blocks) prop = (UInt32)0;
|
||||
break;
|
||||
}
|
||||
@@ -365,7 +388,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;
|
||||
case kpidPackSize: if (_phySize_Defined) prop = _stat.PhySize; break;
|
||||
case kpidPackSize: if (_phySize_Defined) prop = _stat.InSize; break;
|
||||
case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
@@ -483,10 +506,10 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.PhySize));
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.InSize));
|
||||
if (callback)
|
||||
{
|
||||
RINOK(callback->SetTotal(NULL, &_stat.PhySize));
|
||||
RINOK(callback->SetTotal(NULL, &_stat.InSize));
|
||||
}
|
||||
|
||||
CSeekInStreamWrap inStreamImp;
|
||||
@@ -621,7 +644,7 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_stat.Clear();
|
||||
XzStatInfo_Clear(&_stat);
|
||||
|
||||
_isArc = false;
|
||||
_needSeekToStart = false;
|
||||
@@ -637,6 +660,8 @@ STDMETHODIMP CHandler::Close()
|
||||
_blocksArraySize = 0;
|
||||
_maxBlocksSize = 0;
|
||||
|
||||
MainDecodeSRes = SZ_OK;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -743,6 +768,8 @@ static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu,
|
||||
xzu.p.streamFlags = (UInt16)streamFlags;
|
||||
XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p);
|
||||
|
||||
XzUnpacker_SetOutBuf(&xzu.p, dest, unpackSize);
|
||||
|
||||
const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
|
||||
UInt64 packRem = packSizeAligned;
|
||||
|
||||
@@ -771,8 +798,11 @@ static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu,
|
||||
ECoderStatus status;
|
||||
|
||||
SRes res = XzUnpacker_Code(&xzu.p,
|
||||
dest + outPos, &outLen,
|
||||
// dest + outPos,
|
||||
NULL,
|
||||
&outLen,
|
||||
xzu.InBuf + inPos, &inLen,
|
||||
(inLen == 0), // srcFinished
|
||||
CODER_FINISH_END, &status);
|
||||
|
||||
// return E_OUTOFMEMORY;
|
||||
@@ -890,15 +920,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!_stat.UnpackSize_Defined
|
||||
|| _maxBlocksSize == 0 // 18.02
|
||||
|| _maxBlocksSize > kMaxBlockSize_for_GetStream
|
||||
|| _maxBlocksSize != (size_t)_maxBlocksSize)
|
||||
return S_FALSE;
|
||||
|
||||
UInt64 physSize = (UInt64)(sizeof(size_t)) << 29;
|
||||
bool ramSize_Defined = NSystem::GetRamSize(physSize);
|
||||
if (ramSize_Defined)
|
||||
UInt64 memSize;
|
||||
if (!NSystem::GetRamSize(memSize))
|
||||
memSize = (UInt64)(sizeof(size_t)) << 28;
|
||||
{
|
||||
if (_maxBlocksSize > physSize / 4)
|
||||
if (_maxBlocksSize > memSize / 4)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
@@ -917,6 +948,31 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
}
|
||||
|
||||
|
||||
static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder)
|
||||
{
|
||||
Int32 opRes;
|
||||
SRes sres = decoder.MainDecodeSRes; // decoder.Stat.DecodeRes2;
|
||||
if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc)
|
||||
opRes = NExtract::NOperationResult::kIsNotArc;
|
||||
else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
else if (decoder.Stat.DataAfterEnd)
|
||||
opRes = NExtract::NOperationResult::kDataAfterEnd;
|
||||
else if (sres == SZ_ERROR_CRC) // (CrcError)
|
||||
opRes = NExtract::NOperationResult::kCRCError;
|
||||
else if (sres == SZ_ERROR_UNSUPPORTED) // (Unsupported)
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else if (sres == SZ_ERROR_ARCHIVE) // (HeadersError)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (sres == SZ_ERROR_DATA) // (DataError)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (sres != SZ_OK)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
return opRes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -930,7 +986,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (_phySize_Defined)
|
||||
extractCallback->SetTotal(_stat.PhySize);
|
||||
extractCallback->SetTotal(_stat.InSize);
|
||||
|
||||
UInt64 currentTotalPacked = 0;
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalPacked));
|
||||
@@ -959,9 +1015,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
else
|
||||
_needSeekToStart = true;
|
||||
|
||||
|
||||
NCompress::NXz::CDecoder decoder;
|
||||
RINOK(Decode2(_seqStream, realOutStream, decoder, lpsRef));
|
||||
Int32 opRes = decoder.Get_Extract_OperationResult();
|
||||
|
||||
HRESULT hres = Decode(decoder, _seqStream, realOutStream, lpsRef);
|
||||
|
||||
if (!decoder.MainDecodeSRes_wasUsed)
|
||||
return hres == S_OK ? E_FAIL : hres;
|
||||
|
||||
Int32 opRes = Get_Extract_OperationResult(decoder);
|
||||
if (opRes == NExtract::NOperationResult::kOK
|
||||
&& hres != S_OK)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
|
||||
realOutStream.Release();
|
||||
return extractCallback->SetOperationResult(opRes);
|
||||
@@ -1112,7 +1177,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (_stream)
|
||||
{
|
||||
if (_phySize_Defined)
|
||||
RINOK(updateCallback->SetTotal(_stat.PhySize));
|
||||
RINOK(updateCallback->SetTotal(_stat.InSize));
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
@@ -1125,55 +1190,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
HRESULT CHandler::SetSolidFromString(const UString &s)
|
||||
{
|
||||
UString s2 = s;
|
||||
s2.MakeLower_Ascii();
|
||||
|
||||
{
|
||||
const wchar_t *start = ((const wchar_t *)s2);
|
||||
const wchar_t *end;
|
||||
UInt64 v = ConvertStringToUInt64(start, &end);
|
||||
if (start == end)
|
||||
return E_INVALIDARG;
|
||||
if ((unsigned)(end - start) + 1 != s2.Len())
|
||||
return E_INVALIDARG;
|
||||
wchar_t c = *end;
|
||||
{
|
||||
unsigned numBits;
|
||||
switch (c)
|
||||
{
|
||||
case 'b': numBits = 0; break;
|
||||
case 'k': numBits = 10; break;
|
||||
case 'm': numBits = 20; break;
|
||||
case 'g': numBits = 30; break;
|
||||
case 't': numBits = 40; break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
_numSolidBytes = (v << numBits);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)
|
||||
{
|
||||
bool isSolid;
|
||||
switch (value.vt)
|
||||
{
|
||||
case VT_EMPTY: isSolid = true; break;
|
||||
case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
|
||||
case VT_BSTR:
|
||||
if (StringToBool(value.bstrVal, isSolid))
|
||||
break;
|
||||
return SetSolidFromString(value.bstrVal);
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
_numSolidBytes = (isSolid ? XZ_PROPS__BLOCK_SIZE__SOLID : XZ_PROPS__BLOCK_SIZE__AUTO);
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
|
||||
@@ -1183,20 +1200,53 @@ HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
if (name[0] == L's')
|
||||
{
|
||||
name.Delete(0);
|
||||
if (name.IsEmpty())
|
||||
return SetSolidFromPROPVARIANT(value);
|
||||
if (value.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
return SetSolidFromString(name);
|
||||
const wchar_t *s = name.Ptr(1);
|
||||
if (*s == 0)
|
||||
{
|
||||
bool useStr = false;
|
||||
bool isSolid;
|
||||
switch (value.vt)
|
||||
{
|
||||
case VT_EMPTY: isSolid = true; break;
|
||||
case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
|
||||
case VT_BSTR:
|
||||
if (!StringToBool(value.bstrVal, isSolid))
|
||||
useStr = true;
|
||||
break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
if (!useStr)
|
||||
{
|
||||
_numSolidBytes = (isSolid ? XZ_PROPS__BLOCK_SIZE__SOLID : XZ_PROPS__BLOCK_SIZE__AUTO);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return ParseSizeString(s, value,
|
||||
0, // percentsBase
|
||||
_numSolidBytes) ? S_OK: E_INVALIDARG;
|
||||
}
|
||||
|
||||
|
||||
return CMultiMethodProps::SetProperty(name, value);
|
||||
|
||||
#else
|
||||
|
||||
{
|
||||
HRESULT hres;
|
||||
if (SetCommonProperty(name, value, hres))
|
||||
return hres;
|
||||
}
|
||||
|
||||
return E_INVALIDARG;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -1208,6 +1258,8 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
|
||||
RINOK(SetProperty(names[i], values[i]));
|
||||
}
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
if (!_filterMethod.MethodName.IsEmpty())
|
||||
{
|
||||
unsigned k;
|
||||
@@ -1238,12 +1290,13 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
REGISTER_ARC_IO(
|
||||
"xz", "xz txz", "* .tar", 0xC,
|
||||
|
||||
@@ -384,7 +384,7 @@ HRESULT CAddCommon::Compress(
|
||||
methodId = kMethodId_ZipBase + method;
|
||||
break;
|
||||
}
|
||||
RINOK(CreateCoder(
|
||||
RINOK(CreateCoder_Id(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodId, true, _compressEncoder));
|
||||
if (!_compressEncoder)
|
||||
|
||||
@@ -112,7 +112,8 @@ static const CUInt32PCharPair g_HeaderCharacts[] =
|
||||
{ 3, "Descriptor" },
|
||||
// { 5, "Patched" },
|
||||
{ 6, kMethod_StrongCrypto },
|
||||
{ 11, "UTF8" }
|
||||
{ 11, "UTF8" },
|
||||
{ 14, "Alt" }
|
||||
};
|
||||
|
||||
struct CIdToNamePair
|
||||
@@ -169,6 +170,7 @@ static const Byte kProps[] =
|
||||
kpidUnpackVer,
|
||||
kpidVolumeIndex,
|
||||
kpidOffset
|
||||
// kpidIsAltStream
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
@@ -307,6 +309,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
prop = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// case kpidIsAltStream: prop = true; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
COM_TRY_END
|
||||
@@ -333,6 +337,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
UString res;
|
||||
item.GetUnicodeString(res, item.Name, false, _forceCodePage, _specifiedCodePage);
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(res);
|
||||
/*
|
||||
if (item.ParentOfAltStream >= 0)
|
||||
{
|
||||
const CItemEx &prevItem = m_Items[item.ParentOfAltStream];
|
||||
UString prevName;
|
||||
prevItem.GetUnicodeString(prevName, prevItem.Name, false, _forceCodePage, _specifiedCodePage);
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(prevName);
|
||||
if (res.IsPrefixedBy(prevName))
|
||||
if (IsString1PrefixedByString2(res.Ptr(prevName.Len()), k_SpecName_NTFS_STREAM))
|
||||
{
|
||||
res.Delete(prevName.Len(), (unsigned)strlen(k_SpecName_NTFS_STREAM));
|
||||
res.Insert(prevName.Len(), L":");
|
||||
}
|
||||
}
|
||||
*/
|
||||
prop = res;
|
||||
break;
|
||||
}
|
||||
@@ -596,6 +615,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidOffset:
|
||||
prop = item.LocalHeaderPos;
|
||||
break;
|
||||
|
||||
/*
|
||||
case kpidIsAltStream:
|
||||
prop = (bool)(item.ParentOfAltStream >= 0); // item.IsAltStream();
|
||||
break;
|
||||
|
||||
case kpidName:
|
||||
if (item.ParentOfAltStream >= 0)
|
||||
{
|
||||
// extract name of stream here
|
||||
}
|
||||
break;
|
||||
*/
|
||||
}
|
||||
|
||||
prop.Detach(value);
|
||||
@@ -604,6 +636,85 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
|
||||
{
|
||||
*numProps = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)
|
||||
{
|
||||
UNUSED_VAR(index);
|
||||
*propID = 0;
|
||||
*name = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)
|
||||
{
|
||||
*parentType = NParentType::kDir;
|
||||
*parent = (UInt32)(Int32)-1;
|
||||
if (index >= m_Items.Size())
|
||||
return S_OK;
|
||||
const CItemEx &item = m_Items[index];
|
||||
|
||||
if (item.ParentOfAltStream >= 0)
|
||||
{
|
||||
*parentType = NParentType::kAltStream;
|
||||
*parent = item.ParentOfAltStream;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
|
||||
{
|
||||
UNUSED_VAR(index);
|
||||
UNUSED_VAR(propID);
|
||||
*data = NULL;
|
||||
*dataSize = 0;
|
||||
*propType = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CHandler::MarkAltStreams(CObjectVector<CItemEx> &items)
|
||||
{
|
||||
int prevIndex = -1;
|
||||
UString prevName;
|
||||
UString name;
|
||||
|
||||
for (unsigned i = 0; i < items.Size(); i++)
|
||||
{
|
||||
CItemEx &item = m_Items[i];
|
||||
if (item.IsAltStream())
|
||||
{
|
||||
if (prevIndex == -1)
|
||||
continue;
|
||||
if (prevName.IsEmpty())
|
||||
{
|
||||
const CItemEx &prevItem = m_Items[prevIndex];
|
||||
prevItem.GetUnicodeString(prevName, prevItem.Name, false, _forceCodePage, _specifiedCodePage);
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(prevName);
|
||||
}
|
||||
name.Empty();
|
||||
item.GetUnicodeString(name, item.Name, false, _forceCodePage, _specifiedCodePage);
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(name);
|
||||
|
||||
if (name.IsPrefixedBy(prevName))
|
||||
if (IsString1PrefixedByString2(name.Ptr(prevName.Len()), k_SpecName_NTFS_STREAM))
|
||||
item.ParentOfAltStream = prevIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevIndex = i;
|
||||
prevName.Empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
|
||||
{
|
||||
@@ -617,6 +728,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
m_Items.Clear();
|
||||
m_Archive.ClearRefs(); // we don't want to clear error flags
|
||||
}
|
||||
// MarkAltStreams(m_Items);
|
||||
return res;
|
||||
}
|
||||
catch(...) { Close(); throw; }
|
||||
@@ -738,7 +850,7 @@ public:
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
ICompressProgressInfo *compressProgress,
|
||||
#ifndef _7ZIP_ST
|
||||
UInt32 numThreads,
|
||||
UInt32 numThreads, UInt64 memUsage,
|
||||
#endif
|
||||
Int32 &res);
|
||||
};
|
||||
@@ -767,7 +879,7 @@ HRESULT CZipDecoder::Decode(
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
ICompressProgressInfo *compressProgress,
|
||||
#ifndef _7ZIP_ST
|
||||
UInt32 numThreads,
|
||||
UInt32 numThreads, UInt64 memUsage,
|
||||
#endif
|
||||
Int32 &res)
|
||||
{
|
||||
@@ -962,7 +1074,7 @@ HRESULT CZipDecoder::Decode(
|
||||
szMethodID = kMethodId_ZipBase + (Byte)id;
|
||||
}
|
||||
|
||||
RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, false, mi.Coder));
|
||||
RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS szMethodID, false, mi.Coder));
|
||||
|
||||
if (!mi.Coder)
|
||||
{
|
||||
@@ -974,16 +1086,7 @@ HRESULT CZipDecoder::Decode(
|
||||
}
|
||||
|
||||
ICompressCoder *coder = methodItems[m].Coder;
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
|
||||
coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
Byte properties = (Byte)item.Flags;
|
||||
RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
{
|
||||
@@ -994,7 +1097,27 @@ HRESULT CZipDecoder::Decode(
|
||||
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
|
||||
}
|
||||
}
|
||||
// if (memUsage != 0)
|
||||
{
|
||||
CMyComPtr<ICompressSetMemLimit> setMemLimit;
|
||||
coder->QueryInterface(IID_ICompressSetMemLimit, (void **)&setMemLimit);
|
||||
if (setMemLimit)
|
||||
{
|
||||
RINOK(setMemLimit->SetMemLimit(memUsage));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
|
||||
coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
Byte properties = (Byte)item.Flags;
|
||||
RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CMyComPtr<ISequentialInStream> inStreamNew;
|
||||
|
||||
@@ -1319,7 +1442,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
m_Archive, item, realOutStream, extractCallback,
|
||||
progress,
|
||||
#ifndef _7ZIP_ST
|
||||
_props._numThreads,
|
||||
_props._numThreads, _props._memUsage,
|
||||
#endif
|
||||
res);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ extern const char * const kMethodNames2[kNumMethodNames2];
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
// public IArchiveGetRawProps,
|
||||
public IOutArchive,
|
||||
public ISetProperties,
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
@@ -32,6 +33,7 @@ class CHandler:
|
||||
{
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
// MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
|
||||
MY_QUERYINTERFACE_ENTRY(IOutArchive)
|
||||
MY_QUERYINTERFACE_ENTRY(ISetProperties)
|
||||
QUERY_ENTRY_ISetCompressCodecsInfo
|
||||
@@ -39,6 +41,7 @@ public:
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
// INTERFACE_IArchiveGetRawProps(;)
|
||||
INTERFACE_IOutArchive(;)
|
||||
|
||||
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
|
||||
@@ -75,6 +78,10 @@ private:
|
||||
_forceCodePage = false;
|
||||
_specifiedCodePage = CP_OEMCP;
|
||||
}
|
||||
|
||||
// void MarkAltStreams(CObjectVector<CItemEx> &items);
|
||||
|
||||
HRESULT GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -136,6 +136,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
thereAreAesUpdates = true;
|
||||
if (!IntToBool(newProps))
|
||||
ui.IsDir = inputItem.IsDir();
|
||||
// ui.IsAltStream = inputItem.IsAltStream();
|
||||
}
|
||||
|
||||
if (IntToBool(newProps))
|
||||
@@ -175,6 +176,33 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
ui.IsDir = (prop.boolVal != VARIANT_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
bool isAltStream = false;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidIsAltStream, &prop));
|
||||
if (prop.vt == VT_BOOL)
|
||||
isAltStream = (prop.boolVal != VARIANT_FALSE);
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (isAltStream)
|
||||
{
|
||||
if (ui.IsDir)
|
||||
return E_INVALIDARG;
|
||||
int delim = name.ReverseFind(L':');
|
||||
if (delim >= 0)
|
||||
{
|
||||
name.Delete(delim, 1);
|
||||
name.Insert(delim, UString(k_SpecName_NTFS_STREAM));
|
||||
ui.IsAltStream = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
CPropVariant prop;
|
||||
RINOK(callback->GetProperty(i, kpidTimeType, &prop));
|
||||
@@ -348,7 +376,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
{
|
||||
CMethodId methodId;
|
||||
UInt32 numStreams;
|
||||
if (!FindMethod(EXTERNAL_CODECS_VARS methodName, methodId, numStreams))
|
||||
if (FindMethod_Index(EXTERNAL_CODECS_VARS methodName, true,
|
||||
methodId, numStreams) < 0)
|
||||
return E_NOTIMPL;
|
||||
if (numStreams != 1)
|
||||
return E_NOTIMPL;
|
||||
|
||||
@@ -131,6 +131,7 @@ namespace NFileHeader
|
||||
const unsigned kDescriptorUsedMask = 1 << 3;
|
||||
const unsigned kStrongEncrypted = 1 << 6;
|
||||
const unsigned kUtf8 = 1 << 11;
|
||||
const unsigned kAltStream = 1 << 14;
|
||||
|
||||
const unsigned kImplodeDictionarySizeMask = 1 << 1;
|
||||
const unsigned kImplodeLiteralsOnMask = 1 << 2;
|
||||
|
||||
@@ -1993,6 +1993,13 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
|
||||
}
|
||||
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
|
||||
{
|
||||
/* possible cases:
|
||||
- exe with zip inside
|
||||
- sfx: a.exe, a.z02, a.z03,... , a.zip
|
||||
a.exe is start volume.
|
||||
- zip renamed to exe
|
||||
*/
|
||||
|
||||
StartIsExe = true;
|
||||
BaseName = name;
|
||||
StartVolIndex = 0;
|
||||
@@ -2000,7 +2007,22 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
|
||||
We can open arc.zip, if it was requesed to open arc.exe.
|
||||
But it's possible that arc.exe and arc.zip are not parts of same archive.
|
||||
So we can disable such operation */
|
||||
return S_FALSE; // don't open arc.zip instead of arc.exe
|
||||
|
||||
// 18.04: we still want to open zip renamed to exe.
|
||||
/*
|
||||
{
|
||||
UString volName = name;
|
||||
volName += IsUpperCase ? "Z01" : "z01";
|
||||
{
|
||||
CMyComPtr<IInStream> stream;
|
||||
HRESULT res2 = volCallback->GetStream(volName, &stream);
|
||||
if (res2 == S_OK)
|
||||
DisableVolsSearch = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
DisableVolsSearch = true;
|
||||
return S_OK;
|
||||
}
|
||||
else if (ext[0] == 'z' || ext[0] == 'Z')
|
||||
{
|
||||
@@ -2040,6 +2062,9 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
|
||||
HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
|
||||
unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols)
|
||||
{
|
||||
if (Vols.DisableVolsSearch)
|
||||
return S_OK;
|
||||
|
||||
numMissingVols = 0;
|
||||
|
||||
for (unsigned i = start;; i++)
|
||||
@@ -2090,6 +2115,8 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
|
||||
}
|
||||
if (res == S_FALSE || !stream)
|
||||
{
|
||||
if (i == 1 && Vols.StartIsExe)
|
||||
return S_OK;
|
||||
if (Vols.MissingName.IsEmpty())
|
||||
Vols.MissingName = volName;
|
||||
numMissingVols++;
|
||||
|
||||
@@ -20,10 +20,13 @@ class CItemEx: public CItem
|
||||
{
|
||||
public:
|
||||
UInt32 LocalFullHeaderSize; // including Name and Extra
|
||||
// int ParentOfAltStream; // -1, if not AltStream
|
||||
|
||||
bool DescriptorWasRead;
|
||||
|
||||
CItemEx(): DescriptorWasRead(false) {}
|
||||
CItemEx():
|
||||
// ParentOfAltStream(-1),
|
||||
DescriptorWasRead(false) {}
|
||||
|
||||
UInt64 GetLocalFullSize() const
|
||||
{ return LocalFullHeaderSize + GetPackSizeWithDescriptor(); }
|
||||
@@ -159,6 +162,7 @@ struct CVols
|
||||
|
||||
bool NeedSeek;
|
||||
|
||||
bool DisableVolsSearch;
|
||||
bool StartIsExe; // is .exe
|
||||
bool StartIsZ; // is .zip or .zNN
|
||||
bool StartIsZip; // is .zip
|
||||
@@ -198,6 +202,7 @@ struct CVols
|
||||
StreamIndex = -1;
|
||||
NeedSeek = false;
|
||||
|
||||
DisableVolsSearch = false;
|
||||
StartIsExe = false;
|
||||
StartIsZ = false;
|
||||
StartIsZip = false;
|
||||
|
||||
@@ -20,6 +20,12 @@ namespace NZip {
|
||||
|
||||
using namespace NFileHeader;
|
||||
|
||||
|
||||
/*
|
||||
const char *k_SpecName_NTFS_STREAM = "@@NTFS@STREAM@";
|
||||
const char *k_SpecName_MAC_RESOURCE_FORK = "@@MAC@RESOURCE-FORK@";
|
||||
*/
|
||||
|
||||
static const CUInt32PCharPair g_ExtraTypes[] =
|
||||
{
|
||||
{ NExtraID::kZip64, "Zip64" },
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
/*
|
||||
extern const char *k_SpecName_NTFS_STREAM;
|
||||
extern const char *k_SpecName_MAC_RESOURCE_FORK;
|
||||
*/
|
||||
|
||||
struct CVersion
|
||||
{
|
||||
Byte Version;
|
||||
@@ -233,6 +238,7 @@ public:
|
||||
bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
|
||||
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
|
||||
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
|
||||
// bool IsAltStream() const { return (Flags & NFileHeader::NFlags::kAltStream) != 0; }
|
||||
|
||||
unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; }
|
||||
|
||||
@@ -264,6 +270,7 @@ public:
|
||||
void ClearFlags() { Flags = 0; }
|
||||
void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
|
||||
void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }
|
||||
// void SetFlag_AltStream(bool isAltStream) { SetFlag(NFileHeader::NFlags::kAltStream, isAltStream); }
|
||||
void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); }
|
||||
|
||||
UINT GetCodePage() const { return CP_OEMCP; }
|
||||
|
||||
@@ -75,6 +75,7 @@ static void SetFileHeader(
|
||||
item.Name = ui.Name;
|
||||
item.Comment = ui.Comment;
|
||||
item.SetUtf8(ui.IsUtf8);
|
||||
// item.SetFlag_AltStream(ui.IsAltStream);
|
||||
item.ExternalAttrib = ui.Attrib;
|
||||
item.Time = ui.Time;
|
||||
item.Ntfs_MTime = ui.Ntfs_MTime;
|
||||
@@ -280,6 +281,7 @@ public:
|
||||
MY_UNKNOWN_IMP
|
||||
void Create(IProgress *progress, bool inSizeIsMain);
|
||||
void SetProgressOffset(UInt64 progressOffset);
|
||||
void SetProgressOffset_NoLock(UInt64 progressOffset);
|
||||
HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize);
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
@@ -292,11 +294,16 @@ void CMtProgressMixer2::Create(IProgress *progress, bool inSizeIsMain)
|
||||
ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0;
|
||||
}
|
||||
|
||||
void CMtProgressMixer2::SetProgressOffset_NoLock(UInt64 progressOffset)
|
||||
{
|
||||
InSizes[1] = OutSizes[1] = 0;
|
||||
ProgressOffset = progressOffset;
|
||||
}
|
||||
|
||||
void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)
|
||||
{
|
||||
CriticalSection.Enter();
|
||||
InSizes[1] = OutSizes[1] = 0;
|
||||
ProgressOffset = progressOffset;
|
||||
SetProgressOffset_NoLock(progressOffset);
|
||||
CriticalSection.Leave();
|
||||
}
|
||||
|
||||
@@ -384,6 +391,7 @@ static HRESULT UpdateItemOldData(
|
||||
item.Comment = ui.Comment;
|
||||
item.Name = ui.Name;
|
||||
item.SetUtf8(ui.IsUtf8);
|
||||
// item.SetFlag_AltStream(ui.IsAltStream);
|
||||
item.Time = ui.Time;
|
||||
item.Ntfs_MTime = ui.Ntfs_MTime;
|
||||
item.Ntfs_ATime = ui.Ntfs_ATime;
|
||||
@@ -602,8 +610,11 @@ static HRESULT Update2St(
|
||||
lps->InSize = unpackSizeTotal;
|
||||
lps->OutSize = packSizeTotal;
|
||||
RINOK(lps->SetCur());
|
||||
|
||||
archive.WriteCentralDir(items, comment);
|
||||
return S_OK;
|
||||
|
||||
lps->ProgressOffset += kCentralHeaderSize * updateItems.Size() + 1;
|
||||
return lps->SetCur();
|
||||
}
|
||||
|
||||
|
||||
@@ -897,7 +908,7 @@ static HRESULT Update2(
|
||||
{
|
||||
complexity += ui.Size;
|
||||
complexity += kLocalHeaderSize;
|
||||
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
|
||||
mtProgressMixerSpec->Mixer2->SetProgressOffset_NoLock(complexity);
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
memRef2.Skip = true;
|
||||
continue;
|
||||
@@ -1107,8 +1118,13 @@ static HRESULT Update2(
|
||||
}
|
||||
|
||||
RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL));
|
||||
|
||||
archive.WriteCentralDir(items, comment);
|
||||
return S_OK;
|
||||
|
||||
complexity += kCentralHeaderSize * updateItems.Size() + 1;
|
||||
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
|
||||
return mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ struct CUpdateItem
|
||||
bool IsDir;
|
||||
bool NtfsTimeIsDefined;
|
||||
bool IsUtf8;
|
||||
// bool IsAltStream;
|
||||
int IndexInArc;
|
||||
int IndexInClient;
|
||||
UInt32 Attrib;
|
||||
@@ -50,12 +51,19 @@ struct CUpdateItem
|
||||
IsDir = false;
|
||||
NtfsTimeIsDefined = false;
|
||||
IsUtf8 = false;
|
||||
// IsAltStream = false;
|
||||
Size = 0;
|
||||
Name.Empty();
|
||||
Comment.Free();
|
||||
}
|
||||
|
||||
CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {}
|
||||
CUpdateItem():
|
||||
IsDir(false),
|
||||
NtfsTimeIsDefined(false),
|
||||
IsUtf8(false),
|
||||
// IsAltStream(false),
|
||||
Size(0)
|
||||
{}
|
||||
};
|
||||
|
||||
HRESULT Update(
|
||||
|
||||
@@ -1112,18 +1112,6 @@ SOURCE=..\..\Compress\ShrinkDecoder.cpp
|
||||
SOURCE=..\..\Compress\ShrinkDecoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Z"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\ZDecoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\ZDecoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "BWT"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
@@ -1652,10 +1640,6 @@ SOURCE=..\..\Archive\SplitHandler.cpp
|
||||
|
||||
SOURCE=..\..\Archive\XzHandler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\ZHandler.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "UI Common"
|
||||
|
||||
@@ -2636,6 +2620,34 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.c
|
||||
|
||||
!IF "$(CFG)" == "Alone - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2Enc.c
|
||||
|
||||
!IF "$(CFG)" == "Alone - Win32 Release"
|
||||
@@ -2748,6 +2760,34 @@ SOURCE=..\..\..\..\C\MtCoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.c
|
||||
|
||||
!IF "$(CFG)" == "Alone - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Ppmd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -76,7 +76,6 @@ AR_OBJS = \
|
||||
$O\LzmaHandler.obj \
|
||||
$O\SplitHandler.obj \
|
||||
$O\XzHandler.obj \
|
||||
$O\ZHandler.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\CoderMixer2.obj \
|
||||
@@ -170,7 +169,6 @@ COMPRESS_OBJS = \
|
||||
$O\ShrinkDecoder.obj \
|
||||
$O\XzDecoder.obj \
|
||||
$O\XzEncoder.obj \
|
||||
$O\ZDecoder.obj \
|
||||
|
||||
CRYPTO_OBJS = \
|
||||
$O\7zAes.obj \
|
||||
@@ -199,10 +197,12 @@ C_OBJS = \
|
||||
$O\LzFind.obj \
|
||||
$O\LzFindMt.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\Lzma2Enc.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\LzmaEnc.obj \
|
||||
$O\MtCoder.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Ppmd7.obj \
|
||||
$O\Ppmd7Dec.obj \
|
||||
$O\Ppmd7Enc.obj \
|
||||
@@ -324,5 +324,6 @@ ZSTDMT_OBJS = \
|
||||
!include "../../Aes.mak"
|
||||
!include "../../Crc.mak"
|
||||
!include "../../Crc64.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
|
||||
!include "../../7zip.mak"
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#include "../../MyVersionInfo.rc"
|
||||
|
||||
MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za")
|
||||
|
||||
#ifndef UNDER_CE
|
||||
1 24 MOVEABLE PURE "../../UI/Console/Console.manifest"
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,7 @@ RSC=rc.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /FAc /Yu"StdAfx.h" /FD /c
|
||||
# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAc /Yu"StdAfx.h" /FD /c
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
@@ -69,7 +69,7 @@ LINK32=link.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
@@ -94,7 +94,7 @@ LINK32=link.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /Yu"StdAfx.h" /FD /c
|
||||
# ADD CPP /nologo /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c
|
||||
# ADD CPP /nologo /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
@@ -121,7 +121,7 @@ LINK32=link.exe
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
@@ -482,6 +482,14 @@ SOURCE=..\..\..\Windows\FileName.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileSystem.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileSystem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Handle.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -1696,6 +1704,34 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.c
|
||||
|
||||
!IF "$(CFG)" == "Alone - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2Enc.c
|
||||
|
||||
!IF "$(CFG)" == "Alone - Win32 Release"
|
||||
@@ -1789,6 +1825,34 @@ SOURCE=..\..\..\..\C\MtCoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.c
|
||||
|
||||
!IF "$(CFG)" == "Alone - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Threads.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
|
||||
@@ -3,7 +3,7 @@ MY_CONSOLE = 1
|
||||
CFLAGS = $(CFLAGS) -DPROG_VARIANT_R
|
||||
|
||||
!IFNDEF UNDER_CE
|
||||
CFLAGS = $(CFLAGS) -DWIN_LONG_PATH
|
||||
CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE
|
||||
!ENDIF
|
||||
|
||||
COMMON_OBJS = \
|
||||
@@ -33,6 +33,7 @@ WIN_OBJS = \
|
||||
$O\FileIO.obj \
|
||||
$O\FileLink.obj \
|
||||
$O\FileName.obj \
|
||||
$O\FileSystem.obj \
|
||||
$O\MemoryLock.obj \
|
||||
$O\PropVariant.obj \
|
||||
$O\PropVariantConv.obj \
|
||||
@@ -133,10 +134,12 @@ C_OBJS = \
|
||||
$O\LzFind.obj \
|
||||
$O\LzFindMt.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\Lzma2Enc.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\LzmaEnc.obj \
|
||||
$O\MtCoder.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Sha256.obj \
|
||||
$O\Sort.obj \
|
||||
$O\Threads.obj \
|
||||
@@ -150,5 +153,6 @@ C_OBJS = \
|
||||
!include "../../Aes.mak"
|
||||
!include "../../Crc.mak"
|
||||
!include "../../Crc64.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
|
||||
!include "../../7zip.mak"
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#include "../../../../C/7zVersion.rc"
|
||||
|
||||
MY_VERSION_INFO_APP("7-Zip Reduced Standalone Console", "7zr")
|
||||
|
||||
#ifndef UNDER_CE
|
||||
1 24 MOVEABLE PURE "../../UI/Console/Console.manifest"
|
||||
#endif
|
||||
|
||||
@@ -677,6 +677,14 @@ SOURCE=..\..\UI\FileManager\DialogSize.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\UI\FileManager\EditDialog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\UI\FileManager\EditDialog.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\UI\FileManager\LinkDialog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -1004,6 +1012,15 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2Enc.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
@@ -1040,6 +1057,15 @@ SOURCE=..\..\..\..\C\MtCoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Sha256.c
|
||||
|
||||
!IF "$(CFG)" == "FM - Win32 Release"
|
||||
@@ -1549,14 +1575,6 @@ SOURCE=..\..\..\Common\Wildcard.h
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\UI\Common\ArchiveCommandLine.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -48,7 +48,6 @@ WIN_CTRL_OBJS = \
|
||||
$O\FileStreams.obj \
|
||||
|
||||
UI_COMMON_OBJS = \
|
||||
$O\ArchiveCommandLine.obj \
|
||||
$O\ArchiveExtractCallback.obj \
|
||||
$O\ArchiveName.obj \
|
||||
$O\ArchiveOpenCallback.obj \
|
||||
|
||||
@@ -122,10 +122,12 @@ C_OBJS = \
|
||||
$O\LzFind.obj \
|
||||
$O\LzFindMt.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\Lzma2Enc.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\LzmaEnc.obj \
|
||||
$O\MtCoder.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Ppmd7.obj \
|
||||
$O\Ppmd7Dec.obj \
|
||||
$O\Ppmd7Enc.obj \
|
||||
@@ -135,6 +137,7 @@ C_OBJS = \
|
||||
|
||||
!include "../../Aes.mak"
|
||||
!include "../../Crc.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
|
||||
COMPRESS_OBJS = $(COMPRESS_OBJS) \
|
||||
$O\BrotliDecoder.obj \
|
||||
|
||||
@@ -43,6 +43,7 @@ AR_OBJS = \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\CoderMixer2.obj \
|
||||
$O\HandlerOut.obj \
|
||||
$O\ItemNameUtils.obj \
|
||||
$O\OutStreamWithCRC.obj \
|
||||
$O\ParseProperties.obj \
|
||||
@@ -99,7 +100,9 @@ C_OBJS = \
|
||||
$O\CpuArch.obj \
|
||||
$O\Delta.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Ppmd7.obj \
|
||||
$O\Ppmd7Dec.obj \
|
||||
$O\Sha256.obj \
|
||||
@@ -198,5 +201,6 @@ ZSTDMT_OBJS = \
|
||||
|
||||
!include "../../Aes.mak"
|
||||
!include "../../Crc.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
|
||||
!include "../../7zip.mak"
|
||||
|
||||
@@ -85,9 +85,12 @@ C_OBJS = \
|
||||
$O\CpuArch.obj \
|
||||
$O\Delta.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Threads.obj \
|
||||
|
||||
!include "../../Crc.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
|
||||
!include "../../7zip.mak"
|
||||
|
||||
@@ -202,6 +202,7 @@ COMPRESS_OBJS = \
|
||||
$O\DeflateRegister.obj \
|
||||
$O\DeltaFilter.obj \
|
||||
$O\ImplodeDecoder.obj \
|
||||
$O\LzfseDecoder.obj \
|
||||
$O\LzhDecoder.obj \
|
||||
$O\Lzma2Decoder.obj \
|
||||
$O\Lzma2Encoder.obj \
|
||||
@@ -265,10 +266,12 @@ C_OBJS = \
|
||||
$O\LzFind.obj \
|
||||
$O\LzFindMt.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\Lzma2Enc.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\LzmaEnc.obj \
|
||||
$O\MtCoder.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Ppmd7.obj \
|
||||
$O\Ppmd7Dec.obj \
|
||||
$O\Ppmd7Enc.obj \
|
||||
@@ -287,3 +290,4 @@ C_OBJS = \
|
||||
!include "../../Aes.mak"
|
||||
!include "../../Crc.mak"
|
||||
!include "../../Crc64.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
|
||||
@@ -961,6 +961,24 @@ SOURCE=..\..\Compress\HuffmanDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\LzfseDecoder.cpp
|
||||
|
||||
!IF "$(CFG)" == "7z - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\LzfseDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\LzhDecoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -1787,6 +1805,26 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.c
|
||||
|
||||
!IF "$(CFG)" == "7z - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2Enc.c
|
||||
|
||||
!IF "$(CFG)" == "7z - Win32 Release"
|
||||
@@ -1856,6 +1894,26 @@ SOURCE=..\..\..\..\C\MtCoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.c
|
||||
|
||||
!IF "$(CFG)" == "7z - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
|
||||
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Ppmd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -102,12 +102,15 @@ C_OBJS = \
|
||||
$O\LzFind.obj \
|
||||
$O\LzFindMt.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\Lzma2Enc.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\LzmaEnc.obj \
|
||||
$O\MtCoder.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Threads.obj \
|
||||
|
||||
!include "../../Crc.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
|
||||
!include "../../7zip.mak"
|
||||
|
||||
@@ -117,6 +117,10 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Common\HandlerOut.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -293,6 +297,10 @@ SOURCE=..\..\Compress\Lzma2Decoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzma2Decoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzma2Register.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -411,6 +419,14 @@ SOURCE=..\..\..\Windows\Synchronization.cpp
|
||||
|
||||
SOURCE=..\..\..\Windows\Synchronization.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\System.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\System.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Common"
|
||||
|
||||
@@ -822,6 +838,15 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\LzmaDec.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
@@ -831,6 +856,15 @@ SOURCE=..\..\..\..\C\LzmaDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Ppmd7.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
PROG = 7zCon.sfx
|
||||
MY_CONSOLE = 1
|
||||
MY_FIXED = 1
|
||||
|
||||
CFLAGS = $(CFLAGS) \
|
||||
-DEXTRACT_ONLY \
|
||||
-DNO_READ_FROM_CODER \
|
||||
@@ -118,7 +120,9 @@ C_OBJS = \
|
||||
$O\Delta.obj \
|
||||
$O\DllSecur.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Ppmd7.obj \
|
||||
$O\Ppmd7Dec.obj \
|
||||
$O\Sha256.obj \
|
||||
@@ -126,6 +130,7 @@ C_OBJS = \
|
||||
|
||||
!include "../../Aes.mak"
|
||||
!include "../../Crc.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
|
||||
COMPRESS_OBJS = $(COMPRESS_OBJS) \
|
||||
$O\ZstdDecoder.obj \
|
||||
|
||||
@@ -449,6 +449,14 @@ SOURCE=..\..\..\Windows\Synchronization.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\System.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\System.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Window.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -469,6 +477,14 @@ SOURCE=..\..\Common\CreateCoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\CWrappers.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\CWrappers.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\FileStreams.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -724,6 +740,15 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\LzmaDec.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
@@ -733,6 +758,15 @@ SOURCE=..\..\..\..\C\LzmaDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Threads.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
PROG = 7zS.sfx
|
||||
MY_FIXED = 1
|
||||
|
||||
CFLAGS = $(CFLAGS) \
|
||||
-DNO_REGISTRY \
|
||||
-DEXTRACT_ONLY \
|
||||
@@ -33,6 +35,7 @@ WIN_OBJS = \
|
||||
$O\PropVariant.obj \
|
||||
$O\ResourceString.obj \
|
||||
$O\Synchronization.obj \
|
||||
$O\System.obj \
|
||||
$O\Window.obj \
|
||||
|
||||
WIN_CTRL_OBJS = \
|
||||
@@ -40,6 +43,7 @@ WIN_CTRL_OBJS = \
|
||||
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\CreateCoder.obj \
|
||||
$O\CWrappers.obj \
|
||||
$O\FileStreams.obj \
|
||||
$O\InBuffer.obj \
|
||||
$O\FilterCoder.obj \
|
||||
@@ -102,8 +106,11 @@ C_OBJS = \
|
||||
$O\Delta.obj \
|
||||
$O\DllSecur.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Threads.obj \
|
||||
|
||||
!include "../../Crc.mak"
|
||||
!include "../../7zip.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
!include "../../7zip.mak"
|
||||
@@ -633,6 +633,14 @@ SOURCE=..\..\..\Windows\Synchronization.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\System.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\System.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\Window.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -906,6 +914,15 @@ SOURCE=..\..\..\..\C\Lzma2Dec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Lzma2DecMt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\LzmaDec.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
@@ -915,6 +932,15 @@ SOURCE=..\..\..\..\C\LzmaDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\MtDec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\..\C\Ppmd7.c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
PROG = 7z.sfx
|
||||
MY_FIXED = 1
|
||||
|
||||
CFLAGS = $(CFLAGS) \
|
||||
-DNO_REGISTRY \
|
||||
-DEXTRACT_ONLY \
|
||||
@@ -42,6 +44,7 @@ WIN_OBJS = \
|
||||
$O\Shell.obj \
|
||||
$O\System.obj \
|
||||
$O\Synchronization.obj \
|
||||
$O\System.obj \
|
||||
$O\Window.obj \
|
||||
|
||||
WIN_CTRL_OBJS = \
|
||||
@@ -136,7 +139,9 @@ C_OBJS = \
|
||||
$O\Delta.obj \
|
||||
$O\DllSecur.obj \
|
||||
$O\Lzma2Dec.obj \
|
||||
$O\Lzma2DecMt.obj \
|
||||
$O\LzmaDec.obj \
|
||||
$O\MtDec.obj \
|
||||
$O\Ppmd7.obj \
|
||||
$O\Ppmd7Dec.obj \
|
||||
$O\Sha256.obj \
|
||||
@@ -144,6 +149,7 @@ C_OBJS = \
|
||||
|
||||
!include "../../Aes.mak"
|
||||
!include "../../Crc.mak"
|
||||
!include "../../LzmaDec.mak"
|
||||
|
||||
COMPRESS_OBJS = $(COMPRESS_OBJS) \
|
||||
$O\ZstdDecoder.obj \
|
||||
|
||||
@@ -28,14 +28,23 @@ HRESULT SResToHRESULT(SRes res) throw()
|
||||
switch (res)
|
||||
{
|
||||
case SZ_OK: return S_OK;
|
||||
case SZ_ERROR_DATA: return S_FALSE;
|
||||
case SZ_ERROR_CRC: return S_FALSE;
|
||||
|
||||
case SZ_ERROR_DATA:
|
||||
case SZ_ERROR_CRC:
|
||||
case SZ_ERROR_INPUT_EOF:
|
||||
return S_FALSE;
|
||||
|
||||
case SZ_ERROR_MEM: return E_OUTOFMEMORY;
|
||||
case SZ_ERROR_PARAM: return E_INVALIDARG;
|
||||
case SZ_ERROR_PROGRESS: return E_ABORT;
|
||||
case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
|
||||
// case SZ_ERROR_THREAD: return E_FAIL;
|
||||
// case SZ_ERROR_READ: return E_FAIL;
|
||||
// case SZ_ERROR_OUTPUT_EOF:
|
||||
// case SZ_ERROR_READ:
|
||||
// case SZ_ERROR_WRITE:
|
||||
// case SZ_ERROR_THREAD:
|
||||
// case SZ_ERROR_ARCHIVE:
|
||||
// case SZ_ERROR_NO_ARCHIVE:
|
||||
// return E_FAIL;
|
||||
}
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
@@ -148,20 +148,23 @@ HRESULT CExternalCodecs::Load()
|
||||
#endif
|
||||
|
||||
|
||||
bool FindMethod(
|
||||
int FindMethod_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const AString &name,
|
||||
CMethodId &methodId, UInt32 &numStreams)
|
||||
bool encode,
|
||||
CMethodId &methodId,
|
||||
UInt32 &numStreams)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < g_NumCodecs; i++)
|
||||
{
|
||||
const CCodecInfo &codec = *g_Codecs[i];
|
||||
if (StringsAreEqualNoCase_Ascii(name, codec.Name))
|
||||
if ((encode ? codec.CreateEncoder : codec.CreateDecoder)
|
||||
&& StringsAreEqualNoCase_Ascii(name, codec.Name))
|
||||
{
|
||||
methodId = codec.Id;
|
||||
numStreams = codec.NumStreams;
|
||||
return true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,19 +176,51 @@ bool FindMethod(
|
||||
for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
|
||||
{
|
||||
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
|
||||
if (StringsAreEqualNoCase_Ascii(name, codec.Name))
|
||||
if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)
|
||||
&& StringsAreEqualNoCase_Ascii(name, codec.Name))
|
||||
{
|
||||
methodId = codec.Id;
|
||||
numStreams = codec.NumStreams;
|
||||
return true;
|
||||
return g_NumCodecs + i;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int FindMethod_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < g_NumCodecs; i++)
|
||||
{
|
||||
const CCodecInfo &codec = *g_Codecs[i];
|
||||
if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder))
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
|
||||
CHECK_GLOBAL_CODECS
|
||||
|
||||
if (__externalCodecs)
|
||||
for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
|
||||
{
|
||||
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
|
||||
if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned))
|
||||
return g_NumCodecs + i;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool FindMethod(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId,
|
||||
@@ -280,9 +315,11 @@ void GetHashMethods(
|
||||
#endif
|
||||
}
|
||||
|
||||
HRESULT CreateCoder(
|
||||
|
||||
|
||||
HRESULT CreateCoder_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
unsigned i, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter,
|
||||
CCreatedCoder &cod)
|
||||
{
|
||||
@@ -290,11 +327,10 @@ HRESULT CreateCoder(
|
||||
cod.IsFilter = false;
|
||||
cod.NumStreams = 1;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < g_NumCodecs; i++)
|
||||
if (i < g_NumCodecs)
|
||||
{
|
||||
const CCodecInfo &codec = *g_Codecs[i];
|
||||
if (codec.Id == methodId)
|
||||
// if (codec.Id == methodId)
|
||||
{
|
||||
if (encode)
|
||||
{
|
||||
@@ -325,11 +361,12 @@ HRESULT CreateCoder(
|
||||
|
||||
if (__externalCodecs)
|
||||
{
|
||||
i -= g_NumCodecs;
|
||||
cod.IsExternal = true;
|
||||
for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
|
||||
if (i < __externalCodecs->Codecs.Size())
|
||||
{
|
||||
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
|
||||
if (codec.Id == methodId)
|
||||
// if (codec.Id == methodId)
|
||||
{
|
||||
if (encode)
|
||||
{
|
||||
@@ -371,13 +408,50 @@ HRESULT CreateCoder(
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CreateCoder(
|
||||
|
||||
HRESULT CreateCoder_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
unsigned index, bool encode,
|
||||
CCreatedCoder &cod)
|
||||
{
|
||||
CMyComPtr<ICompressFilter> filter;
|
||||
HRESULT res = CreateCoder_Index(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
index, encode,
|
||||
filter, cod);
|
||||
|
||||
if (filter)
|
||||
{
|
||||
cod.IsFilter = true;
|
||||
CFilterCoder *coderSpec = new CFilterCoder(encode);
|
||||
cod.Coder = coderSpec;
|
||||
coderSpec->Filter = filter;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter,
|
||||
CCreatedCoder &cod)
|
||||
{
|
||||
int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode);
|
||||
if (index < 0)
|
||||
return S_OK;
|
||||
return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS index, encode, filter, cod);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CCreatedCoder &cod)
|
||||
{
|
||||
CMyComPtr<ICompressFilter> filter;
|
||||
HRESULT res = CreateCoder(
|
||||
HRESULT res = CreateCoder_Id(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodId, encode,
|
||||
filter, cod);
|
||||
@@ -393,13 +467,14 @@ HRESULT CreateCoder(
|
||||
return res;
|
||||
}
|
||||
|
||||
HRESULT CreateCoder(
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressCoder> &coder)
|
||||
{
|
||||
CCreatedCoder cod;
|
||||
HRESULT res = CreateCoder(
|
||||
HRESULT res = CreateCoder_Id(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodId, encode,
|
||||
cod);
|
||||
@@ -413,7 +488,7 @@ HRESULT CreateFilter(
|
||||
CMyComPtr<ICompressFilter> &filter)
|
||||
{
|
||||
CCreatedCoder cod;
|
||||
return CreateCoder(
|
||||
return CreateCoder_Id(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodId, encode,
|
||||
filter, cod);
|
||||
|
||||
@@ -116,13 +116,12 @@ extern CExternalCodecs g_ExternalCodecs;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
bool FindMethod(
|
||||
int FindMethod_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const AString &name,
|
||||
CMethodId &methodId, UInt32 &numStreams);
|
||||
bool encode,
|
||||
CMethodId &methodId,
|
||||
UInt32 &numStreams);
|
||||
|
||||
bool FindMethod(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
@@ -152,18 +151,29 @@ struct CCreatedCoder
|
||||
};
|
||||
|
||||
|
||||
HRESULT CreateCoder(
|
||||
HRESULT CreateCoder_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
unsigned codecIndex, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Index(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
unsigned index, bool encode,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressFilter> &filter,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder(
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CCreatedCoder &cod);
|
||||
|
||||
HRESULT CreateCoder(
|
||||
HRESULT CreateCoder_Id(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CMethodId methodId, bool encode,
|
||||
CMyComPtr<ICompressCoder> &coder);
|
||||
|
||||
@@ -97,6 +97,33 @@ Byte CInBufferBase::ReadByte_FromNewBlock()
|
||||
|
||||
size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
|
||||
{
|
||||
size_t num = 0;
|
||||
for (;;)
|
||||
{
|
||||
const size_t rem = _bufLim - _buf;
|
||||
if (size <= rem)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(buf, _buf, size);
|
||||
_buf += size;
|
||||
num += size;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
if (rem != 0)
|
||||
{
|
||||
memcpy(buf, _buf, rem);
|
||||
_buf += rem;
|
||||
buf += rem;
|
||||
num += rem;
|
||||
size -= rem;
|
||||
}
|
||||
if (!ReadBlock())
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
if ((size_t)(_bufLim - _buf) >= size)
|
||||
{
|
||||
const Byte *src = _buf;
|
||||
@@ -113,6 +140,7 @@ size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
|
||||
buf[i] = *_buf++;
|
||||
}
|
||||
return size;
|
||||
*/
|
||||
}
|
||||
|
||||
size_t CInBufferBase::Skip(size_t size)
|
||||
|
||||
@@ -253,6 +253,9 @@ struct CNameToPropID
|
||||
const char *Name;
|
||||
};
|
||||
|
||||
|
||||
// the following are related to NCoderPropID::EEnum values
|
||||
|
||||
static const CNameToPropID g_NameToPropID[] =
|
||||
{
|
||||
{ VT_UI4, "" },
|
||||
@@ -275,7 +278,8 @@ static const CNameToPropID g_NameToPropID[] =
|
||||
{ VT_UI8, "expect" },
|
||||
{ VT_UI4, "b" },
|
||||
{ VT_UI4, "check" },
|
||||
{ VT_BSTR, "filter" }
|
||||
{ VT_BSTR, "filter" },
|
||||
{ VT_UI8, "memuse" }
|
||||
};
|
||||
|
||||
static int FindPropIdExact(const UString &name)
|
||||
@@ -293,6 +297,13 @@ static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::C
|
||||
destProp = srcProp;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (varType == VT_UI8 && srcProp.vt == VT_UI4)
|
||||
{
|
||||
destProp = (UInt64)srcProp.ulVal;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (varType == VT_BOOL)
|
||||
{
|
||||
bool res;
|
||||
|
||||
@@ -50,6 +50,17 @@ const UInt32 kNumSelectorsMax = (2 + (kBlockSizeMax / kGroupSize));
|
||||
|
||||
const unsigned kRleModeRepSize = 4;
|
||||
|
||||
/*
|
||||
The number of selectors stored in bzip2 block:
|
||||
(numSelectors <= 18001) - must work with any decoder.
|
||||
(numSelectors == 18002) - works with bzip2 1.0.6 decoder and all derived decoders.
|
||||
(numSelectors > 18002)
|
||||
7-Zip decoder doesn't support it.
|
||||
bzip2 1.0.6 decoder can overflow selector[18002] arrays. But there are another
|
||||
arrays after selector arrays. So the compiled code works.
|
||||
lbzip2 2.5 encoder can write up to (18001 + 7) selectors.
|
||||
*/
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -411,9 +411,13 @@ SRes CBase::ReadBlock2()
|
||||
lens[state4] = (Byte)state3;
|
||||
state5 = 0;
|
||||
}
|
||||
|
||||
// lbzip2 2.5 can produce dummy tree, where lens[i] = kMaxHuffmanLen
|
||||
// BuildFull() returns error for such tree
|
||||
/*
|
||||
for (unsigned i = state4; i < kMaxAlphaSize; i++)
|
||||
lens[i] = 0;
|
||||
if (!huffs[state2].Build(lens))
|
||||
*/
|
||||
if (!huffs[state2].BuildFull(lens, state4))
|
||||
return SZ_ERROR_DATA;
|
||||
@@ -474,7 +478,7 @@ SRes CBase::ReadBlock2()
|
||||
for (len = kNumTableBits + 1; val >= huff->_limits[len]; len++);
|
||||
/*
|
||||
if (len > kNumBitsMax)
|
||||
return SZ_ERROR_DATA;
|
||||
return SZ_ERROR_DATA; // that check is required, if NHuffman::Build() was used instead of BuildFull()
|
||||
*/
|
||||
if (_numBits < len)
|
||||
{
|
||||
|
||||
@@ -969,6 +969,10 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou
|
||||
}
|
||||
}
|
||||
while (Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) != 0);
|
||||
|
||||
if (_seqInStream.Res != S_OK)
|
||||
return _seqInStream.Res;
|
||||
|
||||
if (_lzInWindow.result != SZ_OK)
|
||||
return SResToHRESULT(_lzInWindow.result);
|
||||
return m_OutStream.Flush();
|
||||
|
||||
@@ -56,6 +56,39 @@ public:
|
||||
if (pos == _limitPos)
|
||||
FlushWithCheck();
|
||||
}
|
||||
|
||||
void PutBytes(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
UInt32 pos = _pos;
|
||||
Byte *buf = _buf;
|
||||
buf[pos++] = *data++;
|
||||
size--;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 limitPos = _limitPos;
|
||||
UInt32 rem = limitPos - pos;
|
||||
if (rem == 0)
|
||||
{
|
||||
_pos = pos;
|
||||
FlushWithCheck();
|
||||
pos = _pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
break;
|
||||
|
||||
if (rem > size)
|
||||
rem = size;
|
||||
size -= rem;
|
||||
do
|
||||
buf[pos++] = *data++;
|
||||
while (--rem);
|
||||
}
|
||||
_pos = pos;
|
||||
}
|
||||
|
||||
Byte GetByte(UInt32 distance) const
|
||||
{
|
||||
|
||||
925
CPP/7zip/Compress/LzfseDecoder.cpp
Normal file
925
CPP/7zip/Compress/LzfseDecoder.cpp
Normal file
@@ -0,0 +1,925 @@
|
||||
// LzfseDecoder.cpp
|
||||
|
||||
/*
|
||||
This code implements LZFSE data decompressing.
|
||||
The code from "LZFSE compression library" was used.
|
||||
|
||||
2018 : Igor Pavlov : BSD 3-clause License : the code in this file
|
||||
2015-2017 : Apple Inc : BSD 3-clause License : original "LZFSE compression library" code
|
||||
|
||||
The code in the "LZFSE compression library" is licensed under the "BSD 3-clause License":
|
||||
----
|
||||
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
----
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #define SHOW_DEBUG_INFO
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
#define PRF(x) x
|
||||
#else
|
||||
#define PRF(x)
|
||||
#endif
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "LzfseDecoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NLzfse {
|
||||
|
||||
static const Byte kSignature_LZFSE_V1 = 0x31; // '1'
|
||||
static const Byte kSignature_LZFSE_V2 = 0x32; // '2'
|
||||
|
||||
|
||||
HRESULT CDecoder::GetUInt32(UInt32 &val)
|
||||
{
|
||||
Byte b[4];
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
if (!m_InStream.ReadByte(b[i]))
|
||||
return S_FALSE;
|
||||
val = GetUi32(b);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CDecoder::DecodeUncompressed(UInt32 unpackSize)
|
||||
{
|
||||
PRF(printf("\nUncompressed %7u\n", unpackSize));
|
||||
|
||||
const unsigned kBufSize = 1 << 8;
|
||||
Byte buf[kBufSize];
|
||||
for (;;)
|
||||
{
|
||||
if (unpackSize == 0)
|
||||
return S_OK;
|
||||
UInt32 cur = unpackSize;
|
||||
if (cur > kBufSize)
|
||||
cur = kBufSize;
|
||||
UInt32 cur2 = (UInt32)m_InStream.ReadBytes(buf, cur);
|
||||
m_OutWindowStream.PutBytes(buf, cur2);
|
||||
if (cur != cur2)
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CDecoder::DecodeLzvn(UInt32 unpackSize)
|
||||
{
|
||||
UInt32 packSize;
|
||||
RINOK(GetUInt32(packSize));
|
||||
|
||||
PRF(printf("\nLZVN %7u %7u", unpackSize, packSize));
|
||||
|
||||
UInt32 D = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (packSize == 0)
|
||||
return S_FALSE;
|
||||
Byte b;
|
||||
if (!m_InStream.ReadByte(b))
|
||||
return S_FALSE;
|
||||
packSize--;
|
||||
|
||||
UInt32 M;
|
||||
UInt32 L;
|
||||
|
||||
if (b >= 0xE0)
|
||||
{
|
||||
/*
|
||||
large L - 11100000 LLLLLLLL <LITERALS>
|
||||
small L - 1110LLLL <LITERALS>
|
||||
|
||||
large Rep - 11110000 MMMMMMMM
|
||||
small Rep - 1111MMMM
|
||||
*/
|
||||
|
||||
M = b & 0xF;
|
||||
if (M == 0)
|
||||
{
|
||||
if (packSize == 0)
|
||||
return S_FALSE;
|
||||
Byte b1;
|
||||
if (!m_InStream.ReadByte(b1))
|
||||
return S_FALSE;
|
||||
packSize--;
|
||||
M = (UInt32)b1 + 16;
|
||||
}
|
||||
L = 0;
|
||||
if ((b & 0x10) == 0)
|
||||
{
|
||||
// Literals only
|
||||
L = M;
|
||||
M = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ERROR codes
|
||||
else if ((b & 0xF0) == 0x70) // 0111xxxx
|
||||
return S_FALSE;
|
||||
else if ((b & 0xF0) == 0xD0) // 1101xxxx
|
||||
return S_FALSE;
|
||||
|
||||
else
|
||||
{
|
||||
if ((b & 0xE0) == 0xA0)
|
||||
{
|
||||
// medium - 101LLMMM DDDDDDMM DDDDDDDD <LITERALS>
|
||||
if (packSize < 2)
|
||||
return S_FALSE;
|
||||
Byte b1;
|
||||
if (!m_InStream.ReadByte(b1))
|
||||
return S_FALSE;
|
||||
packSize--;
|
||||
|
||||
Byte b2;
|
||||
if (!m_InStream.ReadByte(b2))
|
||||
return S_FALSE;
|
||||
packSize--;
|
||||
L = (((UInt32)b >> 3) & 3);
|
||||
M = (((UInt32)b & 7) << 2) + (b1 & 3);
|
||||
D = ((UInt32)b1 >> 2) + ((UInt32)b2 << 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
L = (UInt32)b >> 6;
|
||||
M = ((UInt32)b >> 3) & 7;
|
||||
if ((b & 0x7) == 6)
|
||||
{
|
||||
// REP - LLMMM110 <LITERALS>
|
||||
if (L == 0)
|
||||
{
|
||||
// spec
|
||||
if (M == 0)
|
||||
break; // EOS
|
||||
if (M <= 2)
|
||||
continue; // NOP
|
||||
return S_FALSE; // UNDEFINED
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (packSize == 0)
|
||||
return S_FALSE;
|
||||
Byte b1;
|
||||
if (!m_InStream.ReadByte(b1))
|
||||
return S_FALSE;
|
||||
packSize--;
|
||||
|
||||
// large - LLMMM111 DDDDDDDD DDDDDDDD <LITERALS>
|
||||
// small - LLMMMDDD DDDDDDDD <LITERALS>
|
||||
D = ((UInt32)b & 7);
|
||||
if (D == 7)
|
||||
{
|
||||
if (packSize == 0)
|
||||
return S_FALSE;
|
||||
Byte b2;
|
||||
if (!m_InStream.ReadByte(b2))
|
||||
return S_FALSE;
|
||||
packSize--;
|
||||
D = b2;
|
||||
}
|
||||
D = (D << 8) + b1;
|
||||
}
|
||||
}
|
||||
|
||||
M += 3;
|
||||
}
|
||||
{
|
||||
for (unsigned i = 0; i < L; i++)
|
||||
{
|
||||
if (packSize == 0 || unpackSize == 0)
|
||||
return S_FALSE;
|
||||
Byte b1;
|
||||
if (!m_InStream.ReadByte(b1))
|
||||
return S_FALSE;
|
||||
packSize--;
|
||||
m_OutWindowStream.PutByte(b1);
|
||||
unpackSize--;
|
||||
}
|
||||
}
|
||||
|
||||
if (M != 0)
|
||||
{
|
||||
if (unpackSize == 0 || D == 0)
|
||||
return S_FALSE;
|
||||
unsigned cur = M;
|
||||
if (cur > unpackSize)
|
||||
cur = (unsigned)unpackSize;
|
||||
if (!m_OutWindowStream.CopyBlock(D - 1, cur))
|
||||
return S_FALSE;
|
||||
unpackSize -= cur;
|
||||
if (cur != M)
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (unpackSize != 0)
|
||||
return S_FALSE;
|
||||
|
||||
// LZVN encoder writes 7 additional zero bytes
|
||||
if (packSize != 7)
|
||||
return S_FALSE;
|
||||
do
|
||||
{
|
||||
Byte b;
|
||||
if (!m_InStream.ReadByte(b))
|
||||
return S_FALSE;
|
||||
packSize--;
|
||||
if (b != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
while (packSize != 0);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- LZFSE ----------
|
||||
|
||||
#define MATCHES_PER_BLOCK 10000
|
||||
#define LITERALS_PER_BLOCK (4 * MATCHES_PER_BLOCK)
|
||||
|
||||
#define NUM_L_SYMBOLS 20
|
||||
#define NUM_M_SYMBOLS 20
|
||||
#define NUM_D_SYMBOLS 64
|
||||
#define NUM_LIT_SYMBOLS 256
|
||||
|
||||
#define NUM_SYMBOLS ( \
|
||||
NUM_L_SYMBOLS + \
|
||||
NUM_M_SYMBOLS + \
|
||||
NUM_D_SYMBOLS + \
|
||||
NUM_LIT_SYMBOLS)
|
||||
|
||||
#define NUM_L_STATES (1 << 6)
|
||||
#define NUM_M_STATES (1 << 6)
|
||||
#define NUM_D_STATES (1 << 8)
|
||||
#define NUM_LIT_STATES (1 << 10)
|
||||
|
||||
|
||||
typedef UInt32 CFseState;
|
||||
|
||||
|
||||
static UInt32 SumFreqs(const UInt16 *freqs, unsigned num)
|
||||
{
|
||||
UInt32 sum = 0;
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
sum += (UInt32)freqs[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
static MY_FORCE_INLINE unsigned CountZeroBits(UInt32 val, UInt32 mask)
|
||||
{
|
||||
for (unsigned i = 0;;)
|
||||
{
|
||||
if (val & mask)
|
||||
return i;
|
||||
i++;
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static MY_FORCE_INLINE void InitLitTable(const UInt16 *freqs, UInt32 *table)
|
||||
{
|
||||
for (unsigned i = 0; i < NUM_LIT_SYMBOLS; i++)
|
||||
{
|
||||
unsigned f = freqs[i];
|
||||
if (f == 0)
|
||||
continue;
|
||||
|
||||
// 0 < f <= numStates
|
||||
// 0 <= k <= numStatesLog
|
||||
// numStates <= (f<<k) < numStates * 2
|
||||
// 0 < j0 <= f
|
||||
// (f + j0) = next_power_of_2 for f
|
||||
unsigned k = CountZeroBits(f, NUM_LIT_STATES);
|
||||
unsigned j0 = (((unsigned)NUM_LIT_STATES * 2) >> k) - f;
|
||||
|
||||
/*
|
||||
CEntry
|
||||
{
|
||||
Byte k;
|
||||
Byte symbol;
|
||||
UInt16 delta;
|
||||
};
|
||||
*/
|
||||
|
||||
UInt32 e = ((UInt32)i << 8) + k;
|
||||
k += 16;
|
||||
UInt32 d = e + ((UInt32)f << k) - ((UInt32)NUM_LIT_STATES << 16);
|
||||
UInt32 step = (UInt32)1 << k;
|
||||
|
||||
unsigned j = 0;
|
||||
do
|
||||
{
|
||||
*table++ = d;
|
||||
d += step;
|
||||
}
|
||||
while (++j < j0);
|
||||
|
||||
e--;
|
||||
step >>= 1;
|
||||
|
||||
for (j = j0; j < f; j++)
|
||||
{
|
||||
*table++ = e;
|
||||
e += step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte totalBits;
|
||||
Byte extraBits;
|
||||
UInt16 delta;
|
||||
UInt32 vbase;
|
||||
} CExtraEntry;
|
||||
|
||||
|
||||
static void InitExtraDecoderTable(unsigned numStates,
|
||||
unsigned numSymbols,
|
||||
const UInt16 *freqs,
|
||||
const Byte *vbits,
|
||||
CExtraEntry *table)
|
||||
{
|
||||
UInt32 vbase = 0;
|
||||
|
||||
for (unsigned i = 0; i < numSymbols; i++)
|
||||
{
|
||||
unsigned f = freqs[i];
|
||||
unsigned extraBits = vbits[i];
|
||||
|
||||
if (f != 0)
|
||||
{
|
||||
unsigned k = CountZeroBits(f, numStates);
|
||||
unsigned j0 = ((2 * numStates) >> k) - f;
|
||||
|
||||
unsigned j = 0;
|
||||
do
|
||||
{
|
||||
CExtraEntry *e = table++;
|
||||
e->totalBits = (Byte)(k + extraBits);
|
||||
e->extraBits = (Byte)extraBits;
|
||||
e->delta = (UInt16)(((f + j) << k) - numStates);
|
||||
e->vbase = vbase;
|
||||
}
|
||||
while (++j < j0);
|
||||
|
||||
f -= j0;
|
||||
k--;
|
||||
|
||||
for (j = 0; j < f; j++)
|
||||
{
|
||||
CExtraEntry *e = table++;
|
||||
e->totalBits = (Byte)(k + extraBits);
|
||||
e->extraBits = (Byte)extraBits;
|
||||
e->delta = (UInt16)(j << k);
|
||||
e->vbase = vbase;
|
||||
}
|
||||
}
|
||||
|
||||
vbase += ((UInt32)1 << extraBits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const Byte k_L_extra[NUM_L_SYMBOLS] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 8
|
||||
};
|
||||
|
||||
static const Byte k_M_extra[NUM_M_SYMBOLS] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11
|
||||
};
|
||||
|
||||
static const Byte k_D_extra[NUM_D_SYMBOLS] =
|
||||
{
|
||||
0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
|
||||
8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11,
|
||||
12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ---------- CBitStream ----------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 accum;
|
||||
unsigned numBits; // [0, 31] - Number of valid bits in (accum), other bits are 0
|
||||
} CBitStream;
|
||||
|
||||
|
||||
static MY_FORCE_INLINE int FseInStream_Init(CBitStream *s,
|
||||
int n, // [-7, 0], (-n == number_of_unused_bits) in last byte
|
||||
const Byte **pbuf)
|
||||
{
|
||||
*pbuf -= 4;
|
||||
s->accum = GetUi32(*pbuf);
|
||||
if (n)
|
||||
{
|
||||
s->numBits = n + 32;
|
||||
if ((s->accum >> s->numBits) != 0)
|
||||
return -1; // ERROR, encoder should have zeroed the upper bits
|
||||
}
|
||||
else
|
||||
{
|
||||
*pbuf += 1;
|
||||
s->accum >>= 8;
|
||||
s->numBits = 24;
|
||||
}
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
|
||||
// 0 <= numBits < 32
|
||||
#define mask31(x, numBits) ((x) & (((UInt32)1 << (numBits)) - 1))
|
||||
|
||||
#define FseInStream_FLUSH \
|
||||
{ unsigned nbits = (31 - in.numBits) & -8; \
|
||||
if (nbits) { \
|
||||
buf -= (nbits >> 3); \
|
||||
if (buf < buf_check) return S_FALSE; \
|
||||
UInt32 v = GetUi32(buf); \
|
||||
in.accum = (in.accum << nbits) | mask31(v, nbits); \
|
||||
in.numBits += nbits; }}
|
||||
|
||||
|
||||
|
||||
static MY_FORCE_INLINE UInt32 BitStream_Pull(CBitStream *s, unsigned numBits)
|
||||
{
|
||||
s->numBits -= numBits;
|
||||
UInt32 v = s->accum >> s->numBits;
|
||||
s->accum = mask31(s->accum, s->numBits);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
#define DECODE_LIT(dest, pstate) { \
|
||||
UInt32 e = lit_decoder[pstate]; \
|
||||
pstate = (CFseState)((e >> 16) + BitStream_Pull(&in, e & 0xff)); \
|
||||
dest = (Byte)(e >> 8); }
|
||||
|
||||
|
||||
static MY_FORCE_INLINE UInt32 FseDecodeExtra(CFseState *pstate,
|
||||
const CExtraEntry *table,
|
||||
CBitStream *s)
|
||||
{
|
||||
const CExtraEntry *e = &table[*pstate];
|
||||
UInt32 v = BitStream_Pull(s, e->totalBits);
|
||||
unsigned extraBits = e->extraBits;
|
||||
*pstate = (CFseState)(e->delta + (v >> extraBits));
|
||||
return e->vbase + mask31(v, extraBits);
|
||||
}
|
||||
|
||||
|
||||
#define freqs_L (freqs)
|
||||
#define freqs_M (freqs_L + NUM_L_SYMBOLS)
|
||||
#define freqs_D (freqs_M + NUM_M_SYMBOLS)
|
||||
#define freqs_LIT (freqs_D + NUM_D_SYMBOLS)
|
||||
|
||||
#define GET_BITS_64(v, offset, num, dest) dest = (UInt32) ((v >> (offset)) & ((1 << (num)) - 1));
|
||||
#define GET_BITS_32(v, offset, num, dest) dest = (CFseState)((v >> (offset)) & ((1 << (num)) - 1));
|
||||
|
||||
|
||||
HRESULT CDecoder::DecodeLzfse(UInt32 unpackSize, Byte version)
|
||||
{
|
||||
PRF(printf("\nLZFSE-%d %7u", version - '0', unpackSize));
|
||||
|
||||
UInt32 numLiterals;
|
||||
UInt32 litPayloadSize;
|
||||
Int32 literal_bits;
|
||||
|
||||
UInt32 lit_state_0;
|
||||
UInt32 lit_state_1;
|
||||
UInt32 lit_state_2;
|
||||
UInt32 lit_state_3;
|
||||
|
||||
UInt32 numMatches;
|
||||
UInt32 lmdPayloadSize;
|
||||
Int32 lmd_bits;
|
||||
|
||||
CFseState l_state;
|
||||
CFseState m_state;
|
||||
CFseState d_state;
|
||||
|
||||
UInt16 freqs[NUM_SYMBOLS];
|
||||
|
||||
if (version == kSignature_LZFSE_V1)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
// we need examples to test LZFSE-V1 code
|
||||
/*
|
||||
const unsigned k_v1_SubHeaderSize = 7 * 4 + 7 * 2;
|
||||
const unsigned k_v1_HeaderSize = k_v1_SubHeaderSize + NUM_SYMBOLS * 2;
|
||||
_buffer.AllocAtLeast(k_v1_HeaderSize);
|
||||
if (m_InStream.ReadBytes(_buffer, k_v1_HeaderSize) != k_v1_HeaderSize)
|
||||
return S_FALSE;
|
||||
|
||||
const Byte *buf = _buffer;
|
||||
#define GET_32(offs, dest) dest = GetUi32(buf + offs)
|
||||
#define GET_16(offs, dest) dest = GetUi16(buf + offs)
|
||||
|
||||
UInt32 payload_bytes;
|
||||
GET_32(0, payload_bytes);
|
||||
GET_32(4, numLiterals);
|
||||
GET_32(8, numMatches);
|
||||
GET_32(12, litPayloadSize);
|
||||
GET_32(16, lmdPayloadSize);
|
||||
if (litPayloadSize > (1 << 20) || lmdPayloadSize > (1 << 20))
|
||||
return S_FALSE;
|
||||
GET_32(20, literal_bits);
|
||||
if (literal_bits < -7 || literal_bits > 0)
|
||||
return S_FALSE;
|
||||
|
||||
GET_16(24, lit_state_0);
|
||||
GET_16(26, lit_state_1);
|
||||
GET_16(28, lit_state_2);
|
||||
GET_16(30, lit_state_3);
|
||||
|
||||
GET_32(32, lmd_bits);
|
||||
if (lmd_bits < -7 || lmd_bits > 0)
|
||||
return S_FALSE;
|
||||
|
||||
GET_16(36, l_state);
|
||||
GET_16(38, m_state);
|
||||
GET_16(40, d_state);
|
||||
|
||||
for (unsigned i = 0; i < NUM_SYMBOLS; i++)
|
||||
freqs[i] = GetUi16(buf + k_v1_SubHeaderSize + i * 2);
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 headerSize;
|
||||
{
|
||||
const unsigned kPreHeaderSize = 4 * 2; // signature and upackSize
|
||||
const unsigned kHeaderSize = 8 * 3;
|
||||
Byte temp[kHeaderSize];
|
||||
if (m_InStream.ReadBytes(temp, kHeaderSize) != kHeaderSize)
|
||||
return S_FALSE;
|
||||
|
||||
UInt64 v;
|
||||
|
||||
v = GetUi64(temp);
|
||||
GET_BITS_64(v, 0, 20, numLiterals);
|
||||
GET_BITS_64(v, 20, 20, litPayloadSize);
|
||||
GET_BITS_64(v, 40, 20, numMatches);
|
||||
GET_BITS_64(v, 60, 3 + 1, literal_bits); // (NumberOfUsedBits - 1)
|
||||
literal_bits -= 7; // (-NumberOfUnusedBits)
|
||||
if (literal_bits > 0)
|
||||
return S_FALSE;
|
||||
// GET_BITS_64(v, 63, 1, unused);
|
||||
|
||||
v = GetUi64(temp + 8);
|
||||
GET_BITS_64(v, 0, 10, lit_state_0);
|
||||
GET_BITS_64(v, 10, 10, lit_state_1);
|
||||
GET_BITS_64(v, 20, 10, lit_state_2);
|
||||
GET_BITS_64(v, 30, 10, lit_state_3);
|
||||
GET_BITS_64(v, 40, 20, lmdPayloadSize);
|
||||
GET_BITS_64(v, 60, 3 + 1, lmd_bits);
|
||||
lmd_bits -= 7;
|
||||
if (lmd_bits > 0)
|
||||
return S_FALSE;
|
||||
// GET_BITS_64(v, 63, 1, unused)
|
||||
|
||||
UInt32 v32 = GetUi32(temp + 20);
|
||||
// (total header size in bytes; this does not
|
||||
// correspond to a field in the uncompressed header version,
|
||||
// but is required; we wouldn't know the size of the
|
||||
// compresssed header otherwise.
|
||||
GET_BITS_32(v32, 0, 10, l_state);
|
||||
GET_BITS_32(v32, 10, 10, m_state);
|
||||
GET_BITS_32(v32, 20, 10 + 2, d_state);
|
||||
// GET_BITS_64(v, 62, 2, unused);
|
||||
|
||||
headerSize = GetUi32(temp + 16);
|
||||
if (headerSize <= kPreHeaderSize + kHeaderSize)
|
||||
return S_FALSE;
|
||||
headerSize -= kPreHeaderSize + kHeaderSize;
|
||||
}
|
||||
|
||||
// no freqs case is not allowed ?
|
||||
// memset(freqs, 0, sizeof(freqs));
|
||||
// if (headerSize != 0)
|
||||
{
|
||||
static const Byte numBitsTable[32] =
|
||||
{
|
||||
2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14,
|
||||
2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14
|
||||
};
|
||||
|
||||
static const Byte valueTable[32] =
|
||||
{
|
||||
0, 2, 1, 4, 0, 3, 1, 8, 0, 2, 1, 5, 0, 3, 1, 24,
|
||||
0, 2, 1, 6, 0, 3, 1, 8, 0, 2, 1, 7, 0, 3, 1, 24
|
||||
};
|
||||
|
||||
UInt32 accum = 0;
|
||||
unsigned numBits = 0;
|
||||
|
||||
for (unsigned i = 0; i < NUM_SYMBOLS; i++)
|
||||
{
|
||||
while (numBits <= 14 && headerSize != 0)
|
||||
{
|
||||
Byte b;
|
||||
if (!m_InStream.ReadByte(b))
|
||||
return S_FALSE;
|
||||
accum |= (UInt32)b << numBits;
|
||||
numBits += 8;
|
||||
headerSize--;
|
||||
}
|
||||
|
||||
unsigned b = (unsigned)accum & 31;
|
||||
unsigned n = numBitsTable[b];
|
||||
if (numBits < n)
|
||||
return S_FALSE;
|
||||
numBits -= n;
|
||||
UInt32 f = valueTable[b];
|
||||
if (n >= 8)
|
||||
f += ((accum >> 4) & (0x3ff >> (14 - n)));
|
||||
accum >>= n;
|
||||
freqs[i] = (UInt16)f;
|
||||
}
|
||||
|
||||
if (numBits >= 8 || headerSize != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PRF(printf(" Literals=%6u Matches=%6u", numLiterals, numMatches));
|
||||
|
||||
if (numLiterals > LITERALS_PER_BLOCK
|
||||
|| (numLiterals & 3) != 0
|
||||
|| numMatches > MATCHES_PER_BLOCK
|
||||
|| lit_state_0 >= NUM_LIT_STATES
|
||||
|| lit_state_1 >= NUM_LIT_STATES
|
||||
|| lit_state_2 >= NUM_LIT_STATES
|
||||
|| lit_state_3 >= NUM_LIT_STATES
|
||||
|| l_state >= NUM_L_STATES
|
||||
|| m_state >= NUM_M_STATES
|
||||
|| d_state >= NUM_D_STATES)
|
||||
return S_FALSE;
|
||||
|
||||
// only full table is allowed ?
|
||||
if ( SumFreqs(freqs_L, NUM_L_SYMBOLS) != NUM_L_STATES
|
||||
|| SumFreqs(freqs_M, NUM_M_SYMBOLS) != NUM_M_STATES
|
||||
|| SumFreqs(freqs_D, NUM_D_SYMBOLS) != NUM_D_STATES
|
||||
|| SumFreqs(freqs_LIT, NUM_LIT_SYMBOLS) != NUM_LIT_STATES)
|
||||
return S_FALSE;
|
||||
|
||||
|
||||
const unsigned kPad = 16;
|
||||
|
||||
// ---------- Decode literals ----------
|
||||
|
||||
{
|
||||
_literals.AllocAtLeast(LITERALS_PER_BLOCK + 16);
|
||||
_buffer.AllocAtLeast(kPad + litPayloadSize);
|
||||
memset(_buffer, 0, kPad);
|
||||
|
||||
if (m_InStream.ReadBytes(_buffer + kPad, litPayloadSize) != litPayloadSize)
|
||||
return S_FALSE;
|
||||
|
||||
UInt32 lit_decoder[NUM_LIT_STATES];
|
||||
InitLitTable(freqs_LIT, lit_decoder);
|
||||
|
||||
const Byte *buf_start = _buffer + kPad;
|
||||
const Byte *buf_check = buf_start - 4;
|
||||
const Byte *buf = buf_start + litPayloadSize;
|
||||
CBitStream in;
|
||||
if (FseInStream_Init(&in, literal_bits, &buf) != 0)
|
||||
return S_FALSE;
|
||||
|
||||
Byte *lit = _literals;
|
||||
const Byte *lit_limit = lit + numLiterals;
|
||||
for (; lit < lit_limit; lit += 4)
|
||||
{
|
||||
FseInStream_FLUSH
|
||||
DECODE_LIT (lit[0], lit_state_0);
|
||||
DECODE_LIT (lit[1], lit_state_1);
|
||||
FseInStream_FLUSH
|
||||
DECODE_LIT (lit[2], lit_state_2);
|
||||
DECODE_LIT (lit[3], lit_state_3);
|
||||
}
|
||||
|
||||
if ((buf_start - buf) * 8 != (int)in.numBits)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
|
||||
// ---------- Decode LMD ----------
|
||||
|
||||
_buffer.AllocAtLeast(kPad + lmdPayloadSize);
|
||||
memset(_buffer, 0, kPad);
|
||||
if (m_InStream.ReadBytes(_buffer + kPad, lmdPayloadSize) != lmdPayloadSize)
|
||||
return S_FALSE;
|
||||
|
||||
CExtraEntry l_decoder[NUM_L_STATES];
|
||||
CExtraEntry m_decoder[NUM_M_STATES];
|
||||
CExtraEntry d_decoder[NUM_D_STATES];
|
||||
|
||||
InitExtraDecoderTable(NUM_L_STATES, NUM_L_SYMBOLS, freqs_L, k_L_extra, l_decoder);
|
||||
InitExtraDecoderTable(NUM_M_STATES, NUM_M_SYMBOLS, freqs_M, k_M_extra, m_decoder);
|
||||
InitExtraDecoderTable(NUM_D_STATES, NUM_D_SYMBOLS, freqs_D, k_D_extra, d_decoder);
|
||||
|
||||
const Byte *buf_start = _buffer + kPad;
|
||||
const Byte *buf_check = buf_start - 4;
|
||||
const Byte *buf = buf_start + lmdPayloadSize;
|
||||
CBitStream in;
|
||||
if (FseInStream_Init(&in, lmd_bits, &buf))
|
||||
return S_FALSE;
|
||||
|
||||
const Byte *lit = _literals;
|
||||
const Byte *lit_limit = lit + numLiterals;
|
||||
|
||||
UInt32 D = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (numMatches == 0)
|
||||
break;
|
||||
numMatches--;
|
||||
|
||||
FseInStream_FLUSH
|
||||
|
||||
unsigned L = (unsigned)FseDecodeExtra(&l_state, l_decoder, &in);
|
||||
|
||||
FseInStream_FLUSH
|
||||
|
||||
unsigned M = (unsigned)FseDecodeExtra(&m_state, m_decoder, &in);
|
||||
|
||||
FseInStream_FLUSH
|
||||
|
||||
{
|
||||
UInt32 new_D = FseDecodeExtra(&d_state, d_decoder, &in);
|
||||
if (new_D)
|
||||
D = new_D;
|
||||
}
|
||||
|
||||
if (L != 0)
|
||||
{
|
||||
if (L > (size_t)(lit_limit - lit))
|
||||
return S_FALSE;
|
||||
unsigned cur = L;
|
||||
if (cur > unpackSize)
|
||||
cur = (unsigned)unpackSize;
|
||||
m_OutWindowStream.PutBytes(lit, cur);
|
||||
unpackSize -= cur;
|
||||
lit += cur;
|
||||
if (cur != L)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (M != 0)
|
||||
{
|
||||
if (unpackSize == 0 || D == 0)
|
||||
return S_FALSE;
|
||||
unsigned cur = M;
|
||||
if (cur > unpackSize)
|
||||
cur = (unsigned)unpackSize;
|
||||
if (!m_OutWindowStream.CopyBlock(D - 1, cur))
|
||||
return S_FALSE;
|
||||
unpackSize -= cur;
|
||||
if (cur != M)
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (unpackSize != 0)
|
||||
return S_FALSE;
|
||||
|
||||
// LZFSE encoder writes 8 additional zero bytes before LMD payload
|
||||
// We test it:
|
||||
if ((buf - buf_start) * 8 + in.numBits != 64)
|
||||
return S_FALSE;
|
||||
if (GetUi64(buf_start) != 0)
|
||||
return S_FALSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
PRF(printf("\n\nLzfseDecoder %7u %7u\n", (unsigned)*outSize, (unsigned)*inSize));
|
||||
|
||||
const UInt32 kLzfseDictSize = 1 << 18;
|
||||
if (!m_OutWindowStream.Create(kLzfseDictSize))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!m_InStream.Create(1 << 18))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
m_OutWindowStream.SetStream(outStream);
|
||||
m_OutWindowStream.Init(false);
|
||||
m_InStream.SetStream(inStream);
|
||||
m_InStream.Init();
|
||||
|
||||
CCoderReleaser coderReleaser(this);
|
||||
|
||||
UInt64 prevOut = 0;
|
||||
UInt64 prevIn = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const UInt64 pos = m_OutWindowStream.GetProcessedSize();
|
||||
const UInt64 packPos = m_InStream.GetProcessedSize();
|
||||
|
||||
if (progress && ((pos - prevOut) >= (1 << 22) || (packPos - prevIn) >= (1 << 22)))
|
||||
{
|
||||
RINOK(progress->SetRatioInfo(&packPos, &pos));
|
||||
prevIn = packPos;
|
||||
prevOut = pos;
|
||||
}
|
||||
|
||||
const UInt64 rem = *outSize - pos;
|
||||
UInt32 v;
|
||||
RINOK(GetUInt32(v))
|
||||
if ((v & 0xFFFFFF) != 0x787662) // bvx
|
||||
return S_FALSE;
|
||||
v >>= 24;
|
||||
|
||||
if (v == 0x24) // '$', end of stream
|
||||
break;
|
||||
|
||||
UInt32 unpackSize;
|
||||
RINOK(GetUInt32(unpackSize));
|
||||
|
||||
UInt32 cur = unpackSize;
|
||||
if (cur > rem)
|
||||
cur = (UInt32)rem;
|
||||
|
||||
unpackSize -= cur;
|
||||
|
||||
HRESULT res;
|
||||
if (v == kSignature_LZFSE_V1 || v == kSignature_LZFSE_V2)
|
||||
res = DecodeLzfse(cur, (Byte)v);
|
||||
else if (v == 0x6E) // 'n'
|
||||
res = DecodeLzvn(cur);
|
||||
else if (v == 0x2D) // '-'
|
||||
res = DecodeUncompressed(cur);
|
||||
else
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
|
||||
if (unpackSize != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
coderReleaser.NeedFlush = false;
|
||||
HRESULT res = m_OutWindowStream.Flush();
|
||||
if (res == S_OK)
|
||||
if (*inSize != m_InStream.GetProcessedSize()
|
||||
|| *outSize != m_OutWindowStream.GetProcessedSize())
|
||||
res = S_FALSE;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(const CLzOutWindowException &e) { return e.ErrorCode; }
|
||||
catch(...) { return E_OUTOFMEMORY; }
|
||||
// catch(...) { return S_FALSE; }
|
||||
}
|
||||
|
||||
}}
|
||||
58
CPP/7zip/Compress/LzfseDecoder.h
Normal file
58
CPP/7zip/Compress/LzfseDecoder.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// LzfseDecoder.h
|
||||
|
||||
#ifndef __LZFSE_DECODER_H
|
||||
#define __LZFSE_DECODER_H
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
#include "../Common/InBuffer.h"
|
||||
|
||||
#include "LzOutWindow.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NLzfse {
|
||||
|
||||
class CDecoder:
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLzOutWindow m_OutWindowStream;
|
||||
CInBuffer m_InStream;
|
||||
CByteBuffer _literals;
|
||||
CByteBuffer _buffer;
|
||||
|
||||
class CCoderReleaser
|
||||
{
|
||||
CDecoder *m_Coder;
|
||||
public:
|
||||
bool NeedFlush;
|
||||
CCoderReleaser(CDecoder *coder): m_Coder(coder), NeedFlush(true) {}
|
||||
~CCoderReleaser()
|
||||
{
|
||||
if (NeedFlush)
|
||||
m_Coder->m_OutWindowStream.Flush();
|
||||
}
|
||||
};
|
||||
friend class CCoderReleaser;
|
||||
|
||||
HRESULT GetUInt32(UInt32 &val);
|
||||
|
||||
HRESULT DecodeUncompressed(UInt32 unpackSize);
|
||||
HRESULT DecodeLzvn(UInt32 unpackSize);
|
||||
HRESULT DecodeLzfse(UInt32 unpackSize, Byte version);
|
||||
|
||||
STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize,
|
||||
const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -2,81 +2,48 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
// #include "../../../C/CpuTicks.h"
|
||||
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "Lzma2Decoder.h"
|
||||
|
||||
static HRESULT SResToHRESULT(SRes res)
|
||||
{
|
||||
switch (res)
|
||||
{
|
||||
case SZ_OK: return S_OK;
|
||||
case SZ_ERROR_MEM: return E_OUTOFMEMORY;
|
||||
case SZ_ERROR_PARAM: return E_INVALIDARG;
|
||||
case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
|
||||
case SZ_ERROR_DATA: return S_FALSE;
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
namespace NCompress {
|
||||
namespace NLzma2 {
|
||||
|
||||
CDecoder::CDecoder():
|
||||
_inBuf(NULL),
|
||||
_finishMode(false),
|
||||
_outSizeDefined(false),
|
||||
_outStep(1 << 22),
|
||||
_inBufSize(0),
|
||||
_inBufSizeNew(1 << 20)
|
||||
{
|
||||
Lzma2Dec_Construct(&_state);
|
||||
}
|
||||
_dec(NULL)
|
||||
, _inProcessed(0)
|
||||
, _prop(0xFF)
|
||||
, _finishMode(false)
|
||||
, _inBufSize(1 << 20)
|
||||
, _outStep(1 << 20)
|
||||
#ifndef _7ZIP_ST
|
||||
, _tryMt(1)
|
||||
, _numThreads(1)
|
||||
, _memUsage((UInt64)(sizeof(size_t)) << 28)
|
||||
#endif
|
||||
{}
|
||||
|
||||
CDecoder::~CDecoder()
|
||||
{
|
||||
Lzma2Dec_Free(&_state, &g_Alloc);
|
||||
MidFree(_inBuf);
|
||||
if (_dec)
|
||||
Lzma2DecMt_Destroy(_dec);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; }
|
||||
STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
|
||||
STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; }
|
||||
|
||||
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
|
||||
{
|
||||
if (size != 1)
|
||||
return E_NOTIMPL;
|
||||
|
||||
RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc)));
|
||||
|
||||
if (!_inBuf || _inBufSize != _inBufSizeNew)
|
||||
{
|
||||
MidFree(_inBuf);
|
||||
_inBufSize = 0;
|
||||
_inBuf = (Byte *)MidAlloc(_inBufSizeNew);
|
||||
if (!_inBuf)
|
||||
return E_OUTOFMEMORY;
|
||||
_inBufSize = _inBufSizeNew;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
{
|
||||
_outSizeDefined = (outSize != NULL);
|
||||
_outSize = 0;
|
||||
if (_outSizeDefined)
|
||||
_outSize = *outSize;
|
||||
_inPos = _inLim = 0;
|
||||
_inProcessed = 0;
|
||||
_outProcessed = 0;
|
||||
|
||||
Lzma2Dec_Init(&_state);
|
||||
|
||||
if (prop[0] > 40)
|
||||
return E_NOTIMPL;
|
||||
_prop = prop[0];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -88,6 +55,137 @@ STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
static UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize)
|
||||
{
|
||||
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||
UInt64 blockSize = (UInt64)dictSize << 2;
|
||||
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||
if (blockSize < dictSize) blockSize = dictSize;
|
||||
blockSize += (kMinSize - 1);
|
||||
blockSize &= ~(UInt64)(kMinSize - 1);
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
#define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)))
|
||||
|
||||
#endif
|
||||
|
||||
#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \
|
||||
if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;
|
||||
|
||||
#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
|
||||
if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
_inProcessed = 0;
|
||||
|
||||
if (!_dec)
|
||||
{
|
||||
_dec = Lzma2DecMt_Create(
|
||||
// &g_AlignedAlloc,
|
||||
&g_Alloc,
|
||||
&g_MidAlloc);
|
||||
if (!_dec)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
CLzma2DecMtProps props;
|
||||
Lzma2DecMtProps_Init(&props);
|
||||
|
||||
props.inBufSize_ST = _inBufSize;
|
||||
props.outStep_ST = _outStep;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
{
|
||||
props.numThreads = 1;
|
||||
UInt32 numThreads = _numThreads;
|
||||
|
||||
if (_tryMt && numThreads >= 1)
|
||||
{
|
||||
UInt64 useLimit = _memUsage;
|
||||
UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop);
|
||||
UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize);
|
||||
size_t expectedBlockSize = (size_t)expectedBlockSize64;
|
||||
size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16;
|
||||
if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize)
|
||||
{
|
||||
props.outBlockMax = expectedBlockSize;
|
||||
props.inBlockMax = inBlockMax;
|
||||
const size_t kOverheadSize = props.inBufSize_MT + (1 << 16);
|
||||
UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize);
|
||||
if (numThreads > okThreads)
|
||||
numThreads = (UInt32)okThreads;
|
||||
if (numThreads == 0)
|
||||
numThreads = 1;
|
||||
props.numThreads = numThreads;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CSeqInStreamWrap inWrap;
|
||||
CSeqOutStreamWrap outWrap;
|
||||
CCompressProgressWrap progressWrap;
|
||||
|
||||
inWrap.Init(inStream);
|
||||
outWrap.Init(outStream);
|
||||
progressWrap.Init(progress);
|
||||
|
||||
SRes res;
|
||||
|
||||
UInt64 inProcessed = 0;
|
||||
int isMT = False;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
isMT = _tryMt;
|
||||
#endif
|
||||
|
||||
// UInt64 cpuTicks = GetCpuTicks();
|
||||
|
||||
res = Lzma2DecMt_Decode(_dec, _prop, &props,
|
||||
&outWrap.vt, outSize, _finishMode,
|
||||
&inWrap.vt,
|
||||
&inProcessed,
|
||||
&isMT,
|
||||
progress ? &progressWrap.vt : NULL);
|
||||
|
||||
/*
|
||||
cpuTicks = GetCpuTicks() - cpuTicks;
|
||||
printf("\n ticks = %10I64u\n", cpuTicks / 1000000);
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
/* we reset _tryMt, only if p->props.numThreads was changed */
|
||||
if (props.numThreads > 1)
|
||||
_tryMt = isMT;
|
||||
#endif
|
||||
|
||||
_inProcessed = inProcessed;
|
||||
|
||||
RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
|
||||
RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
|
||||
RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
|
||||
|
||||
if (res == SZ_OK && _finishMode)
|
||||
{
|
||||
if (inSize && *inSize != inProcessed)
|
||||
res = SZ_ERROR_DATA;
|
||||
if (outSize && *outSize != outWrap.Processed)
|
||||
res = SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
return SResToHRESULT(res);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
{
|
||||
*value = _inProcessed;
|
||||
@@ -95,109 +193,51 @@ STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)
|
||||
{
|
||||
if (!_inBuf)
|
||||
return S_FALSE;
|
||||
|
||||
SetOutStreamSize(outSize);
|
||||
|
||||
SizeT wrPos = _state.decoder.dicPos;
|
||||
HRESULT readRes = S_OK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (_inPos == _inLim && readRes == S_OK)
|
||||
{
|
||||
_inPos = _inLim = 0;
|
||||
readRes = inStream->Read(_inBuf, _inBufSize, &_inLim);
|
||||
}
|
||||
|
||||
const SizeT dicPos = _state.decoder.dicPos;
|
||||
SizeT size;
|
||||
{
|
||||
SizeT next = _state.decoder.dicBufSize;
|
||||
if (next - wrPos > _outStep)
|
||||
next = wrPos + _outStep;
|
||||
size = next - dicPos;
|
||||
}
|
||||
|
||||
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
const UInt64 rem = _outSize - _outProcessed;
|
||||
if (size >= rem)
|
||||
{
|
||||
size = (SizeT)rem;
|
||||
if (_finishMode)
|
||||
finishMode = LZMA_FINISH_END;
|
||||
}
|
||||
}
|
||||
|
||||
SizeT inProcessed = _inLim - _inPos;
|
||||
ELzmaStatus status;
|
||||
|
||||
SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status);
|
||||
|
||||
|
||||
_inPos += (UInt32)inProcessed;
|
||||
_inProcessed += inProcessed;
|
||||
const SizeT outProcessed = _state.decoder.dicPos - dicPos;
|
||||
_outProcessed += outProcessed;
|
||||
|
||||
|
||||
bool outFinished = (_outSizeDefined && _outProcessed >= _outSize);
|
||||
|
||||
bool needStop = (res != 0
|
||||
|| (inProcessed == 0 && outProcessed == 0)
|
||||
|| status == LZMA_STATUS_FINISHED_WITH_MARK
|
||||
|| (!_finishMode && outFinished));
|
||||
|
||||
if (needStop || outProcessed >= size)
|
||||
{
|
||||
HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos);
|
||||
|
||||
if (_state.decoder.dicPos == _state.decoder.dicBufSize)
|
||||
_state.decoder.dicPos = 0;
|
||||
wrPos = _state.decoder.dicPos;
|
||||
|
||||
RINOK(res2);
|
||||
|
||||
if (needStop)
|
||||
{
|
||||
if (res != 0)
|
||||
return S_FALSE;
|
||||
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
if (_finishMode)
|
||||
{
|
||||
if (inSize && *inSize != _inProcessed)
|
||||
return S_FALSE;
|
||||
if (_outSizeDefined && _outSize != _outProcessed)
|
||||
return S_FALSE;
|
||||
}
|
||||
return readRes;
|
||||
}
|
||||
|
||||
if (!_finishMode && outFinished)
|
||||
return readRes;
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (progress)
|
||||
{
|
||||
RINOK(progress->SetRatioInfo(&_inProcessed, &_outProcessed));
|
||||
}
|
||||
}
|
||||
_numThreads = numThreads;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetMemLimit(UInt64 memUsage)
|
||||
{
|
||||
_memUsage = memUsage;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
|
||||
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
{
|
||||
CLzma2DecMtProps props;
|
||||
Lzma2DecMtProps_Init(&props);
|
||||
props.inBufSize_ST = _inBufSize;
|
||||
props.outStep_ST = _outStep;
|
||||
|
||||
_inProcessed = 0;
|
||||
|
||||
if (!_dec)
|
||||
{
|
||||
_dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc);
|
||||
if (!_dec)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
_inWrap.Init(_inStream);
|
||||
|
||||
SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt);
|
||||
|
||||
if (res != SZ_OK)
|
||||
return SResToHRESULT(res);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
|
||||
STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
|
||||
|
||||
@@ -207,62 +247,17 @@ STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
const UInt64 rem = _outSize - _outProcessed;
|
||||
if (size >= rem)
|
||||
{
|
||||
size = (UInt32)rem;
|
||||
if (_finishMode)
|
||||
finishMode = LZMA_FINISH_END;
|
||||
}
|
||||
}
|
||||
size_t size2 = size;
|
||||
UInt64 inProcessed = 0;
|
||||
|
||||
HRESULT readRes = S_OK;
|
||||
SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (_inPos == _inLim && readRes == S_OK)
|
||||
{
|
||||
_inPos = _inLim = 0;
|
||||
readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
|
||||
}
|
||||
|
||||
SizeT inProcessed = _inLim - _inPos;
|
||||
SizeT outProcessed = size;
|
||||
ELzmaStatus status;
|
||||
|
||||
SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
|
||||
_inBuf + _inPos, &inProcessed, finishMode, &status);
|
||||
|
||||
|
||||
_inPos += (UInt32)inProcessed;
|
||||
_inProcessed += inProcessed;
|
||||
_outProcessed += outProcessed;
|
||||
size -= (UInt32)outProcessed;
|
||||
data = (Byte *)data + outProcessed;
|
||||
if (processedSize)
|
||||
*processedSize += (UInt32)outProcessed;
|
||||
|
||||
if (res != 0)
|
||||
return S_FALSE;
|
||||
|
||||
/*
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
return readRes;
|
||||
|
||||
if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
{
|
||||
if (_finishMode && _outSizeDefined && _outProcessed >= _outSize)
|
||||
return S_FALSE;
|
||||
return readRes;
|
||||
}
|
||||
*/
|
||||
|
||||
if (inProcessed == 0 && outProcessed == 0)
|
||||
return readRes;
|
||||
}
|
||||
_inProcessed += inProcessed;
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)size2;
|
||||
if (res != SZ_OK)
|
||||
return SResToHRESULT(res);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
#ifndef __LZMA2_DECODER_H
|
||||
#define __LZMA2_DECODER_H
|
||||
|
||||
#include "../../../C/Lzma2Dec.h"
|
||||
#include "../../../C/Lzma2DecMt.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../ICoder.h"
|
||||
#include "../Common/CWrappers.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NLzma2 {
|
||||
@@ -17,28 +16,26 @@ class CDecoder:
|
||||
public ICompressSetFinishMode,
|
||||
public ICompressGetInStreamProcessedSize,
|
||||
public ICompressSetBufSize,
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
public ICompressSetInStream,
|
||||
public ICompressSetOutStreamSize,
|
||||
public ISequentialInStream,
|
||||
#endif
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
public ICompressSetCoderMt,
|
||||
public ICompressSetMemLimit,
|
||||
#endif
|
||||
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Byte *_inBuf;
|
||||
UInt32 _inPos;
|
||||
UInt32 _inLim;
|
||||
|
||||
bool _finishMode;
|
||||
bool _outSizeDefined;
|
||||
UInt64 _outSize;
|
||||
CLzma2DecMtHandle _dec;
|
||||
UInt64 _inProcessed;
|
||||
UInt64 _outProcessed;
|
||||
|
||||
UInt32 _outStep;
|
||||
Byte _prop;
|
||||
int _finishMode;
|
||||
UInt32 _inBufSize;
|
||||
UInt32 _inBufSizeNew;
|
||||
|
||||
CLzma2Dec _state;
|
||||
UInt32 _outStep;
|
||||
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
|
||||
@@ -46,11 +43,18 @@ public:
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
|
||||
#endif
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetMemLimit)
|
||||
#endif
|
||||
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
@@ -59,20 +63,28 @@ public:
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
#ifndef _7ZIP_ST
|
||||
private:
|
||||
int _tryMt;
|
||||
UInt32 _numThreads;
|
||||
UInt64 _memUsage;
|
||||
public:
|
||||
STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
|
||||
STDMETHOD(SetMemLimit)(UInt64 memUsage);
|
||||
#endif
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
private:
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
CSeqInStreamWrap _inWrap;
|
||||
public:
|
||||
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
#endif
|
||||
|
||||
CDecoder();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user