Update LZMA SDK files to version 18.05

pull/1635/head
jsteube 6 years ago
parent cc8fa3ee80
commit 5ea70dc549

@ -1,374 +1,374 @@
/* 7zTypes.h -- Basic types /* 7zTypes.h -- Basic types
2017-07-17 : Igor Pavlov : Public domain */ 2017-07-17 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H #ifndef __7Z_TYPES_H
#define __7Z_TYPES_H #define __7Z_TYPES_H
#ifdef _WIN32 #ifdef _WIN32
/* #include <windows.h> */ /* #include <windows.h> */
#endif #endif
#include <stddef.h> #include <stddef.h>
#ifndef EXTERN_C_BEGIN #ifndef EXTERN_C_BEGIN
#ifdef __cplusplus #ifdef __cplusplus
#define EXTERN_C_BEGIN extern "C" { #define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END } #define EXTERN_C_END }
#else #else
#define EXTERN_C_BEGIN #define EXTERN_C_BEGIN
#define EXTERN_C_END #define EXTERN_C_END
#endif #endif
#endif #endif
EXTERN_C_BEGIN EXTERN_C_BEGIN
#define SZ_OK 0 #define SZ_OK 0
#define SZ_ERROR_DATA 1 #define SZ_ERROR_DATA 1
#define SZ_ERROR_MEM 2 #define SZ_ERROR_MEM 2
#define SZ_ERROR_CRC 3 #define SZ_ERROR_CRC 3
#define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_UNSUPPORTED 4
#define SZ_ERROR_PARAM 5 #define SZ_ERROR_PARAM 5
#define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_INPUT_EOF 6
#define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_OUTPUT_EOF 7
#define SZ_ERROR_READ 8 #define SZ_ERROR_READ 8
#define SZ_ERROR_WRITE 9 #define SZ_ERROR_WRITE 9
#define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_PROGRESS 10
#define SZ_ERROR_FAIL 11 #define SZ_ERROR_FAIL 11
#define SZ_ERROR_THREAD 12 #define SZ_ERROR_THREAD 12
#define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_ARCHIVE 16
#define SZ_ERROR_NO_ARCHIVE 17 #define SZ_ERROR_NO_ARCHIVE 17
typedef int SRes; typedef int SRes;
#ifdef _WIN32 #ifdef _WIN32
/* typedef DWORD WRes; */ /* typedef DWORD WRes; */
typedef unsigned WRes; typedef unsigned WRes;
#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x) #define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
#else #else
typedef int WRes; typedef int WRes;
#define MY__FACILITY_WIN32 7 #define MY__FACILITY_WIN32 7
#define MY__FACILITY__WRes MY__FACILITY_WIN32 #define MY__FACILITY__WRes MY__FACILITY_WIN32
#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000))) #define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
#endif #endif
#ifndef RINOK #ifndef RINOK
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
#endif #endif
typedef unsigned char Byte; typedef unsigned char Byte;
typedef short Int16; typedef short Int16;
typedef unsigned short UInt16; typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG #ifdef _LZMA_UINT32_IS_ULONG
typedef long Int32; typedef long Int32;
typedef unsigned long UInt32; typedef unsigned long UInt32;
#else #else
typedef int Int32; typedef int Int32;
typedef unsigned int UInt32; typedef unsigned int UInt32;
#endif #endif
#ifdef _SZ_NO_INT_64 #ifdef _SZ_NO_INT_64
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
NOTES: Some code will work incorrectly in that case! */ NOTES: Some code will work incorrectly in that case! */
typedef long Int64; typedef long Int64;
typedef unsigned long UInt64; typedef unsigned long UInt64;
#else #else
#if defined(_MSC_VER) || defined(__BORLANDC__) #if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64; typedef __int64 Int64;
typedef unsigned __int64 UInt64; typedef unsigned __int64 UInt64;
#define UINT64_CONST(n) n #define UINT64_CONST(n) n
#else #else
typedef long long int Int64; typedef long long int Int64;
typedef unsigned long long int UInt64; typedef unsigned long long int UInt64;
#define UINT64_CONST(n) n ## ULL #define UINT64_CONST(n) n ## ULL
#endif #endif
#endif #endif
#ifdef _LZMA_NO_SYSTEM_SIZE_T #ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT; typedef UInt32 SizeT;
#else #else
typedef size_t SizeT; typedef size_t SizeT;
#endif #endif
typedef int Bool; typedef int Bool;
#define True 1 #define True 1
#define False 0 #define False 0
#ifdef _WIN32 #ifdef _WIN32
#define MY_STD_CALL __stdcall #define MY_STD_CALL __stdcall
#else #else
#define MY_STD_CALL #define MY_STD_CALL
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
#if _MSC_VER >= 1300 #if _MSC_VER >= 1300
#define MY_NO_INLINE __declspec(noinline) #define MY_NO_INLINE __declspec(noinline)
#else #else
#define MY_NO_INLINE #define MY_NO_INLINE
#endif #endif
#define MY_FORCE_INLINE __forceinline #define MY_FORCE_INLINE __forceinline
#define MY_CDECL __cdecl #define MY_CDECL __cdecl
#define MY_FAST_CALL __fastcall #define MY_FAST_CALL __fastcall
#else #else
#define MY_NO_INLINE #define MY_NO_INLINE
#define MY_FORCE_INLINE #define MY_FORCE_INLINE
#define MY_CDECL #define MY_CDECL
#define MY_FAST_CALL #define MY_FAST_CALL
/* inline keyword : for C++ / C99 */ /* inline keyword : for C++ / C99 */
/* GCC, clang: */ /* GCC, clang: */
/* /*
#if defined (__GNUC__) && (__GNUC__ >= 4) #if defined (__GNUC__) && (__GNUC__ >= 4)
#define MY_FORCE_INLINE __attribute__((always_inline)) #define MY_FORCE_INLINE __attribute__((always_inline))
#define MY_NO_INLINE __attribute__((noinline)) #define MY_NO_INLINE __attribute__((noinline))
#endif #endif
*/ */
#endif #endif
/* The following interfaces use first parameter as pointer to structure */ /* The following interfaces use first parameter as pointer to structure */
typedef struct IByteIn IByteIn; typedef struct IByteIn IByteIn;
struct IByteIn struct IByteIn
{ {
Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */ Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */
}; };
#define IByteIn_Read(p) (p)->Read(p) #define IByteIn_Read(p) (p)->Read(p)
typedef struct IByteOut IByteOut; typedef struct IByteOut IByteOut;
struct IByteOut struct IByteOut
{ {
void (*Write)(const IByteOut *p, Byte b); void (*Write)(const IByteOut *p, Byte b);
}; };
#define IByteOut_Write(p, b) (p)->Write(p, b) #define IByteOut_Write(p, b) (p)->Write(p, b)
typedef struct ISeqInStream ISeqInStream; typedef struct ISeqInStream ISeqInStream;
struct ISeqInStream struct ISeqInStream
{ {
SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size); SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */ (output(*size) < input(*size)) is allowed */
}; };
#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size) #define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
/* it can return SZ_ERROR_INPUT_EOF */ /* it can return SZ_ERROR_INPUT_EOF */
SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size);
SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType);
SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf); SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf);
typedef struct ISeqOutStream ISeqOutStream; typedef struct ISeqOutStream ISeqOutStream;
struct ISeqOutStream struct ISeqOutStream
{ {
size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size); size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes. /* Returns: result - the number of actually written bytes.
(result < size) means error */ (result < size) means error */
}; };
#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size) #define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
typedef enum typedef enum
{ {
SZ_SEEK_SET = 0, SZ_SEEK_SET = 0,
SZ_SEEK_CUR = 1, SZ_SEEK_CUR = 1,
SZ_SEEK_END = 2 SZ_SEEK_END = 2
} ESzSeek; } ESzSeek;
typedef struct ISeekInStream ISeekInStream; typedef struct ISeekInStream ISeekInStream;
struct ISeekInStream struct ISeekInStream
{ {
SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin); SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin);
}; };
#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size) #define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size)
#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) #define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
typedef struct ILookInStream ILookInStream; typedef struct ILookInStream ILookInStream;
struct ILookInStream struct ILookInStream
{ {
SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size); SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed (output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */ (output(*size) < input(*size)) is allowed */
SRes (*Skip)(const ILookInStream *p, size_t offset); SRes (*Skip)(const ILookInStream *p, size_t offset);
/* offset must be <= output(*size) of Look */ /* offset must be <= output(*size) of Look */
SRes (*Read)(const ILookInStream *p, void *buf, size_t *size); SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */ /* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin); SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin);
}; };
#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size) #define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size)
#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset) #define ILookInStream_Skip(p, offset) (p)->Skip(p, offset)
#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size) #define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size)
#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) #define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size); SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size);
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset); SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset);
/* reads via ILookInStream::Read */ /* reads via ILookInStream::Read */
SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType);
SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size); SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size);
typedef struct typedef struct
{ {
ILookInStream vt; ILookInStream vt;
const ISeekInStream *realStream; const ISeekInStream *realStream;
size_t pos; size_t pos;
size_t size; /* it's data size */ size_t size; /* it's data size */
/* the following variables must be set outside */ /* the following variables must be set outside */
Byte *buf; Byte *buf;
size_t bufSize; size_t bufSize;
} CLookToRead2; } CLookToRead2;
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead); void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);
#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; } #define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; }
typedef struct typedef struct
{ {
ISeqInStream vt; ISeqInStream vt;
const ILookInStream *realStream; const ILookInStream *realStream;
} CSecToLook; } CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p); void SecToLook_CreateVTable(CSecToLook *p);
typedef struct typedef struct
{ {
ISeqInStream vt; ISeqInStream vt;
const ILookInStream *realStream; const ILookInStream *realStream;
} CSecToRead; } CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p); void SecToRead_CreateVTable(CSecToRead *p);
typedef struct ICompressProgress ICompressProgress; typedef struct ICompressProgress ICompressProgress;
struct ICompressProgress struct ICompressProgress
{ {
SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize); SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break. /* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */ Value (UInt64)(Int64)-1 for size means unknown value. */
}; };
#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize) #define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
typedef struct ISzAlloc ISzAlloc; typedef struct ISzAlloc ISzAlloc;
typedef const ISzAlloc * ISzAllocPtr; typedef const ISzAlloc * ISzAllocPtr;
struct ISzAlloc struct ISzAlloc
{ {
void *(*Alloc)(ISzAllocPtr p, size_t size); void *(*Alloc)(ISzAllocPtr p, size_t size);
void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */ void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
}; };
#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size) #define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)
#define ISzAlloc_Free(p, a) (p)->Free(p, a) #define ISzAlloc_Free(p, a) (p)->Free(p, a)
/* deprecated */ /* deprecated */
#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size) #define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)
#define IAlloc_Free(p, a) ISzAlloc_Free(p, a) #define IAlloc_Free(p, a) ISzAlloc_Free(p, a)
#ifndef MY_offsetof #ifndef MY_offsetof
#ifdef offsetof #ifdef offsetof
#define MY_offsetof(type, m) offsetof(type, m) #define MY_offsetof(type, m) offsetof(type, m)
/* /*
#define MY_offsetof(type, m) FIELD_OFFSET(type, m) #define MY_offsetof(type, m) FIELD_OFFSET(type, m)
*/ */
#else #else
#define MY_offsetof(type, m) ((size_t)&(((type *)0)->m)) #define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))
#endif #endif
#endif #endif
#ifndef MY_container_of #ifndef MY_container_of
/* /*
#define MY_container_of(ptr, type, m) container_of(ptr, type, m) #define MY_container_of(ptr, type, m) container_of(ptr, type, m)
#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m) #define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)
#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m))) #define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))
#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m)))) #define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))
*/ */
/* /*
GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly" GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly"
GCC 3.4.4 : classes with constructor GCC 3.4.4 : classes with constructor
GCC 4.8.1 : classes with non-public variable members" GCC 4.8.1 : classes with non-public variable members"
*/ */
#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) #define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
#endif #endif
#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr)) #define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr))
/* /*
#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) #define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
*/ */
#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m) #define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m)
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) #define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
/* /*
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m) #define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m)
*/ */
#ifdef _WIN32 #ifdef _WIN32
#define CHAR_PATH_SEPARATOR '\\' #define CHAR_PATH_SEPARATOR '\\'
#define WCHAR_PATH_SEPARATOR L'\\' #define WCHAR_PATH_SEPARATOR L'\\'
#define STRING_PATH_SEPARATOR "\\" #define STRING_PATH_SEPARATOR "\\"
#define WSTRING_PATH_SEPARATOR L"\\" #define WSTRING_PATH_SEPARATOR L"\\"
#else #else
#define CHAR_PATH_SEPARATOR '/' #define CHAR_PATH_SEPARATOR '/'
#define WCHAR_PATH_SEPARATOR L'/' #define WCHAR_PATH_SEPARATOR L'/'
#define STRING_PATH_SEPARATOR "/" #define STRING_PATH_SEPARATOR "/"
#define WSTRING_PATH_SEPARATOR L"/" #define WSTRING_PATH_SEPARATOR L"/"
#endif #endif
EXTERN_C_END EXTERN_C_END
#endif #endif

@ -1,145 +1,455 @@
/* Alloc.c -- Memory allocation functions /* Alloc.c -- Memory allocation functions
2017-06-15 : Igor Pavlov : Public domain */ 2018-04-27 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#ifdef _WIN32 #include <stdio.h>
#include <windows.h>
#endif #ifdef _WIN32
#include <stdlib.h> #include <windows.h>
#endif
#include "Alloc.h" #include <stdlib.h>
/* #define _SZ_ALLOC_DEBUG */ #include "Alloc.h"
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ /* #define _SZ_ALLOC_DEBUG */
#ifdef _SZ_ALLOC_DEBUG
#include <stdio.h> /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
int g_allocCount = 0; #ifdef _SZ_ALLOC_DEBUG
int g_allocCountMid = 0;
int g_allocCountBig = 0; #include <stdio.h>
#endif int g_allocCount = 0;
int g_allocCountMid = 0;
void *MyAlloc(size_t size) int g_allocCountBig = 0;
{
if (size == 0)
return NULL; #define CONVERT_INT_TO_STR(charType, tempSize) \
#ifdef _SZ_ALLOC_DEBUG unsigned char temp[tempSize]; unsigned i = 0; \
{ while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \
void *p = malloc(size); *s++ = (charType)('0' + (unsigned)val); \
fprintf(stderr, "\nAlloc %10u bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); while (i != 0) { i--; *s++ = temp[i]; } \
return p; *s = 0;
}
#else static void ConvertUInt64ToString(UInt64 val, char *s)
return malloc(size); {
#endif CONVERT_INT_TO_STR(char, 24);
} }
void MyFree(void *address) #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
{
#ifdef _SZ_ALLOC_DEBUG static void ConvertUInt64ToHex(UInt64 val, char *s)
if (address) {
fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); UInt64 v = val;
#endif unsigned i;
free(address); for (i = 1;; i++)
} {
v >>= 4;
#ifdef _WIN32 if (v == 0)
break;
void *MidAlloc(size_t size) }
{ s[i] = 0;
if (size == 0) do
return NULL; {
#ifdef _SZ_ALLOC_DEBUG unsigned t = (unsigned)(val & 0xF);
fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); val >>= 4;
#endif s[--i] = GET_HEX_CHAR(t);
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); }
} while (i);
}
void MidFree(void *address)
{ #define DEBUG_OUT_STREAM stderr
#ifdef _SZ_ALLOC_DEBUG
if (address) static void Print(const char *s)
fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); {
#endif fputs(s, DEBUG_OUT_STREAM);
if (!address) }
return;
VirtualFree(address, 0, MEM_RELEASE); static void PrintAligned(const char *s, size_t align)
} {
size_t len = strlen(s);
#ifndef MEM_LARGE_PAGES for(;;)
#undef _7ZIP_LARGE_PAGES {
#endif fputc(' ', DEBUG_OUT_STREAM);
if (len >= align)
#ifdef _7ZIP_LARGE_PAGES break;
SIZE_T g_LargePageSize = 0; ++len;
typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); }
#endif Print(s);
}
void SetLargePageSize(void)
{ static void PrintLn()
#ifdef _7ZIP_LARGE_PAGES {
SIZE_T size; Print("\n");
GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) }
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
if (!largePageMinimum) static void PrintHex(UInt64 v, size_t align)
return; {
size = largePageMinimum(); char s[32];
if (size == 0 || (size & (size - 1)) != 0) ConvertUInt64ToHex(v, s);
return; PrintAligned(s, align);
g_LargePageSize = size; }
#endif
} static void PrintDec(UInt64 v, size_t align)
{
char s[32];
void *BigAlloc(size_t size) ConvertUInt64ToString(v, s);
{ PrintAligned(s, align);
if (size == 0) }
return NULL;
#ifdef _SZ_ALLOC_DEBUG static void PrintAddr(void *p)
fprintf(stderr, "\nAlloc_Big %10u bytes; count = %10d", size, g_allocCountBig++); {
#endif PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12);
}
#ifdef _7ZIP_LARGE_PAGES
{
SIZE_T ps = g_LargePageSize; #define PRINT_ALLOC(name, cnt, size, ptr) \
if (ps != 0 && ps <= (1 << 30) && size > (ps / 2)) Print(name " "); \
{ PrintDec(cnt++, 10); \
size_t size2; PrintHex(size, 10); \
ps--; PrintAddr(ptr); \
size2 = (size + ps) & ~ps; PrintLn();
if (size2 >= size)
{ #define PRINT_FREE(name, cnt, ptr) if (ptr) { \
void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); Print(name " "); \
if (res) PrintDec(--cnt, 10); \
return res; PrintAddr(ptr); \
} PrintLn(); }
}
} #else
#endif
#define PRINT_ALLOC(name, cnt, size, ptr)
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); #define PRINT_FREE(name, cnt, ptr)
} #define Print(s)
#define PrintLn()
void BigFree(void *address) #define PrintHex(v, align)
{ #define PrintDec(v, align)
#ifdef _SZ_ALLOC_DEBUG #define PrintAddr(p)
if (address)
fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif
#endif
if (!address)
return; void *MyAlloc(size_t size)
VirtualFree(address, 0, MEM_RELEASE); {
} if (size == 0)
return NULL;
#endif #ifdef _SZ_ALLOC_DEBUG
{
void *p = malloc(size);
static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); } PRINT_ALLOC("Alloc ", g_allocCount, size, p);
static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); } return p;
ISzAlloc const g_Alloc = { SzAlloc, SzFree }; }
#else
static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); } return malloc(size);
static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); } #endif
ISzAlloc const g_BigAlloc = { SzBigAlloc, SzBigFree }; }
void MyFree(void *address)
{
PRINT_FREE("Free ", g_allocCount, address);
free(address);
}
#ifdef _WIN32
void *MidAlloc(size_t size)
{
if (size == 0)
return NULL;
PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL);
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
}
void MidFree(void *address)
{
PRINT_FREE("Free-Mid", g_allocCountMid, address);
if (!address)
return;
VirtualFree(address, 0, MEM_RELEASE);
}
#ifndef MEM_LARGE_PAGES
#undef _7ZIP_LARGE_PAGES
#endif
#ifdef _7ZIP_LARGE_PAGES
SIZE_T g_LargePageSize = 0;
typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
#endif
void SetLargePageSize()
{
#ifdef _7ZIP_LARGE_PAGES
SIZE_T size;
GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
if (!largePageMinimum)
return;
size = largePageMinimum();
if (size == 0 || (size & (size - 1)) != 0)
return;
g_LargePageSize = size;
#endif
}
void *BigAlloc(size_t size)
{
if (size == 0)
return NULL;
PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL);
#ifdef _7ZIP_LARGE_PAGES
{
SIZE_T ps = g_LargePageSize;
if (ps != 0 && ps <= (1 << 30) && size > (ps / 2))
{
size_t size2;
ps--;
size2 = (size + ps) & ~ps;
if (size2 >= size)
{
void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
if (res)
return res;
}
}
}
#endif
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
}
void BigFree(void *address)
{
PRINT_FREE("Free-Big", g_allocCountBig, address);
if (!address)
return;
VirtualFree(address, 0, MEM_RELEASE);
}
#endif
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); }
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); }
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;
}

@ -1,37 +1,51 @@
/* Alloc.h -- Memory allocation functions /* Alloc.h -- Memory allocation functions
2017-04-03 : Igor Pavlov : Public domain */ 2018-02-19 : Igor Pavlov : Public domain */
#ifndef __COMMON_ALLOC_H #ifndef __COMMON_ALLOC_H
#define __COMMON_ALLOC_H #define __COMMON_ALLOC_H
#include "7zTypes.h" #include "7zTypes.h"
EXTERN_C_BEGIN EXTERN_C_BEGIN
void *MyAlloc(size_t size); void *MyAlloc(size_t size);
void MyFree(void *address); void MyFree(void *address);
#ifdef _WIN32 #ifdef _WIN32
void SetLargePageSize(void); void SetLargePageSize();
void *MidAlloc(size_t size); void *MidAlloc(size_t size);
void MidFree(void *address); void MidFree(void *address);
void *BigAlloc(size_t size); void *BigAlloc(size_t size);
void BigFree(void *address); void BigFree(void *address);
#else #else
#define MidAlloc(size) MyAlloc(size) #define MidAlloc(size) MyAlloc(size)
#define MidFree(address) MyFree(address) #define MidFree(address) MyFree(address)
#define BigAlloc(size) MyAlloc(size) #define BigAlloc(size) MyAlloc(size)
#define BigFree(address) MyFree(address) #define BigFree(address) MyFree(address)
#endif #endif
extern const ISzAlloc g_Alloc; extern const ISzAlloc g_Alloc;
extern const ISzAlloc g_BigAlloc; extern const ISzAlloc g_BigAlloc;
extern const ISzAlloc g_MidAlloc;
EXTERN_C_END extern const ISzAlloc g_AlignedAlloc;
#endif
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
#endif

@ -1,33 +1,33 @@
/* Compiler.h /* Compiler.h
2017-04-03 : Igor Pavlov : Public domain */ 2017-04-03 : Igor Pavlov : Public domain */
#ifndef __7Z_COMPILER_H #ifndef __7Z_COMPILER_H
#define __7Z_COMPILER_H #define __7Z_COMPILER_H
#ifdef _MSC_VER #ifdef _MSC_VER
#ifdef UNDER_CE #ifdef UNDER_CE
#define RPC_NO_WINDOWS_H #define RPC_NO_WINDOWS_H
/* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */ /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */
#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
#pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int
#endif #endif
#if _MSC_VER >= 1300 #if _MSC_VER >= 1300
#pragma warning(disable : 4996) // This function or variable may be unsafe #pragma warning(disable : 4996) // This function or variable may be unsafe
#else #else
#pragma warning(disable : 4511) // copy constructor could not be generated #pragma warning(disable : 4511) // copy constructor could not be generated
#pragma warning(disable : 4512) // assignment operator could not be generated #pragma warning(disable : 4512) // assignment operator could not be generated
#pragma warning(disable : 4514) // unreferenced inline function has been removed #pragma warning(disable : 4514) // unreferenced inline function has been removed
#pragma warning(disable : 4702) // unreachable code #pragma warning(disable : 4702) // unreachable code
#pragma warning(disable : 4710) // not inlined #pragma warning(disable : 4710) // not inlined
#pragma warning(disable : 4714) // function marked as __forceinline not inlined #pragma warning(disable : 4714) // function marked as __forceinline not inlined
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
#endif #endif
#endif #endif
#define UNUSED_VAR(x) (void)x; #define UNUSED_VAR(x) (void)x;
/* #define UNUSED_VAR(x) x=x; */ /* #define UNUSED_VAR(x) x=x; */
#endif #endif

@ -1,374 +1,488 @@
/* Lzma2Dec.c -- LZMA2 Decoder /* Lzma2Dec.c -- LZMA2 Decoder
2017-04-03 : Igor Pavlov : Public domain */ 2018-02-19 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */ /* #define SHOW_DEBUG_INFO */
#include "Precomp.h" #include "Precomp.h"
#ifdef SHOW_DEBUG_INFO #ifdef SHOW_DEBUG_INFO
#include <stdio.h> #include <stdio.h>
#endif #endif
#include <string.h> #include <string.h>
#include "Lzma2Dec.h" #include "Lzma2Dec.h"
/* /*
00000000 - EOS 00000000 - End of data
00000001 U U - Uncompressed Reset Dic 00000001 U U - Uncompressed, reset dic, need reset state and set new prop
00000010 U U - Uncompressed No Reset 00000010 U U - Uncompressed, no reset
100uuuuu U U P P - LZMA no reset 100uuuuu U U P P - LZMA, no reset
101uuuuu U U P P - LZMA reset state 101uuuuu U U P P - LZMA, reset state
110uuuuu U U P P S - LZMA reset state + new prop 110uuuuu U U P P S - LZMA, reset state + set new prop
111uuuuu U U P P S - LZMA reset state + new prop + reset dic 111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
u, U - Unpack Size u, U - Unpack Size
P - Pack Size P - Pack Size
S - Props S - Props
*/ */
#define LZMA2_CONTROL_LZMA (1 << 7) #define LZMA2_CONTROL_COPY_RESET_DIC 1
#define LZMA2_CONTROL_COPY_NO_RESET 2
#define LZMA2_CONTROL_COPY_RESET_DIC 1 #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
#define LZMA2_CONTROL_EOF 0
#define LZMA2_LCLP_MAX 4
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0) #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3) #ifdef SHOW_DEBUG_INFO
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2) #define PRF(x) x
#else
#define LZMA2_LCLP_MAX 4 #define PRF(x)
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) #endif
#ifdef SHOW_DEBUG_INFO typedef enum
#define PRF(x) x {
#else LZMA2_STATE_CONTROL,
#define PRF(x) LZMA2_STATE_UNPACK0,
#endif LZMA2_STATE_UNPACK1,
LZMA2_STATE_PACK0,
typedef enum LZMA2_STATE_PACK1,
{ LZMA2_STATE_PROP,
LZMA2_STATE_CONTROL, LZMA2_STATE_DATA,
LZMA2_STATE_UNPACK0, LZMA2_STATE_DATA_CONT,
LZMA2_STATE_UNPACK1, LZMA2_STATE_FINISHED,
LZMA2_STATE_PACK0, LZMA2_STATE_ERROR
LZMA2_STATE_PACK1, } ELzma2State;
LZMA2_STATE_PROP,
LZMA2_STATE_DATA, static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
LZMA2_STATE_DATA_CONT, {
LZMA2_STATE_FINISHED, UInt32 dicSize;
LZMA2_STATE_ERROR if (prop > 40)
} ELzma2State; return SZ_ERROR_UNSUPPORTED;
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) props[0] = (Byte)LZMA2_LCLP_MAX;
{ props[1] = (Byte)(dicSize);
UInt32 dicSize; props[2] = (Byte)(dicSize >> 8);
if (prop > 40) props[3] = (Byte)(dicSize >> 16);
return SZ_ERROR_UNSUPPORTED; props[4] = (Byte)(dicSize >> 24);
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); return SZ_OK;
props[0] = (Byte)LZMA2_LCLP_MAX; }
props[1] = (Byte)(dicSize);
props[2] = (Byte)(dicSize >> 8); SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
props[3] = (Byte)(dicSize >> 16); {
props[4] = (Byte)(dicSize >> 24); Byte props[LZMA_PROPS_SIZE];
return SZ_OK; RINOK(Lzma2Dec_GetOldProps(prop, props));
} return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
}
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
{ SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
Byte props[LZMA_PROPS_SIZE]; {
RINOK(Lzma2Dec_GetOldProps(prop, props)); Byte props[LZMA_PROPS_SIZE];
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); RINOK(Lzma2Dec_GetOldProps(prop, props));
} return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
}
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
{ void Lzma2Dec_Init(CLzma2Dec *p)
Byte props[LZMA_PROPS_SIZE]; {
RINOK(Lzma2Dec_GetOldProps(prop, props)); p->state = LZMA2_STATE_CONTROL;
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); p->needInitLevel = 0xE0;
} p->isExtraMode = False;
p->unpackSize = 0;
void Lzma2Dec_Init(CLzma2Dec *p)
{ // p->decoder.dicPos = 0; // we can use it instead of full init
p->state = LZMA2_STATE_CONTROL; LzmaDec_Init(&p->decoder);
p->needInitDic = True; }
p->needInitState = True;
p->needInitProp = True; static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
LzmaDec_Init(&p->decoder); {
} switch (p->state)
{
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) case LZMA2_STATE_CONTROL:
{ p->isExtraMode = False;
switch (p->state) p->control = b;
{ PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
case LZMA2_STATE_CONTROL: PRF(printf(" %02X", (unsigned)b));
p->control = b; if (b == 0)
PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos)); return LZMA2_STATE_FINISHED;
PRF(printf(" %2X", (unsigned)b)); if (LZMA2_IS_UNCOMPRESSED_STATE(p))
if (b == 0) {
return LZMA2_STATE_FINISHED; if (b == LZMA2_CONTROL_COPY_RESET_DIC)
if (LZMA2_IS_UNCOMPRESSED_STATE(p)) p->needInitLevel = 0xC0;
{ else if (b > 2 || p->needInitLevel == 0xE0)
if (b > 2) return LZMA2_STATE_ERROR;
return LZMA2_STATE_ERROR; }
p->unpackSize = 0; else
} {
else if (b < p->needInitLevel)
p->unpackSize = (UInt32)(b & 0x1F) << 16; return LZMA2_STATE_ERROR;
return LZMA2_STATE_UNPACK0; p->needInitLevel = 0;
p->unpackSize = (UInt32)(b & 0x1F) << 16;
case LZMA2_STATE_UNPACK0: }
p->unpackSize |= (UInt32)b << 8; return LZMA2_STATE_UNPACK0;
return LZMA2_STATE_UNPACK1;
case LZMA2_STATE_UNPACK0:
case LZMA2_STATE_UNPACK1: p->unpackSize |= (UInt32)b << 8;
p->unpackSize |= (UInt32)b; return LZMA2_STATE_UNPACK1;
p->unpackSize++;
PRF(printf(" %8u", (unsigned)p->unpackSize)); case LZMA2_STATE_UNPACK1:
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; p->unpackSize |= (UInt32)b;
p->unpackSize++;
case LZMA2_STATE_PACK0: PRF(printf(" %7u", (unsigned)p->unpackSize));
p->packSize = (UInt32)b << 8; return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
return LZMA2_STATE_PACK1;
case LZMA2_STATE_PACK0:
case LZMA2_STATE_PACK1: p->packSize = (UInt32)b << 8;
p->packSize |= (UInt32)b; return LZMA2_STATE_PACK1;
p->packSize++;
PRF(printf(" %8u", (unsigned)p->packSize)); case LZMA2_STATE_PACK1:
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: p->packSize |= (UInt32)b;
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); p->packSize++;
// if (p->packSize < 5) return LZMA2_STATE_ERROR;
case LZMA2_STATE_PROP: PRF(printf(" %5u", (unsigned)p->packSize));
{ return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
unsigned lc, lp;
if (b >= (9 * 5 * 5)) case LZMA2_STATE_PROP:
return LZMA2_STATE_ERROR; {
lc = b % 9; unsigned lc, lp;
b /= 9; if (b >= (9 * 5 * 5))
p->decoder.prop.pb = b / 5; return LZMA2_STATE_ERROR;
lp = b % 5; lc = b % 9;
if (lc + lp > LZMA2_LCLP_MAX) b /= 9;
return LZMA2_STATE_ERROR; p->decoder.prop.pb = (Byte)(b / 5);
p->decoder.prop.lc = lc; lp = b % 5;
p->decoder.prop.lp = lp; if (lc + lp > LZMA2_LCLP_MAX)
p->needInitProp = False; return LZMA2_STATE_ERROR;
return LZMA2_STATE_DATA; p->decoder.prop.lc = (Byte)lc;
} p->decoder.prop.lp = (Byte)lp;
} return LZMA2_STATE_DATA;
return LZMA2_STATE_ERROR; }
} }
return LZMA2_STATE_ERROR;
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) }
{
memcpy(p->dic + p->dicPos, src, size); static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
p->dicPos += size; {
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) memcpy(p->dic + p->dicPos, src, size);
p->checkDicSize = p->prop.dicSize; p->dicPos += size;
p->processedPos += (UInt32)size; if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
} p->checkDicSize = p->prop.dicSize;
p->processedPos += (UInt32)size;
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState); }
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
SizeT inSize = *srcLen; const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
*srcLen = 0; {
*status = LZMA_STATUS_NOT_SPECIFIED; SizeT inSize = *srcLen;
*srcLen = 0;
while (p->state != LZMA2_STATE_ERROR) *status = LZMA_STATUS_NOT_SPECIFIED;
{
SizeT dicPos; while (p->state != LZMA2_STATE_ERROR)
{
if (p->state == LZMA2_STATE_FINISHED) SizeT dicPos;
{
*status = LZMA_STATUS_FINISHED_WITH_MARK; if (p->state == LZMA2_STATE_FINISHED)
return SZ_OK; {
} *status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
dicPos = p->decoder.dicPos; }
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) dicPos = p->decoder.dicPos;
{
*status = LZMA_STATUS_NOT_FINISHED; if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
return SZ_OK; {
} *status = LZMA_STATUS_NOT_FINISHED;
return SZ_OK;
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) }
{
if (*srcLen == inSize) if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{ {
*status = LZMA_STATUS_NEEDS_MORE_INPUT; if (*srcLen == inSize)
return SZ_OK; {
} *status = LZMA_STATUS_NEEDS_MORE_INPUT;
(*srcLen)++; return SZ_OK;
p->state = Lzma2Dec_UpdateState(p, *src++); }
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED) (*srcLen)++;
break; p->state = Lzma2Dec_UpdateState(p, *src++);
continue; if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
} break;
continue;
{ }
SizeT inCur = inSize - *srcLen;
SizeT outCur = dicLimit - dicPos; {
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; SizeT inCur = inSize - *srcLen;
SizeT outCur = dicLimit - dicPos;
if (outCur >= p->unpackSize) ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
{
outCur = (SizeT)p->unpackSize; if (outCur >= p->unpackSize)
curFinishMode = LZMA_FINISH_END; {
} outCur = (SizeT)p->unpackSize;
curFinishMode = LZMA_FINISH_END;
if (LZMA2_IS_UNCOMPRESSED_STATE(p)) }
{
if (inCur == 0) if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{ {
*status = LZMA_STATUS_NEEDS_MORE_INPUT; if (inCur == 0)
return SZ_OK; {
} *status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
if (p->state == LZMA2_STATE_DATA) }
{
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); if (p->state == LZMA2_STATE_DATA)
if (initDic) {
p->needInitProp = p->needInitState = True; Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
else if (p->needInitDic) LzmaDec_InitDicAndState(&p->decoder, initDic, False);
break; }
p->needInitDic = False;
LzmaDec_InitDicAndState(&p->decoder, initDic, False); if (inCur > outCur)
} inCur = outCur;
if (inCur == 0)
if (inCur > outCur) break;
inCur = outCur;
if (inCur == 0) LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
break;
src += inCur;
LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur); *srcLen += inCur;
p->unpackSize -= (UInt32)inCur;
src += inCur; p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
*srcLen += inCur; }
p->unpackSize -= (UInt32)inCur; else
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; {
} SRes res;
else
{ if (p->state == LZMA2_STATE_DATA)
SRes res; {
Bool initDic = (p->control >= 0xE0);
if (p->state == LZMA2_STATE_DATA) Bool initState = (p->control >= 0xA0);
{ LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
unsigned mode = LZMA2_GET_LZMA_MODE(p); p->state = LZMA2_STATE_DATA_CONT;
Bool initDic = (mode == 3); }
Bool initState = (mode != 0);
if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) if (inCur > p->packSize)
break; inCur = (SizeT)p->packSize;
LzmaDec_InitDicAndState(&p->decoder, initDic, initState); res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
p->needInitDic = False;
p->needInitState = False; src += inCur;
p->state = LZMA2_STATE_DATA_CONT; *srcLen += inCur;
} p->packSize -= (UInt32)inCur;
outCur = p->decoder.dicPos - dicPos;
if (inCur > p->packSize) p->unpackSize -= (UInt32)outCur;
inCur = (SizeT)p->packSize;
if (res != 0)
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status); break;
src += inCur; if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
*srcLen += inCur; {
p->packSize -= (UInt32)inCur; if (p->packSize == 0)
outCur = p->decoder.dicPos - dicPos; break;
p->unpackSize -= (UInt32)outCur; return SZ_OK;
}
if (res != 0)
break; if (inCur == 0 && outCur == 0)
{
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
{ || p->unpackSize != 0
if (p->packSize == 0) || p->packSize != 0)
break; break;
return SZ_OK; p->state = LZMA2_STATE_CONTROL;
} }
if (inCur == 0 && outCur == 0) *status = LZMA_STATUS_NOT_SPECIFIED;
{ }
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK }
|| p->unpackSize != 0 }
|| p->packSize != 0)
break; *status = LZMA_STATUS_NOT_SPECIFIED;
p->state = LZMA2_STATE_CONTROL; p->state = LZMA2_STATE_ERROR;
} return SZ_ERROR_DATA;
}
*status = LZMA_STATUS_NOT_SPECIFIED;
}
}
}
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
*status = LZMA_STATUS_NOT_SPECIFIED; SizeT outSize,
p->state = LZMA2_STATE_ERROR; const Byte *src, SizeT *srcLen,
return SZ_ERROR_DATA; int checkFinishBlock)
} {
SizeT inSize = *srcLen;
*srcLen = 0;
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{ while (p->state != LZMA2_STATE_ERROR)
SizeT outSize = *destLen, inSize = *srcLen; {
*srcLen = *destLen = 0; if (p->state == LZMA2_STATE_FINISHED)
return LZMA_STATUS_FINISHED_WITH_MARK;
for (;;)
{ if (outSize == 0 && !checkFinishBlock)
SizeT inCur = inSize, outCur, dicPos; return LZMA_STATUS_NOT_FINISHED;
ELzmaFinishMode curFinishMode;
SRes res; if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{
if (p->decoder.dicPos == p->decoder.dicBufSize) if (*srcLen == inSize)
p->decoder.dicPos = 0; return LZMA_STATUS_NEEDS_MORE_INPUT;
dicPos = p->decoder.dicPos; (*srcLen)++;
curFinishMode = LZMA_FINISH_ANY;
outCur = p->decoder.dicBufSize - dicPos; p->state = Lzma2Dec_UpdateState(p, *src++);
if (outCur >= outSize) if (p->state == LZMA2_STATE_UNPACK0)
{ {
outCur = outSize; // if (p->decoder.dicPos != 0)
curFinishMode = finishMode; 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;
res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status); }
src += inCur; // The following code can be commented.
inSize -= inCur; // It's not big problem, if we read additional input bytes.
*srcLen += inCur; // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
outCur = p->decoder.dicPos - dicPos;
memcpy(dest, p->decoder.dic + dicPos, outCur); if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
dest += outCur; {
outSize -= outCur; // checkFinishBlock is true. So we expect that block must be finished,
*destLen += outCur; // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
if (res != 0) // break;
return res; return LZMA_STATUS_NOT_FINISHED;
if (outCur == 0 || outSize == 0) }
return SZ_OK;
} if (p->state == LZMA2_STATE_DATA)
} return LZMA2_PARSE_STATUS_NEW_CHUNK;
continue;
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, }
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
{ if (outSize == 0)
CLzma2Dec p; return LZMA_STATUS_NOT_FINISHED;
SRes res;
SizeT outSize = *destLen, inSize = *srcLen; {
*destLen = *srcLen = 0; SizeT inCur = inSize - *srcLen;
*status = LZMA_STATUS_NOT_SPECIFIED;
Lzma2Dec_Construct(&p); if (LZMA2_IS_UNCOMPRESSED_STATE(p))
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); {
p.decoder.dic = dest; if (inCur == 0)
p.decoder.dicBufSize = outSize; return LZMA_STATUS_NEEDS_MORE_INPUT;
Lzma2Dec_Init(&p); if (inCur > p->unpackSize)
*srcLen = inSize; inCur = p->unpackSize;
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); if (inCur > outSize)
*destLen = p.decoder.dicPos; inCur = outSize;
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) p->decoder.dicPos += inCur;
res = SZ_ERROR_INPUT_EOF; src += inCur;
Lzma2Dec_FreeProbs(&p, alloc); *srcLen += inCur;
return res; 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;
*srcLen = *destLen = 0;
for (;;)
{
SizeT inCur = inSize, outCur, dicPos;
ELzmaFinishMode curFinishMode;
SRes res;
if (p->decoder.dicPos == p->decoder.dicBufSize)
p->decoder.dicPos = 0;
dicPos = p->decoder.dicPos;
curFinishMode = LZMA_FINISH_ANY;
outCur = p->decoder.dicBufSize - dicPos;
if (outCur >= outSize)
{
outCur = outSize;
curFinishMode = finishMode;
}
res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
src += inCur;
inSize -= inCur;
*srcLen += inCur;
outCur = p->decoder.dicPos - dicPos;
memcpy(dest, p->decoder.dic + dicPos, outCur);
dest += outCur;
outSize -= outCur;
*destLen += outCur;
if (res != 0)
return res;
if (outCur == 0 || outSize == 0)
return SZ_OK;
}
}
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
{
CLzma2Dec p;
SRes res;
SizeT outSize = *destLen, inSize = *srcLen;
*destLen = *srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED;
Lzma2Dec_Construct(&p);
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
p.decoder.dic = dest;
p.decoder.dicBufSize = outSize;
Lzma2Dec_Init(&p);
*srcLen = inSize;
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
*destLen = p.decoder.dicPos;
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
res = SZ_ERROR_INPUT_EOF;
Lzma2Dec_FreeProbs(&p, alloc);
return res;
}

@ -1,80 +1,120 @@
/* Lzma2Dec.h -- LZMA2 Decoder /* Lzma2Dec.h -- LZMA2 Decoder
2017-04-03 : Igor Pavlov : Public domain */ 2018-02-19 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H #ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H #define __LZMA2_DEC_H
#include "LzmaDec.h" #include "LzmaDec.h"
EXTERN_C_BEGIN EXTERN_C_BEGIN
/* ---------- State Interface ---------- */ /* ---------- State Interface ---------- */
typedef struct typedef struct
{ {
CLzmaDec decoder; unsigned state;
UInt32 packSize; Byte control;
UInt32 unpackSize; Byte needInitLevel;
unsigned state; Byte isExtraMode;
Byte control; Byte _pad_;
Bool needInitDic; UInt32 packSize;
Bool needInitState; UInt32 unpackSize;
Bool needInitProp; CLzmaDec decoder;
} CLzma2Dec; } CLzma2Dec;
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) #define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc); #define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc)
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc); #define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc)
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
void Lzma2Dec_Init(CLzma2Dec *p); void Lzma2Dec_Init(CLzma2Dec *p);
/*
/* finishMode:
finishMode: It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
It has meaning only if the decoding reaches output limit (*destLen or dicLimit). LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_ANY - use smallest number of input bytes LZMA_FINISH_END - read EndOfStream marker after decoding
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
Returns: SZ_OK
SZ_OK status:
status: LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_NEEDS_MORE_INPUT SZ_ERROR_DATA - Data error
SZ_ERROR_DATA - Data error */
*/
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- LZMA2 block and chunk parsing ---------- */
/* ---------- One Call Interface ---------- */
/*
/* Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.
finishMode: It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:
It has meaning only if the decoding reaches output limit (*destLen). - LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.
LZMA_FINISH_ANY - use smallest number of input bytes - LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.
LZMA_FINISH_END - read EndOfStream marker after decoding CLzma2Dec::unpackSize contains unpack size of that chunk
*/
Returns:
SZ_OK typedef enum
status: {
LZMA_STATUS_FINISHED_WITH_MARK /*
LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NOT_SPECIFIED // data error
SZ_ERROR_DATA - Data error LZMA_STATUS_FINISHED_WITH_MARK
SZ_ERROR_MEM - Memory allocation error LZMA_STATUS_NOT_FINISHED //
SZ_ERROR_UNSUPPORTED - Unsupported properties LZMA_STATUS_NEEDS_MORE_INPUT
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused
*/ */
LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, LZMA2_PARSE_STATUS_NEW_CHUNK
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc); } ELzma2ParseStatus;
EXTERN_C_END ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
SizeT outSize, // output size
#endif 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 ---------- */
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);
EXTERN_C_END
#endif

File diff suppressed because it is too large Load Diff

@ -1,227 +1,234 @@
/* LzmaDec.h -- LZMA Decoder /* LzmaDec.h -- LZMA Decoder
2017-04-03 : Igor Pavlov : Public domain */ 2018-04-21 : Igor Pavlov : Public domain */
#ifndef __LZMA_DEC_H #ifndef __LZMA_DEC_H
#define __LZMA_DEC_H #define __LZMA_DEC_H
#include "7zTypes.h" #include "7zTypes.h"
EXTERN_C_BEGIN EXTERN_C_BEGIN
/* #define _LZMA_PROB32 */ /* #define _LZMA_PROB32 */
/* _LZMA_PROB32 can increase the speed on some CPUs, /* _LZMA_PROB32 can increase the speed on some CPUs,
but memory usage for CLzmaDec::probs will be doubled in that case */ but memory usage for CLzmaDec::probs will be doubled in that case */
#ifdef _LZMA_PROB32 typedef
#define CLzmaProb UInt32 #ifdef _LZMA_PROB32
#else UInt32
#define CLzmaProb UInt16 #else
#endif UInt16
#endif
CLzmaProb;
/* ---------- LZMA Properties ---------- */
#define LZMA_PROPS_SIZE 5 /* ---------- LZMA Properties ---------- */
typedef struct _CLzmaProps #define LZMA_PROPS_SIZE 5
{
unsigned lc, lp, pb; typedef struct _CLzmaProps
UInt32 dicSize; {
} CLzmaProps; Byte lc;
Byte lp;
/* LzmaProps_Decode - decodes properties Byte pb;
Returns: Byte _pad_;
SZ_OK UInt32 dicSize;
SZ_ERROR_UNSUPPORTED - Unsupported properties } CLzmaProps;
*/
/* LzmaProps_Decode - decodes properties
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); Returns:
SZ_OK
SZ_ERROR_UNSUPPORTED - Unsupported properties
/* ---------- LZMA Decoder state ---------- */ */
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
#define LZMA_REQUIRED_INPUT_MAX 20 /* ---------- LZMA Decoder state ---------- */
typedef struct /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
{ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
CLzmaProps prop;
CLzmaProb *probs; #define LZMA_REQUIRED_INPUT_MAX 20
Byte *dic;
const Byte *buf; typedef struct
UInt32 range, code; {
SizeT dicPos; /* Don't change this structure. ASM code can use it. */
SizeT dicBufSize; CLzmaProps prop;
UInt32 processedPos; CLzmaProb *probs;
UInt32 checkDicSize; CLzmaProb *probs_1664;
unsigned state; Byte *dic;
UInt32 reps[4]; SizeT dicBufSize;
unsigned remainLen; SizeT dicPos;
int needFlush; const Byte *buf;
int needInitState; UInt32 range;
UInt32 numProbs; UInt32 code;
unsigned tempBufSize; UInt32 processedPos;
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; UInt32 checkDicSize;
} CLzmaDec; UInt32 reps[4];
UInt32 state;
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } UInt32 remainLen;
void LzmaDec_Init(CLzmaDec *p); UInt32 numProbs;
unsigned tempBufSize;
/* There are two types of LZMA streams: Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
0) Stream with end mark. That end mark adds about 6 bytes to compressed size. } CLzmaDec;
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
typedef enum
{ void LzmaDec_Init(CLzmaDec *p);
LZMA_FINISH_ANY, /* finish at any point */
LZMA_FINISH_END /* block must be finished at the end */ /* There are two types of LZMA streams:
} ELzmaFinishMode; - 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. */
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
typedef enum
You must use LZMA_FINISH_END, when you know that current output buffer {
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. LZMA_FINISH_ANY, /* finish at any point */
LZMA_FINISH_END /* block must be finished at the end */
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, } ELzmaFinishMode;
and output value of destLen will be less than output buffer size limit.
You can check status result also. /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
You can use multiple checks to test data integrity after full decompression: You must use LZMA_FINISH_END, when you know that current output buffer
1) Check Result and "status" variable. covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
3) Check that output(srcLen) = compressedSize, if you know real compressedSize. If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
You must use correct finish mode in that case. */ and output value of destLen will be less than output buffer size limit.
You can check status result also.
typedef enum
{ You can use multiple checks to test data integrity after full decompression:
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ 1) Check Result and "status" variable.
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ You must use correct finish mode in that case. */
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
} ELzmaStatus; typedef enum
{
/* ELzmaStatus is used only as output value for function call */ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
/* ---------- Interfaces ---------- */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
/* There are 3 levels of interfaces: } ELzmaStatus;
1) Dictionary Interface
2) Buffer Interface /* ELzmaStatus is used only as output value for function call */
3) One Call Interface
You can select any of these interfaces, but don't mix functions from different
groups for same object. */ /* ---------- Interfaces ---------- */
/* There are 3 levels of interfaces:
/* There are two variants to allocate state for Dictionary Interface: 1) Dictionary Interface
1) LzmaDec_Allocate / LzmaDec_Free 2) Buffer Interface
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs 3) One Call Interface
You can use variant 2, if you set dictionary buffer manually. You can select any of these interfaces, but don't mix functions from different
For Buffer Interface you must always use variant 1. groups for same object. */
LzmaDec_Allocate* can return:
SZ_OK /* There are two variants to allocate state for Dictionary Interface:
SZ_ERROR_MEM - Memory allocation error 1) LzmaDec_Allocate / LzmaDec_Free
SZ_ERROR_UNSUPPORTED - Unsupported properties 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
*/ You can use variant 2, if you set dictionary buffer manually.
For Buffer Interface you must always use variant 1.
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc); LzmaDec_Allocate* can return:
SZ_OK
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAllocPtr alloc); SZ_ERROR_MEM - Memory allocation error
void LzmaDec_Free(CLzmaDec *state, ISzAllocPtr alloc); SZ_ERROR_UNSUPPORTED - Unsupported properties
*/
/* ---------- Dictionary Interface ---------- */
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
/* You can use it, if you want to eliminate the overhead for data copying from void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
dictionary to some other external buffer.
You must work with CLzmaDec variables directly in this interface. SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
STEPS:
LzmaDec_Constr() /* ---------- Dictionary Interface ---------- */
LzmaDec_Allocate()
for (each new stream) /* You can use it, if you want to eliminate the overhead for data copying from
{ dictionary to some other external buffer.
LzmaDec_Init() You must work with CLzmaDec variables directly in this interface.
while (it needs more decompression)
{ STEPS:
LzmaDec_DecodeToDic() LzmaDec_Construct()
use data from CLzmaDec::dic and update CLzmaDec::dicPos LzmaDec_Allocate()
} for (each new stream)
} {
LzmaDec_Free() LzmaDec_Init()
*/ while (it needs more decompression)
{
/* LzmaDec_DecodeToDic LzmaDec_DecodeToDic()
use data from CLzmaDec::dic and update CLzmaDec::dicPos
The decoding to internal dictionary buffer (CLzmaDec::dic). }
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! }
LzmaDec_Free()
finishMode: */
It has meaning only if the decoding reaches output limit (dicLimit).
LZMA_FINISH_ANY - Decode just dicLimit bytes. /* LzmaDec_DecodeToDic
LZMA_FINISH_END - Stream must be finished after dicLimit.
The decoding to internal dictionary buffer (CLzmaDec::dic).
Returns: You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
SZ_OK
status: finishMode:
LZMA_STATUS_FINISHED_WITH_MARK It has meaning only if the decoding reaches output limit (dicLimit).
LZMA_STATUS_NOT_FINISHED LZMA_FINISH_ANY - Decode just dicLimit bytes.
LZMA_STATUS_NEEDS_MORE_INPUT LZMA_FINISH_END - Stream must be finished after dicLimit.
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error Returns:
*/ SZ_OK
status:
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, LZMA_STATUS_FINISHED_WITH_MARK
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
/* ---------- Buffer Interface ---------- */ SZ_ERROR_DATA - Data error
*/
/* It's zlib-like interface.
See LzmaDec_DecodeToDic description for information about STEPS and return results, SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
to work with CLzmaDec variables manually.
finishMode: /* ---------- Buffer Interface ---------- */
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes. /* It's zlib-like interface.
LZMA_FINISH_END - Stream must be finished after (*destLen). See LzmaDec_DecodeToDic description for information about STEPS and return results,
*/ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
to work with CLzmaDec variables manually.
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
/* ---------- One Call Interface ---------- */ LZMA_FINISH_END - Stream must be finished after (*destLen).
*/
/* LzmaDecode
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
finishMode: const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen). /* ---------- One Call Interface ---------- */
Returns: /* LzmaDecode
SZ_OK
status: finishMode:
LZMA_STATUS_FINISHED_WITH_MARK It has meaning only if the decoding reaches output limit (*destLen).
LZMA_STATUS_NOT_FINISHED LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK LZMA_FINISH_END - Stream must be finished after (*destLen).
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error Returns:
SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_OK
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). status:
*/ LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, SZ_ERROR_DATA - Data error
ELzmaStatus *status, ISzAllocPtr alloc); SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
EXTERN_C_END SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
#endif
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAllocPtr alloc);
EXTERN_C_END
#endif

@ -1,10 +1,10 @@
/* Precomp.h -- StdAfx /* Precomp.h -- StdAfx
2013-11-12 : Igor Pavlov : Public domain */ 2013-11-12 : Igor Pavlov : Public domain */
#ifndef __7Z_PRECOMP_H #ifndef __7Z_PRECOMP_H
#define __7Z_PRECOMP_H #define __7Z_PRECOMP_H
#include "Compiler.h" #include "Compiler.h"
/* #include "7zTypes.h" */ /* #include "7zTypes.h" */
#endif #endif

Loading…
Cancel
Save