mirror of https://github.com/mgba-emu/mgba.git
All: Support 7-Zip files (fixes #151)
This commit is contained in:
parent
a30ca1ac2c
commit
c50b228243
1
CHANGES
1
CHANGES
|
@ -19,6 +19,7 @@ Features:
|
||||||
- Save directory of last loaded file
|
- Save directory of last loaded file
|
||||||
- Support BPS patches
|
- Support BPS patches
|
||||||
- Configurable game overrides
|
- Configurable game overrides
|
||||||
|
- Support loading 7-Zip files
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- ARM7: Extend prefetch by one stage
|
- ARM7: Extend prefetch by one stage
|
||||||
- GBA Audio: Support 16-bit writes to FIFO audio
|
- GBA Audio: Support 16-bit writes to FIFO audio
|
||||||
|
|
|
@ -9,6 +9,7 @@ set(USE_PNG ON CACHE BOOL "Whether or not to enable PNG support")
|
||||||
set(USE_LIBZIP ON CACHE BOOL "Whether or not to enable ZIP support")
|
set(USE_LIBZIP ON CACHE BOOL "Whether or not to enable ZIP support")
|
||||||
set(USE_MAGICK ON CACHE BOOL "Whether or not to enable ImageMagick support")
|
set(USE_MAGICK ON CACHE BOOL "Whether or not to enable ImageMagick support")
|
||||||
set(USE_BLIP ON CACHE BOOL "Whether or not to enable blip_buf support")
|
set(USE_BLIP ON CACHE BOOL "Whether or not to enable blip_buf support")
|
||||||
|
set(USE_LZMA ON CACHE BOOL "Whether or not to enable 7-Zip support")
|
||||||
set(BUILD_QT ON CACHE BOOL "Build Qt frontend")
|
set(BUILD_QT ON CACHE BOOL "Build Qt frontend")
|
||||||
set(BUILD_SDL ON CACHE BOOL "Build SDL frontend")
|
set(BUILD_SDL ON CACHE BOOL "Build SDL frontend")
|
||||||
set(BUILD_PERF OFF CACHE BOOL "Build performance profiling tool")
|
set(BUILD_PERF OFF CACHE BOOL "Build performance profiling tool")
|
||||||
|
@ -204,6 +205,32 @@ if(USE_LIBZIP)
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libzip2")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libzip2")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (USE_LZMA)
|
||||||
|
include_directories(AFTER ${CMAKE_SOURCE_DIR}/third-party/lzma)
|
||||||
|
add_definitions(-D_7ZIP_PPMD_SUPPPORT)
|
||||||
|
set(LZMA_SRC
|
||||||
|
${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-lzma.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/7zAlloc.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/7zArcIn.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/7zBuf.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/7zBuf2.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/7zCrc.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/7zCrcOpt.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/7zDec.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/CpuArch.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/LzmaDec.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/Lzma2Dec.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/Bra.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/Bra86.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/Bcj2.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/Ppmd7.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/Ppmd7Dec.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/7zFile.c
|
||||||
|
${CMAKE_SOURCE_DIR}/src/third-party/lzma/7zStream.c)
|
||||||
|
list(APPEND UTIL_SRC ${LZMA_SRC})
|
||||||
|
add_definitions(-DENABLE_LZMA)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Binaries
|
# Binaries
|
||||||
add_library(${BINARY_NAME} SHARED
|
add_library(${BINARY_NAME} SHARED
|
||||||
${ARM_SRC}
|
${ARM_SRC}
|
||||||
|
@ -263,6 +290,7 @@ message(STATUS " Video recording: ${USE_FFMPEG}")
|
||||||
message(STATUS " GIF recording: ${USE_MAGICK}")
|
message(STATUS " GIF recording: ${USE_MAGICK}")
|
||||||
message(STATUS " Screenshot/advanced savestate support: ${USE_PNG}")
|
message(STATUS " Screenshot/advanced savestate support: ${USE_PNG}")
|
||||||
message(STATUS " ZIP support: ${USE_LIBZIP}")
|
message(STATUS " ZIP support: ${USE_LIBZIP}")
|
||||||
|
message(STATUS " 7-Zip support: ${USE_LZMA}")
|
||||||
message(STATUS " Better audio resampling: ${USE_BLIP}")
|
message(STATUS " Better audio resampling: ${USE_BLIP}")
|
||||||
message(STATUS "Frontend summary:")
|
message(STATUS "Frontend summary:")
|
||||||
message(STATUS " Qt: ${BUILD_QT}")
|
message(STATUS " Qt: ${BUILD_QT}")
|
||||||
|
|
|
@ -269,8 +269,16 @@ void GBAMapArgumentsToContext(const struct GBAArguments* args, struct GBAThread*
|
||||||
threadContext->stateDir = threadContext->gameDir;
|
threadContext->stateDir = threadContext->gameDir;
|
||||||
} else {
|
} else {
|
||||||
threadContext->rom = VFileOpen(args->fname, O_RDONLY);
|
threadContext->rom = VFileOpen(args->fname, O_RDONLY);
|
||||||
|
threadContext->gameDir = 0;
|
||||||
#if ENABLE_LIBZIP
|
#if ENABLE_LIBZIP
|
||||||
threadContext->gameDir = VDirOpenZip(args->fname, 0);
|
if (!threadContext->gameDir) {
|
||||||
|
threadContext->gameDir = VDirOpenZip(args->fname, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if ENABLE_LZMA
|
||||||
|
if (!threadContext->gameDir) {
|
||||||
|
threadContext->gameDir = VDirOpen7z(args->fname, 0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
threadContext->fname = args->fname;
|
threadContext->fname = args->fname;
|
||||||
|
|
|
@ -186,6 +186,7 @@ void GameController::openGame() {
|
||||||
m_threadContext.sync.audioWait = m_audioSync;
|
m_threadContext.sync.audioWait = m_audioSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_threadContext.gameDir = 0;
|
||||||
m_threadContext.fname = strdup(m_fname.toLocal8Bit().constData());
|
m_threadContext.fname = strdup(m_fname.toLocal8Bit().constData());
|
||||||
if (m_dirmode) {
|
if (m_dirmode) {
|
||||||
m_threadContext.gameDir = VDirOpen(m_threadContext.fname);
|
m_threadContext.gameDir = VDirOpen(m_threadContext.fname);
|
||||||
|
@ -193,7 +194,14 @@ void GameController::openGame() {
|
||||||
} else {
|
} else {
|
||||||
m_threadContext.rom = VFileOpen(m_threadContext.fname, O_RDONLY);
|
m_threadContext.rom = VFileOpen(m_threadContext.fname, O_RDONLY);
|
||||||
#if ENABLE_LIBZIP
|
#if ENABLE_LIBZIP
|
||||||
m_threadContext.gameDir = VDirOpenZip(m_threadContext.fname, 0);
|
if (!m_threadContext.gameDir) {
|
||||||
|
m_threadContext.gameDir = VDirOpenZip(m_threadContext.fname, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if ENABLE_LZMA
|
||||||
|
if (!m_threadContext.gameDir) {
|
||||||
|
m_threadContext.gameDir = VDirOpen7z(m_threadContext.fname, 0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
/* 7z.h -- 7z interface
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_H
|
||||||
|
#define __7Z_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define k7zStartHeaderSize 0x20
|
||||||
|
#define k7zSignatureSize 6
|
||||||
|
|
||||||
|
extern Byte k7zSignature[k7zSignatureSize];
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const Byte *Data;
|
||||||
|
size_t Size;
|
||||||
|
} CSzData;
|
||||||
|
|
||||||
|
/* CSzCoderInfo & CSzFolder support only default methods */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t PropsOffset;
|
||||||
|
UInt32 MethodID;
|
||||||
|
Byte NumInStreams;
|
||||||
|
Byte NumOutStreams;
|
||||||
|
Byte PropsSize;
|
||||||
|
} CSzCoderInfo;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt32 InIndex;
|
||||||
|
UInt32 OutIndex;
|
||||||
|
} CSzBindPair;
|
||||||
|
|
||||||
|
#define SZ_NUM_CODERS_IN_FOLDER_MAX 4
|
||||||
|
#define SZ_NUM_BINDS_IN_FOLDER_MAX 3
|
||||||
|
#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4
|
||||||
|
#define SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX 4
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt32 NumCoders;
|
||||||
|
UInt32 NumBindPairs;
|
||||||
|
UInt32 NumPackStreams;
|
||||||
|
UInt32 MainOutStream;
|
||||||
|
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
|
||||||
|
CSzBindPair BindPairs[SZ_NUM_BINDS_IN_FOLDER_MAX];
|
||||||
|
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
|
||||||
|
UInt64 CodersUnpackSizes[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX];
|
||||||
|
} CSzFolder;
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t CodersDataOffset;
|
||||||
|
size_t UnpackSizeDataOffset;
|
||||||
|
// UInt32 StartCoderUnpackSizesIndex;
|
||||||
|
UInt32 StartPackStreamIndex;
|
||||||
|
// UInt32 IndexOfMainOutStream;
|
||||||
|
} CSzFolder2;
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt32 Low;
|
||||||
|
UInt32 High;
|
||||||
|
} CNtfsFileTime;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte *Defs; /* MSB 0 bit numbering */
|
||||||
|
UInt32 *Vals;
|
||||||
|
} CSzBitUi32s;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte *Defs; /* MSB 0 bit numbering */
|
||||||
|
// UInt64 *Vals;
|
||||||
|
CNtfsFileTime *Vals;
|
||||||
|
} CSzBitUi64s;
|
||||||
|
|
||||||
|
#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||||
|
|
||||||
|
#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt32 NumPackStreams;
|
||||||
|
UInt32 NumFolders;
|
||||||
|
|
||||||
|
UInt64 *PackPositions; // NumPackStreams + 1
|
||||||
|
CSzBitUi32s FolderCRCs;
|
||||||
|
|
||||||
|
size_t *FoCodersOffsets;
|
||||||
|
size_t *FoSizesOffsets;
|
||||||
|
// UInt32 StartCoderUnpackSizesIndex;
|
||||||
|
UInt32 *FoStartPackStreamIndex;
|
||||||
|
|
||||||
|
// CSzFolder2 *Folders; // +1 item for sum values
|
||||||
|
Byte *CodersData;
|
||||||
|
Byte *UnpackSizesData;
|
||||||
|
size_t UnpackSizesDataSize;
|
||||||
|
// UInt64 *CoderUnpackSizes;
|
||||||
|
} CSzAr;
|
||||||
|
|
||||||
|
|
||||||
|
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
|
||||||
|
ILookInStream *stream, UInt64 startPos,
|
||||||
|
Byte *outBuffer, size_t outSize,
|
||||||
|
ISzAlloc *allocMain);
|
||||||
|
|
||||||
|
/*
|
||||||
|
SzExtract extracts file from archive
|
||||||
|
|
||||||
|
*outBuffer must be 0 before first call for each new archive.
|
||||||
|
|
||||||
|
Extracting cache:
|
||||||
|
If you need to decompress more than one file, you can send
|
||||||
|
these values from previous call:
|
||||||
|
*blockIndex,
|
||||||
|
*outBuffer,
|
||||||
|
*outBufferSize
|
||||||
|
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||||
|
it will increase decompression speed.
|
||||||
|
|
||||||
|
If you use external function, you can declare these 3 cache variables
|
||||||
|
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||||
|
|
||||||
|
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CSzAr db;
|
||||||
|
|
||||||
|
UInt64 startPosAfterHeader;
|
||||||
|
UInt64 dataPos;
|
||||||
|
|
||||||
|
UInt32 NumFiles;
|
||||||
|
|
||||||
|
UInt64 *UnpackPositions;
|
||||||
|
// Byte *IsEmptyFiles;
|
||||||
|
Byte *IsDirs;
|
||||||
|
CSzBitUi32s CRCs;
|
||||||
|
|
||||||
|
CSzBitUi32s Attribs;
|
||||||
|
// CSzBitUi32s Parents;
|
||||||
|
CSzBitUi64s MTime;
|
||||||
|
CSzBitUi64s CTime;
|
||||||
|
|
||||||
|
// UInt32 *FolderStartPackStreamIndex;
|
||||||
|
UInt32 *FolderStartFileIndex; // + 1
|
||||||
|
UInt32 *FileIndexToFolderIndexMap;
|
||||||
|
|
||||||
|
size_t *FileNameOffsets; /* in 2-byte steps */
|
||||||
|
Byte *FileNames; /* UTF-16-LE */
|
||||||
|
} CSzArEx;
|
||||||
|
|
||||||
|
#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i))
|
||||||
|
|
||||||
|
#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i])
|
||||||
|
|
||||||
|
void SzArEx_Init(CSzArEx *p);
|
||||||
|
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
||||||
|
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||||
|
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if dest == NULL, the return value specifies the required size of the buffer,
|
||||||
|
in 16-bit characters, including the null-terminating character.
|
||||||
|
if dest != NULL, the return value specifies the number of 16-bit characters that
|
||||||
|
are written to the dest, including the null-terminating character. */
|
||||||
|
|
||||||
|
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||||
|
|
||||||
|
/*
|
||||||
|
size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);
|
||||||
|
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes SzArEx_Extract(
|
||||||
|
const CSzArEx *db,
|
||||||
|
ILookInStream *inStream,
|
||||||
|
UInt32 fileIndex, /* index of file */
|
||||||
|
UInt32 *blockIndex, /* index of solid block */
|
||||||
|
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||||
|
size_t *outBufferSize, /* buffer size for output buffer */
|
||||||
|
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||||
|
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||||
|
ISzAlloc *allocMain,
|
||||||
|
ISzAlloc *allocTemp);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
SzArEx_Open Errors:
|
||||||
|
SZ_ERROR_NO_ARCHIVE
|
||||||
|
SZ_ERROR_ARCHIVE
|
||||||
|
SZ_ERROR_UNSUPPORTED
|
||||||
|
SZ_ERROR_MEM
|
||||||
|
SZ_ERROR_CRC
|
||||||
|
SZ_ERROR_INPUT_EOF
|
||||||
|
SZ_ERROR_FAIL
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
|
||||||
|
ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* 7zAlloc.c -- Allocation functions
|
||||||
|
2010-10-29 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "7zAlloc.h"
|
||||||
|
|
||||||
|
/* #define _SZ_ALLOC_DEBUG */
|
||||||
|
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
||||||
|
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
int g_allocCount = 0;
|
||||||
|
int g_allocCountTemp = 0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *SzAlloc(void *p, size_t size)
|
||||||
|
{
|
||||||
|
p = p;
|
||||||
|
if (size == 0)
|
||||||
|
return 0;
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
|
||||||
|
g_allocCount++;
|
||||||
|
#endif
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SzFree(void *p, void *address)
|
||||||
|
{
|
||||||
|
p = p;
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
if (address != 0)
|
||||||
|
{
|
||||||
|
g_allocCount--;
|
||||||
|
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
free(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *SzAllocTemp(void *p, size_t size)
|
||||||
|
{
|
||||||
|
p = p;
|
||||||
|
if (size == 0)
|
||||||
|
return 0;
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
|
||||||
|
g_allocCountTemp++;
|
||||||
|
#ifdef _WIN32
|
||||||
|
return HeapAlloc(GetProcessHeap(), 0, size);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SzFreeTemp(void *p, void *address)
|
||||||
|
{
|
||||||
|
p = p;
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
if (address != 0)
|
||||||
|
{
|
||||||
|
g_allocCountTemp--;
|
||||||
|
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
HeapFree(GetProcessHeap(), 0, address);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
free(address);
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* 7zAlloc.h -- Allocation functions
|
||||||
|
2010-10-29 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_ALLOC_H
|
||||||
|
#define __7Z_ALLOC_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void *SzAlloc(void *p, size_t size);
|
||||||
|
void SzFree(void *p, void *address);
|
||||||
|
|
||||||
|
void *SzAllocTemp(void *p, size_t size);
|
||||||
|
void SzFreeTemp(void *p, void *address);
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,36 @@
|
||||||
|
/* 7zBuf.c -- Byte Buffer
|
||||||
|
2013-01-21 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "7zBuf.h"
|
||||||
|
|
||||||
|
void Buf_Init(CBuf *p)
|
||||||
|
{
|
||||||
|
p->data = 0;
|
||||||
|
p->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
p->size = 0;
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
p->data = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p->data = (Byte *)alloc->Alloc(alloc, size);
|
||||||
|
if (p->data != 0)
|
||||||
|
{
|
||||||
|
p->size = size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buf_Free(CBuf *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->data);
|
||||||
|
p->data = 0;
|
||||||
|
p->size = 0;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* 7zBuf.h -- Byte Buffer
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_BUF_H
|
||||||
|
#define __7Z_BUF_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte *data;
|
||||||
|
size_t size;
|
||||||
|
} CBuf;
|
||||||
|
|
||||||
|
void Buf_Init(CBuf *p);
|
||||||
|
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
|
||||||
|
void Buf_Free(CBuf *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte *data;
|
||||||
|
size_t size;
|
||||||
|
size_t pos;
|
||||||
|
} CDynBuf;
|
||||||
|
|
||||||
|
void DynBuf_Construct(CDynBuf *p);
|
||||||
|
void DynBuf_SeekToBeg(CDynBuf *p);
|
||||||
|
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
|
||||||
|
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* 7zBuf2.c -- Byte Buffer
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "7zBuf.h"
|
||||||
|
|
||||||
|
void DynBuf_Construct(CDynBuf *p)
|
||||||
|
{
|
||||||
|
p->data = 0;
|
||||||
|
p->size = 0;
|
||||||
|
p->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynBuf_SeekToBeg(CDynBuf *p)
|
||||||
|
{
|
||||||
|
p->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
if (size > p->size - p->pos)
|
||||||
|
{
|
||||||
|
size_t newSize = p->pos + size;
|
||||||
|
Byte *data;
|
||||||
|
newSize += newSize / 4;
|
||||||
|
data = (Byte *)alloc->Alloc(alloc, newSize);
|
||||||
|
if (data == 0)
|
||||||
|
return 0;
|
||||||
|
p->size = newSize;
|
||||||
|
memcpy(data, p->data, p->pos);
|
||||||
|
alloc->Free(alloc, p->data);
|
||||||
|
p->data = data;
|
||||||
|
}
|
||||||
|
memcpy(p->data + p->pos, buf, size);
|
||||||
|
p->pos += size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->data);
|
||||||
|
p->data = 0;
|
||||||
|
p->size = 0;
|
||||||
|
p->pos = 0;
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* 7zCrc.c -- CRC32 init
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "7zCrc.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
|
#define kCrcPoly 0xEDB88320
|
||||||
|
|
||||||
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
#define CRC_NUM_TABLES 8
|
||||||
|
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||||
|
#elif defined(MY_CPU_LE)
|
||||||
|
#define CRC_NUM_TABLES 4
|
||||||
|
#else
|
||||||
|
#define CRC_NUM_TABLES 5
|
||||||
|
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
||||||
|
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MY_CPU_BE
|
||||||
|
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||||
|
|
||||||
|
CRC_FUNC g_CrcUpdate;
|
||||||
|
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
|
||||||
|
|
||||||
|
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
return g_CrcUpdate(v, data, size, g_CrcTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||||
|
{
|
||||||
|
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL CrcGenerateTable()
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
UInt32 r = i;
|
||||||
|
unsigned j;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||||
|
g_CrcTable[i] = r;
|
||||||
|
}
|
||||||
|
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||||
|
{
|
||||||
|
UInt32 r = g_CrcTable[i - 256];
|
||||||
|
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE
|
||||||
|
|
||||||
|
g_CrcUpdate = CrcUpdateT4;
|
||||||
|
|
||||||
|
#if CRC_NUM_TABLES == 8
|
||||||
|
if (!CPU_Is_InOrder())
|
||||||
|
g_CrcUpdate = CrcUpdateT8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
#ifndef MY_CPU_BE
|
||||||
|
UInt32 k = 1;
|
||||||
|
if (*(const Byte *)&k == 1)
|
||||||
|
g_CrcUpdate = CrcUpdateT4;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
|
||||||
|
{
|
||||||
|
UInt32 x = g_CrcTable[i - 256];
|
||||||
|
g_CrcTable[i] = CRC_UINT32_SWAP(x);
|
||||||
|
}
|
||||||
|
g_CrcUpdate = CrcUpdateT1_BeT4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* 7zCrc.h -- CRC32 calculation
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_CRC_H
|
||||||
|
#define __7Z_CRC_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
extern UInt32 g_CrcTable[];
|
||||||
|
|
||||||
|
/* Call CrcGenerateTable one time before other CRC functions */
|
||||||
|
void MY_FAST_CALL CrcGenerateTable(void);
|
||||||
|
|
||||||
|
#define CRC_INIT_VAL 0xFFFFFFFF
|
||||||
|
#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
|
||||||
|
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||||
|
|
||||||
|
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
|
||||||
|
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,66 @@
|
||||||
|
/* 7zCrcOpt.c -- CRC32 calculation
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
|
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||||
|
|
||||||
|
#ifndef MY_CPU_BE
|
||||||
|
|
||||||
|
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||||
|
{
|
||||||
|
const Byte *p = (const Byte *)data;
|
||||||
|
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||||
|
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||||
|
for (; size >= 4; size -= 4, p += 4)
|
||||||
|
{
|
||||||
|
v ^= *(const UInt32 *)p;
|
||||||
|
v =
|
||||||
|
table[0x300 + (v & 0xFF)] ^
|
||||||
|
table[0x200 + ((v >> 8) & 0xFF)] ^
|
||||||
|
table[0x100 + ((v >> 16) & 0xFF)] ^
|
||||||
|
table[0x000 + ((v >> 24))];
|
||||||
|
}
|
||||||
|
for (; size > 0; size--, p++)
|
||||||
|
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||||
|
{
|
||||||
|
return CrcUpdateT4(v, data, size, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MY_CPU_LE
|
||||||
|
|
||||||
|
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
||||||
|
|
||||||
|
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||||
|
{
|
||||||
|
const Byte *p = (const Byte *)data;
|
||||||
|
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||||
|
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||||
|
v = CRC_UINT32_SWAP(v);
|
||||||
|
table += 0x100;
|
||||||
|
for (; size >= 4; size -= 4, p += 4)
|
||||||
|
{
|
||||||
|
v ^= *(const UInt32 *)p;
|
||||||
|
v =
|
||||||
|
table[0x000 + (v & 0xFF)] ^
|
||||||
|
table[0x100 + ((v >> 8) & 0xFF)] ^
|
||||||
|
table[0x200 + ((v >> 16) & 0xFF)] ^
|
||||||
|
table[0x300 + ((v >> 24))];
|
||||||
|
}
|
||||||
|
table -= 0x100;
|
||||||
|
v = CRC_UINT32_SWAP(v);
|
||||||
|
for (; size > 0; size--, p++)
|
||||||
|
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,493 @@
|
||||||
|
/* 7zDec.c -- Decoding from 7z folder
|
||||||
|
2014-06-16 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* #define _7ZIP_PPMD_SUPPPORT */
|
||||||
|
|
||||||
|
#include "7z.h"
|
||||||
|
|
||||||
|
#include "Bcj2.h"
|
||||||
|
#include "Bra.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
#include "LzmaDec.h"
|
||||||
|
#include "Lzma2Dec.h"
|
||||||
|
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||||
|
#include "Ppmd7.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define k_Copy 0
|
||||||
|
#define k_LZMA2 0x21
|
||||||
|
#define k_LZMA 0x30101
|
||||||
|
#define k_BCJ 0x03030103
|
||||||
|
#define k_PPC 0x03030205
|
||||||
|
#define k_ARM 0x03030501
|
||||||
|
#define k_ARMT 0x03030701
|
||||||
|
#define k_SPARC 0x03030805
|
||||||
|
#define k_BCJ2 0x0303011B
|
||||||
|
|
||||||
|
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||||
|
|
||||||
|
#define k_PPMD 0x30401
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
IByteIn p;
|
||||||
|
const Byte *cur;
|
||||||
|
const Byte *end;
|
||||||
|
const Byte *begin;
|
||||||
|
UInt64 processed;
|
||||||
|
Bool extra;
|
||||||
|
SRes res;
|
||||||
|
ILookInStream *inStream;
|
||||||
|
} CByteInToLook;
|
||||||
|
|
||||||
|
static Byte ReadByte(void *pp)
|
||||||
|
{
|
||||||
|
CByteInToLook *p = (CByteInToLook *)pp;
|
||||||
|
if (p->cur != p->end)
|
||||||
|
return *p->cur++;
|
||||||
|
if (p->res == SZ_OK)
|
||||||
|
{
|
||||||
|
size_t size = p->cur - p->begin;
|
||||||
|
p->processed += size;
|
||||||
|
p->res = p->inStream->Skip(p->inStream, size);
|
||||||
|
size = (1 << 25);
|
||||||
|
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
|
||||||
|
p->cur = p->begin;
|
||||||
|
p->end = p->begin + size;
|
||||||
|
if (size != 0)
|
||||||
|
return *p->cur++;;
|
||||||
|
}
|
||||||
|
p->extra = True;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||||
|
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||||
|
{
|
||||||
|
CPpmd7 ppmd;
|
||||||
|
CByteInToLook s;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
s.p.Read = ReadByte;
|
||||||
|
s.inStream = inStream;
|
||||||
|
s.begin = s.end = s.cur = NULL;
|
||||||
|
s.extra = False;
|
||||||
|
s.res = SZ_OK;
|
||||||
|
s.processed = 0;
|
||||||
|
|
||||||
|
if (propsSize != 5)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned order = props[0];
|
||||||
|
UInt32 memSize = GetUi32(props + 1);
|
||||||
|
if (order < PPMD7_MIN_ORDER ||
|
||||||
|
order > PPMD7_MAX_ORDER ||
|
||||||
|
memSize < PPMD7_MIN_MEM_SIZE ||
|
||||||
|
memSize > PPMD7_MAX_MEM_SIZE)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
Ppmd7_Construct(&ppmd);
|
||||||
|
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
Ppmd7_Init(&ppmd, order);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CPpmd7z_RangeDec rc;
|
||||||
|
Ppmd7z_RangeDec_CreateVTable(&rc);
|
||||||
|
rc.Stream = &s.p;
|
||||||
|
if (!Ppmd7z_RangeDec_Init(&rc))
|
||||||
|
res = SZ_ERROR_DATA;
|
||||||
|
else if (s.extra)
|
||||||
|
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
for (i = 0; i < outSize; i++)
|
||||||
|
{
|
||||||
|
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
|
||||||
|
if (s.extra || sym < 0)
|
||||||
|
break;
|
||||||
|
outBuffer[i] = (Byte)sym;
|
||||||
|
}
|
||||||
|
if (i != outSize)
|
||||||
|
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||||
|
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
|
||||||
|
res = SZ_ERROR_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ppmd7_Free(&ppmd, allocMain);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||||
|
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||||
|
{
|
||||||
|
CLzmaDec state;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
LzmaDec_Construct(&state);
|
||||||
|
RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));
|
||||||
|
state.dic = outBuffer;
|
||||||
|
state.dicBufSize = outSize;
|
||||||
|
LzmaDec_Init(&state);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Byte *inBuf = NULL;
|
||||||
|
size_t lookahead = (1 << 18);
|
||||||
|
if (lookahead > inSize)
|
||||||
|
lookahead = (size_t)inSize;
|
||||||
|
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
{
|
||||||
|
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
||||||
|
ELzmaStatus status;
|
||||||
|
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||||
|
lookahead -= inProcessed;
|
||||||
|
inSize -= inProcessed;
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
|
||||||
|
{
|
||||||
|
if (state.dicBufSize != outSize || lookahead != 0 ||
|
||||||
|
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||||
|
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
||||||
|
res = SZ_ERROR_DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res = inStream->Skip((void *)inStream, inProcessed);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LzmaDec_FreeProbs(&state, allocMain);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||||
|
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||||
|
{
|
||||||
|
CLzma2Dec state;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
Lzma2Dec_Construct(&state);
|
||||||
|
if (propsSize != 1)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));
|
||||||
|
state.decoder.dic = outBuffer;
|
||||||
|
state.decoder.dicBufSize = outSize;
|
||||||
|
Lzma2Dec_Init(&state);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Byte *inBuf = NULL;
|
||||||
|
size_t lookahead = (1 << 18);
|
||||||
|
if (lookahead > inSize)
|
||||||
|
lookahead = (size_t)inSize;
|
||||||
|
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
{
|
||||||
|
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
|
||||||
|
ELzmaStatus status;
|
||||||
|
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||||
|
lookahead -= inProcessed;
|
||||||
|
inSize -= inProcessed;
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
|
||||||
|
{
|
||||||
|
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
|
||||||
|
(status != LZMA_STATUS_FINISHED_WITH_MARK))
|
||||||
|
res = SZ_ERROR_DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res = inStream->Skip((void *)inStream, inProcessed);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Lzma2Dec_FreeProbs(&state, allocMain);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
||||||
|
{
|
||||||
|
while (inSize > 0)
|
||||||
|
{
|
||||||
|
void *inBuf;
|
||||||
|
size_t curSize = (1 << 18);
|
||||||
|
if (curSize > inSize)
|
||||||
|
curSize = (size_t)inSize;
|
||||||
|
RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
|
||||||
|
if (curSize == 0)
|
||||||
|
return SZ_ERROR_INPUT_EOF;
|
||||||
|
memcpy(outBuffer, inBuf, curSize);
|
||||||
|
outBuffer += curSize;
|
||||||
|
inSize -= curSize;
|
||||||
|
RINOK(inStream->Skip((void *)inStream, curSize));
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool IS_MAIN_METHOD(UInt32 m)
|
||||||
|
{
|
||||||
|
switch (m)
|
||||||
|
{
|
||||||
|
case k_Copy:
|
||||||
|
case k_LZMA:
|
||||||
|
case k_LZMA2:
|
||||||
|
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||||
|
case k_PPMD:
|
||||||
|
#endif
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
c->NumInStreams == 1 &&
|
||||||
|
c->NumOutStreams == 1 &&
|
||||||
|
/* c->MethodID <= (UInt32)0xFFFFFFFF && */
|
||||||
|
IS_MAIN_METHOD((UInt32)c->MethodID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
|
||||||
|
|
||||||
|
static SRes CheckSupportedFolder(const CSzFolder *f)
|
||||||
|
{
|
||||||
|
if (f->NumCoders < 1 || f->NumCoders > 4)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
if (!IS_SUPPORTED_CODER(&f->Coders[0]))
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
if (f->NumCoders == 1)
|
||||||
|
{
|
||||||
|
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
if (f->NumCoders == 2)
|
||||||
|
{
|
||||||
|
const CSzCoderInfo *c = &f->Coders[1];
|
||||||
|
if (
|
||||||
|
/* c->MethodID > (UInt32)0xFFFFFFFF || */
|
||||||
|
c->NumInStreams != 1 ||
|
||||||
|
c->NumOutStreams != 1 ||
|
||||||
|
f->NumPackStreams != 1 ||
|
||||||
|
f->PackStreams[0] != 0 ||
|
||||||
|
f->NumBindPairs != 1 ||
|
||||||
|
f->BindPairs[0].InIndex != 1 ||
|
||||||
|
f->BindPairs[0].OutIndex != 0)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
switch ((UInt32)c->MethodID)
|
||||||
|
{
|
||||||
|
case k_BCJ:
|
||||||
|
case k_ARM:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
if (f->NumCoders == 4)
|
||||||
|
{
|
||||||
|
if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
|
||||||
|
!IS_SUPPORTED_CODER(&f->Coders[2]) ||
|
||||||
|
!IS_BCJ2(&f->Coders[3]))
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
if (f->NumPackStreams != 4 ||
|
||||||
|
f->PackStreams[0] != 2 ||
|
||||||
|
f->PackStreams[1] != 6 ||
|
||||||
|
f->PackStreams[2] != 1 ||
|
||||||
|
f->PackStreams[3] != 0 ||
|
||||||
|
f->NumBindPairs != 3 ||
|
||||||
|
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
|
||||||
|
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
|
||||||
|
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
|
||||||
|
|
||||||
|
static SRes SzFolder_Decode2(const CSzFolder *folder,
|
||||||
|
const Byte *propsData,
|
||||||
|
const UInt64 *unpackSizes,
|
||||||
|
const UInt64 *packPositions,
|
||||||
|
ILookInStream *inStream, UInt64 startPos,
|
||||||
|
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
|
||||||
|
Byte *tempBuf[])
|
||||||
|
{
|
||||||
|
UInt32 ci;
|
||||||
|
SizeT tempSizes[3] = { 0, 0, 0};
|
||||||
|
SizeT tempSize3 = 0;
|
||||||
|
Byte *tempBuf3 = 0;
|
||||||
|
|
||||||
|
RINOK(CheckSupportedFolder(folder));
|
||||||
|
|
||||||
|
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||||
|
{
|
||||||
|
const CSzCoderInfo *coder = &folder->Coders[ci];
|
||||||
|
|
||||||
|
if (IS_MAIN_METHOD((UInt32)coder->MethodID))
|
||||||
|
{
|
||||||
|
UInt32 si = 0;
|
||||||
|
UInt64 offset;
|
||||||
|
UInt64 inSize;
|
||||||
|
Byte *outBufCur = outBuffer;
|
||||||
|
SizeT outSizeCur = outSize;
|
||||||
|
if (folder->NumCoders == 4)
|
||||||
|
{
|
||||||
|
UInt32 indices[] = { 3, 2, 0 };
|
||||||
|
UInt64 unpackSize = unpackSizes[ci];
|
||||||
|
si = indices[ci];
|
||||||
|
if (ci < 2)
|
||||||
|
{
|
||||||
|
Byte *temp;
|
||||||
|
outSizeCur = (SizeT)unpackSize;
|
||||||
|
if (outSizeCur != unpackSize)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
|
||||||
|
if (temp == 0 && outSizeCur != 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
outBufCur = tempBuf[1 - ci] = temp;
|
||||||
|
tempSizes[1 - ci] = outSizeCur;
|
||||||
|
}
|
||||||
|
else if (ci == 2)
|
||||||
|
{
|
||||||
|
if (unpackSize > outSize) /* check it */
|
||||||
|
return SZ_ERROR_PARAM;
|
||||||
|
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||||
|
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
offset = packPositions[si];
|
||||||
|
inSize = packPositions[si + 1] - offset;
|
||||||
|
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||||
|
|
||||||
|
if (coder->MethodID == k_Copy)
|
||||||
|
{
|
||||||
|
if (inSize != outSizeCur) /* check it */
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||||
|
}
|
||||||
|
else if (coder->MethodID == k_LZMA)
|
||||||
|
{
|
||||||
|
RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||||
|
}
|
||||||
|
else if (coder->MethodID == k_LZMA2)
|
||||||
|
{
|
||||||
|
RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||||
|
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||||
|
#else
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (coder->MethodID == k_BCJ2)
|
||||||
|
{
|
||||||
|
UInt64 offset = packPositions[1];
|
||||||
|
UInt64 s3Size = packPositions[2] - offset;
|
||||||
|
SRes res;
|
||||||
|
if (ci != 3)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||||
|
tempSizes[2] = (SizeT)s3Size;
|
||||||
|
if (tempSizes[2] != s3Size)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
|
||||||
|
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
||||||
|
RINOK(res)
|
||||||
|
|
||||||
|
res = Bcj2_Decode(
|
||||||
|
tempBuf3, tempSize3,
|
||||||
|
tempBuf[0], tempSizes[0],
|
||||||
|
tempBuf[1], tempSizes[1],
|
||||||
|
tempBuf[2], tempSizes[2],
|
||||||
|
outBuffer, outSize);
|
||||||
|
RINOK(res)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ci != 1)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
switch (coder->MethodID)
|
||||||
|
{
|
||||||
|
case k_BCJ:
|
||||||
|
{
|
||||||
|
UInt32 state;
|
||||||
|
x86_Convert_Init(state);
|
||||||
|
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CASE_BRA_CONV(ARM)
|
||||||
|
default:
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
|
||||||
|
ILookInStream *inStream, UInt64 startPos,
|
||||||
|
Byte *outBuffer, size_t outSize,
|
||||||
|
ISzAlloc *allocMain)
|
||||||
|
{
|
||||||
|
SRes res;
|
||||||
|
CSzFolder folder;
|
||||||
|
CSzData sd;
|
||||||
|
CSzData sdSizes;
|
||||||
|
|
||||||
|
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
|
||||||
|
sd.Data = data;
|
||||||
|
sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex];
|
||||||
|
|
||||||
|
sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex];
|
||||||
|
sdSizes.Size =
|
||||||
|
p->FoSizesOffsets[folderIndex + 1] -
|
||||||
|
p->FoSizesOffsets[folderIndex];
|
||||||
|
|
||||||
|
res = SzGetNextFolderItem(&folder, &sd, &sdSizes);
|
||||||
|
|
||||||
|
if (res != SZ_OK)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.MainOutStream])
|
||||||
|
return SZ_ERROR_FAIL;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Byte *tempBuf[3] = { 0, 0, 0};
|
||||||
|
res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes,
|
||||||
|
p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
|
||||||
|
inStream, startPos,
|
||||||
|
outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
IAlloc_Free(allocMain, tempBuf[i]);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,286 @@
|
||||||
|
/* 7zFile.c -- File IO
|
||||||
|
2009-11-24 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "7zFile.h"
|
||||||
|
|
||||||
|
#ifndef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
#ifndef UNDER_CE
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
ReadFile and WriteFile functions in Windows have BUG:
|
||||||
|
If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
|
||||||
|
from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
|
||||||
|
(Insufficient system resources exist to complete the requested service).
|
||||||
|
Probably in some version of Windows there are problems with other sizes:
|
||||||
|
for 32 MB (maybe also for 16 MB).
|
||||||
|
And message can be "Network connection was lost"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define kChunkSizeMax (1 << 22)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void File_Construct(CSzFile *p)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
p->handle = INVALID_HANDLE_VALUE;
|
||||||
|
#else
|
||||||
|
p->file = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
|
||||||
|
static WRes File_Open(CSzFile *p, const char *name, int writeMode)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
p->handle = CreateFileA(name,
|
||||||
|
writeMode ? GENERIC_WRITE : GENERIC_READ,
|
||||||
|
FILE_SHARE_READ, NULL,
|
||||||
|
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
|
||||||
|
#else
|
||||||
|
p->file = fopen(name, writeMode ? "wb+" : "rb");
|
||||||
|
return (p->file != 0) ? 0 :
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
2; /* ENOENT */
|
||||||
|
#else
|
||||||
|
errno;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
|
||||||
|
WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
|
||||||
|
{
|
||||||
|
p->handle = CreateFileW(name,
|
||||||
|
writeMode ? GENERIC_WRITE : GENERIC_READ,
|
||||||
|
FILE_SHARE_READ, NULL,
|
||||||
|
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
|
||||||
|
}
|
||||||
|
WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
|
||||||
|
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WRes File_Close(CSzFile *p)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
if (p->handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
if (!CloseHandle(p->handle))
|
||||||
|
return GetLastError();
|
||||||
|
p->handle = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (p->file != NULL)
|
||||||
|
{
|
||||||
|
int res = fclose(p->file);
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
p->file = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes File_Read(CSzFile *p, void *data, size_t *size)
|
||||||
|
{
|
||||||
|
size_t originalSize = *size;
|
||||||
|
if (originalSize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
*size = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
|
||||||
|
DWORD processed = 0;
|
||||||
|
BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);
|
||||||
|
data = (void *)((Byte *)data + processed);
|
||||||
|
originalSize -= processed;
|
||||||
|
*size += processed;
|
||||||
|
if (!res)
|
||||||
|
return GetLastError();
|
||||||
|
if (processed == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (originalSize > 0);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
*size = fread(data, 1, originalSize, p->file);
|
||||||
|
if (*size == originalSize)
|
||||||
|
return 0;
|
||||||
|
return ferror(p->file);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes File_Write(CSzFile *p, const void *data, size_t *size)
|
||||||
|
{
|
||||||
|
size_t originalSize = *size;
|
||||||
|
if (originalSize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
*size = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
|
||||||
|
DWORD processed = 0;
|
||||||
|
BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);
|
||||||
|
data = (void *)((Byte *)data + processed);
|
||||||
|
originalSize -= processed;
|
||||||
|
*size += processed;
|
||||||
|
if (!res)
|
||||||
|
return GetLastError();
|
||||||
|
if (processed == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (originalSize > 0);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
*size = fwrite(data, 1, originalSize, p->file);
|
||||||
|
if (*size == originalSize)
|
||||||
|
return 0;
|
||||||
|
return ferror(p->file);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
LARGE_INTEGER value;
|
||||||
|
DWORD moveMethod;
|
||||||
|
value.LowPart = (DWORD)*pos;
|
||||||
|
value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */
|
||||||
|
switch (origin)
|
||||||
|
{
|
||||||
|
case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;
|
||||||
|
case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;
|
||||||
|
case SZ_SEEK_END: moveMethod = FILE_END; break;
|
||||||
|
default: return ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);
|
||||||
|
if (value.LowPart == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
WRes res = GetLastError();
|
||||||
|
if (res != NO_ERROR)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
*pos = ((Int64)value.HighPart << 32) | value.LowPart;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int moveMethod;
|
||||||
|
int res;
|
||||||
|
switch (origin)
|
||||||
|
{
|
||||||
|
case SZ_SEEK_SET: moveMethod = SEEK_SET; break;
|
||||||
|
case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;
|
||||||
|
case SZ_SEEK_END: moveMethod = SEEK_END; break;
|
||||||
|
default: return 1;
|
||||||
|
}
|
||||||
|
res = fseek(p->file, (long)*pos, moveMethod);
|
||||||
|
*pos = ftell(p->file);
|
||||||
|
return res;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes File_GetLength(CSzFile *p, UInt64 *length)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
DWORD sizeHigh;
|
||||||
|
DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
|
||||||
|
if (sizeLow == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
DWORD res = GetLastError();
|
||||||
|
if (res != NO_ERROR)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
*length = (((UInt64)sizeHigh) << 32) + sizeLow;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
long pos = ftell(p->file);
|
||||||
|
int res = fseek(p->file, 0, SEEK_END);
|
||||||
|
*length = ftell(p->file);
|
||||||
|
fseek(p->file, pos, SEEK_SET);
|
||||||
|
return res;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- FileSeqInStream ---------- */
|
||||||
|
|
||||||
|
static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CFileSeqInStream *p = (CFileSeqInStream *)pp;
|
||||||
|
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
|
||||||
|
{
|
||||||
|
p->s.Read = FileSeqInStream_Read;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- FileInStream ---------- */
|
||||||
|
|
||||||
|
static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CFileInStream *p = (CFileInStream *)pp;
|
||||||
|
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||||
|
{
|
||||||
|
CFileInStream *p = (CFileInStream *)pp;
|
||||||
|
return File_Seek(&p->file, pos, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileInStream_CreateVTable(CFileInStream *p)
|
||||||
|
{
|
||||||
|
p->s.Read = FileInStream_Read;
|
||||||
|
p->s.Seek = FileInStream_Seek;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- FileOutStream ---------- */
|
||||||
|
|
||||||
|
static size_t FileOutStream_Write(void *pp, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
CFileOutStream *p = (CFileOutStream *)pp;
|
||||||
|
File_Write(&p->file, data, &size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileOutStream_CreateVTable(CFileOutStream *p)
|
||||||
|
{
|
||||||
|
p->s.Write = FileOutStream_Write;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* 7zFile.h -- File IO
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_FILE_H
|
||||||
|
#define __7Z_FILE_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define USE_WINDOWS_FILE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
/* ---------- File ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
HANDLE handle;
|
||||||
|
#else
|
||||||
|
FILE *file;
|
||||||
|
#endif
|
||||||
|
} CSzFile;
|
||||||
|
|
||||||
|
void File_Construct(CSzFile *p);
|
||||||
|
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
|
||||||
|
WRes InFile_Open(CSzFile *p, const char *name);
|
||||||
|
WRes OutFile_Open(CSzFile *p, const char *name);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
|
||||||
|
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
|
||||||
|
#endif
|
||||||
|
WRes File_Close(CSzFile *p);
|
||||||
|
|
||||||
|
/* reads max(*size, remain file's size) bytes */
|
||||||
|
WRes File_Read(CSzFile *p, void *data, size_t *size);
|
||||||
|
|
||||||
|
/* writes *size bytes */
|
||||||
|
WRes File_Write(CSzFile *p, const void *data, size_t *size);
|
||||||
|
|
||||||
|
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);
|
||||||
|
WRes File_GetLength(CSzFile *p, UInt64 *length);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- FileInStream ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream s;
|
||||||
|
CSzFile file;
|
||||||
|
} CFileSeqInStream;
|
||||||
|
|
||||||
|
void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeekInStream s;
|
||||||
|
CSzFile file;
|
||||||
|
} CFileInStream;
|
||||||
|
|
||||||
|
void FileInStream_CreateVTable(CFileInStream *p);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqOutStream s;
|
||||||
|
CSzFile file;
|
||||||
|
} CFileOutStream;
|
||||||
|
|
||||||
|
void FileOutStream_CreateVTable(CFileOutStream *p);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,171 @@
|
||||||
|
/* 7zStream.c -- 7z Stream functions
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||||
|
{
|
||||||
|
while (size != 0)
|
||||||
|
{
|
||||||
|
size_t processed = size;
|
||||||
|
RINOK(stream->Read(stream, buf, &processed));
|
||||||
|
if (processed == 0)
|
||||||
|
return errorType;
|
||||||
|
buf = (void *)((Byte *)buf + processed);
|
||||||
|
size -= processed;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
|
||||||
|
{
|
||||||
|
size_t processed = 1;
|
||||||
|
RINOK(stream->Read(stream, buf, &processed));
|
||||||
|
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
|
||||||
|
{
|
||||||
|
Int64 t = offset;
|
||||||
|
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
const void *lookBuf;
|
||||||
|
if (*size == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
RINOK(stream->Look(stream, &lookBuf, size));
|
||||||
|
memcpy(buf, lookBuf, *size);
|
||||||
|
return stream->Skip(stream, *size);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
||||||
|
{
|
||||||
|
while (size != 0)
|
||||||
|
{
|
||||||
|
size_t processed = size;
|
||||||
|
RINOK(stream->Read(stream, buf, &processed));
|
||||||
|
if (processed == 0)
|
||||||
|
return errorType;
|
||||||
|
buf = (void *)((Byte *)buf + processed);
|
||||||
|
size -= processed;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
|
||||||
|
{
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
size_t size2 = p->size - p->pos;
|
||||||
|
if (size2 == 0 && *size > 0)
|
||||||
|
{
|
||||||
|
p->pos = 0;
|
||||||
|
size2 = LookToRead_BUF_SIZE;
|
||||||
|
res = p->realStream->Read(p->realStream, p->buf, &size2);
|
||||||
|
p->size = size2;
|
||||||
|
}
|
||||||
|
if (size2 < *size)
|
||||||
|
*size = size2;
|
||||||
|
*buf = p->buf + p->pos;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
|
||||||
|
{
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
size_t size2 = p->size - p->pos;
|
||||||
|
if (size2 == 0 && *size > 0)
|
||||||
|
{
|
||||||
|
p->pos = 0;
|
||||||
|
if (*size > LookToRead_BUF_SIZE)
|
||||||
|
*size = LookToRead_BUF_SIZE;
|
||||||
|
res = p->realStream->Read(p->realStream, p->buf, size);
|
||||||
|
size2 = p->size = *size;
|
||||||
|
}
|
||||||
|
if (size2 < *size)
|
||||||
|
*size = size2;
|
||||||
|
*buf = p->buf + p->pos;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Skip(void *pp, size_t offset)
|
||||||
|
{
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
p->pos += offset;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
size_t rem = p->size - p->pos;
|
||||||
|
if (rem == 0)
|
||||||
|
return p->realStream->Read(p->realStream, buf, size);
|
||||||
|
if (rem > *size)
|
||||||
|
rem = *size;
|
||||||
|
memcpy(buf, p->buf + p->pos, rem);
|
||||||
|
p->pos += rem;
|
||||||
|
*size = rem;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||||
|
{
|
||||||
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
|
p->pos = p->size = 0;
|
||||||
|
return p->realStream->Seek(p->realStream, pos, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
|
||||||
|
{
|
||||||
|
p->s.Look = lookahead ?
|
||||||
|
LookToRead_Look_Lookahead :
|
||||||
|
LookToRead_Look_Exact;
|
||||||
|
p->s.Skip = LookToRead_Skip;
|
||||||
|
p->s.Read = LookToRead_Read;
|
||||||
|
p->s.Seek = LookToRead_Seek;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LookToRead_Init(CLookToRead *p)
|
||||||
|
{
|
||||||
|
p->pos = p->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CSecToLook *p = (CSecToLook *)pp;
|
||||||
|
return LookInStream_LookRead(p->realStream, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecToLook_CreateVTable(CSecToLook *p)
|
||||||
|
{
|
||||||
|
p->s.Read = SecToLook_Read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
CSecToRead *p = (CSecToRead *)pp;
|
||||||
|
return p->realStream->Read(p->realStream, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecToRead_CreateVTable(CSecToRead *p)
|
||||||
|
{
|
||||||
|
p->s.Read = SecToRead_Read;
|
||||||
|
}
|
|
@ -0,0 +1,256 @@
|
||||||
|
/* 7zTypes.h -- Basic types
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_TYPES_H
|
||||||
|
#define __7Z_TYPES_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* #include <windows.h> */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef EXTERN_C_BEGIN
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define EXTERN_C_BEGIN extern "C" {
|
||||||
|
#define EXTERN_C_END }
|
||||||
|
#else
|
||||||
|
#define EXTERN_C_BEGIN
|
||||||
|
#define EXTERN_C_END
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define SZ_OK 0
|
||||||
|
|
||||||
|
#define SZ_ERROR_DATA 1
|
||||||
|
#define SZ_ERROR_MEM 2
|
||||||
|
#define SZ_ERROR_CRC 3
|
||||||
|
#define SZ_ERROR_UNSUPPORTED 4
|
||||||
|
#define SZ_ERROR_PARAM 5
|
||||||
|
#define SZ_ERROR_INPUT_EOF 6
|
||||||
|
#define SZ_ERROR_OUTPUT_EOF 7
|
||||||
|
#define SZ_ERROR_READ 8
|
||||||
|
#define SZ_ERROR_WRITE 9
|
||||||
|
#define SZ_ERROR_PROGRESS 10
|
||||||
|
#define SZ_ERROR_FAIL 11
|
||||||
|
#define SZ_ERROR_THREAD 12
|
||||||
|
|
||||||
|
#define SZ_ERROR_ARCHIVE 16
|
||||||
|
#define SZ_ERROR_NO_ARCHIVE 17
|
||||||
|
|
||||||
|
typedef int SRes;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* typedef DWORD WRes; */
|
||||||
|
typedef unsigned WRes;
|
||||||
|
#else
|
||||||
|
typedef int WRes;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RINOK
|
||||||
|
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char Byte;
|
||||||
|
typedef short Int16;
|
||||||
|
typedef unsigned short UInt16;
|
||||||
|
|
||||||
|
#ifdef _LZMA_UINT32_IS_ULONG
|
||||||
|
typedef long Int32;
|
||||||
|
typedef unsigned long UInt32;
|
||||||
|
#else
|
||||||
|
typedef int Int32;
|
||||||
|
typedef unsigned int UInt32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _SZ_NO_INT_64
|
||||||
|
|
||||||
|
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||||
|
NOTES: Some code will work incorrectly in that case! */
|
||||||
|
|
||||||
|
typedef long Int64;
|
||||||
|
typedef unsigned long UInt64;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||||
|
typedef __int64 Int64;
|
||||||
|
typedef unsigned __int64 UInt64;
|
||||||
|
#define UINT64_CONST(n) n
|
||||||
|
#else
|
||||||
|
typedef long long int Int64;
|
||||||
|
typedef unsigned long long int UInt64;
|
||||||
|
#define UINT64_CONST(n) n ## ULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
||||||
|
typedef UInt32 SizeT;
|
||||||
|
#else
|
||||||
|
typedef size_t SizeT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef int Bool;
|
||||||
|
#define True 1
|
||||||
|
#define False 0
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define MY_STD_CALL __stdcall
|
||||||
|
#else
|
||||||
|
#define MY_STD_CALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1300
|
||||||
|
#define MY_NO_INLINE __declspec(noinline)
|
||||||
|
#else
|
||||||
|
#define MY_NO_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MY_CDECL __cdecl
|
||||||
|
#define MY_FAST_CALL __fastcall
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define MY_NO_INLINE
|
||||||
|
#define MY_CDECL
|
||||||
|
#define MY_FAST_CALL
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* The following interfaces use first parameter as pointer to structure */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||||
|
} IByteIn;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void (*Write)(void *p, Byte b);
|
||||||
|
} IByteOut;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||||
|
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||||
|
(output(*size) < input(*size)) is allowed */
|
||||||
|
} ISeqInStream;
|
||||||
|
|
||||||
|
/* it can return SZ_ERROR_INPUT_EOF */
|
||||||
|
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
|
||||||
|
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||||
|
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t (*Write)(void *p, const void *buf, size_t size);
|
||||||
|
/* Returns: result - the number of actually written bytes.
|
||||||
|
(result < size) means error */
|
||||||
|
} ISeqOutStream;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SZ_SEEK_SET = 0,
|
||||||
|
SZ_SEEK_CUR = 1,
|
||||||
|
SZ_SEEK_END = 2
|
||||||
|
} ESzSeek;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||||
|
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||||
|
} ISeekInStream;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Look)(void *p, const void **buf, size_t *size);
|
||||||
|
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||||
|
(output(*size) > input(*size)) is not allowed
|
||||||
|
(output(*size) < input(*size)) is allowed */
|
||||||
|
SRes (*Skip)(void *p, size_t offset);
|
||||||
|
/* offset must be <= output(*size) of Look */
|
||||||
|
|
||||||
|
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||||
|
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
||||||
|
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||||
|
} ILookInStream;
|
||||||
|
|
||||||
|
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
|
||||||
|
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
|
||||||
|
|
||||||
|
/* reads via ILookInStream::Read */
|
||||||
|
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||||
|
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
|
||||||
|
|
||||||
|
#define LookToRead_BUF_SIZE (1 << 14)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ILookInStream s;
|
||||||
|
ISeekInStream *realStream;
|
||||||
|
size_t pos;
|
||||||
|
size_t size;
|
||||||
|
Byte buf[LookToRead_BUF_SIZE];
|
||||||
|
} CLookToRead;
|
||||||
|
|
||||||
|
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
|
||||||
|
void LookToRead_Init(CLookToRead *p);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream s;
|
||||||
|
ILookInStream *realStream;
|
||||||
|
} CSecToLook;
|
||||||
|
|
||||||
|
void SecToLook_CreateVTable(CSecToLook *p);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream s;
|
||||||
|
ILookInStream *realStream;
|
||||||
|
} CSecToRead;
|
||||||
|
|
||||||
|
void SecToRead_CreateVTable(CSecToRead *p);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
|
||||||
|
/* Returns: result. (result != SZ_OK) means break.
|
||||||
|
Value (UInt64)(Int64)-1 for size means unknown value. */
|
||||||
|
} ICompressProgress;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void *(*Alloc)(void *p, size_t size);
|
||||||
|
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||||
|
} ISzAlloc;
|
||||||
|
|
||||||
|
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
||||||
|
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#define CHAR_PATH_SEPARATOR '\\'
|
||||||
|
#define WCHAR_PATH_SEPARATOR L'\\'
|
||||||
|
#define STRING_PATH_SEPARATOR "\\"
|
||||||
|
#define WSTRING_PATH_SEPARATOR L"\\"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define CHAR_PATH_SEPARATOR '/'
|
||||||
|
#define WCHAR_PATH_SEPARATOR L'/'
|
||||||
|
#define STRING_PATH_SEPARATOR "/"
|
||||||
|
#define WSTRING_PATH_SEPARATOR L"/"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,10 @@
|
||||||
|
#define MY_VER_MAJOR 9
|
||||||
|
#define MY_VER_MINOR 38
|
||||||
|
#define MY_VER_BUILD 00
|
||||||
|
#define MY_VERSION "9.38 beta"
|
||||||
|
// #define MY_7ZIP_VERSION "9.38"
|
||||||
|
#define MY_DATE "2015-01-03"
|
||||||
|
#undef MY_COPYRIGHT
|
||||||
|
#undef MY_VERSION_COPYRIGHT_DATE
|
||||||
|
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
|
||||||
|
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
|
|
@ -0,0 +1,55 @@
|
||||||
|
#define MY_VS_FFI_FILEFLAGSMASK 0x0000003FL
|
||||||
|
#define MY_VOS_NT_WINDOWS32 0x00040004L
|
||||||
|
#define MY_VOS_CE_WINDOWS32 0x00050004L
|
||||||
|
|
||||||
|
#define MY_VFT_APP 0x00000001L
|
||||||
|
#define MY_VFT_DLL 0x00000002L
|
||||||
|
|
||||||
|
// #include <WinVer.h>
|
||||||
|
|
||||||
|
#ifndef MY_VERSION
|
||||||
|
#include "7zVersion.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define DBG_FL VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
#define DBG_FL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MY_VERSION_INFO(fileType, descr, intName, origName) \
|
||||||
|
LANGUAGE 9, 1 \
|
||||||
|
1 VERSIONINFO \
|
||||||
|
FILEVERSION MY_VER \
|
||||||
|
PRODUCTVERSION MY_VER \
|
||||||
|
FILEFLAGSMASK MY_VS_FFI_FILEFLAGSMASK \
|
||||||
|
FILEFLAGS DBG_FL \
|
||||||
|
FILEOS MY_VOS_NT_WINDOWS32 \
|
||||||
|
FILETYPE fileType \
|
||||||
|
FILESUBTYPE 0x0L \
|
||||||
|
BEGIN \
|
||||||
|
BLOCK "StringFileInfo" \
|
||||||
|
BEGIN \
|
||||||
|
BLOCK "040904b0" \
|
||||||
|
BEGIN \
|
||||||
|
VALUE "CompanyName", "Igor Pavlov" \
|
||||||
|
VALUE "FileDescription", descr \
|
||||||
|
VALUE "FileVersion", MY_VERSION \
|
||||||
|
VALUE "InternalName", intName \
|
||||||
|
VALUE "LegalCopyright", MY_COPYRIGHT \
|
||||||
|
VALUE "OriginalFilename", origName \
|
||||||
|
VALUE "ProductName", "7-Zip" \
|
||||||
|
VALUE "ProductVersion", MY_VERSION \
|
||||||
|
END \
|
||||||
|
END \
|
||||||
|
BLOCK "VarFileInfo" \
|
||||||
|
BEGIN \
|
||||||
|
VALUE "Translation", 0x409, 1200 \
|
||||||
|
END \
|
||||||
|
END
|
||||||
|
|
||||||
|
#define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(MY_VFT_APP, descr, intName, intName ".exe")
|
||||||
|
|
||||||
|
#define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(MY_VFT_DLL, descr, intName, intName ".dll")
|
|
@ -0,0 +1,284 @@
|
||||||
|
/* Aes.c -- AES encryption / decryption
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Aes.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
|
static UInt32 T[256 * 4];
|
||||||
|
static Byte Sbox[256] = {
|
||||||
|
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||||
|
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||||
|
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||||
|
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||||
|
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||||
|
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||||
|
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||||
|
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||||
|
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||||
|
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||||
|
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||||
|
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||||
|
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||||
|
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||||
|
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||||
|
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
|
||||||
|
AES_CODE_FUNC g_AesCbc_Encode;
|
||||||
|
AES_CODE_FUNC g_AesCbc_Decode;
|
||||||
|
AES_CODE_FUNC g_AesCtr_Code;
|
||||||
|
|
||||||
|
static UInt32 D[256 * 4];
|
||||||
|
static Byte InvS[256];
|
||||||
|
|
||||||
|
static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
|
||||||
|
|
||||||
|
#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)
|
||||||
|
|
||||||
|
#define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24))
|
||||||
|
|
||||||
|
#define gb0(x) ( (x) & 0xFF)
|
||||||
|
#define gb1(x) (((x) >> ( 8)) & 0xFF)
|
||||||
|
#define gb2(x) (((x) >> (16)) & 0xFF)
|
||||||
|
#define gb3(x) (((x) >> (24)) & 0xFF)
|
||||||
|
|
||||||
|
void AesGenTables(void)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
InvS[Sbox[i]] = (Byte)i;
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
UInt32 a1 = Sbox[i];
|
||||||
|
UInt32 a2 = xtime(a1);
|
||||||
|
UInt32 a3 = a2 ^ a1;
|
||||||
|
T[ i] = Ui32(a2, a1, a1, a3);
|
||||||
|
T[0x100 + i] = Ui32(a3, a2, a1, a1);
|
||||||
|
T[0x200 + i] = Ui32(a1, a3, a2, a1);
|
||||||
|
T[0x300 + i] = Ui32(a1, a1, a3, a2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
UInt32 a1 = InvS[i];
|
||||||
|
UInt32 a2 = xtime(a1);
|
||||||
|
UInt32 a4 = xtime(a2);
|
||||||
|
UInt32 a8 = xtime(a4);
|
||||||
|
UInt32 a9 = a8 ^ a1;
|
||||||
|
UInt32 aB = a8 ^ a2 ^ a1;
|
||||||
|
UInt32 aD = a8 ^ a4 ^ a1;
|
||||||
|
UInt32 aE = a8 ^ a4 ^ a2;
|
||||||
|
D[ i] = Ui32(aE, a9, aD, aB);
|
||||||
|
D[0x100 + i] = Ui32(aB, aE, a9, aD);
|
||||||
|
D[0x200 + i] = Ui32(aD, aB, aE, a9);
|
||||||
|
D[0x300 + i] = Ui32(a9, aD, aB, aE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_AesCbc_Encode = AesCbc_Encode;
|
||||||
|
g_AesCbc_Decode = AesCbc_Decode;
|
||||||
|
g_AesCtr_Code = AesCtr_Code;
|
||||||
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
if (CPU_Is_Aes_Supported())
|
||||||
|
{
|
||||||
|
g_AesCbc_Encode = AesCbc_Encode_Intel;
|
||||||
|
g_AesCbc_Decode = AesCbc_Decode_Intel;
|
||||||
|
g_AesCtr_Code = AesCtr_Code_Intel;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])]
|
||||||
|
#define HT4(m, i, s, p) m[i] = \
|
||||||
|
HT(i, 0, s) ^ \
|
||||||
|
HT(i, 1, s) ^ \
|
||||||
|
HT(i, 2, s) ^ \
|
||||||
|
HT(i, 3, s) ^ w[p + i]
|
||||||
|
/* such order (2031) in HT16 is for VC6/K8 speed optimization) */
|
||||||
|
#define HT16(m, s, p) \
|
||||||
|
HT4(m, 2, s, p); \
|
||||||
|
HT4(m, 0, s, p); \
|
||||||
|
HT4(m, 3, s, p); \
|
||||||
|
HT4(m, 1, s, p); \
|
||||||
|
|
||||||
|
#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])]
|
||||||
|
#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];
|
||||||
|
|
||||||
|
#define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])]
|
||||||
|
#define HD4(m, i, s, p) m[i] = \
|
||||||
|
HD(i, 0, s) ^ \
|
||||||
|
HD(i, 1, s) ^ \
|
||||||
|
HD(i, 2, s) ^ \
|
||||||
|
HD(i, 3, s) ^ w[p + i];
|
||||||
|
/* such order (0231) in HD16 is for VC6/K8 speed optimization) */
|
||||||
|
#define HD16(m, s, p) \
|
||||||
|
HD4(m, 0, s, p); \
|
||||||
|
HD4(m, 2, s, p); \
|
||||||
|
HD4(m, 3, s, p); \
|
||||||
|
HD4(m, 1, s, p); \
|
||||||
|
|
||||||
|
#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])]
|
||||||
|
#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];
|
||||||
|
|
||||||
|
void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)
|
||||||
|
{
|
||||||
|
unsigned i, wSize;
|
||||||
|
wSize = keySize + 28;
|
||||||
|
keySize /= 4;
|
||||||
|
w[0] = ((UInt32)keySize / 2) + 3;
|
||||||
|
w += 4;
|
||||||
|
|
||||||
|
for (i = 0; i < keySize; i++, key += 4)
|
||||||
|
w[i] = GetUi32(key);
|
||||||
|
|
||||||
|
for (; i < wSize; i++)
|
||||||
|
{
|
||||||
|
UInt32 t = w[i - 1];
|
||||||
|
unsigned rem = i % keySize;
|
||||||
|
if (rem == 0)
|
||||||
|
t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]);
|
||||||
|
else if (keySize > 6 && rem == 4)
|
||||||
|
t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]);
|
||||||
|
w[i] = w[i - keySize] ^ t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)
|
||||||
|
{
|
||||||
|
unsigned i, num;
|
||||||
|
Aes_SetKey_Enc(w, key, keySize);
|
||||||
|
num = keySize + 20;
|
||||||
|
w += 8;
|
||||||
|
for (i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
UInt32 r = w[i];
|
||||||
|
w[i] =
|
||||||
|
D[ Sbox[gb0(r)]] ^
|
||||||
|
D[0x100 + Sbox[gb1(r)]] ^
|
||||||
|
D[0x200 + Sbox[gb2(r)]] ^
|
||||||
|
D[0x300 + Sbox[gb3(r)]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Aes_Encode and Aes_Decode functions work with little-endian words.
|
||||||
|
src and dest are pointers to 4 UInt32 words.
|
||||||
|
arc and dest can point to same block */
|
||||||
|
|
||||||
|
static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src)
|
||||||
|
{
|
||||||
|
UInt32 s[4];
|
||||||
|
UInt32 m[4];
|
||||||
|
UInt32 numRounds2 = w[0];
|
||||||
|
w += 4;
|
||||||
|
s[0] = src[0] ^ w[0];
|
||||||
|
s[1] = src[1] ^ w[1];
|
||||||
|
s[2] = src[2] ^ w[2];
|
||||||
|
s[3] = src[3] ^ w[3];
|
||||||
|
w += 4;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
HT16(m, s, 0);
|
||||||
|
if (--numRounds2 == 0)
|
||||||
|
break;
|
||||||
|
HT16(s, m, 4);
|
||||||
|
w += 8;
|
||||||
|
}
|
||||||
|
w += 4;
|
||||||
|
FT4(0); FT4(1); FT4(2); FT4(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src)
|
||||||
|
{
|
||||||
|
UInt32 s[4];
|
||||||
|
UInt32 m[4];
|
||||||
|
UInt32 numRounds2 = w[0];
|
||||||
|
w += 4 + numRounds2 * 8;
|
||||||
|
s[0] = src[0] ^ w[0];
|
||||||
|
s[1] = src[1] ^ w[1];
|
||||||
|
s[2] = src[2] ^ w[2];
|
||||||
|
s[3] = src[3] ^ w[3];
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
w -= 8;
|
||||||
|
HD16(m, s, 4);
|
||||||
|
if (--numRounds2 == 0)
|
||||||
|
break;
|
||||||
|
HD16(s, m, 0);
|
||||||
|
}
|
||||||
|
FD4(0); FD4(1); FD4(2); FD4(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AesCbc_Init(UInt32 *p, const Byte *iv)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
p[i] = GetUi32(iv + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
p[0] ^= GetUi32(data);
|
||||||
|
p[1] ^= GetUi32(data + 4);
|
||||||
|
p[2] ^= GetUi32(data + 8);
|
||||||
|
p[3] ^= GetUi32(data + 12);
|
||||||
|
|
||||||
|
Aes_Encode(p + 4, p, p);
|
||||||
|
|
||||||
|
SetUi32(data, p[0]);
|
||||||
|
SetUi32(data + 4, p[1]);
|
||||||
|
SetUi32(data + 8, p[2]);
|
||||||
|
SetUi32(data + 12, p[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
UInt32 in[4], out[4];
|
||||||
|
for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
in[0] = GetUi32(data);
|
||||||
|
in[1] = GetUi32(data + 4);
|
||||||
|
in[2] = GetUi32(data + 8);
|
||||||
|
in[3] = GetUi32(data + 12);
|
||||||
|
|
||||||
|
Aes_Decode(p + 4, out, in);
|
||||||
|
|
||||||
|
SetUi32(data, p[0] ^ out[0]);
|
||||||
|
SetUi32(data + 4, p[1] ^ out[1]);
|
||||||
|
SetUi32(data + 8, p[2] ^ out[2]);
|
||||||
|
SetUi32(data + 12, p[3] ^ out[3]);
|
||||||
|
|
||||||
|
p[0] = in[0];
|
||||||
|
p[1] = in[1];
|
||||||
|
p[2] = in[2];
|
||||||
|
p[3] = in[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
for (; numBlocks != 0; numBlocks--)
|
||||||
|
{
|
||||||
|
UInt32 temp[4];
|
||||||
|
Byte buf[16];
|
||||||
|
int i;
|
||||||
|
if (++p[0] == 0)
|
||||||
|
p[1]++;
|
||||||
|
Aes_Encode(p + 4, temp, p);
|
||||||
|
SetUi32(buf, temp[0]);
|
||||||
|
SetUi32(buf + 4, temp[1]);
|
||||||
|
SetUi32(buf + 8, temp[2]);
|
||||||
|
SetUi32(buf + 12, temp[3]);
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
*data++ ^= buf[i];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* Aes.h -- AES encryption / decryption
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __AES_H
|
||||||
|
#define __AES_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define AES_BLOCK_SIZE 16
|
||||||
|
|
||||||
|
/* Call AesGenTables one time before other AES functions */
|
||||||
|
void AesGenTables(void);
|
||||||
|
|
||||||
|
/* UInt32 pointers must be 16-byte aligned */
|
||||||
|
|
||||||
|
/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */
|
||||||
|
#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4)
|
||||||
|
|
||||||
|
/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */
|
||||||
|
/* keySize = 16 or 24 or 32 (bytes) */
|
||||||
|
typedef void (MY_FAST_CALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize);
|
||||||
|
void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize);
|
||||||
|
void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize);
|
||||||
|
|
||||||
|
/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */
|
||||||
|
void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */
|
||||||
|
/* data - 16-byte aligned pointer to data */
|
||||||
|
/* numBlocks - the number of 16-byte blocks in data array */
|
||||||
|
typedef void (MY_FAST_CALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
extern AES_CODE_FUNC g_AesCbc_Encode;
|
||||||
|
extern AES_CODE_FUNC g_AesCbc_Decode;
|
||||||
|
extern AES_CODE_FUNC g_AesCtr_Code;
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,184 @@
|
||||||
|
/* AesOpt.c -- Intel's AES
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
#if _MSC_VER >= 1500
|
||||||
|
#define USE_INTEL_AES
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_INTEL_AES
|
||||||
|
|
||||||
|
#include <wmmintrin.h>
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Encode_Intel(__m128i *p, __m128i *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
__m128i m = *p;
|
||||||
|
for (; numBlocks != 0; numBlocks--, data++)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||||
|
const __m128i *w = p + 3;
|
||||||
|
m = _mm_xor_si128(m, *data);
|
||||||
|
m = _mm_xor_si128(m, p[2]);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m = _mm_aesenc_si128(m, w[0]);
|
||||||
|
m = _mm_aesenc_si128(m, w[1]);
|
||||||
|
w += 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
m = _mm_aesenc_si128(m, w[0]);
|
||||||
|
m = _mm_aesenclast_si128(m, w[1]);
|
||||||
|
*data = m;
|
||||||
|
}
|
||||||
|
*p = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NUM_WAYS 3
|
||||||
|
|
||||||
|
#define AES_OP_W(op, n) { \
|
||||||
|
const __m128i t = w[n]; \
|
||||||
|
m0 = op(m0, t); \
|
||||||
|
m1 = op(m1, t); \
|
||||||
|
m2 = op(m2, t); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define AES_DEC(n) AES_OP_W(_mm_aesdec_si128, n)
|
||||||
|
#define AES_DEC_LAST(n) AES_OP_W(_mm_aesdeclast_si128, n)
|
||||||
|
#define AES_ENC(n) AES_OP_W(_mm_aesenc_si128, n)
|
||||||
|
#define AES_ENC_LAST(n) AES_OP_W(_mm_aesenclast_si128, n)
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Decode_Intel(__m128i *p, __m128i *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
__m128i iv = *p;
|
||||||
|
for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1);
|
||||||
|
const __m128i *w = p + numRounds2 * 2;
|
||||||
|
__m128i m0, m1, m2;
|
||||||
|
{
|
||||||
|
const __m128i t = w[2];
|
||||||
|
m0 = _mm_xor_si128(t, data[0]);
|
||||||
|
m1 = _mm_xor_si128(t, data[1]);
|
||||||
|
m2 = _mm_xor_si128(t, data[2]);
|
||||||
|
}
|
||||||
|
numRounds2--;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
AES_DEC(1)
|
||||||
|
AES_DEC(0)
|
||||||
|
w -= 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
AES_DEC(1)
|
||||||
|
AES_DEC_LAST(0)
|
||||||
|
|
||||||
|
{
|
||||||
|
__m128i t;
|
||||||
|
t = _mm_xor_si128(m0, iv); iv = data[0]; data[0] = t;
|
||||||
|
t = _mm_xor_si128(m1, iv); iv = data[1]; data[1] = t;
|
||||||
|
t = _mm_xor_si128(m2, iv); iv = data[2]; data[2] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; numBlocks != 0; numBlocks--, data++)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1);
|
||||||
|
const __m128i *w = p + numRounds2 * 2;
|
||||||
|
__m128i m = _mm_xor_si128(w[2], *data);
|
||||||
|
numRounds2--;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m = _mm_aesdec_si128(m, w[1]);
|
||||||
|
m = _mm_aesdec_si128(m, w[0]);
|
||||||
|
w -= 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
m = _mm_aesdec_si128(m, w[1]);
|
||||||
|
m = _mm_aesdeclast_si128(m, w[0]);
|
||||||
|
|
||||||
|
m = _mm_xor_si128(m, iv);
|
||||||
|
iv = *data;
|
||||||
|
*data = m;
|
||||||
|
}
|
||||||
|
*p = iv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCtr_Code_Intel(__m128i *p, __m128i *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
__m128i ctr = *p;
|
||||||
|
__m128i one;
|
||||||
|
one.m128i_u64[0] = 1;
|
||||||
|
one.m128i_u64[1] = 0;
|
||||||
|
for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||||
|
const __m128i *w = p;
|
||||||
|
__m128i m0, m1, m2;
|
||||||
|
{
|
||||||
|
const __m128i t = w[2];
|
||||||
|
ctr = _mm_add_epi64(ctr, one); m0 = _mm_xor_si128(ctr, t);
|
||||||
|
ctr = _mm_add_epi64(ctr, one); m1 = _mm_xor_si128(ctr, t);
|
||||||
|
ctr = _mm_add_epi64(ctr, one); m2 = _mm_xor_si128(ctr, t);
|
||||||
|
}
|
||||||
|
w += 3;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
AES_ENC(0)
|
||||||
|
AES_ENC(1)
|
||||||
|
w += 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
AES_ENC(0)
|
||||||
|
AES_ENC_LAST(1)
|
||||||
|
data[0] = _mm_xor_si128(data[0], m0);
|
||||||
|
data[1] = _mm_xor_si128(data[1], m1);
|
||||||
|
data[2] = _mm_xor_si128(data[2], m2);
|
||||||
|
}
|
||||||
|
for (; numBlocks != 0; numBlocks--, data++)
|
||||||
|
{
|
||||||
|
UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
|
||||||
|
const __m128i *w = p;
|
||||||
|
__m128i m;
|
||||||
|
ctr = _mm_add_epi64(ctr, one);
|
||||||
|
m = _mm_xor_si128(ctr, p[2]);
|
||||||
|
w += 3;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m = _mm_aesenc_si128(m, w[0]);
|
||||||
|
m = _mm_aesenc_si128(m, w[1]);
|
||||||
|
w += 2;
|
||||||
|
}
|
||||||
|
while (--numRounds2 != 0);
|
||||||
|
m = _mm_aesenc_si128(m, w[0]);
|
||||||
|
m = _mm_aesenclast_si128(m, w[1]);
|
||||||
|
*data = _mm_xor_si128(*data, m);
|
||||||
|
}
|
||||||
|
*p = ctr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
AesCbc_Encode(p, data, numBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
AesCbc_Decode(p, data, numBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *p, Byte *data, size_t numBlocks)
|
||||||
|
{
|
||||||
|
AesCtr_Code(p, data, numBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,127 @@
|
||||||
|
/* Alloc.c -- Memory allocation functions
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "Alloc.h"
|
||||||
|
|
||||||
|
/* #define _SZ_ALLOC_DEBUG */
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *MyAlloc(size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return 0;
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
{
|
||||||
|
void *p = malloc(size);
|
||||||
|
fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return malloc(size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyFree(void *address)
|
||||||
|
{
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
if (address != 0)
|
||||||
|
fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address);
|
||||||
|
#endif
|
||||||
|
free(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
void *MidAlloc(size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return 0;
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
|
||||||
|
#endif
|
||||||
|
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MidFree(void *address)
|
||||||
|
{
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
if (address != 0)
|
||||||
|
fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
|
||||||
|
#endif
|
||||||
|
if (address == 0)
|
||||||
|
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 = 0;
|
||||||
|
GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
|
||||||
|
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
|
||||||
|
if (largePageMinimum == 0)
|
||||||
|
return;
|
||||||
|
size = largePageMinimum();
|
||||||
|
if (size == 0 || (size & (size - 1)) != 0)
|
||||||
|
return;
|
||||||
|
g_LargePageSize = size;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *BigAlloc(size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return 0;
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _7ZIP_LARGE_PAGES
|
||||||
|
if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
|
||||||
|
{
|
||||||
|
void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
|
||||||
|
MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BigFree(void *address)
|
||||||
|
{
|
||||||
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
if (address != 0)
|
||||||
|
fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (address == 0)
|
||||||
|
return;
|
||||||
|
VirtualFree(address, 0, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* Alloc.h -- Memory allocation functions
|
||||||
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __COMMON_ALLOC_H
|
||||||
|
#define __COMMON_ALLOC_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *MyAlloc(size_t size);
|
||||||
|
void MyFree(void *address);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
void SetLargePageSize();
|
||||||
|
|
||||||
|
void *MidAlloc(size_t size);
|
||||||
|
void MidFree(void *address);
|
||||||
|
void *BigAlloc(size_t size);
|
||||||
|
void BigFree(void *address);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define MidAlloc(size) MyAlloc(size)
|
||||||
|
#define MidFree(address) MyFree(address)
|
||||||
|
#define BigAlloc(size) MyAlloc(size)
|
||||||
|
#define BigFree(address) MyFree(address)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,134 @@
|
||||||
|
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
||||||
|
2008-10-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Bcj2.h"
|
||||||
|
|
||||||
|
#ifdef _LZMA_PROB32
|
||||||
|
#define CProb UInt32
|
||||||
|
#else
|
||||||
|
#define CProb UInt16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
|
||||||
|
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
|
||||||
|
|
||||||
|
#define kNumTopBits 24
|
||||||
|
#define kTopValue ((UInt32)1 << kNumTopBits)
|
||||||
|
|
||||||
|
#define kNumBitModelTotalBits 11
|
||||||
|
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||||
|
#define kNumMoveBits 5
|
||||||
|
|
||||||
|
#define RC_READ_BYTE (*buffer++)
|
||||||
|
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
|
||||||
|
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
|
||||||
|
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
|
||||||
|
|
||||||
|
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
|
||||||
|
|
||||||
|
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
||||||
|
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
|
||||||
|
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
|
||||||
|
|
||||||
|
int Bcj2_Decode(
|
||||||
|
const Byte *buf0, SizeT size0,
|
||||||
|
const Byte *buf1, SizeT size1,
|
||||||
|
const Byte *buf2, SizeT size2,
|
||||||
|
const Byte *buf3, SizeT size3,
|
||||||
|
Byte *outBuf, SizeT outSize)
|
||||||
|
{
|
||||||
|
CProb p[256 + 2];
|
||||||
|
SizeT inPos = 0, outPos = 0;
|
||||||
|
|
||||||
|
const Byte *buffer, *bufferLim;
|
||||||
|
UInt32 range, code;
|
||||||
|
Byte prevByte = 0;
|
||||||
|
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
|
||||||
|
p[i] = kBitModelTotal >> 1;
|
||||||
|
|
||||||
|
buffer = buf3;
|
||||||
|
bufferLim = buffer + size3;
|
||||||
|
RC_INIT2
|
||||||
|
|
||||||
|
if (outSize == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Byte b;
|
||||||
|
CProb *prob;
|
||||||
|
UInt32 bound;
|
||||||
|
UInt32 ttt;
|
||||||
|
|
||||||
|
SizeT limit = size0 - inPos;
|
||||||
|
if (outSize - outPos < limit)
|
||||||
|
limit = outSize - outPos;
|
||||||
|
while (limit != 0)
|
||||||
|
{
|
||||||
|
Byte b = buf0[inPos];
|
||||||
|
outBuf[outPos++] = b;
|
||||||
|
if (IsJ(prevByte, b))
|
||||||
|
break;
|
||||||
|
inPos++;
|
||||||
|
prevByte = b;
|
||||||
|
limit--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit == 0 || outPos == outSize)
|
||||||
|
break;
|
||||||
|
|
||||||
|
b = buf0[inPos++];
|
||||||
|
|
||||||
|
if (b == 0xE8)
|
||||||
|
prob = p + prevByte;
|
||||||
|
else if (b == 0xE9)
|
||||||
|
prob = p + 256;
|
||||||
|
else
|
||||||
|
prob = p + 257;
|
||||||
|
|
||||||
|
IF_BIT_0(prob)
|
||||||
|
{
|
||||||
|
UPDATE_0(prob)
|
||||||
|
prevByte = b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UInt32 dest;
|
||||||
|
const Byte *v;
|
||||||
|
UPDATE_1(prob)
|
||||||
|
if (b == 0xE8)
|
||||||
|
{
|
||||||
|
v = buf1;
|
||||||
|
if (size1 < 4)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
buf1 += 4;
|
||||||
|
size1 -= 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v = buf2;
|
||||||
|
if (size2 < 4)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
buf2 += 4;
|
||||||
|
size2 -= 4;
|
||||||
|
}
|
||||||
|
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
|
||||||
|
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
|
||||||
|
outBuf[outPos++] = (Byte)dest;
|
||||||
|
if (outPos == outSize)
|
||||||
|
break;
|
||||||
|
outBuf[outPos++] = (Byte)(dest >> 8);
|
||||||
|
if (outPos == outSize)
|
||||||
|
break;
|
||||||
|
outBuf[outPos++] = (Byte)(dest >> 16);
|
||||||
|
if (outPos == outSize)
|
||||||
|
break;
|
||||||
|
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __BCJ2_H
|
||||||
|
#define __BCJ2_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
/*
|
||||||
|
Conditions:
|
||||||
|
outSize <= FullOutputSize,
|
||||||
|
where FullOutputSize is full size of output stream of x86_2 filter.
|
||||||
|
|
||||||
|
If buf0 overlaps outBuf, there are two required conditions:
|
||||||
|
1) (buf0 >= outBuf)
|
||||||
|
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
SZ_ERROR_DATA - Data error
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Bcj2_Decode(
|
||||||
|
const Byte *buf0, SizeT size0,
|
||||||
|
const Byte *buf1, SizeT size1,
|
||||||
|
const Byte *buf2, SizeT size2,
|
||||||
|
const Byte *buf3, SizeT size3,
|
||||||
|
Byte *outBuf, SizeT outSize);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,135 @@
|
||||||
|
/* Bra.c -- Converters for RISC code
|
||||||
|
2010-04-16 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Bra.h"
|
||||||
|
|
||||||
|
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
if (size < 4)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
ip += 8;
|
||||||
|
for (i = 0; i <= size; i += 4)
|
||||||
|
{
|
||||||
|
if (data[i + 3] == 0xEB)
|
||||||
|
{
|
||||||
|
UInt32 dest;
|
||||||
|
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);
|
||||||
|
src <<= 2;
|
||||||
|
if (encoding)
|
||||||
|
dest = ip + (UInt32)i + src;
|
||||||
|
else
|
||||||
|
dest = src - (ip + (UInt32)i);
|
||||||
|
dest >>= 2;
|
||||||
|
data[i + 2] = (Byte)(dest >> 16);
|
||||||
|
data[i + 1] = (Byte)(dest >> 8);
|
||||||
|
data[i + 0] = (Byte)dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
if (size < 4)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
ip += 4;
|
||||||
|
for (i = 0; i <= size; i += 2)
|
||||||
|
{
|
||||||
|
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
||||||
|
(data[i + 3] & 0xF8) == 0xF8)
|
||||||
|
{
|
||||||
|
UInt32 dest;
|
||||||
|
UInt32 src =
|
||||||
|
(((UInt32)data[i + 1] & 0x7) << 19) |
|
||||||
|
((UInt32)data[i + 0] << 11) |
|
||||||
|
(((UInt32)data[i + 3] & 0x7) << 8) |
|
||||||
|
(data[i + 2]);
|
||||||
|
|
||||||
|
src <<= 1;
|
||||||
|
if (encoding)
|
||||||
|
dest = ip + (UInt32)i + src;
|
||||||
|
else
|
||||||
|
dest = src - (ip + (UInt32)i);
|
||||||
|
dest >>= 1;
|
||||||
|
|
||||||
|
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
|
||||||
|
data[i + 0] = (Byte)(dest >> 11);
|
||||||
|
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
|
||||||
|
data[i + 2] = (Byte)dest;
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
if (size < 4)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
for (i = 0; i <= size; i += 4)
|
||||||
|
{
|
||||||
|
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
|
||||||
|
{
|
||||||
|
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |
|
||||||
|
((UInt32)data[i + 1] << 16) |
|
||||||
|
((UInt32)data[i + 2] << 8) |
|
||||||
|
((UInt32)data[i + 3] & (~3));
|
||||||
|
|
||||||
|
UInt32 dest;
|
||||||
|
if (encoding)
|
||||||
|
dest = ip + (UInt32)i + src;
|
||||||
|
else
|
||||||
|
dest = src - (ip + (UInt32)i);
|
||||||
|
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
|
||||||
|
data[i + 1] = (Byte)(dest >> 16);
|
||||||
|
data[i + 2] = (Byte)(dest >> 8);
|
||||||
|
data[i + 3] &= 0x3;
|
||||||
|
data[i + 3] |= dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
if (size < 4)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
for (i = 0; i <= size; i += 4)
|
||||||
|
{
|
||||||
|
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
|
||||||
|
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
|
||||||
|
{
|
||||||
|
UInt32 src =
|
||||||
|
((UInt32)data[i + 0] << 24) |
|
||||||
|
((UInt32)data[i + 1] << 16) |
|
||||||
|
((UInt32)data[i + 2] << 8) |
|
||||||
|
((UInt32)data[i + 3]);
|
||||||
|
UInt32 dest;
|
||||||
|
|
||||||
|
src <<= 2;
|
||||||
|
if (encoding)
|
||||||
|
dest = ip + i + src;
|
||||||
|
else
|
||||||
|
dest = src - (ip + i);
|
||||||
|
dest >>= 2;
|
||||||
|
|
||||||
|
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
|
||||||
|
|
||||||
|
data[i + 0] = (Byte)(dest >> 24);
|
||||||
|
data[i + 1] = (Byte)(dest >> 16);
|
||||||
|
data[i + 2] = (Byte)(dest >> 8);
|
||||||
|
data[i + 3] = (Byte)dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/* Bra.h -- Branch converters for executables
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __BRA_H
|
||||||
|
#define __BRA_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
/*
|
||||||
|
These functions convert relative addresses to absolute addresses
|
||||||
|
in CALL instructions to increase the compression ratio.
|
||||||
|
|
||||||
|
In:
|
||||||
|
data - data buffer
|
||||||
|
size - size of data
|
||||||
|
ip - current virtual Instruction Pinter (IP) value
|
||||||
|
state - state variable for x86 converter
|
||||||
|
encoding - 0 (for decoding), 1 (for encoding)
|
||||||
|
|
||||||
|
Out:
|
||||||
|
state - state variable for x86 converter
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The number of processed bytes. If you call these functions with multiple calls,
|
||||||
|
you must start next call with first byte after block of processed bytes.
|
||||||
|
|
||||||
|
Type Endian Alignment LookAhead
|
||||||
|
|
||||||
|
x86 little 1 4
|
||||||
|
ARMT little 2 2
|
||||||
|
ARM little 4 0
|
||||||
|
PPC big 4 0
|
||||||
|
SPARC big 4 0
|
||||||
|
IA64 little 16 0
|
||||||
|
|
||||||
|
size must be >= Alignment + LookAhead, if it's not last block.
|
||||||
|
If (size < Alignment + LookAhead), converter returns 0.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
UInt32 ip = 0;
|
||||||
|
for ()
|
||||||
|
{
|
||||||
|
; size must be >= Alignment + LookAhead, if it's not last block
|
||||||
|
SizeT processed = Convert(data, size, ip, 1);
|
||||||
|
data += processed;
|
||||||
|
size -= processed;
|
||||||
|
ip += processed;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define x86_Convert_Init(state) { state = 0; }
|
||||||
|
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
|
||||||
|
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Bra.h"
|
||||||
|
|
||||||
|
#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
|
||||||
|
|
||||||
|
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
||||||
|
{
|
||||||
|
SizeT pos = 0;
|
||||||
|
UInt32 mask = *state & 7;
|
||||||
|
if (size < 5)
|
||||||
|
return 0;
|
||||||
|
size -= 4;
|
||||||
|
ip += 5;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Byte *p = data + pos;
|
||||||
|
const Byte *limit = data + size;
|
||||||
|
for (; p < limit; p++)
|
||||||
|
if ((*p & 0xFE) == 0xE8)
|
||||||
|
break;
|
||||||
|
|
||||||
|
{
|
||||||
|
SizeT d = (SizeT)(p - data - pos);
|
||||||
|
pos = (SizeT)(p - data);
|
||||||
|
if (p >= limit)
|
||||||
|
{
|
||||||
|
*state = (d > 2 ? 0 : mask >> (unsigned)d);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
if (d > 2)
|
||||||
|
mask = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask >>= (unsigned)d;
|
||||||
|
if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1])))
|
||||||
|
{
|
||||||
|
mask = (mask >> 1) | 4;
|
||||||
|
pos++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test86MSByte(p[4]))
|
||||||
|
{
|
||||||
|
UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
||||||
|
UInt32 cur = ip + (UInt32)pos;
|
||||||
|
pos += 5;
|
||||||
|
if (encoding)
|
||||||
|
v += cur;
|
||||||
|
else
|
||||||
|
v -= cur;
|
||||||
|
if (mask != 0)
|
||||||
|
{
|
||||||
|
unsigned sh = (mask & 6) << 2;
|
||||||
|
if (Test86MSByte((Byte)(v >> sh)))
|
||||||
|
{
|
||||||
|
v ^= (((UInt32)0x100 << sh) - 1);
|
||||||
|
if (encoding)
|
||||||
|
v += cur;
|
||||||
|
else
|
||||||
|
v -= cur;
|
||||||
|
}
|
||||||
|
mask = 0;
|
||||||
|
}
|
||||||
|
p[1] = (Byte)v;
|
||||||
|
p[2] = (Byte)(v >> 8);
|
||||||
|
p[3] = (Byte)(v >> 16);
|
||||||
|
p[4] = (Byte)(0 - ((v >> 24) & 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = (mask >> 1) | 4;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* BraIA64.c -- Converter for IA-64 code
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Bra.h"
|
||||||
|
|
||||||
|
static const Byte kBranchTable[32] =
|
||||||
|
{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
4, 4, 6, 6, 0, 0, 7, 7,
|
||||||
|
4, 4, 0, 0, 4, 4, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
if (size < 16)
|
||||||
|
return 0;
|
||||||
|
size -= 16;
|
||||||
|
for (i = 0; i <= size; i += 16)
|
||||||
|
{
|
||||||
|
UInt32 instrTemplate = data[i] & 0x1F;
|
||||||
|
UInt32 mask = kBranchTable[instrTemplate];
|
||||||
|
UInt32 bitPos = 5;
|
||||||
|
int slot;
|
||||||
|
for (slot = 0; slot < 3; slot++, bitPos += 41)
|
||||||
|
{
|
||||||
|
UInt32 bytePos, bitRes;
|
||||||
|
UInt64 instruction, instNorm;
|
||||||
|
int j;
|
||||||
|
if (((mask >> slot) & 1) == 0)
|
||||||
|
continue;
|
||||||
|
bytePos = (bitPos >> 3);
|
||||||
|
bitRes = bitPos & 0x7;
|
||||||
|
instruction = 0;
|
||||||
|
for (j = 0; j < 6; j++)
|
||||||
|
instruction += (UInt64)data[i + j + bytePos] << (8 * j);
|
||||||
|
|
||||||
|
instNorm = instruction >> bitRes;
|
||||||
|
if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0)
|
||||||
|
{
|
||||||
|
UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
|
||||||
|
UInt32 dest;
|
||||||
|
src |= ((UInt32)(instNorm >> 36) & 1) << 20;
|
||||||
|
|
||||||
|
src <<= 4;
|
||||||
|
|
||||||
|
if (encoding)
|
||||||
|
dest = ip + (UInt32)i + src;
|
||||||
|
else
|
||||||
|
dest = src - (ip + (UInt32)i);
|
||||||
|
|
||||||
|
dest >>= 4;
|
||||||
|
|
||||||
|
instNorm &= ~((UInt64)(0x8FFFFF) << 13);
|
||||||
|
instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);
|
||||||
|
instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));
|
||||||
|
|
||||||
|
instruction &= (1 << bitRes) - 1;
|
||||||
|
instruction |= (instNorm << bitRes);
|
||||||
|
for (j = 0; j < 6; j++)
|
||||||
|
data[i + j + bytePos] = (Byte)(instruction >> (8 * j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* Compiler.h -- Compiler ypes
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_COMPILER_H
|
||||||
|
#define __7Z_COMPILER_H
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
#define RPC_NO_WINDOWS_H
|
||||||
|
/* #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 : 4214) // nonstandard extension used : bit field types other than int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1300
|
||||||
|
#pragma warning(disable : 4996) // This function or variable may be unsafe
|
||||||
|
#else
|
||||||
|
#pragma warning(disable : 4511) // copy constructor could not be generated
|
||||||
|
#pragma warning(disable : 4512) // assignment operator could not be generated
|
||||||
|
#pragma warning(disable : 4702) // unreachable code
|
||||||
|
#pragma warning(disable : 4710) // not inlined
|
||||||
|
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,190 @@
|
||||||
|
/* CpuArch.c -- CPU specific code
|
||||||
|
2012-05-29: Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
|
||||||
|
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
|
||||||
|
#define USE_ASM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_ASM) && _MSC_VER >= 1500
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
|
||||||
|
static UInt32 CheckFlag(UInt32 flag)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
__asm pushfd;
|
||||||
|
__asm pop EAX;
|
||||||
|
__asm mov EDX, EAX;
|
||||||
|
__asm xor EAX, flag;
|
||||||
|
__asm push EAX;
|
||||||
|
__asm popfd;
|
||||||
|
__asm pushfd;
|
||||||
|
__asm pop EAX;
|
||||||
|
__asm xor EAX, EDX;
|
||||||
|
__asm push EDX;
|
||||||
|
__asm popfd;
|
||||||
|
__asm and flag, EAX;
|
||||||
|
#else
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"pushf\n\t"
|
||||||
|
"pop %%EAX\n\t"
|
||||||
|
"movl %%EAX,%%EDX\n\t"
|
||||||
|
"xorl %0,%%EAX\n\t"
|
||||||
|
"push %%EAX\n\t"
|
||||||
|
"popf\n\t"
|
||||||
|
"pushf\n\t"
|
||||||
|
"pop %%EAX\n\t"
|
||||||
|
"xorl %%EDX,%%EAX\n\t"
|
||||||
|
"push %%EDX\n\t"
|
||||||
|
"popf\n\t"
|
||||||
|
"andl %%EAX, %0\n\t":
|
||||||
|
"=c" (flag) : "c" (flag));
|
||||||
|
#endif
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
|
||||||
|
#else
|
||||||
|
#define CHECK_CPUID_IS_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
||||||
|
{
|
||||||
|
#ifdef USE_ASM
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
UInt32 a2, b2, c2, d2;
|
||||||
|
__asm xor EBX, EBX;
|
||||||
|
__asm xor ECX, ECX;
|
||||||
|
__asm xor EDX, EDX;
|
||||||
|
__asm mov EAX, function;
|
||||||
|
__asm cpuid;
|
||||||
|
__asm mov a2, EAX;
|
||||||
|
__asm mov b2, EBX;
|
||||||
|
__asm mov c2, ECX;
|
||||||
|
__asm mov d2, EDX;
|
||||||
|
|
||||||
|
*a = a2;
|
||||||
|
*b = b2;
|
||||||
|
*c = c2;
|
||||||
|
*d = d2;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
#if defined(MY_CPU_X86) && defined(__PIC__)
|
||||||
|
"mov %%ebx, %%edi;"
|
||||||
|
"cpuid;"
|
||||||
|
"xchgl %%ebx, %%edi;"
|
||||||
|
: "=a" (*a) ,
|
||||||
|
"=D" (*b) ,
|
||||||
|
#else
|
||||||
|
"cpuid"
|
||||||
|
: "=a" (*a) ,
|
||||||
|
"=b" (*b) ,
|
||||||
|
#endif
|
||||||
|
"=c" (*c) ,
|
||||||
|
"=d" (*d)
|
||||||
|
: "0" (function)) ;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int CPUInfo[4];
|
||||||
|
__cpuid(CPUInfo, function);
|
||||||
|
*a = CPUInfo[0];
|
||||||
|
*b = CPUInfo[1];
|
||||||
|
*c = CPUInfo[2];
|
||||||
|
*d = CPUInfo[3];
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
|
||||||
|
{
|
||||||
|
CHECK_CPUID_IS_SUPPORTED
|
||||||
|
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
|
||||||
|
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UInt32 kVendors[][3] =
|
||||||
|
{
|
||||||
|
{ 0x756E6547, 0x49656E69, 0x6C65746E},
|
||||||
|
{ 0x68747541, 0x69746E65, 0x444D4163},
|
||||||
|
{ 0x746E6543, 0x48727561, 0x736C7561}
|
||||||
|
};
|
||||||
|
|
||||||
|
int x86cpuid_GetFirm(const Cx86cpuid *p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
|
||||||
|
{
|
||||||
|
const UInt32 *v = kVendors[i];
|
||||||
|
if (v[0] == p->vendor[0] &&
|
||||||
|
v[1] == p->vendor[1] &&
|
||||||
|
v[2] == p->vendor[2])
|
||||||
|
return (int)i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool CPU_Is_InOrder()
|
||||||
|
{
|
||||||
|
Cx86cpuid p;
|
||||||
|
int firm;
|
||||||
|
UInt32 family, model;
|
||||||
|
if (!x86cpuid_CheckAndRead(&p))
|
||||||
|
return True;
|
||||||
|
family = x86cpuid_GetFamily(&p);
|
||||||
|
model = x86cpuid_GetModel(&p);
|
||||||
|
firm = x86cpuid_GetFirm(&p);
|
||||||
|
switch (firm)
|
||||||
|
{
|
||||||
|
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
|
||||||
|
/* Atom CPU */
|
||||||
|
model == 0x100C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
|
||||||
|
|| model == 0x2006 /* 45 nm, Z6xx */
|
||||||
|
|| model == 0x2007 /* 32 nm, Z2460 */
|
||||||
|
|| model == 0x3005 /* 32 nm, Z2760 */
|
||||||
|
|| model == 0x3006 /* 32 nm, N2xxx, D2xxx */
|
||||||
|
)));
|
||||||
|
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
|
||||||
|
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
static Bool CPU_Sys_Is_SSE_Supported()
|
||||||
|
{
|
||||||
|
OSVERSIONINFO vi;
|
||||||
|
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||||
|
if (!GetVersionEx(&vi))
|
||||||
|
return False;
|
||||||
|
return (vi.dwMajorVersion >= 5);
|
||||||
|
}
|
||||||
|
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
|
||||||
|
#else
|
||||||
|
#define CHECK_SYS_SSE_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Bool CPU_Is_Aes_Supported()
|
||||||
|
{
|
||||||
|
Cx86cpuid p;
|
||||||
|
CHECK_SYS_SSE_SUPPORT
|
||||||
|
if (!x86cpuid_CheckAndRead(&p))
|
||||||
|
return False;
|
||||||
|
return (p.c >> 25) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,157 @@
|
||||||
|
/* CpuArch.h -- CPU specific code
|
||||||
|
2013-11-12: Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __CPU_ARCH_H
|
||||||
|
#define __CPU_ARCH_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
/*
|
||||||
|
MY_CPU_LE means that CPU is LITTLE ENDIAN.
|
||||||
|
If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).
|
||||||
|
|
||||||
|
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
|
||||||
|
If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
|
||||||
|
#define MY_CPU_AMD64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_M_IX86) || defined(__i386__)
|
||||||
|
#define MY_CPU_X86
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
||||||
|
#define MY_CPU_X86_OR_AMD64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_X86) || defined(_M_ARM)
|
||||||
|
#define MY_CPU_32BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_M_ARM)
|
||||||
|
#define MY_CPU_ARM_LE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_M_IA64)
|
||||||
|
#define MY_CPU_IA64_LE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_X86_OR_AMD64)
|
||||||
|
#define MY_CPU_LE_UNALIGN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
|
||||||
|
#define MY_CPU_LE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__BIG_ENDIAN__) || defined(__m68k__) || defined(__ARMEB__) || defined(__MIPSEB__)
|
||||||
|
#define MY_CPU_BE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
|
||||||
|
Stop_Compiling_Bad_Endian
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE_UNALIGN
|
||||||
|
|
||||||
|
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
|
||||||
|
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
|
||||||
|
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
|
||||||
|
#define SetUi16(p, d) *(UInt16 *)(p) = (d);
|
||||||
|
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
|
||||||
|
#define SetUi64(p, d) *(UInt64 *)(p) = (d);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
|
||||||
|
|
||||||
|
#define GetUi32(p) ( \
|
||||||
|
((const Byte *)(p))[0] | \
|
||||||
|
((UInt32)((const Byte *)(p))[1] << 8) | \
|
||||||
|
((UInt32)((const Byte *)(p))[2] << 16) | \
|
||||||
|
((UInt32)((const Byte *)(p))[3] << 24))
|
||||||
|
|
||||||
|
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||||
|
|
||||||
|
#define SetUi16(p, d) { UInt32 _x_ = (d); \
|
||||||
|
((Byte *)(p))[0] = (Byte)_x_; \
|
||||||
|
((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
|
||||||
|
|
||||||
|
#define SetUi32(p, d) { UInt32 _x_ = (d); \
|
||||||
|
((Byte *)(p))[0] = (Byte)_x_; \
|
||||||
|
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
|
||||||
|
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
|
||||||
|
((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
|
||||||
|
|
||||||
|
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
|
||||||
|
SetUi32(p, (UInt32)_x64_); \
|
||||||
|
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#pragma intrinsic(_byteswap_ulong)
|
||||||
|
#pragma intrinsic(_byteswap_uint64)
|
||||||
|
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
|
||||||
|
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define GetBe32(p) ( \
|
||||||
|
((UInt32)((const Byte *)(p))[0] << 24) | \
|
||||||
|
((UInt32)((const Byte *)(p))[1] << 16) | \
|
||||||
|
((UInt32)((const Byte *)(p))[2] << 8) | \
|
||||||
|
((const Byte *)(p))[3] )
|
||||||
|
|
||||||
|
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GetBe16(p) ((UInt16)(((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]))
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt32 maxFunc;
|
||||||
|
UInt32 vendor[3];
|
||||||
|
UInt32 ver;
|
||||||
|
UInt32 b;
|
||||||
|
UInt32 c;
|
||||||
|
UInt32 d;
|
||||||
|
} Cx86cpuid;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CPU_FIRM_INTEL,
|
||||||
|
CPU_FIRM_AMD,
|
||||||
|
CPU_FIRM_VIA
|
||||||
|
};
|
||||||
|
|
||||||
|
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
|
||||||
|
int x86cpuid_GetFirm(const Cx86cpuid *p);
|
||||||
|
|
||||||
|
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
|
||||||
|
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
|
||||||
|
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
|
||||||
|
|
||||||
|
Bool CPU_Is_InOrder();
|
||||||
|
Bool CPU_Is_Aes_Supported();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,64 @@
|
||||||
|
/* Delta.c -- Delta converter
|
||||||
|
2009-05-26 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Delta.h"
|
||||||
|
|
||||||
|
void Delta_Init(Byte *state)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < DELTA_STATE_SIZE; i++)
|
||||||
|
state[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
dest[i] = src[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||||
|
{
|
||||||
|
Byte buf[DELTA_STATE_SIZE];
|
||||||
|
unsigned j = 0;
|
||||||
|
MyMemCpy(buf, state, delta);
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
for (i = 0; i < size;)
|
||||||
|
{
|
||||||
|
for (j = 0; j < delta && i < size; i++, j++)
|
||||||
|
{
|
||||||
|
Byte b = data[i];
|
||||||
|
data[i] = (Byte)(b - buf[j]);
|
||||||
|
buf[j] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == delta)
|
||||||
|
j = 0;
|
||||||
|
MyMemCpy(state, buf + j, delta - j);
|
||||||
|
MyMemCpy(state + delta - j, buf, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||||
|
{
|
||||||
|
Byte buf[DELTA_STATE_SIZE];
|
||||||
|
unsigned j = 0;
|
||||||
|
MyMemCpy(buf, state, delta);
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
for (i = 0; i < size;)
|
||||||
|
{
|
||||||
|
for (j = 0; j < delta && i < size; i++, j++)
|
||||||
|
{
|
||||||
|
buf[j] = data[i] = (Byte)(buf[j] + data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == delta)
|
||||||
|
j = 0;
|
||||||
|
MyMemCpy(state, buf + j, delta - j);
|
||||||
|
MyMemCpy(state + delta - j, buf, j);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* Delta.h -- Delta converter
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __DELTA_H
|
||||||
|
#define __DELTA_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define DELTA_STATE_SIZE 256
|
||||||
|
|
||||||
|
void Delta_Init(Byte *state);
|
||||||
|
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||||
|
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,763 @@
|
||||||
|
/* LzFind.c -- Match finder for LZ algorithms
|
||||||
|
2009-04-22 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "LzFind.h"
|
||||||
|
#include "LzHash.h"
|
||||||
|
|
||||||
|
#define kEmptyHashValue 0
|
||||||
|
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
|
||||||
|
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
|
||||||
|
#define kNormalizeMask (~(kNormalizeStepMin - 1))
|
||||||
|
#define kMaxHistorySize ((UInt32)3 << 30)
|
||||||
|
|
||||||
|
#define kStartMaxLen 3
|
||||||
|
|
||||||
|
static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
if (!p->directInput)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->bufferBase);
|
||||||
|
p->bufferBase = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
|
||||||
|
|
||||||
|
static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
|
||||||
|
if (p->directInput)
|
||||||
|
{
|
||||||
|
p->blockSize = blockSize;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (p->bufferBase == 0 || p->blockSize != blockSize)
|
||||||
|
{
|
||||||
|
LzInWindow_Free(p, alloc);
|
||||||
|
p->blockSize = blockSize;
|
||||||
|
p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
|
||||||
|
}
|
||||||
|
return (p->bufferBase != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
|
||||||
|
Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
|
||||||
|
|
||||||
|
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
|
||||||
|
|
||||||
|
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
|
||||||
|
{
|
||||||
|
p->posLimit -= subValue;
|
||||||
|
p->pos -= subValue;
|
||||||
|
p->streamPos -= subValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MatchFinder_ReadBlock(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
if (p->streamEndWasReached || p->result != SZ_OK)
|
||||||
|
return;
|
||||||
|
if (p->directInput)
|
||||||
|
{
|
||||||
|
UInt32 curSize = 0xFFFFFFFF - p->streamPos;
|
||||||
|
if (curSize > p->directInputRem)
|
||||||
|
curSize = (UInt32)p->directInputRem;
|
||||||
|
p->directInputRem -= curSize;
|
||||||
|
p->streamPos += curSize;
|
||||||
|
if (p->directInputRem == 0)
|
||||||
|
p->streamEndWasReached = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Byte *dest = p->buffer + (p->streamPos - p->pos);
|
||||||
|
size_t size = (p->bufferBase + p->blockSize - dest);
|
||||||
|
if (size == 0)
|
||||||
|
return;
|
||||||
|
p->result = p->stream->Read(p->stream, dest, &size);
|
||||||
|
if (p->result != SZ_OK)
|
||||||
|
return;
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
p->streamEndWasReached = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p->streamPos += (UInt32)size;
|
||||||
|
if (p->streamPos - p->pos > p->keepSizeAfter)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinder_MoveBlock(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
memmove(p->bufferBase,
|
||||||
|
p->buffer - p->keepSizeBefore,
|
||||||
|
(size_t)(p->streamPos - p->pos + p->keepSizeBefore));
|
||||||
|
p->buffer = p->bufferBase + p->keepSizeBefore;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MatchFinder_NeedMove(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
if (p->directInput)
|
||||||
|
return 0;
|
||||||
|
/* if (p->streamEndWasReached) return 0; */
|
||||||
|
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinder_ReadIfRequired(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
if (p->streamEndWasReached)
|
||||||
|
return;
|
||||||
|
if (p->keepSizeAfter >= p->streamPos - p->pos)
|
||||||
|
MatchFinder_ReadBlock(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
if (MatchFinder_NeedMove(p))
|
||||||
|
MatchFinder_MoveBlock(p);
|
||||||
|
MatchFinder_ReadBlock(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
p->cutValue = 32;
|
||||||
|
p->btMode = 1;
|
||||||
|
p->numHashBytes = 4;
|
||||||
|
p->bigHash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define kCrcPoly 0xEDB88320
|
||||||
|
|
||||||
|
void MatchFinder_Construct(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
p->bufferBase = 0;
|
||||||
|
p->directInput = 0;
|
||||||
|
p->hash = 0;
|
||||||
|
MatchFinder_SetDefaultSettings(p);
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
UInt32 r = i;
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||||
|
p->crc[i] = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->hash);
|
||||||
|
p->hash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
MatchFinder_FreeThisClassMemory(p, alloc);
|
||||||
|
LzInWindow_Free(p, alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
|
||||||
|
if (sizeInBytes / sizeof(CLzRef) != num)
|
||||||
|
return 0;
|
||||||
|
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||||
|
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
||||||
|
ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
UInt32 sizeReserv;
|
||||||
|
if (historySize > kMaxHistorySize)
|
||||||
|
{
|
||||||
|
MatchFinder_Free(p, alloc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sizeReserv = historySize >> 1;
|
||||||
|
if (historySize > ((UInt32)2 << 30))
|
||||||
|
sizeReserv = historySize >> 2;
|
||||||
|
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
|
||||||
|
|
||||||
|
p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
|
||||||
|
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
|
||||||
|
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
|
||||||
|
if (LzInWindow_Create(p, sizeReserv, alloc))
|
||||||
|
{
|
||||||
|
UInt32 newCyclicBufferSize = historySize + 1;
|
||||||
|
UInt32 hs;
|
||||||
|
p->matchMaxLen = matchMaxLen;
|
||||||
|
{
|
||||||
|
p->fixedHashSize = 0;
|
||||||
|
if (p->numHashBytes == 2)
|
||||||
|
hs = (1 << 16) - 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hs = historySize - 1;
|
||||||
|
hs |= (hs >> 1);
|
||||||
|
hs |= (hs >> 2);
|
||||||
|
hs |= (hs >> 4);
|
||||||
|
hs |= (hs >> 8);
|
||||||
|
hs >>= 1;
|
||||||
|
hs |= 0xFFFF; /* don't change it! It's required for Deflate */
|
||||||
|
if (hs > (1 << 24))
|
||||||
|
{
|
||||||
|
if (p->numHashBytes == 3)
|
||||||
|
hs = (1 << 24) - 1;
|
||||||
|
else
|
||||||
|
hs >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->hashMask = hs;
|
||||||
|
hs++;
|
||||||
|
if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
|
||||||
|
if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
|
||||||
|
if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
|
||||||
|
hs += p->fixedHashSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
UInt32 prevSize = p->hashSizeSum + p->numSons;
|
||||||
|
UInt32 newSize;
|
||||||
|
p->historySize = historySize;
|
||||||
|
p->hashSizeSum = hs;
|
||||||
|
p->cyclicBufferSize = newCyclicBufferSize;
|
||||||
|
p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
|
||||||
|
newSize = p->hashSizeSum + p->numSons;
|
||||||
|
if (p->hash != 0 && prevSize == newSize)
|
||||||
|
return 1;
|
||||||
|
MatchFinder_FreeThisClassMemory(p, alloc);
|
||||||
|
p->hash = AllocRefs(newSize, alloc);
|
||||||
|
if (p->hash != 0)
|
||||||
|
{
|
||||||
|
p->son = p->hash + p->hashSizeSum;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MatchFinder_Free(p, alloc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MatchFinder_SetLimits(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
UInt32 limit = kMaxValForNormalize - p->pos;
|
||||||
|
UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
|
||||||
|
if (limit2 < limit)
|
||||||
|
limit = limit2;
|
||||||
|
limit2 = p->streamPos - p->pos;
|
||||||
|
if (limit2 <= p->keepSizeAfter)
|
||||||
|
{
|
||||||
|
if (limit2 > 0)
|
||||||
|
limit2 = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
limit2 -= p->keepSizeAfter;
|
||||||
|
if (limit2 < limit)
|
||||||
|
limit = limit2;
|
||||||
|
{
|
||||||
|
UInt32 lenLimit = p->streamPos - p->pos;
|
||||||
|
if (lenLimit > p->matchMaxLen)
|
||||||
|
lenLimit = p->matchMaxLen;
|
||||||
|
p->lenLimit = lenLimit;
|
||||||
|
}
|
||||||
|
p->posLimit = p->pos + limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinder_Init(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
for (i = 0; i < p->hashSizeSum; i++)
|
||||||
|
p->hash[i] = kEmptyHashValue;
|
||||||
|
p->cyclicBufferPos = 0;
|
||||||
|
p->buffer = p->bufferBase;
|
||||||
|
p->pos = p->streamPos = p->cyclicBufferSize;
|
||||||
|
p->result = SZ_OK;
|
||||||
|
p->streamEndWasReached = 0;
|
||||||
|
MatchFinder_ReadBlock(p);
|
||||||
|
MatchFinder_SetLimits(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
return (p->pos - p->historySize - 1) & kNormalizeMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
for (i = 0; i < numItems; i++)
|
||||||
|
{
|
||||||
|
UInt32 value = items[i];
|
||||||
|
if (value <= subValue)
|
||||||
|
value = kEmptyHashValue;
|
||||||
|
else
|
||||||
|
value -= subValue;
|
||||||
|
items[i] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MatchFinder_Normalize(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
UInt32 subValue = MatchFinder_GetSubValue(p);
|
||||||
|
MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
|
||||||
|
MatchFinder_ReduceOffsets(p, subValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MatchFinder_CheckLimits(CMatchFinder *p)
|
||||||
|
{
|
||||||
|
if (p->pos == kMaxValForNormalize)
|
||||||
|
MatchFinder_Normalize(p);
|
||||||
|
if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
|
||||||
|
MatchFinder_CheckAndMoveAndRead(p);
|
||||||
|
if (p->cyclicBufferPos == p->cyclicBufferSize)
|
||||||
|
p->cyclicBufferPos = 0;
|
||||||
|
MatchFinder_SetLimits(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||||
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
||||||
|
UInt32 *distances, UInt32 maxLen)
|
||||||
|
{
|
||||||
|
son[_cyclicBufferPos] = curMatch;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UInt32 delta = pos - curMatch;
|
||||||
|
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||||
|
return distances;
|
||||||
|
{
|
||||||
|
const Byte *pb = cur - delta;
|
||||||
|
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
||||||
|
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
|
||||||
|
{
|
||||||
|
UInt32 len = 0;
|
||||||
|
while (++len != lenLimit)
|
||||||
|
if (pb[len] != cur[len])
|
||||||
|
break;
|
||||||
|
if (maxLen < len)
|
||||||
|
{
|
||||||
|
*distances++ = maxLen = len;
|
||||||
|
*distances++ = delta - 1;
|
||||||
|
if (len == lenLimit)
|
||||||
|
return distances;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||||
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
||||||
|
UInt32 *distances, UInt32 maxLen)
|
||||||
|
{
|
||||||
|
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||||
|
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||||
|
UInt32 len0 = 0, len1 = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UInt32 delta = pos - curMatch;
|
||||||
|
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||||
|
{
|
||||||
|
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||||
|
return distances;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||||
|
const Byte *pb = cur - delta;
|
||||||
|
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||||
|
if (pb[len] == cur[len])
|
||||||
|
{
|
||||||
|
if (++len != lenLimit && pb[len] == cur[len])
|
||||||
|
while (++len != lenLimit)
|
||||||
|
if (pb[len] != cur[len])
|
||||||
|
break;
|
||||||
|
if (maxLen < len)
|
||||||
|
{
|
||||||
|
*distances++ = maxLen = len;
|
||||||
|
*distances++ = delta - 1;
|
||||||
|
if (len == lenLimit)
|
||||||
|
{
|
||||||
|
*ptr1 = pair[0];
|
||||||
|
*ptr0 = pair[1];
|
||||||
|
return distances;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pb[len] < cur[len])
|
||||||
|
{
|
||||||
|
*ptr1 = curMatch;
|
||||||
|
ptr1 = pair + 1;
|
||||||
|
curMatch = *ptr1;
|
||||||
|
len1 = len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ptr0 = curMatch;
|
||||||
|
ptr0 = pair;
|
||||||
|
curMatch = *ptr0;
|
||||||
|
len0 = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||||
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
|
||||||
|
{
|
||||||
|
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||||
|
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||||
|
UInt32 len0 = 0, len1 = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UInt32 delta = pos - curMatch;
|
||||||
|
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||||
|
{
|
||||||
|
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||||
|
const Byte *pb = cur - delta;
|
||||||
|
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||||
|
if (pb[len] == cur[len])
|
||||||
|
{
|
||||||
|
while (++len != lenLimit)
|
||||||
|
if (pb[len] != cur[len])
|
||||||
|
break;
|
||||||
|
{
|
||||||
|
if (len == lenLimit)
|
||||||
|
{
|
||||||
|
*ptr1 = pair[0];
|
||||||
|
*ptr0 = pair[1];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pb[len] < cur[len])
|
||||||
|
{
|
||||||
|
*ptr1 = curMatch;
|
||||||
|
ptr1 = pair + 1;
|
||||||
|
curMatch = *ptr1;
|
||||||
|
len1 = len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ptr0 = curMatch;
|
||||||
|
ptr0 = pair;
|
||||||
|
curMatch = *ptr0;
|
||||||
|
len0 = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MOVE_POS \
|
||||||
|
++p->cyclicBufferPos; \
|
||||||
|
p->buffer++; \
|
||||||
|
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
|
||||||
|
|
||||||
|
#define MOVE_POS_RET MOVE_POS return offset;
|
||||||
|
|
||||||
|
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
|
||||||
|
|
||||||
|
#define GET_MATCHES_HEADER2(minLen, ret_op) \
|
||||||
|
UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
|
||||||
|
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
|
||||||
|
cur = p->buffer;
|
||||||
|
|
||||||
|
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
|
||||||
|
#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
|
||||||
|
|
||||||
|
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
|
||||||
|
|
||||||
|
#define GET_MATCHES_FOOTER(offset, maxLen) \
|
||||||
|
offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
|
||||||
|
distances + offset, maxLen) - distances); MOVE_POS_RET;
|
||||||
|
|
||||||
|
#define SKIP_FOOTER \
|
||||||
|
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
|
||||||
|
|
||||||
|
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 offset;
|
||||||
|
GET_MATCHES_HEADER(2)
|
||||||
|
HASH2_CALC;
|
||||||
|
curMatch = p->hash[hashValue];
|
||||||
|
p->hash[hashValue] = p->pos;
|
||||||
|
offset = 0;
|
||||||
|
GET_MATCHES_FOOTER(offset, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 offset;
|
||||||
|
GET_MATCHES_HEADER(3)
|
||||||
|
HASH_ZIP_CALC;
|
||||||
|
curMatch = p->hash[hashValue];
|
||||||
|
p->hash[hashValue] = p->pos;
|
||||||
|
offset = 0;
|
||||||
|
GET_MATCHES_FOOTER(offset, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 hash2Value, delta2, maxLen, offset;
|
||||||
|
GET_MATCHES_HEADER(3)
|
||||||
|
|
||||||
|
HASH3_CALC;
|
||||||
|
|
||||||
|
delta2 = p->pos - p->hash[hash2Value];
|
||||||
|
curMatch = p->hash[kFix3HashSize + hashValue];
|
||||||
|
|
||||||
|
p->hash[hash2Value] =
|
||||||
|
p->hash[kFix3HashSize + hashValue] = p->pos;
|
||||||
|
|
||||||
|
|
||||||
|
maxLen = 2;
|
||||||
|
offset = 0;
|
||||||
|
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||||
|
{
|
||||||
|
for (; maxLen != lenLimit; maxLen++)
|
||||||
|
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||||
|
break;
|
||||||
|
distances[0] = maxLen;
|
||||||
|
distances[1] = delta2 - 1;
|
||||||
|
offset = 2;
|
||||||
|
if (maxLen == lenLimit)
|
||||||
|
{
|
||||||
|
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||||
|
MOVE_POS_RET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GET_MATCHES_FOOTER(offset, maxLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||||
|
GET_MATCHES_HEADER(4)
|
||||||
|
|
||||||
|
HASH4_CALC;
|
||||||
|
|
||||||
|
delta2 = p->pos - p->hash[ hash2Value];
|
||||||
|
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||||
|
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||||
|
|
||||||
|
p->hash[ hash2Value] =
|
||||||
|
p->hash[kFix3HashSize + hash3Value] =
|
||||||
|
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||||
|
|
||||||
|
maxLen = 1;
|
||||||
|
offset = 0;
|
||||||
|
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||||
|
{
|
||||||
|
distances[0] = maxLen = 2;
|
||||||
|
distances[1] = delta2 - 1;
|
||||||
|
offset = 2;
|
||||||
|
}
|
||||||
|
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||||
|
{
|
||||||
|
maxLen = 3;
|
||||||
|
distances[offset + 1] = delta3 - 1;
|
||||||
|
offset += 2;
|
||||||
|
delta2 = delta3;
|
||||||
|
}
|
||||||
|
if (offset != 0)
|
||||||
|
{
|
||||||
|
for (; maxLen != lenLimit; maxLen++)
|
||||||
|
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||||
|
break;
|
||||||
|
distances[offset - 2] = maxLen;
|
||||||
|
if (maxLen == lenLimit)
|
||||||
|
{
|
||||||
|
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||||
|
MOVE_POS_RET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxLen < 3)
|
||||||
|
maxLen = 3;
|
||||||
|
GET_MATCHES_FOOTER(offset, maxLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||||
|
GET_MATCHES_HEADER(4)
|
||||||
|
|
||||||
|
HASH4_CALC;
|
||||||
|
|
||||||
|
delta2 = p->pos - p->hash[ hash2Value];
|
||||||
|
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||||
|
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||||
|
|
||||||
|
p->hash[ hash2Value] =
|
||||||
|
p->hash[kFix3HashSize + hash3Value] =
|
||||||
|
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||||
|
|
||||||
|
maxLen = 1;
|
||||||
|
offset = 0;
|
||||||
|
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||||
|
{
|
||||||
|
distances[0] = maxLen = 2;
|
||||||
|
distances[1] = delta2 - 1;
|
||||||
|
offset = 2;
|
||||||
|
}
|
||||||
|
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||||
|
{
|
||||||
|
maxLen = 3;
|
||||||
|
distances[offset + 1] = delta3 - 1;
|
||||||
|
offset += 2;
|
||||||
|
delta2 = delta3;
|
||||||
|
}
|
||||||
|
if (offset != 0)
|
||||||
|
{
|
||||||
|
for (; maxLen != lenLimit; maxLen++)
|
||||||
|
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||||
|
break;
|
||||||
|
distances[offset - 2] = maxLen;
|
||||||
|
if (maxLen == lenLimit)
|
||||||
|
{
|
||||||
|
p->son[p->cyclicBufferPos] = curMatch;
|
||||||
|
MOVE_POS_RET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxLen < 3)
|
||||||
|
maxLen = 3;
|
||||||
|
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||||
|
distances + offset, maxLen) - (distances));
|
||||||
|
MOVE_POS_RET
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 offset;
|
||||||
|
GET_MATCHES_HEADER(3)
|
||||||
|
HASH_ZIP_CALC;
|
||||||
|
curMatch = p->hash[hashValue];
|
||||||
|
p->hash[hashValue] = p->pos;
|
||||||
|
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||||
|
distances, 2) - (distances));
|
||||||
|
MOVE_POS_RET
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
SKIP_HEADER(2)
|
||||||
|
HASH2_CALC;
|
||||||
|
curMatch = p->hash[hashValue];
|
||||||
|
p->hash[hashValue] = p->pos;
|
||||||
|
SKIP_FOOTER
|
||||||
|
}
|
||||||
|
while (--num != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
SKIP_HEADER(3)
|
||||||
|
HASH_ZIP_CALC;
|
||||||
|
curMatch = p->hash[hashValue];
|
||||||
|
p->hash[hashValue] = p->pos;
|
||||||
|
SKIP_FOOTER
|
||||||
|
}
|
||||||
|
while (--num != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
UInt32 hash2Value;
|
||||||
|
SKIP_HEADER(3)
|
||||||
|
HASH3_CALC;
|
||||||
|
curMatch = p->hash[kFix3HashSize + hashValue];
|
||||||
|
p->hash[hash2Value] =
|
||||||
|
p->hash[kFix3HashSize + hashValue] = p->pos;
|
||||||
|
SKIP_FOOTER
|
||||||
|
}
|
||||||
|
while (--num != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
UInt32 hash2Value, hash3Value;
|
||||||
|
SKIP_HEADER(4)
|
||||||
|
HASH4_CALC;
|
||||||
|
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||||
|
p->hash[ hash2Value] =
|
||||||
|
p->hash[kFix3HashSize + hash3Value] = p->pos;
|
||||||
|
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||||
|
SKIP_FOOTER
|
||||||
|
}
|
||||||
|
while (--num != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
UInt32 hash2Value, hash3Value;
|
||||||
|
SKIP_HEADER(4)
|
||||||
|
HASH4_CALC;
|
||||||
|
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||||
|
p->hash[ hash2Value] =
|
||||||
|
p->hash[kFix3HashSize + hash3Value] =
|
||||||
|
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||||
|
p->son[p->cyclicBufferPos] = curMatch;
|
||||||
|
MOVE_POS
|
||||||
|
}
|
||||||
|
while (--num != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
SKIP_HEADER(3)
|
||||||
|
HASH_ZIP_CALC;
|
||||||
|
curMatch = p->hash[hashValue];
|
||||||
|
p->hash[hashValue] = p->pos;
|
||||||
|
p->son[p->cyclicBufferPos] = curMatch;
|
||||||
|
MOVE_POS
|
||||||
|
}
|
||||||
|
while (--num != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
|
||||||
|
{
|
||||||
|
vTable->Init = (Mf_Init_Func)MatchFinder_Init;
|
||||||
|
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
|
||||||
|
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
|
||||||
|
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
|
||||||
|
if (!p->btMode)
|
||||||
|
{
|
||||||
|
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
|
||||||
|
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
|
||||||
|
}
|
||||||
|
else if (p->numHashBytes == 2)
|
||||||
|
{
|
||||||
|
vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
|
||||||
|
vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
|
||||||
|
}
|
||||||
|
else if (p->numHashBytes == 3)
|
||||||
|
{
|
||||||
|
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
|
||||||
|
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
|
||||||
|
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* LzFind.h -- Match finder for LZ algorithms
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZ_FIND_H
|
||||||
|
#define __LZ_FIND_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
typedef UInt32 CLzRef;
|
||||||
|
|
||||||
|
typedef struct _CMatchFinder
|
||||||
|
{
|
||||||
|
Byte *buffer;
|
||||||
|
UInt32 pos;
|
||||||
|
UInt32 posLimit;
|
||||||
|
UInt32 streamPos;
|
||||||
|
UInt32 lenLimit;
|
||||||
|
|
||||||
|
UInt32 cyclicBufferPos;
|
||||||
|
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||||
|
|
||||||
|
UInt32 matchMaxLen;
|
||||||
|
CLzRef *hash;
|
||||||
|
CLzRef *son;
|
||||||
|
UInt32 hashMask;
|
||||||
|
UInt32 cutValue;
|
||||||
|
|
||||||
|
Byte *bufferBase;
|
||||||
|
ISeqInStream *stream;
|
||||||
|
int streamEndWasReached;
|
||||||
|
|
||||||
|
UInt32 blockSize;
|
||||||
|
UInt32 keepSizeBefore;
|
||||||
|
UInt32 keepSizeAfter;
|
||||||
|
|
||||||
|
UInt32 numHashBytes;
|
||||||
|
int directInput;
|
||||||
|
size_t directInputRem;
|
||||||
|
int btMode;
|
||||||
|
int bigHash;
|
||||||
|
UInt32 historySize;
|
||||||
|
UInt32 fixedHashSize;
|
||||||
|
UInt32 hashSizeSum;
|
||||||
|
UInt32 numSons;
|
||||||
|
SRes result;
|
||||||
|
UInt32 crc[256];
|
||||||
|
} CMatchFinder;
|
||||||
|
|
||||||
|
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||||
|
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
|
||||||
|
|
||||||
|
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
||||||
|
|
||||||
|
int MatchFinder_NeedMove(CMatchFinder *p);
|
||||||
|
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||||
|
void MatchFinder_MoveBlock(CMatchFinder *p);
|
||||||
|
void MatchFinder_ReadIfRequired(CMatchFinder *p);
|
||||||
|
|
||||||
|
void MatchFinder_Construct(CMatchFinder *p);
|
||||||
|
|
||||||
|
/* Conditions:
|
||||||
|
historySize <= 3 GB
|
||||||
|
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
|
||||||
|
*/
|
||||||
|
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||||
|
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
||||||
|
ISzAlloc *alloc);
|
||||||
|
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
|
||||||
|
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
|
||||||
|
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
|
||||||
|
|
||||||
|
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
||||||
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||||
|
UInt32 *distances, UInt32 maxLen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Conditions:
|
||||||
|
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
|
||||||
|
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void (*Mf_Init_Func)(void *object);
|
||||||
|
typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
|
||||||
|
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
|
||||||
|
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
||||||
|
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
|
||||||
|
typedef void (*Mf_Skip_Func)(void *object, UInt32);
|
||||||
|
|
||||||
|
typedef struct _IMatchFinder
|
||||||
|
{
|
||||||
|
Mf_Init_Func Init;
|
||||||
|
Mf_GetIndexByte_Func GetIndexByte;
|
||||||
|
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
|
||||||
|
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
|
||||||
|
Mf_GetMatches_Func GetMatches;
|
||||||
|
Mf_Skip_Func Skip;
|
||||||
|
} IMatchFinder;
|
||||||
|
|
||||||
|
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||||
|
|
||||||
|
void MatchFinder_Init(CMatchFinder *p);
|
||||||
|
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||||
|
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||||
|
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||||
|
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,794 @@
|
||||||
|
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
|
||||||
|
2014-12-29 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "LzHash.h"
|
||||||
|
|
||||||
|
#include "LzFindMt.h"
|
||||||
|
|
||||||
|
void MtSync_Construct(CMtSync *p)
|
||||||
|
{
|
||||||
|
p->wasCreated = False;
|
||||||
|
p->csWasInitialized = False;
|
||||||
|
p->csWasEntered = False;
|
||||||
|
Thread_Construct(&p->thread);
|
||||||
|
Event_Construct(&p->canStart);
|
||||||
|
Event_Construct(&p->wasStarted);
|
||||||
|
Event_Construct(&p->wasStopped);
|
||||||
|
Semaphore_Construct(&p->freeSemaphore);
|
||||||
|
Semaphore_Construct(&p->filledSemaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MtSync_GetNextBlock(CMtSync *p)
|
||||||
|
{
|
||||||
|
if (p->needStart)
|
||||||
|
{
|
||||||
|
p->numProcessedBlocks = 1;
|
||||||
|
p->needStart = False;
|
||||||
|
p->stopWriting = False;
|
||||||
|
p->exit = False;
|
||||||
|
Event_Reset(&p->wasStarted);
|
||||||
|
Event_Reset(&p->wasStopped);
|
||||||
|
|
||||||
|
Event_Set(&p->canStart);
|
||||||
|
Event_Wait(&p->wasStarted);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CriticalSection_Leave(&p->cs);
|
||||||
|
p->csWasEntered = False;
|
||||||
|
p->numProcessedBlocks++;
|
||||||
|
Semaphore_Release1(&p->freeSemaphore);
|
||||||
|
}
|
||||||
|
Semaphore_Wait(&p->filledSemaphore);
|
||||||
|
CriticalSection_Enter(&p->cs);
|
||||||
|
p->csWasEntered = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MtSync_StopWriting must be called if Writing was started */
|
||||||
|
|
||||||
|
void MtSync_StopWriting(CMtSync *p)
|
||||||
|
{
|
||||||
|
UInt32 myNumBlocks = p->numProcessedBlocks;
|
||||||
|
if (!Thread_WasCreated(&p->thread) || p->needStart)
|
||||||
|
return;
|
||||||
|
p->stopWriting = True;
|
||||||
|
if (p->csWasEntered)
|
||||||
|
{
|
||||||
|
CriticalSection_Leave(&p->cs);
|
||||||
|
p->csWasEntered = False;
|
||||||
|
}
|
||||||
|
Semaphore_Release1(&p->freeSemaphore);
|
||||||
|
|
||||||
|
Event_Wait(&p->wasStopped);
|
||||||
|
|
||||||
|
while (myNumBlocks++ != p->numProcessedBlocks)
|
||||||
|
{
|
||||||
|
Semaphore_Wait(&p->filledSemaphore);
|
||||||
|
Semaphore_Release1(&p->freeSemaphore);
|
||||||
|
}
|
||||||
|
p->needStart = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MtSync_Destruct(CMtSync *p)
|
||||||
|
{
|
||||||
|
if (Thread_WasCreated(&p->thread))
|
||||||
|
{
|
||||||
|
MtSync_StopWriting(p);
|
||||||
|
p->exit = True;
|
||||||
|
if (p->needStart)
|
||||||
|
Event_Set(&p->canStart);
|
||||||
|
Thread_Wait(&p->thread);
|
||||||
|
Thread_Close(&p->thread);
|
||||||
|
}
|
||||||
|
if (p->csWasInitialized)
|
||||||
|
{
|
||||||
|
CriticalSection_Delete(&p->cs);
|
||||||
|
p->csWasInitialized = False;
|
||||||
|
}
|
||||||
|
|
||||||
|
Event_Close(&p->canStart);
|
||||||
|
Event_Close(&p->wasStarted);
|
||||||
|
Event_Close(&p->wasStopped);
|
||||||
|
Semaphore_Close(&p->freeSemaphore);
|
||||||
|
Semaphore_Close(&p->filledSemaphore);
|
||||||
|
|
||||||
|
p->wasCreated = False;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
|
||||||
|
|
||||||
|
static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
|
||||||
|
{
|
||||||
|
if (p->wasCreated)
|
||||||
|
return SZ_OK;
|
||||||
|
|
||||||
|
RINOK_THREAD(CriticalSection_Init(&p->cs));
|
||||||
|
p->csWasInitialized = True;
|
||||||
|
|
||||||
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart));
|
||||||
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
|
||||||
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
|
||||||
|
|
||||||
|
RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
|
||||||
|
RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
|
||||||
|
|
||||||
|
p->needStart = True;
|
||||||
|
|
||||||
|
RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj));
|
||||||
|
p->wasCreated = True;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks)
|
||||||
|
{
|
||||||
|
SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
MtSync_Destruct(p);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MtSync_Init(CMtSync *p) { p->needStart = True; }
|
||||||
|
|
||||||
|
#define kMtMaxValForNormalize 0xFFFFFFFF
|
||||||
|
|
||||||
|
#define DEF_GetHeads2(name, v, action) \
|
||||||
|
static void GetHeads ## name(const Byte *p, UInt32 pos, \
|
||||||
|
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
|
||||||
|
{ action; for (; numHeads != 0; numHeads--) { \
|
||||||
|
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
|
||||||
|
|
||||||
|
#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
|
||||||
|
|
||||||
|
DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )
|
||||||
|
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
|
||||||
|
DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
|
||||||
|
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
|
||||||
|
/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
|
||||||
|
|
||||||
|
void HashThreadFunc(CMatchFinderMt *mt)
|
||||||
|
{
|
||||||
|
CMtSync *p = &mt->hashSync;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UInt32 numProcessedBlocks = 0;
|
||||||
|
Event_Wait(&p->canStart);
|
||||||
|
Event_Set(&p->wasStarted);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (p->exit)
|
||||||
|
return;
|
||||||
|
if (p->stopWriting)
|
||||||
|
{
|
||||||
|
p->numProcessedBlocks = numProcessedBlocks;
|
||||||
|
Event_Set(&p->wasStopped);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CMatchFinder *mf = mt->MatchFinder;
|
||||||
|
if (MatchFinder_NeedMove(mf))
|
||||||
|
{
|
||||||
|
CriticalSection_Enter(&mt->btSync.cs);
|
||||||
|
CriticalSection_Enter(&mt->hashSync.cs);
|
||||||
|
{
|
||||||
|
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
|
||||||
|
const Byte *afterPtr;
|
||||||
|
MatchFinder_MoveBlock(mf);
|
||||||
|
afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
|
||||||
|
mt->pointerToCurPos -= beforePtr - afterPtr;
|
||||||
|
mt->buffer -= beforePtr - afterPtr;
|
||||||
|
}
|
||||||
|
CriticalSection_Leave(&mt->btSync.cs);
|
||||||
|
CriticalSection_Leave(&mt->hashSync.cs);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Semaphore_Wait(&p->freeSemaphore);
|
||||||
|
|
||||||
|
MatchFinder_ReadIfRequired(mf);
|
||||||
|
if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))
|
||||||
|
{
|
||||||
|
UInt32 subValue = (mf->pos - mf->historySize - 1);
|
||||||
|
MatchFinder_ReduceOffsets(mf, subValue);
|
||||||
|
MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
|
||||||
|
UInt32 num = mf->streamPos - mf->pos;
|
||||||
|
heads[0] = 2;
|
||||||
|
heads[1] = num;
|
||||||
|
if (num >= mf->numHashBytes)
|
||||||
|
{
|
||||||
|
num = num - mf->numHashBytes + 1;
|
||||||
|
if (num > kMtHashBlockSize - 2)
|
||||||
|
num = kMtHashBlockSize - 2;
|
||||||
|
mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);
|
||||||
|
heads[0] += num;
|
||||||
|
}
|
||||||
|
mf->pos += num;
|
||||||
|
mf->buffer += num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Semaphore_Release1(&p->filledSemaphore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
||||||
|
{
|
||||||
|
MtSync_GetNextBlock(&p->hashSync);
|
||||||
|
p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
|
||||||
|
p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];
|
||||||
|
p->hashNumAvail = p->hashBuf[p->hashBufPos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
#define kEmptyHashValue 0
|
||||||
|
|
||||||
|
/* #define MFMT_GM_INLINE */
|
||||||
|
|
||||||
|
#ifdef MFMT_GM_INLINE
|
||||||
|
|
||||||
|
#define NO_INLINE MY_FAST_CALL
|
||||||
|
|
||||||
|
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
|
||||||
|
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||||
|
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
UInt32 *distances = _distances + 1;
|
||||||
|
UInt32 curMatch = pos - *hash++;
|
||||||
|
|
||||||
|
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||||
|
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||||
|
UInt32 len0 = 0, len1 = 0;
|
||||||
|
UInt32 cutValue = _cutValue;
|
||||||
|
UInt32 maxLen = _maxLen;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UInt32 delta = pos - curMatch;
|
||||||
|
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||||
|
{
|
||||||
|
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||||
|
const Byte *pb = cur - delta;
|
||||||
|
UInt32 len = (len0 < len1 ? len0 : len1);
|
||||||
|
if (pb[len] == cur[len])
|
||||||
|
{
|
||||||
|
if (++len != lenLimit && pb[len] == cur[len])
|
||||||
|
while (++len != lenLimit)
|
||||||
|
if (pb[len] != cur[len])
|
||||||
|
break;
|
||||||
|
if (maxLen < len)
|
||||||
|
{
|
||||||
|
*distances++ = maxLen = len;
|
||||||
|
*distances++ = delta - 1;
|
||||||
|
if (len == lenLimit)
|
||||||
|
{
|
||||||
|
*ptr1 = pair[0];
|
||||||
|
*ptr0 = pair[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pb[len] < cur[len])
|
||||||
|
{
|
||||||
|
*ptr1 = curMatch;
|
||||||
|
ptr1 = pair + 1;
|
||||||
|
curMatch = *ptr1;
|
||||||
|
len1 = len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ptr0 = curMatch;
|
||||||
|
ptr0 = pair;
|
||||||
|
curMatch = *ptr0;
|
||||||
|
len0 = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
_cyclicBufferPos++;
|
||||||
|
cur++;
|
||||||
|
{
|
||||||
|
UInt32 num = (UInt32)(distances - _distances);
|
||||||
|
*_distances = num - 1;
|
||||||
|
_distances += num;
|
||||||
|
limit -= num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (limit > 0 && --size != 0);
|
||||||
|
*posRes = pos;
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 numProcessed = 0;
|
||||||
|
UInt32 curPos = 2;
|
||||||
|
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
|
||||||
|
distances[1] = p->hashNumAvail;
|
||||||
|
while (curPos < limit)
|
||||||
|
{
|
||||||
|
if (p->hashBufPos == p->hashBufPosLimit)
|
||||||
|
{
|
||||||
|
MatchFinderMt_GetNextBlock_Hash(p);
|
||||||
|
distances[1] = numProcessed + p->hashNumAvail;
|
||||||
|
if (p->hashNumAvail >= p->numHashBytes)
|
||||||
|
continue;
|
||||||
|
for (; p->hashNumAvail != 0; p->hashNumAvail--)
|
||||||
|
distances[curPos++] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
UInt32 size = p->hashBufPosLimit - p->hashBufPos;
|
||||||
|
UInt32 lenLimit = p->matchMaxLen;
|
||||||
|
UInt32 pos = p->pos;
|
||||||
|
UInt32 cyclicBufferPos = p->cyclicBufferPos;
|
||||||
|
if (lenLimit >= p->hashNumAvail)
|
||||||
|
lenLimit = p->hashNumAvail;
|
||||||
|
{
|
||||||
|
UInt32 size2 = p->hashNumAvail - lenLimit + 1;
|
||||||
|
if (size2 < size)
|
||||||
|
size = size2;
|
||||||
|
size2 = p->cyclicBufferSize - cyclicBufferPos;
|
||||||
|
if (size2 < size)
|
||||||
|
size = size2;
|
||||||
|
}
|
||||||
|
#ifndef MFMT_GM_INLINE
|
||||||
|
while (curPos < limit && size-- != 0)
|
||||||
|
{
|
||||||
|
UInt32 *startDistances = distances + curPos;
|
||||||
|
UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
|
||||||
|
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||||
|
startDistances + 1, p->numHashBytes - 1) - startDistances);
|
||||||
|
*startDistances = num - 1;
|
||||||
|
curPos += num;
|
||||||
|
cyclicBufferPos++;
|
||||||
|
pos++;
|
||||||
|
p->buffer++;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
UInt32 posRes;
|
||||||
|
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
||||||
|
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
|
||||||
|
p->hashBufPos += posRes - pos;
|
||||||
|
cyclicBufferPos += posRes - pos;
|
||||||
|
p->buffer += posRes - pos;
|
||||||
|
pos = posRes;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
numProcessed += pos - p->pos;
|
||||||
|
p->hashNumAvail -= pos - p->pos;
|
||||||
|
p->pos = pos;
|
||||||
|
if (cyclicBufferPos == p->cyclicBufferSize)
|
||||||
|
cyclicBufferPos = 0;
|
||||||
|
p->cyclicBufferPos = cyclicBufferPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
distances[0] = curPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
||||||
|
{
|
||||||
|
CMtSync *sync = &p->hashSync;
|
||||||
|
if (!sync->needStart)
|
||||||
|
{
|
||||||
|
CriticalSection_Enter(&sync->cs);
|
||||||
|
sync->csWasEntered = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);
|
||||||
|
|
||||||
|
if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
|
||||||
|
{
|
||||||
|
UInt32 subValue = p->pos - p->cyclicBufferSize;
|
||||||
|
MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
|
||||||
|
p->pos -= subValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sync->needStart)
|
||||||
|
{
|
||||||
|
CriticalSection_Leave(&sync->cs);
|
||||||
|
sync->csWasEntered = False;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BtThreadFunc(CMatchFinderMt *mt)
|
||||||
|
{
|
||||||
|
CMtSync *p = &mt->btSync;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UInt32 blockIndex = 0;
|
||||||
|
Event_Wait(&p->canStart);
|
||||||
|
Event_Set(&p->wasStarted);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (p->exit)
|
||||||
|
return;
|
||||||
|
if (p->stopWriting)
|
||||||
|
{
|
||||||
|
p->numProcessedBlocks = blockIndex;
|
||||||
|
MtSync_StopWriting(&mt->hashSync);
|
||||||
|
Event_Set(&p->wasStopped);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Semaphore_Wait(&p->freeSemaphore);
|
||||||
|
BtFillBlock(mt, blockIndex++);
|
||||||
|
Semaphore_Release1(&p->filledSemaphore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinderMt_Construct(CMatchFinderMt *p)
|
||||||
|
{
|
||||||
|
p->hashBuf = 0;
|
||||||
|
MtSync_Construct(&p->hashSync);
|
||||||
|
MtSync_Construct(&p->btSync);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->hashBuf);
|
||||||
|
p->hashBuf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
MtSync_Destruct(&p->hashSync);
|
||||||
|
MtSync_Destruct(&p->btSync);
|
||||||
|
MatchFinderMt_FreeMem(p, alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
|
||||||
|
#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
|
||||||
|
|
||||||
|
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
|
||||||
|
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)
|
||||||
|
{
|
||||||
|
Byte allocaDummy[0x180];
|
||||||
|
allocaDummy[0] = 0;
|
||||||
|
allocaDummy[1] = allocaDummy[0];
|
||||||
|
BtThreadFunc((CMatchFinderMt *)p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
|
||||||
|
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
CMatchFinder *mf = p->MatchFinder;
|
||||||
|
p->historySize = historySize;
|
||||||
|
if (kMtBtBlockSize <= matchMaxLen * 4)
|
||||||
|
return SZ_ERROR_PARAM;
|
||||||
|
if (p->hashBuf == 0)
|
||||||
|
{
|
||||||
|
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
|
||||||
|
if (p->hashBuf == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
p->btBuf = p->hashBuf + kHashBufferSize;
|
||||||
|
}
|
||||||
|
keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
|
||||||
|
keepAddBufferAfter += kMtHashBlockSize;
|
||||||
|
if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
|
||||||
|
RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
|
||||||
|
RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call it after ReleaseStream / SetStream */
|
||||||
|
void MatchFinderMt_Init(CMatchFinderMt *p)
|
||||||
|
{
|
||||||
|
CMatchFinder *mf = p->MatchFinder;
|
||||||
|
p->btBufPos = p->btBufPosLimit = 0;
|
||||||
|
p->hashBufPos = p->hashBufPosLimit = 0;
|
||||||
|
MatchFinder_Init(mf);
|
||||||
|
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
|
||||||
|
p->btNumAvailBytes = 0;
|
||||||
|
p->lzPos = p->historySize + 1;
|
||||||
|
|
||||||
|
p->hash = mf->hash;
|
||||||
|
p->fixedHashSize = mf->fixedHashSize;
|
||||||
|
p->crc = mf->crc;
|
||||||
|
|
||||||
|
p->son = mf->son;
|
||||||
|
p->matchMaxLen = mf->matchMaxLen;
|
||||||
|
p->numHashBytes = mf->numHashBytes;
|
||||||
|
p->pos = mf->pos;
|
||||||
|
p->buffer = mf->buffer;
|
||||||
|
p->cyclicBufferPos = mf->cyclicBufferPos;
|
||||||
|
p->cyclicBufferSize = mf->cyclicBufferSize;
|
||||||
|
p->cutValue = mf->cutValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ReleaseStream is required to finish multithreading */
|
||||||
|
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
|
||||||
|
{
|
||||||
|
MtSync_StopWriting(&p->btSync);
|
||||||
|
/* p->MatchFinder->ReleaseStream(); */
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinderMt_Normalize(CMatchFinderMt *p)
|
||||||
|
{
|
||||||
|
MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
|
||||||
|
p->lzPos = p->historySize + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
||||||
|
{
|
||||||
|
UInt32 blockIndex;
|
||||||
|
MtSync_GetNextBlock(&p->btSync);
|
||||||
|
blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);
|
||||||
|
p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
|
||||||
|
p->btBufPosLimit += p->btBuf[p->btBufPos++];
|
||||||
|
p->btNumAvailBytes = p->btBuf[p->btBufPos++];
|
||||||
|
if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
|
||||||
|
MatchFinderMt_Normalize(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
|
||||||
|
{
|
||||||
|
return p->pointerToCurPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
|
||||||
|
|
||||||
|
UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
|
||||||
|
{
|
||||||
|
GET_NEXT_BLOCK_IF_REQUIRED;
|
||||||
|
return p->btNumAvailBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
|
||||||
|
{
|
||||||
|
return p->pointerToCurPos[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 hash2Value, curMatch2;
|
||||||
|
UInt32 *hash = p->hash;
|
||||||
|
const Byte *cur = p->pointerToCurPos;
|
||||||
|
UInt32 lzPos = p->lzPos;
|
||||||
|
MT_HASH2_CALC
|
||||||
|
|
||||||
|
curMatch2 = hash[hash2Value];
|
||||||
|
hash[hash2Value] = lzPos;
|
||||||
|
|
||||||
|
if (curMatch2 >= matchMinPos)
|
||||||
|
if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||||
|
{
|
||||||
|
*distances++ = 2;
|
||||||
|
*distances++ = lzPos - curMatch2 - 1;
|
||||||
|
}
|
||||||
|
return distances;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
|
||||||
|
UInt32 *hash = p->hash;
|
||||||
|
const Byte *cur = p->pointerToCurPos;
|
||||||
|
UInt32 lzPos = p->lzPos;
|
||||||
|
MT_HASH3_CALC
|
||||||
|
|
||||||
|
curMatch2 = hash[ hash2Value];
|
||||||
|
curMatch3 = hash[kFix3HashSize + hash3Value];
|
||||||
|
|
||||||
|
hash[ hash2Value] =
|
||||||
|
hash[kFix3HashSize + hash3Value] =
|
||||||
|
lzPos;
|
||||||
|
|
||||||
|
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||||
|
{
|
||||||
|
distances[1] = lzPos - curMatch2 - 1;
|
||||||
|
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
|
||||||
|
{
|
||||||
|
distances[0] = 3;
|
||||||
|
return distances + 2;
|
||||||
|
}
|
||||||
|
distances[0] = 2;
|
||||||
|
distances += 2;
|
||||||
|
}
|
||||||
|
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
||||||
|
{
|
||||||
|
*distances++ = 3;
|
||||||
|
*distances++ = lzPos - curMatch3 - 1;
|
||||||
|
}
|
||||||
|
return distances;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
||||||
|
{
|
||||||
|
UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
|
||||||
|
UInt32 *hash = p->hash;
|
||||||
|
const Byte *cur = p->pointerToCurPos;
|
||||||
|
UInt32 lzPos = p->lzPos;
|
||||||
|
MT_HASH4_CALC
|
||||||
|
|
||||||
|
curMatch2 = hash[ hash2Value];
|
||||||
|
curMatch3 = hash[kFix3HashSize + hash3Value];
|
||||||
|
curMatch4 = hash[kFix4HashSize + hash4Value];
|
||||||
|
|
||||||
|
hash[ hash2Value] =
|
||||||
|
hash[kFix3HashSize + hash3Value] =
|
||||||
|
hash[kFix4HashSize + hash4Value] =
|
||||||
|
lzPos;
|
||||||
|
|
||||||
|
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
||||||
|
{
|
||||||
|
distances[1] = lzPos - curMatch2 - 1;
|
||||||
|
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
|
||||||
|
{
|
||||||
|
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
|
||||||
|
return distances + 2;
|
||||||
|
}
|
||||||
|
distances[0] = 2;
|
||||||
|
distances += 2;
|
||||||
|
}
|
||||||
|
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
||||||
|
{
|
||||||
|
distances[1] = lzPos - curMatch3 - 1;
|
||||||
|
if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
|
||||||
|
{
|
||||||
|
distances[0] = 4;
|
||||||
|
return distances + 2;
|
||||||
|
}
|
||||||
|
distances[0] = 3;
|
||||||
|
distances += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curMatch4 >= matchMinPos)
|
||||||
|
if (
|
||||||
|
cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
|
||||||
|
cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
*distances++ = 4;
|
||||||
|
*distances++ = lzPos - curMatch4 - 1;
|
||||||
|
}
|
||||||
|
return distances;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
|
||||||
|
|
||||||
|
UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||||
|
{
|
||||||
|
const UInt32 *btBuf = p->btBuf + p->btBufPos;
|
||||||
|
UInt32 len = *btBuf++;
|
||||||
|
p->btBufPos += 1 + len;
|
||||||
|
p->btNumAvailBytes--;
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
for (i = 0; i < len; i += 2)
|
||||||
|
{
|
||||||
|
*distances++ = *btBuf++;
|
||||||
|
*distances++ = *btBuf++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INCREASE_LZ_POS
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
||||||
|
{
|
||||||
|
const UInt32 *btBuf = p->btBuf + p->btBufPos;
|
||||||
|
UInt32 len = *btBuf++;
|
||||||
|
p->btBufPos += 1 + len;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
if (p->btNumAvailBytes-- >= 4)
|
||||||
|
len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Condition: there are matches in btBuf with length < p->numHashBytes */
|
||||||
|
UInt32 *distances2;
|
||||||
|
p->btNumAvailBytes--;
|
||||||
|
distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*distances2++ = *btBuf++;
|
||||||
|
*distances2++ = *btBuf++;
|
||||||
|
}
|
||||||
|
while ((len -= 2) != 0);
|
||||||
|
len = (UInt32)(distances2 - (distances));
|
||||||
|
}
|
||||||
|
INCREASE_LZ_POS
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED
|
||||||
|
#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
|
||||||
|
#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
|
||||||
|
|
||||||
|
void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
|
||||||
|
{
|
||||||
|
SKIP_HEADER2_MT { p->btNumAvailBytes--;
|
||||||
|
SKIP_FOOTER_MT
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
|
||||||
|
{
|
||||||
|
SKIP_HEADER_MT(2)
|
||||||
|
UInt32 hash2Value;
|
||||||
|
MT_HASH2_CALC
|
||||||
|
hash[hash2Value] = p->lzPos;
|
||||||
|
SKIP_FOOTER_MT
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
|
||||||
|
{
|
||||||
|
SKIP_HEADER_MT(3)
|
||||||
|
UInt32 hash2Value, hash3Value;
|
||||||
|
MT_HASH3_CALC
|
||||||
|
hash[kFix3HashSize + hash3Value] =
|
||||||
|
hash[ hash2Value] =
|
||||||
|
p->lzPos;
|
||||||
|
SKIP_FOOTER_MT
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
|
||||||
|
{
|
||||||
|
SKIP_HEADER_MT(4)
|
||||||
|
UInt32 hash2Value, hash3Value, hash4Value;
|
||||||
|
MT_HASH4_CALC
|
||||||
|
hash[kFix4HashSize + hash4Value] =
|
||||||
|
hash[kFix3HashSize + hash3Value] =
|
||||||
|
hash[ hash2Value] =
|
||||||
|
p->lzPos;
|
||||||
|
SKIP_FOOTER_MT
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
|
||||||
|
{
|
||||||
|
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
|
||||||
|
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
|
||||||
|
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
|
||||||
|
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
|
||||||
|
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
|
||||||
|
switch(p->MatchFinder->numHashBytes)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
p->GetHeadsFunc = GetHeads2;
|
||||||
|
p->MixMatchesFunc = (Mf_Mix_Matches)0;
|
||||||
|
vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
|
||||||
|
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
p->GetHeadsFunc = GetHeads3;
|
||||||
|
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;
|
||||||
|
vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* case 4: */
|
||||||
|
p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
|
||||||
|
/* p->GetHeadsFunc = GetHeads4; */
|
||||||
|
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
|
||||||
|
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
default:
|
||||||
|
p->GetHeadsFunc = GetHeads5;
|
||||||
|
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
|
||||||
|
vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZ_FIND_MT_H
|
||||||
|
#define __LZ_FIND_MT_H
|
||||||
|
|
||||||
|
#include "LzFind.h"
|
||||||
|
#include "Threads.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define kMtHashBlockSize (1 << 13)
|
||||||
|
#define kMtHashNumBlocks (1 << 3)
|
||||||
|
#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)
|
||||||
|
|
||||||
|
#define kMtBtBlockSize (1 << 14)
|
||||||
|
#define kMtBtNumBlocks (1 << 6)
|
||||||
|
#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)
|
||||||
|
|
||||||
|
typedef struct _CMtSync
|
||||||
|
{
|
||||||
|
Bool wasCreated;
|
||||||
|
Bool needStart;
|
||||||
|
Bool exit;
|
||||||
|
Bool stopWriting;
|
||||||
|
|
||||||
|
CThread thread;
|
||||||
|
CAutoResetEvent canStart;
|
||||||
|
CAutoResetEvent wasStarted;
|
||||||
|
CAutoResetEvent wasStopped;
|
||||||
|
CSemaphore freeSemaphore;
|
||||||
|
CSemaphore filledSemaphore;
|
||||||
|
Bool csWasInitialized;
|
||||||
|
Bool csWasEntered;
|
||||||
|
CCriticalSection cs;
|
||||||
|
UInt32 numProcessedBlocks;
|
||||||
|
} CMtSync;
|
||||||
|
|
||||||
|
typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
|
||||||
|
|
||||||
|
/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
|
||||||
|
#define kMtCacheLineDummy 128
|
||||||
|
|
||||||
|
typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
|
||||||
|
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
|
||||||
|
|
||||||
|
typedef struct _CMatchFinderMt
|
||||||
|
{
|
||||||
|
/* LZ */
|
||||||
|
const Byte *pointerToCurPos;
|
||||||
|
UInt32 *btBuf;
|
||||||
|
UInt32 btBufPos;
|
||||||
|
UInt32 btBufPosLimit;
|
||||||
|
UInt32 lzPos;
|
||||||
|
UInt32 btNumAvailBytes;
|
||||||
|
|
||||||
|
UInt32 *hash;
|
||||||
|
UInt32 fixedHashSize;
|
||||||
|
UInt32 historySize;
|
||||||
|
const UInt32 *crc;
|
||||||
|
|
||||||
|
Mf_Mix_Matches MixMatchesFunc;
|
||||||
|
|
||||||
|
/* LZ + BT */
|
||||||
|
CMtSync btSync;
|
||||||
|
Byte btDummy[kMtCacheLineDummy];
|
||||||
|
|
||||||
|
/* BT */
|
||||||
|
UInt32 *hashBuf;
|
||||||
|
UInt32 hashBufPos;
|
||||||
|
UInt32 hashBufPosLimit;
|
||||||
|
UInt32 hashNumAvail;
|
||||||
|
|
||||||
|
CLzRef *son;
|
||||||
|
UInt32 matchMaxLen;
|
||||||
|
UInt32 numHashBytes;
|
||||||
|
UInt32 pos;
|
||||||
|
Byte *buffer;
|
||||||
|
UInt32 cyclicBufferPos;
|
||||||
|
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
|
||||||
|
UInt32 cutValue;
|
||||||
|
|
||||||
|
/* BT + Hash */
|
||||||
|
CMtSync hashSync;
|
||||||
|
/* Byte hashDummy[kMtCacheLineDummy]; */
|
||||||
|
|
||||||
|
/* Hash */
|
||||||
|
Mf_GetHeads GetHeadsFunc;
|
||||||
|
CMatchFinder *MatchFinder;
|
||||||
|
} CMatchFinderMt;
|
||||||
|
|
||||||
|
void MatchFinderMt_Construct(CMatchFinderMt *p);
|
||||||
|
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
|
||||||
|
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
|
||||||
|
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);
|
||||||
|
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
|
||||||
|
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,54 @@
|
||||||
|
/* LzHash.h -- HASH functions for LZ algorithms
|
||||||
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZ_HASH_H
|
||||||
|
#define __LZ_HASH_H
|
||||||
|
|
||||||
|
#define kHash2Size (1 << 10)
|
||||||
|
#define kHash3Size (1 << 16)
|
||||||
|
#define kHash4Size (1 << 20)
|
||||||
|
|
||||||
|
#define kFix3HashSize (kHash2Size)
|
||||||
|
#define kFix4HashSize (kHash2Size + kHash3Size)
|
||||||
|
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||||
|
|
||||||
|
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
|
||||||
|
|
||||||
|
#define HASH3_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
hash2Value = temp & (kHash2Size - 1); \
|
||||||
|
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||||
|
|
||||||
|
#define HASH4_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
hash2Value = temp & (kHash2Size - 1); \
|
||||||
|
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||||
|
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
|
||||||
|
|
||||||
|
#define HASH5_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
hash2Value = temp & (kHash2Size - 1); \
|
||||||
|
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||||
|
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
|
||||||
|
hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
|
||||||
|
hash4Value &= (kHash4Size - 1); }
|
||||||
|
|
||||||
|
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||||
|
#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||||
|
|
||||||
|
|
||||||
|
#define MT_HASH2_CALC \
|
||||||
|
hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||||
|
|
||||||
|
#define MT_HASH3_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
hash2Value = temp & (kHash2Size - 1); \
|
||||||
|
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||||
|
|
||||||
|
#define MT_HASH4_CALC { \
|
||||||
|
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||||
|
hash2Value = temp & (kHash2Size - 1); \
|
||||||
|
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
||||||
|
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,352 @@
|
||||||
|
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||||
|
2010-12-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
/* #define SHOW_DEBUG_INFO */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#ifdef SHOW_DEBUG_INFO
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
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_LCLP_MAX 4
|
||||||
|
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||||
|
|
||||||
|
#ifdef SHOW_DEBUG_INFO
|
||||||
|
#define PRF(x) x
|
||||||
|
#else
|
||||||
|
#define PRF(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
LZMA2_STATE_CONTROL,
|
||||||
|
LZMA2_STATE_UNPACK0,
|
||||||
|
LZMA2_STATE_UNPACK1,
|
||||||
|
LZMA2_STATE_PACK0,
|
||||||
|
LZMA2_STATE_PACK1,
|
||||||
|
LZMA2_STATE_PROP,
|
||||||
|
LZMA2_STATE_DATA,
|
||||||
|
LZMA2_STATE_DATA_CONT,
|
||||||
|
LZMA2_STATE_FINISHED,
|
||||||
|
LZMA2_STATE_ERROR
|
||||||
|
} ELzma2State;
|
||||||
|
|
||||||
|
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
|
||||||
|
{
|
||||||
|
UInt32 dicSize;
|
||||||
|
if (prop > 40)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||||
|
props[0] = (Byte)LZMA2_LCLP_MAX;
|
||||||
|
props[1] = (Byte)(dicSize);
|
||||||
|
props[2] = (Byte)(dicSize >> 8);
|
||||||
|
props[3] = (Byte)(dicSize >> 16);
|
||||||
|
props[4] = (Byte)(dicSize >> 24);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
|
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
|
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lzma2Dec_Init(CLzma2Dec *p)
|
||||||
|
{
|
||||||
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
|
p->needInitDic = True;
|
||||||
|
p->needInitState = True;
|
||||||
|
p->needInitProp = True;
|
||||||
|
LzmaDec_Init(&p->decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||||
|
{
|
||||||
|
switch(p->state)
|
||||||
|
{
|
||||||
|
case LZMA2_STATE_CONTROL:
|
||||||
|
p->control = b;
|
||||||
|
PRF(printf("\n %4X ", p->decoder.dicPos));
|
||||||
|
PRF(printf(" %2X", b));
|
||||||
|
if (p->control == 0)
|
||||||
|
return LZMA2_STATE_FINISHED;
|
||||||
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
|
{
|
||||||
|
if ((p->control & 0x7F) > 2)
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
p->unpackSize = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
|
||||||
|
return LZMA2_STATE_UNPACK0;
|
||||||
|
|
||||||
|
case LZMA2_STATE_UNPACK0:
|
||||||
|
p->unpackSize |= (UInt32)b << 8;
|
||||||
|
return LZMA2_STATE_UNPACK1;
|
||||||
|
|
||||||
|
case LZMA2_STATE_UNPACK1:
|
||||||
|
p->unpackSize |= (UInt32)b;
|
||||||
|
p->unpackSize++;
|
||||||
|
PRF(printf(" %8d", p->unpackSize));
|
||||||
|
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||||
|
|
||||||
|
case LZMA2_STATE_PACK0:
|
||||||
|
p->packSize = (UInt32)b << 8;
|
||||||
|
return LZMA2_STATE_PACK1;
|
||||||
|
|
||||||
|
case LZMA2_STATE_PACK1:
|
||||||
|
p->packSize |= (UInt32)b;
|
||||||
|
p->packSize++;
|
||||||
|
PRF(printf(" %8d", p->packSize));
|
||||||
|
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
|
||||||
|
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
||||||
|
|
||||||
|
case LZMA2_STATE_PROP:
|
||||||
|
{
|
||||||
|
int lc, lp;
|
||||||
|
if (b >= (9 * 5 * 5))
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
lc = b % 9;
|
||||||
|
b /= 9;
|
||||||
|
p->decoder.prop.pb = 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;
|
||||||
|
return LZMA2_STATE_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
|
||||||
|
{
|
||||||
|
memcpy(p->dic + p->dicPos, src, size);
|
||||||
|
p->dicPos += 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);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||||
|
{
|
||||||
|
SizeT inSize = *srcLen;
|
||||||
|
*srcLen = 0;
|
||||||
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
|
||||||
|
while (p->state != LZMA2_STATE_FINISHED)
|
||||||
|
{
|
||||||
|
SizeT dicPos = p->decoder.dicPos;
|
||||||
|
if (p->state == LZMA2_STATE_ERROR)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||||
|
{
|
||||||
|
*status = LZMA_STATUS_NOT_FINISHED;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||||
|
{
|
||||||
|
if (*srcLen == inSize)
|
||||||
|
{
|
||||||
|
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
(*srcLen)++;
|
||||||
|
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
SizeT destSizeCur = dicLimit - dicPos;
|
||||||
|
SizeT srcSizeCur = inSize - *srcLen;
|
||||||
|
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||||
|
|
||||||
|
if (p->unpackSize <= destSizeCur)
|
||||||
|
{
|
||||||
|
destSizeCur = (SizeT)p->unpackSize;
|
||||||
|
curFinishMode = LZMA_FINISH_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
|
{
|
||||||
|
if (*srcLen == inSize)
|
||||||
|
{
|
||||||
|
*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 (initDic)
|
||||||
|
p->needInitProp = p->needInitState = True;
|
||||||
|
else if (p->needInitDic)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
p->needInitDic = False;
|
||||||
|
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcSizeCur > destSizeCur)
|
||||||
|
srcSizeCur = destSizeCur;
|
||||||
|
|
||||||
|
if (srcSizeCur == 0)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
|
||||||
|
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
|
||||||
|
|
||||||
|
src += srcSizeCur;
|
||||||
|
*srcLen += srcSizeCur;
|
||||||
|
p->unpackSize -= (UInt32)srcSizeCur;
|
||||||
|
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SizeT outSizeProcessed;
|
||||||
|
SRes res;
|
||||||
|
|
||||||
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
|
{
|
||||||
|
int mode = LZMA2_GET_LZMA_MODE(p);
|
||||||
|
Bool initDic = (mode == 3);
|
||||||
|
Bool initState = (mode > 0);
|
||||||
|
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
|
||||||
|
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||||
|
p->needInitDic = False;
|
||||||
|
p->needInitState = False;
|
||||||
|
p->state = LZMA2_STATE_DATA_CONT;
|
||||||
|
}
|
||||||
|
if (srcSizeCur > p->packSize)
|
||||||
|
srcSizeCur = (SizeT)p->packSize;
|
||||||
|
|
||||||
|
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||||
|
|
||||||
|
src += srcSizeCur;
|
||||||
|
*srcLen += srcSizeCur;
|
||||||
|
p->packSize -= (UInt32)srcSizeCur;
|
||||||
|
|
||||||
|
outSizeProcessed = p->decoder.dicPos - dicPos;
|
||||||
|
p->unpackSize -= (UInt32)outSizeProcessed;
|
||||||
|
|
||||||
|
RINOK(res);
|
||||||
|
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (srcSizeCur == 0 && outSizeProcessed == 0)
|
||||||
|
{
|
||||||
|
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
|
||||||
|
p->unpackSize != 0 || p->packSize != 0)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
|
}
|
||||||
|
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||||
|
*status = LZMA_STATUS_NOT_FINISHED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 srcSizeCur = inSize, outSizeCur, dicPos;
|
||||||
|
ELzmaFinishMode curFinishMode;
|
||||||
|
SRes res;
|
||||||
|
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||||
|
p->decoder.dicPos = 0;
|
||||||
|
dicPos = p->decoder.dicPos;
|
||||||
|
if (outSize > p->decoder.dicBufSize - dicPos)
|
||||||
|
{
|
||||||
|
outSizeCur = p->decoder.dicBufSize;
|
||||||
|
curFinishMode = LZMA_FINISH_ANY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outSizeCur = dicPos + outSize;
|
||||||
|
curFinishMode = finishMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||||
|
src += srcSizeCur;
|
||||||
|
inSize -= srcSizeCur;
|
||||||
|
*srcLen += srcSizeCur;
|
||||||
|
outSizeCur = p->decoder.dicPos - dicPos;
|
||||||
|
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
|
||||||
|
dest += outSizeCur;
|
||||||
|
outSize -= outSizeCur;
|
||||||
|
*destLen += outSizeCur;
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
if (outSizeCur == 0 || outSize == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *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;
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA2_DEC_H
|
||||||
|
#define __LZMA2_DEC_H
|
||||||
|
|
||||||
|
#include "LzmaDec.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
/* ---------- State Interface ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaDec decoder;
|
||||||
|
UInt32 packSize;
|
||||||
|
UInt32 unpackSize;
|
||||||
|
int state;
|
||||||
|
Byte control;
|
||||||
|
Bool needInitDic;
|
||||||
|
Bool needInitState;
|
||||||
|
Bool needInitProp;
|
||||||
|
} 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);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
||||||
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
||||||
|
void Lzma2Dec_Init(CLzma2Dec *p);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
finishMode:
|
||||||
|
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
|
||||||
|
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
|
||||||
|
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||||
|
SZ_ERROR_DATA - Data error
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- 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, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,493 @@
|
||||||
|
/* Lzma2Enc.c -- LZMA2 Encoder
|
||||||
|
2012-06-19 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
/* #include <stdio.h> */
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* #define _7ZIP_ST */
|
||||||
|
|
||||||
|
#include "Lzma2Enc.h"
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
#include "MtCoder.h"
|
||||||
|
#else
|
||||||
|
#define NUM_MT_CODER_THREADS_MAX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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_LCLP_MAX 4
|
||||||
|
|
||||||
|
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||||
|
|
||||||
|
#define LZMA2_PACK_SIZE_MAX (1 << 16)
|
||||||
|
#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX
|
||||||
|
#define LZMA2_UNPACK_SIZE_MAX (1 << 21)
|
||||||
|
#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX
|
||||||
|
|
||||||
|
#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)
|
||||||
|
|
||||||
|
|
||||||
|
#define PRF(x) /* x */
|
||||||
|
|
||||||
|
/* ---------- CLzma2EncInt ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaEncHandle enc;
|
||||||
|
UInt64 srcPos;
|
||||||
|
Byte props;
|
||||||
|
Bool needInitState;
|
||||||
|
Bool needInitProp;
|
||||||
|
} CLzma2EncInt;
|
||||||
|
|
||||||
|
static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)
|
||||||
|
{
|
||||||
|
Byte propsEncoded[LZMA_PROPS_SIZE];
|
||||||
|
SizeT propsSize = LZMA_PROPS_SIZE;
|
||||||
|
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
|
||||||
|
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
|
||||||
|
p->srcPos = 0;
|
||||||
|
p->props = propsEncoded[0];
|
||||||
|
p->needInitState = True;
|
||||||
|
p->needInitProp = True;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
|
||||||
|
ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
||||||
|
UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
|
||||||
|
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
|
||||||
|
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
|
||||||
|
void LzmaEnc_Finish(CLzmaEncHandle pp);
|
||||||
|
void LzmaEnc_SaveState(CLzmaEncHandle pp);
|
||||||
|
void LzmaEnc_RestoreState(CLzmaEncHandle pp);
|
||||||
|
|
||||||
|
|
||||||
|
static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
|
||||||
|
size_t *packSizeRes, ISeqOutStream *outStream)
|
||||||
|
{
|
||||||
|
size_t packSizeLimit = *packSizeRes;
|
||||||
|
size_t packSize = packSizeLimit;
|
||||||
|
UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
|
||||||
|
unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
|
||||||
|
Bool useCopyBlock;
|
||||||
|
SRes res;
|
||||||
|
|
||||||
|
*packSizeRes = 0;
|
||||||
|
if (packSize < lzHeaderSize)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
packSize -= lzHeaderSize;
|
||||||
|
|
||||||
|
LzmaEnc_SaveState(p->enc);
|
||||||
|
res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,
|
||||||
|
outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);
|
||||||
|
|
||||||
|
PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize));
|
||||||
|
|
||||||
|
if (unpackSize == 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (res != SZ_ERROR_OUTPUT_EOF)
|
||||||
|
return res;
|
||||||
|
res = SZ_OK;
|
||||||
|
useCopyBlock = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useCopyBlock)
|
||||||
|
{
|
||||||
|
size_t destPos = 0;
|
||||||
|
PRF(printf("################# COPY "));
|
||||||
|
while (unpackSize > 0)
|
||||||
|
{
|
||||||
|
UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
|
||||||
|
if (packSizeLimit - destPos < u + 3)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
|
||||||
|
outBuf[destPos++] = (Byte)((u - 1) >> 8);
|
||||||
|
outBuf[destPos++] = (Byte)(u - 1);
|
||||||
|
memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);
|
||||||
|
unpackSize -= u;
|
||||||
|
destPos += u;
|
||||||
|
p->srcPos += u;
|
||||||
|
if (outStream)
|
||||||
|
{
|
||||||
|
*packSizeRes += destPos;
|
||||||
|
if (outStream->Write(outStream, outBuf, destPos) != destPos)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
destPos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*packSizeRes = destPos;
|
||||||
|
/* needInitState = True; */
|
||||||
|
}
|
||||||
|
LzmaEnc_RestoreState(p->enc);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
size_t destPos = 0;
|
||||||
|
UInt32 u = unpackSize - 1;
|
||||||
|
UInt32 pm = (UInt32)(packSize - 1);
|
||||||
|
unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
|
||||||
|
|
||||||
|
PRF(printf(" "));
|
||||||
|
|
||||||
|
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
|
||||||
|
outBuf[destPos++] = (Byte)(u >> 8);
|
||||||
|
outBuf[destPos++] = (Byte)u;
|
||||||
|
outBuf[destPos++] = (Byte)(pm >> 8);
|
||||||
|
outBuf[destPos++] = (Byte)pm;
|
||||||
|
|
||||||
|
if (p->needInitProp)
|
||||||
|
outBuf[destPos++] = p->props;
|
||||||
|
|
||||||
|
p->needInitProp = False;
|
||||||
|
p->needInitState = False;
|
||||||
|
destPos += packSize;
|
||||||
|
p->srcPos += unpackSize;
|
||||||
|
|
||||||
|
if (outStream)
|
||||||
|
if (outStream->Write(outStream, outBuf, destPos) != destPos)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
*packSizeRes = destPos;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Lzma2 Props ---------- */
|
||||||
|
|
||||||
|
void Lzma2EncProps_Init(CLzma2EncProps *p)
|
||||||
|
{
|
||||||
|
LzmaEncProps_Init(&p->lzmaProps);
|
||||||
|
p->numTotalThreads = -1;
|
||||||
|
p->numBlockThreads = -1;
|
||||||
|
p->blockSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
|
||||||
|
{
|
||||||
|
int t1, t1n, t2, t3;
|
||||||
|
{
|
||||||
|
CLzmaEncProps lzmaProps = p->lzmaProps;
|
||||||
|
LzmaEncProps_Normalize(&lzmaProps);
|
||||||
|
t1n = lzmaProps.numThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
t1 = p->lzmaProps.numThreads;
|
||||||
|
t2 = p->numBlockThreads;
|
||||||
|
t3 = p->numTotalThreads;
|
||||||
|
|
||||||
|
if (t2 > NUM_MT_CODER_THREADS_MAX)
|
||||||
|
t2 = NUM_MT_CODER_THREADS_MAX;
|
||||||
|
|
||||||
|
if (t3 <= 0)
|
||||||
|
{
|
||||||
|
if (t2 <= 0)
|
||||||
|
t2 = 1;
|
||||||
|
t3 = t1n * t2;
|
||||||
|
}
|
||||||
|
else if (t2 <= 0)
|
||||||
|
{
|
||||||
|
t2 = t3 / t1n;
|
||||||
|
if (t2 == 0)
|
||||||
|
{
|
||||||
|
t1 = 1;
|
||||||
|
t2 = t3;
|
||||||
|
}
|
||||||
|
if (t2 > NUM_MT_CODER_THREADS_MAX)
|
||||||
|
t2 = NUM_MT_CODER_THREADS_MAX;
|
||||||
|
}
|
||||||
|
else if (t1 <= 0)
|
||||||
|
{
|
||||||
|
t1 = t3 / t2;
|
||||||
|
if (t1 == 0)
|
||||||
|
t1 = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
t3 = t1n * t2;
|
||||||
|
|
||||||
|
p->lzmaProps.numThreads = t1;
|
||||||
|
|
||||||
|
LzmaEncProps_Normalize(&p->lzmaProps);
|
||||||
|
|
||||||
|
if (p->blockSize == 0)
|
||||||
|
{
|
||||||
|
UInt32 dictSize = p->lzmaProps.dictSize;
|
||||||
|
UInt64 blockSize = (UInt64)dictSize << 2;
|
||||||
|
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||||
|
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||||
|
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||||
|
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||||
|
if (blockSize < dictSize) blockSize = dictSize;
|
||||||
|
p->blockSize = (size_t)blockSize;
|
||||||
|
}
|
||||||
|
if (t2 > 1)
|
||||||
|
{
|
||||||
|
UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1;
|
||||||
|
if (temp > p->lzmaProps.reduceSize)
|
||||||
|
{
|
||||||
|
UInt64 numBlocks = temp / p->blockSize;
|
||||||
|
if (numBlocks < t2)
|
||||||
|
{
|
||||||
|
t2 = (UInt32)numBlocks;
|
||||||
|
t3 = t1 * t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->numBlockThreads = t2;
|
||||||
|
p->numTotalThreads = t3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
|
||||||
|
{
|
||||||
|
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Lzma2 ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte propEncoded;
|
||||||
|
CLzma2EncProps props;
|
||||||
|
|
||||||
|
Byte *outBuf;
|
||||||
|
|
||||||
|
ISzAlloc *alloc;
|
||||||
|
ISzAlloc *allocBig;
|
||||||
|
|
||||||
|
CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
CMtCoder mtCoder;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} CLzma2Enc;
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Lzma2EncThread ---------- */
|
||||||
|
|
||||||
|
static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
|
||||||
|
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
UInt64 packTotal = 0;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
if (mainEncoder->outBuf == 0)
|
||||||
|
{
|
||||||
|
mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
|
||||||
|
if (mainEncoder->outBuf == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
}
|
||||||
|
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
|
||||||
|
RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
|
||||||
|
mainEncoder->alloc, mainEncoder->allocBig));
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
|
||||||
|
res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
packTotal += packSize;
|
||||||
|
res = Progress(progress, p->srcPos, packTotal);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (packSize == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LzmaEnc_Finish(p->enc);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
Byte b = 0;
|
||||||
|
if (outStream->Write(outStream, &b, 1) != 1)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
IMtCoderCallback funcTable;
|
||||||
|
CLzma2Enc *lzma2Enc;
|
||||||
|
} CMtCallbackImp;
|
||||||
|
|
||||||
|
static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,
|
||||||
|
const Byte *src, size_t srcSize, int finished)
|
||||||
|
{
|
||||||
|
CMtCallbackImp *imp = (CMtCallbackImp *)pp;
|
||||||
|
CLzma2Enc *mainEncoder = imp->lzma2Enc;
|
||||||
|
CLzma2EncInt *p = &mainEncoder->coders[index];
|
||||||
|
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
{
|
||||||
|
size_t destLim = *destSize;
|
||||||
|
*destSize = 0;
|
||||||
|
|
||||||
|
if (srcSize != 0)
|
||||||
|
{
|
||||||
|
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
|
||||||
|
|
||||||
|
RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,
|
||||||
|
mainEncoder->alloc, mainEncoder->allocBig));
|
||||||
|
|
||||||
|
while (p->srcPos < srcSize)
|
||||||
|
{
|
||||||
|
size_t packSize = destLim - *destSize;
|
||||||
|
res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
*destSize += packSize;
|
||||||
|
|
||||||
|
if (packSize == 0)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_PROGRESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LzmaEnc_Finish(p->enc);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (finished)
|
||||||
|
{
|
||||||
|
if (*destSize == destLim)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
dest[(*destSize)++] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------- Lzma2Enc ---------- */
|
||||||
|
|
||||||
|
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
|
||||||
|
if (p == 0)
|
||||||
|
return NULL;
|
||||||
|
Lzma2EncProps_Init(&p->props);
|
||||||
|
Lzma2EncProps_Normalize(&p->props);
|
||||||
|
p->outBuf = 0;
|
||||||
|
p->alloc = alloc;
|
||||||
|
p->allocBig = allocBig;
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
p->coders[i].enc = 0;
|
||||||
|
}
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
MtCoder_Construct(&p->mtCoder);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
{
|
||||||
|
CLzma2EncInt *t = &p->coders[i];
|
||||||
|
if (t->enc)
|
||||||
|
{
|
||||||
|
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
|
||||||
|
t->enc = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
MtCoder_Destruct(&p->mtCoder);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IAlloc_Free(p->alloc, p->outBuf);
|
||||||
|
IAlloc_Free(p->alloc, pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
CLzmaEncProps lzmaProps = props->lzmaProps;
|
||||||
|
LzmaEncProps_Normalize(&lzmaProps);
|
||||||
|
if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
|
||||||
|
return SZ_ERROR_PARAM;
|
||||||
|
p->props = *props;
|
||||||
|
Lzma2EncProps_Normalize(&p->props);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
unsigned i;
|
||||||
|
UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
|
||||||
|
for (i = 0; i < 40; i++)
|
||||||
|
if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
|
||||||
|
break;
|
||||||
|
return (Byte)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
|
||||||
|
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < p->props.numBlockThreads; i++)
|
||||||
|
{
|
||||||
|
CLzma2EncInt *t = &p->coders[i];
|
||||||
|
if (t->enc == NULL)
|
||||||
|
{
|
||||||
|
t->enc = LzmaEnc_Create(p->alloc);
|
||||||
|
if (t->enc == NULL)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
if (p->props.numBlockThreads <= 1)
|
||||||
|
#endif
|
||||||
|
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
|
||||||
|
{
|
||||||
|
CMtCallbackImp mtCallback;
|
||||||
|
|
||||||
|
mtCallback.funcTable.Code = MtCallbackImp_Code;
|
||||||
|
mtCallback.lzma2Enc = p;
|
||||||
|
|
||||||
|
p->mtCoder.progress = progress;
|
||||||
|
p->mtCoder.inStream = inStream;
|
||||||
|
p->mtCoder.outStream = outStream;
|
||||||
|
p->mtCoder.alloc = p->alloc;
|
||||||
|
p->mtCoder.mtCallback = &mtCallback.funcTable;
|
||||||
|
|
||||||
|
p->mtCoder.blockSize = p->props.blockSize;
|
||||||
|
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
|
||||||
|
p->mtCoder.numThreads = p->props.numBlockThreads;
|
||||||
|
|
||||||
|
return MtCoder_Code(&p->mtCoder);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* Lzma2Enc.h -- LZMA2 Encoder
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA2_ENC_H
|
||||||
|
#define __LZMA2_ENC_H
|
||||||
|
|
||||||
|
#include "LzmaEnc.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaEncProps lzmaProps;
|
||||||
|
size_t blockSize;
|
||||||
|
int numBlockThreads;
|
||||||
|
int numTotalThreads;
|
||||||
|
} CLzma2EncProps;
|
||||||
|
|
||||||
|
void Lzma2EncProps_Init(CLzma2EncProps *p);
|
||||||
|
void Lzma2EncProps_Normalize(CLzma2EncProps *p);
|
||||||
|
|
||||||
|
/* ---------- CLzmaEnc2Handle Interface ---------- */
|
||||||
|
|
||||||
|
/* Lzma2Enc_* functions can return the following exit codes:
|
||||||
|
Returns:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||||
|
SZ_ERROR_WRITE - Write callback error
|
||||||
|
SZ_ERROR_PROGRESS - some break from progress callback
|
||||||
|
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void * CLzma2EncHandle;
|
||||||
|
|
||||||
|
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
void Lzma2Enc_Destroy(CLzma2EncHandle p);
|
||||||
|
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
|
||||||
|
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
|
||||||
|
SRes Lzma2Enc_Encode(CLzma2EncHandle p,
|
||||||
|
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
|
||||||
|
|
||||||
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
/* Lzma2Encode
|
||||||
|
Return code:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_PARAM - Incorrect paramater
|
||||||
|
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||||
|
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||||
|
const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,
|
||||||
|
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
*/
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* Lzma86.h -- LZMA + x86 (BCJ) Filter
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA86_H
|
||||||
|
#define __LZMA86_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define LZMA86_SIZE_OFFSET (1 + 5)
|
||||||
|
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
|
||||||
|
|
||||||
|
/*
|
||||||
|
It's an example for LZMA + x86 Filter use.
|
||||||
|
You can use .lzma86 extension, if you write that stream to file.
|
||||||
|
.lzma86 header adds one additional byte to standard .lzma header.
|
||||||
|
.lzma86 header (14 bytes):
|
||||||
|
Offset Size Description
|
||||||
|
0 1 = 0 - no filter, pure LZMA
|
||||||
|
= 1 - x86 filter + LZMA
|
||||||
|
1 1 lc, lp and pb in encoded form
|
||||||
|
2 4 dictSize (little endian)
|
||||||
|
6 8 uncompressed size (little endian)
|
||||||
|
|
||||||
|
|
||||||
|
Lzma86_Encode
|
||||||
|
-------------
|
||||||
|
level - compression level: 0 <= level <= 9, the default value for "level" is 5.
|
||||||
|
|
||||||
|
dictSize - The dictionary size in bytes. The maximum value is
|
||||||
|
128 MB = (1 << 27) bytes for 32-bit version
|
||||||
|
1 GB = (1 << 30) bytes for 64-bit version
|
||||||
|
The default value is 16 MB = (1 << 24) bytes, for level = 5.
|
||||||
|
It's recommended to use the dictionary that is larger than 4 KB and
|
||||||
|
that can be calculated as (1 << N) or (3 << N) sizes.
|
||||||
|
For better compression ratio dictSize must be >= inSize.
|
||||||
|
|
||||||
|
filterMode:
|
||||||
|
SZ_FILTER_NO - no Filter
|
||||||
|
SZ_FILTER_YES - x86 Filter
|
||||||
|
SZ_FILTER_AUTO - it tries both alternatives to select best.
|
||||||
|
Encoder will use 2 or 3 passes:
|
||||||
|
2 passes when FILTER_NO provides better compression.
|
||||||
|
3 passes when FILTER_YES provides better compression.
|
||||||
|
|
||||||
|
Lzma86Encode allocates Data with MyAlloc functions.
|
||||||
|
RAM Requirements for compressing:
|
||||||
|
RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize
|
||||||
|
filterMode FilterBlockSize
|
||||||
|
SZ_FILTER_NO 0
|
||||||
|
SZ_FILTER_YES inSize
|
||||||
|
SZ_FILTER_AUTO inSize
|
||||||
|
|
||||||
|
|
||||||
|
Return code:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_PARAM - Incorrect paramater
|
||||||
|
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||||
|
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum ESzFilterMode
|
||||||
|
{
|
||||||
|
SZ_FILTER_NO,
|
||||||
|
SZ_FILTER_YES,
|
||||||
|
SZ_FILTER_AUTO
|
||||||
|
};
|
||||||
|
|
||||||
|
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
||||||
|
int level, UInt32 dictSize, int filterMode);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Lzma86_GetUnpackSize:
|
||||||
|
In:
|
||||||
|
src - input data
|
||||||
|
srcLen - input data size
|
||||||
|
Out:
|
||||||
|
unpackSize - size of uncompressed stream
|
||||||
|
Return code:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_INPUT_EOF - Error in headers
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Lzma86_Decode:
|
||||||
|
In:
|
||||||
|
dest - output data
|
||||||
|
destLen - output data size
|
||||||
|
src - input data
|
||||||
|
srcLen - input data size
|
||||||
|
Out:
|
||||||
|
destLen - processed output size
|
||||||
|
srcLen - processed input size
|
||||||
|
Return code:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_DATA - Data error
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_UNSUPPORTED - unsupported file
|
||||||
|
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder
|
||||||
|
2009-08-14 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Lzma86.h"
|
||||||
|
|
||||||
|
#include "Alloc.h"
|
||||||
|
#include "Bra.h"
|
||||||
|
#include "LzmaDec.h"
|
||||||
|
|
||||||
|
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||||
|
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||||
|
|
||||||
|
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
if (srcLen < LZMA86_HEADER_SIZE)
|
||||||
|
return SZ_ERROR_INPUT_EOF;
|
||||||
|
*unpackSize = 0;
|
||||||
|
for (i = 0; i < sizeof(UInt64); i++)
|
||||||
|
*unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)
|
||||||
|
{
|
||||||
|
ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||||
|
SRes res;
|
||||||
|
int useFilter;
|
||||||
|
SizeT inSizePure;
|
||||||
|
ELzmaStatus status;
|
||||||
|
|
||||||
|
if (*srcLen < LZMA86_HEADER_SIZE)
|
||||||
|
return SZ_ERROR_INPUT_EOF;
|
||||||
|
|
||||||
|
useFilter = src[0];
|
||||||
|
|
||||||
|
if (useFilter > 1)
|
||||||
|
{
|
||||||
|
*destLen = 0;
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
inSizePure = *srcLen - LZMA86_HEADER_SIZE;
|
||||||
|
res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure,
|
||||||
|
src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc);
|
||||||
|
*srcLen = inSizePure + LZMA86_HEADER_SIZE;
|
||||||
|
if (res != SZ_OK)
|
||||||
|
return res;
|
||||||
|
if (useFilter == 1)
|
||||||
|
{
|
||||||
|
UInt32 x86State;
|
||||||
|
x86_Convert_Init(x86State);
|
||||||
|
x86_Convert(dest, *destLen, 0, &x86State, 0);
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
|
||||||
|
2009-08-14 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Lzma86.h"
|
||||||
|
|
||||||
|
#include "Alloc.h"
|
||||||
|
#include "Bra.h"
|
||||||
|
#include "LzmaEnc.h"
|
||||||
|
|
||||||
|
#define SZE_OUT_OVERFLOW SZE_DATA_ERROR
|
||||||
|
|
||||||
|
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||||
|
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||||
|
|
||||||
|
int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
||||||
|
int level, UInt32 dictSize, int filterMode)
|
||||||
|
{
|
||||||
|
ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||||
|
size_t outSize2 = *destLen;
|
||||||
|
Byte *filteredStream;
|
||||||
|
Bool useFilter;
|
||||||
|
int mainResult = SZ_ERROR_OUTPUT_EOF;
|
||||||
|
CLzmaEncProps props;
|
||||||
|
LzmaEncProps_Init(&props);
|
||||||
|
props.level = level;
|
||||||
|
props.dictSize = dictSize;
|
||||||
|
|
||||||
|
*destLen = 0;
|
||||||
|
if (outSize2 < LZMA86_HEADER_SIZE)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
UInt64 t = srcLen;
|
||||||
|
for (i = 0; i < 8; i++, t >>= 8)
|
||||||
|
dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredStream = 0;
|
||||||
|
useFilter = (filterMode != SZ_FILTER_NO);
|
||||||
|
if (useFilter)
|
||||||
|
{
|
||||||
|
if (srcLen != 0)
|
||||||
|
{
|
||||||
|
filteredStream = (Byte *)MyAlloc(srcLen);
|
||||||
|
if (filteredStream == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
memcpy(filteredStream, src, srcLen);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
UInt32 x86State;
|
||||||
|
x86_Convert_Init(x86State);
|
||||||
|
x86_Convert(filteredStream, srcLen, 0, &x86State, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t minSize = 0;
|
||||||
|
Bool bestIsFiltered = False;
|
||||||
|
|
||||||
|
/* passes for SZ_FILTER_AUTO:
|
||||||
|
0 - BCJ + LZMA
|
||||||
|
1 - LZMA
|
||||||
|
2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.
|
||||||
|
*/
|
||||||
|
int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < numPasses; i++)
|
||||||
|
{
|
||||||
|
size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
|
||||||
|
size_t outPropsSize = 5;
|
||||||
|
SRes curRes;
|
||||||
|
Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
|
||||||
|
if (curModeIsFiltered && !bestIsFiltered)
|
||||||
|
break;
|
||||||
|
if (useFilter && i == 0)
|
||||||
|
curModeIsFiltered = True;
|
||||||
|
|
||||||
|
curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,
|
||||||
|
curModeIsFiltered ? filteredStream : src, srcLen,
|
||||||
|
&props, dest + 1, &outPropsSize, 0,
|
||||||
|
NULL, &g_Alloc, &g_Alloc);
|
||||||
|
|
||||||
|
if (curRes != SZ_ERROR_OUTPUT_EOF)
|
||||||
|
{
|
||||||
|
if (curRes != SZ_OK)
|
||||||
|
{
|
||||||
|
mainResult = curRes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (outSizeProcessed <= minSize || mainResult != SZ_OK)
|
||||||
|
{
|
||||||
|
minSize = outSizeProcessed;
|
||||||
|
bestIsFiltered = curModeIsFiltered;
|
||||||
|
mainResult = SZ_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dest[0] = (Byte)(bestIsFiltered ? 1 : 0);
|
||||||
|
*destLen = LZMA86_HEADER_SIZE + minSize;
|
||||||
|
}
|
||||||
|
if (useFilter)
|
||||||
|
MyFree(filteredStream);
|
||||||
|
return mainResult;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,227 @@
|
||||||
|
/* LzmaDec.h -- LZMA Decoder
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA_DEC_H
|
||||||
|
#define __LZMA_DEC_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
/* #define _LZMA_PROB32 */
|
||||||
|
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||||
|
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||||
|
|
||||||
|
#ifdef _LZMA_PROB32
|
||||||
|
#define CLzmaProb UInt32
|
||||||
|
#else
|
||||||
|
#define CLzmaProb UInt16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- LZMA Properties ---------- */
|
||||||
|
|
||||||
|
#define LZMA_PROPS_SIZE 5
|
||||||
|
|
||||||
|
typedef struct _CLzmaProps
|
||||||
|
{
|
||||||
|
unsigned lc, lp, pb;
|
||||||
|
UInt32 dicSize;
|
||||||
|
} CLzmaProps;
|
||||||
|
|
||||||
|
/* LzmaProps_Decode - decodes properties
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- LZMA Decoder state ---------- */
|
||||||
|
|
||||||
|
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
|
||||||
|
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
||||||
|
|
||||||
|
#define LZMA_REQUIRED_INPUT_MAX 20
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaProps prop;
|
||||||
|
CLzmaProb *probs;
|
||||||
|
Byte *dic;
|
||||||
|
const Byte *buf;
|
||||||
|
UInt32 range, code;
|
||||||
|
SizeT dicPos;
|
||||||
|
SizeT dicBufSize;
|
||||||
|
UInt32 processedPos;
|
||||||
|
UInt32 checkDicSize;
|
||||||
|
unsigned state;
|
||||||
|
UInt32 reps[4];
|
||||||
|
unsigned remainLen;
|
||||||
|
int needFlush;
|
||||||
|
int needInitState;
|
||||||
|
UInt32 numProbs;
|
||||||
|
unsigned tempBufSize;
|
||||||
|
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||||
|
} CLzmaDec;
|
||||||
|
|
||||||
|
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
LZMA_FINISH_ANY, /* finish at any point */
|
||||||
|
LZMA_FINISH_END /* block must be finished at the end */
|
||||||
|
} ELzmaFinishMode;
|
||||||
|
|
||||||
|
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
||||||
|
and output value of destLen will be less than output buffer size limit.
|
||||||
|
You can check status result also.
|
||||||
|
|
||||||
|
You can use multiple checks to test data integrity after full decompression:
|
||||||
|
1) Check Result and "status" variable.
|
||||||
|
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||||
|
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||||
|
You must use correct finish mode in that case. */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
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 */
|
||||||
|
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 */
|
||||||
|
} ELzmaStatus;
|
||||||
|
|
||||||
|
/* ELzmaStatus is used only as output value for function call */
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Interfaces ---------- */
|
||||||
|
|
||||||
|
/* There are 3 levels of interfaces:
|
||||||
|
1) Dictionary Interface
|
||||||
|
2) Buffer Interface
|
||||||
|
3) One Call Interface
|
||||||
|
You can select any of these interfaces, but don't mix functions from different
|
||||||
|
groups for same object. */
|
||||||
|
|
||||||
|
|
||||||
|
/* There are two variants to allocate state for Dictionary Interface:
|
||||||
|
1) LzmaDec_Allocate / LzmaDec_Free
|
||||||
|
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.
|
||||||
|
|
||||||
|
LzmaDec_Allocate* can return:
|
||||||
|
SZ_OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
|
||||||
|
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
|
||||||
|
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
/* ---------- Dictionary Interface ---------- */
|
||||||
|
|
||||||
|
/* You can use it, if you want to eliminate the overhead for data copying from
|
||||||
|
dictionary to some other external buffer.
|
||||||
|
You must work with CLzmaDec variables directly in this interface.
|
||||||
|
|
||||||
|
STEPS:
|
||||||
|
LzmaDec_Constr()
|
||||||
|
LzmaDec_Allocate()
|
||||||
|
for (each new stream)
|
||||||
|
{
|
||||||
|
LzmaDec_Init()
|
||||||
|
while (it needs more decompression)
|
||||||
|
{
|
||||||
|
LzmaDec_DecodeToDic()
|
||||||
|
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LzmaDec_Free()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* LzmaDec_DecodeToDic
|
||||||
|
|
||||||
|
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
||||||
|
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
||||||
|
|
||||||
|
finishMode:
|
||||||
|
It has meaning only if the decoding reaches output limit (dicLimit).
|
||||||
|
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
||||||
|
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
status:
|
||||||
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
|
LZMA_STATUS_NOT_FINISHED
|
||||||
|
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||||
|
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||||
|
SZ_ERROR_DATA - Data error
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Buffer Interface ---------- */
|
||||||
|
|
||||||
|
/* It's zlib-like interface.
|
||||||
|
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.
|
||||||
|
|
||||||
|
finishMode:
|
||||||
|
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).
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
/* LzmaDecode
|
||||||
|
|
||||||
|
finishMode:
|
||||||
|
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).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
status:
|
||||||
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
|
LZMA_STATUS_NOT_FINISHED
|
||||||
|
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||||
|
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 LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||||
|
ELzmaStatus *status, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,78 @@
|
||||||
|
/* LzmaEnc.h -- LZMA Encoder
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA_ENC_H
|
||||||
|
#define __LZMA_ENC_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define LZMA_PROPS_SIZE 5
|
||||||
|
|
||||||
|
typedef struct _CLzmaEncProps
|
||||||
|
{
|
||||||
|
int level; /* 0 <= level <= 9 */
|
||||||
|
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
|
||||||
|
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version
|
||||||
|
default = (1 << 24) */
|
||||||
|
UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.
|
||||||
|
Encoder uses this value to reduce dictionary size */
|
||||||
|
int lc; /* 0 <= lc <= 8, default = 3 */
|
||||||
|
int lp; /* 0 <= lp <= 4, default = 0 */
|
||||||
|
int pb; /* 0 <= pb <= 4, default = 2 */
|
||||||
|
int algo; /* 0 - fast, 1 - normal, default = 1 */
|
||||||
|
int fb; /* 5 <= fb <= 273, default = 32 */
|
||||||
|
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
|
||||||
|
int numHashBytes; /* 2, 3 or 4, default = 4 */
|
||||||
|
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
|
||||||
|
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
|
||||||
|
int numThreads; /* 1 or 2, default = 2 */
|
||||||
|
} CLzmaEncProps;
|
||||||
|
|
||||||
|
void LzmaEncProps_Init(CLzmaEncProps *p);
|
||||||
|
void LzmaEncProps_Normalize(CLzmaEncProps *p);
|
||||||
|
UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- CLzmaEncHandle Interface ---------- */
|
||||||
|
|
||||||
|
/* LzmaEnc_* functions can return the following exit codes:
|
||||||
|
Returns:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||||
|
SZ_ERROR_WRITE - Write callback error.
|
||||||
|
SZ_ERROR_PROGRESS - some break from progress callback
|
||||||
|
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void * CLzmaEncHandle;
|
||||||
|
|
||||||
|
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
|
||||||
|
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
|
||||||
|
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
|
||||||
|
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||||
|
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||||
|
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
|
||||||
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
/* LzmaEncode
|
||||||
|
Return code:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_PARAM - Incorrect paramater
|
||||||
|
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||||
|
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||||
|
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||||
|
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* LzmaLib.c -- LZMA library wrapper
|
||||||
|
2008-08-05
|
||||||
|
Igor Pavlov
|
||||||
|
Public domain */
|
||||||
|
|
||||||
|
#include "LzmaEnc.h"
|
||||||
|
#include "LzmaDec.h"
|
||||||
|
#include "Alloc.h"
|
||||||
|
#include "LzmaLib.h"
|
||||||
|
|
||||||
|
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||||
|
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||||
|
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||||
|
|
||||||
|
MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
|
||||||
|
unsigned char *outProps, size_t *outPropsSize,
|
||||||
|
int level, /* 0 <= level <= 9, default = 5 */
|
||||||
|
unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
|
||||||
|
int lc, /* 0 <= lc <= 8, default = 3 */
|
||||||
|
int lp, /* 0 <= lp <= 4, default = 0 */
|
||||||
|
int pb, /* 0 <= pb <= 4, default = 2 */
|
||||||
|
int fb, /* 5 <= fb <= 273, default = 32 */
|
||||||
|
int numThreads /* 1 or 2, default = 2 */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CLzmaEncProps props;
|
||||||
|
LzmaEncProps_Init(&props);
|
||||||
|
props.level = level;
|
||||||
|
props.dictSize = dictSize;
|
||||||
|
props.lc = lc;
|
||||||
|
props.lp = lp;
|
||||||
|
props.pb = pb;
|
||||||
|
props.fb = fb;
|
||||||
|
props.numThreads = numThreads;
|
||||||
|
|
||||||
|
return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0,
|
||||||
|
NULL, &g_Alloc, &g_Alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen,
|
||||||
|
const unsigned char *props, size_t propsSize)
|
||||||
|
{
|
||||||
|
ELzmaStatus status;
|
||||||
|
return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc);
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
/* LzmaLib.h -- LZMA library interface
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA_LIB_H
|
||||||
|
#define __LZMA_LIB_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define MY_STDAPI int MY_STD_CALL
|
||||||
|
|
||||||
|
#define LZMA_PROPS_SIZE 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
RAM requirements for LZMA:
|
||||||
|
for compression: (dictSize * 11.5 + 6 MB) + state_size
|
||||||
|
for decompression: dictSize + state_size
|
||||||
|
state_size = (4 + (1.5 << (lc + lp))) KB
|
||||||
|
by default (lc=3, lp=0), state_size = 16 KB.
|
||||||
|
|
||||||
|
LZMA properties (5 bytes) format
|
||||||
|
Offset Size Description
|
||||||
|
0 1 lc, lp and pb in encoded form.
|
||||||
|
1 4 dictSize (little endian).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
LzmaCompress
|
||||||
|
------------
|
||||||
|
|
||||||
|
outPropsSize -
|
||||||
|
In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
|
||||||
|
Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
|
||||||
|
|
||||||
|
LZMA Encoder will use defult values for any parameter, if it is
|
||||||
|
-1 for any from: level, loc, lp, pb, fb, numThreads
|
||||||
|
0 for dictSize
|
||||||
|
|
||||||
|
level - compression level: 0 <= level <= 9;
|
||||||
|
|
||||||
|
level dictSize algo fb
|
||||||
|
0: 16 KB 0 32
|
||||||
|
1: 64 KB 0 32
|
||||||
|
2: 256 KB 0 32
|
||||||
|
3: 1 MB 0 32
|
||||||
|
4: 4 MB 0 32
|
||||||
|
5: 16 MB 1 32
|
||||||
|
6: 32 MB 1 32
|
||||||
|
7+: 64 MB 1 64
|
||||||
|
|
||||||
|
The default value for "level" is 5.
|
||||||
|
|
||||||
|
algo = 0 means fast method
|
||||||
|
algo = 1 means normal method
|
||||||
|
|
||||||
|
dictSize - The dictionary size in bytes. The maximum value is
|
||||||
|
128 MB = (1 << 27) bytes for 32-bit version
|
||||||
|
1 GB = (1 << 30) bytes for 64-bit version
|
||||||
|
The default value is 16 MB = (1 << 24) bytes.
|
||||||
|
It's recommended to use the dictionary that is larger than 4 KB and
|
||||||
|
that can be calculated as (1 << N) or (3 << N) sizes.
|
||||||
|
|
||||||
|
lc - The number of literal context bits (high bits of previous literal).
|
||||||
|
It can be in the range from 0 to 8. The default value is 3.
|
||||||
|
Sometimes lc=4 gives the gain for big files.
|
||||||
|
|
||||||
|
lp - The number of literal pos bits (low bits of current position for literals).
|
||||||
|
It can be in the range from 0 to 4. The default value is 0.
|
||||||
|
The lp switch is intended for periodical data when the period is equal to 2^lp.
|
||||||
|
For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's
|
||||||
|
better to set lc=0, if you change lp switch.
|
||||||
|
|
||||||
|
pb - The number of pos bits (low bits of current position).
|
||||||
|
It can be in the range from 0 to 4. The default value is 2.
|
||||||
|
The pb switch is intended for periodical data when the period is equal 2^pb.
|
||||||
|
|
||||||
|
fb - Word size (the number of fast bytes).
|
||||||
|
It can be in the range from 5 to 273. The default value is 32.
|
||||||
|
Usually, a big number gives a little bit better compression ratio and
|
||||||
|
slower compression process.
|
||||||
|
|
||||||
|
numThreads - The number of thereads. 1 or 2. The default value is 2.
|
||||||
|
Fast mode (algo = 0) can use only 1 thread.
|
||||||
|
|
||||||
|
Out:
|
||||||
|
destLen - processed output size
|
||||||
|
Returns:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_PARAM - Incorrect paramater
|
||||||
|
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||||
|
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||||
|
*/
|
||||||
|
|
||||||
|
MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
|
||||||
|
unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */
|
||||||
|
int level, /* 0 <= level <= 9, default = 5 */
|
||||||
|
unsigned dictSize, /* default = (1 << 24) */
|
||||||
|
int lc, /* 0 <= lc <= 8, default = 3 */
|
||||||
|
int lp, /* 0 <= lp <= 4, default = 0 */
|
||||||
|
int pb, /* 0 <= pb <= 4, default = 2 */
|
||||||
|
int fb, /* 5 <= fb <= 273, default = 32 */
|
||||||
|
int numThreads /* 1 or 2, default = 2 */
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
LzmaUncompress
|
||||||
|
--------------
|
||||||
|
In:
|
||||||
|
dest - output data
|
||||||
|
destLen - output data size
|
||||||
|
src - input data
|
||||||
|
srcLen - input data size
|
||||||
|
Out:
|
||||||
|
destLen - processed output size
|
||||||
|
srcLen - processed input size
|
||||||
|
Returns:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_DATA - Data error
|
||||||
|
SZ_ERROR_MEM - Memory allocation arror
|
||||||
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
|
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src)
|
||||||
|
*/
|
||||||
|
|
||||||
|
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
|
||||||
|
const unsigned char *props, size_t propsSize);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,329 @@
|
||||||
|
/* MtCoder.c -- Multi-thread Coder
|
||||||
|
2010-09-24 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "MtCoder.h"
|
||||||
|
|
||||||
|
void LoopThread_Construct(CLoopThread *p)
|
||||||
|
{
|
||||||
|
Thread_Construct(&p->thread);
|
||||||
|
Event_Construct(&p->startEvent);
|
||||||
|
Event_Construct(&p->finishedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoopThread_Close(CLoopThread *p)
|
||||||
|
{
|
||||||
|
Thread_Close(&p->thread);
|
||||||
|
Event_Close(&p->startEvent);
|
||||||
|
Event_Close(&p->finishedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
|
||||||
|
{
|
||||||
|
CLoopThread *p = (CLoopThread *)pp;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (Event_Wait(&p->startEvent) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
if (p->stop)
|
||||||
|
return 0;
|
||||||
|
p->res = p->func(p->param);
|
||||||
|
if (Event_Set(&p->finishedEvent) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes LoopThread_Create(CLoopThread *p)
|
||||||
|
{
|
||||||
|
p->stop = 0;
|
||||||
|
RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));
|
||||||
|
RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));
|
||||||
|
return Thread_Create(&p->thread, LoopThreadFunc, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes LoopThread_StopAndWait(CLoopThread *p)
|
||||||
|
{
|
||||||
|
p->stop = 1;
|
||||||
|
if (Event_Set(&p->startEvent) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
return Thread_Wait(&p->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }
|
||||||
|
WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }
|
||||||
|
|
||||||
|
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
|
||||||
|
{
|
||||||
|
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
p->inSizes[i] = p->outSizes[i] = 0;
|
||||||
|
p->totalInSize = p->totalOutSize = 0;
|
||||||
|
p->progress = progress;
|
||||||
|
p->res = SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MtProgress_Reinit(CMtProgress *p, unsigned index)
|
||||||
|
{
|
||||||
|
p->inSizes[index] = 0;
|
||||||
|
p->outSizes[index] = 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;
|
||||||
|
CriticalSection_Enter(&p->cs);
|
||||||
|
UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)
|
||||||
|
UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)
|
||||||
|
if (p->res == SZ_OK)
|
||||||
|
p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);
|
||||||
|
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 void MtCoder_SetError(CMtCoder* p, SRes res)
|
||||||
|
{
|
||||||
|
CriticalSection_Enter(&p->cs);
|
||||||
|
if (p->res == SZ_OK)
|
||||||
|
p->res = res;
|
||||||
|
CriticalSection_Leave(&p->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- MtThread ---------- */
|
||||||
|
|
||||||
|
void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
|
||||||
|
{
|
||||||
|
p->mtCoder = mtCoder;
|
||||||
|
p->outBuf = 0;
|
||||||
|
p->inBuf = 0;
|
||||||
|
Event_Construct(&p->canRead);
|
||||||
|
Event_Construct(&p->canWrite);
|
||||||
|
LoopThread_Construct(&p->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }
|
||||||
|
|
||||||
|
static void CMtThread_CloseEvents(CMtThread *p)
|
||||||
|
{
|
||||||
|
Event_Close(&p->canRead);
|
||||||
|
Event_Close(&p->canWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CMtThread_Destruct(CMtThread *p)
|
||||||
|
{
|
||||||
|
CMtThread_CloseEvents(p);
|
||||||
|
|
||||||
|
if (Thread_WasCreated(&p->thread.thread))
|
||||||
|
{
|
||||||
|
LoopThread_StopAndWait(&p->thread);
|
||||||
|
LoopThread_Close(&p->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->mtCoder->alloc)
|
||||||
|
IAlloc_Free(p->mtCoder->alloc, p->outBuf);
|
||||||
|
p->outBuf = 0;
|
||||||
|
|
||||||
|
if (p->mtCoder->alloc)
|
||||||
|
IAlloc_Free(p->mtCoder->alloc, p->inBuf);
|
||||||
|
p->inBuf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MY_BUF_ALLOC(buf, size, newSize) \
|
||||||
|
if (buf == 0 || size != newSize) \
|
||||||
|
{ IAlloc_Free(p->mtCoder->alloc, buf); \
|
||||||
|
size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \
|
||||||
|
if (buf == 0) return SZ_ERROR_MEM; }
|
||||||
|
|
||||||
|
static SRes CMtThread_Prepare(CMtThread *p)
|
||||||
|
{
|
||||||
|
MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)
|
||||||
|
MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)
|
||||||
|
|
||||||
|
p->stopReading = False;
|
||||||
|
p->stopWriting = False;
|
||||||
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));
|
||||||
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));
|
||||||
|
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
|
||||||
|
{
|
||||||
|
size_t size = *processedSize;
|
||||||
|
*processedSize = 0;
|
||||||
|
while (size != 0)
|
||||||
|
{
|
||||||
|
size_t curSize = size;
|
||||||
|
SRes res = stream->Read(stream, data, &curSize);
|
||||||
|
*processedSize += curSize;
|
||||||
|
data += curSize;
|
||||||
|
size -= curSize;
|
||||||
|
RINOK(res);
|
||||||
|
if (curSize == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads - 1 ? 0 : p->index + 1]
|
||||||
|
|
||||||
|
static SRes MtThread_Process(CMtThread *p, Bool *stop)
|
||||||
|
{
|
||||||
|
CMtThread *next;
|
||||||
|
*stop = True;
|
||||||
|
if (Event_Wait(&p->canRead) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
|
||||||
|
next = GET_NEXT_THREAD(p);
|
||||||
|
|
||||||
|
if (p->stopReading)
|
||||||
|
{
|
||||||
|
next->stopReading = True;
|
||||||
|
return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t size = p->mtCoder->blockSize;
|
||||||
|
size_t destSize = p->outBufSize;
|
||||||
|
|
||||||
|
RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));
|
||||||
|
next->stopReading = *stop = (size != p->mtCoder->blockSize);
|
||||||
|
if (Event_Set(&next->canRead) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
|
||||||
|
RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,
|
||||||
|
p->outBuf, &destSize, p->inBuf, size, *stop));
|
||||||
|
|
||||||
|
MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);
|
||||||
|
|
||||||
|
if (Event_Wait(&p->canWrite) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
if (p->stopWriting)
|
||||||
|
return SZ_ERROR_FAIL;
|
||||||
|
if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
|
||||||
|
{
|
||||||
|
CMtThread *p = (CMtThread *)pp;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Bool stop;
|
||||||
|
CMtThread *next = GET_NEXT_THREAD(p);
|
||||||
|
SRes res = MtThread_Process(p, &stop);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
{
|
||||||
|
MtCoder_SetError(p->mtCoder, res);
|
||||||
|
MtProgress_SetError(&p->mtCoder->mtProgress, res);
|
||||||
|
next->stopReading = True;
|
||||||
|
next->stopWriting = True;
|
||||||
|
Event_Set(&next->canRead);
|
||||||
|
Event_Set(&next->canWrite);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (stop)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MtCoder_Construct(CMtCoder* p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
p->alloc = 0;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
{
|
||||||
|
CMtThread *t = &p->threads[i];
|
||||||
|
t->index = i;
|
||||||
|
CMtThread_Construct(t, p);
|
||||||
|
}
|
||||||
|
CriticalSection_Init(&p->cs);
|
||||||
|
CriticalSection_Init(&p->mtProgress.cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MtCoder_Destruct(CMtCoder* p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
CMtThread_Destruct(&p->threads[i]);
|
||||||
|
CriticalSection_Delete(&p->cs);
|
||||||
|
CriticalSection_Delete(&p->mtProgress.cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes MtCoder_Code(CMtCoder *p)
|
||||||
|
{
|
||||||
|
unsigned i, numThreads = p->numThreads;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
p->res = SZ_OK;
|
||||||
|
|
||||||
|
MtProgress_Init(&p->mtProgress, p->progress);
|
||||||
|
|
||||||
|
for (i = 0; i < numThreads; i++)
|
||||||
|
{
|
||||||
|
RINOK(CMtThread_Prepare(&p->threads[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numThreads; i++)
|
||||||
|
{
|
||||||
|
CMtThread *t = &p->threads[i];
|
||||||
|
CLoopThread *lt = &t->thread;
|
||||||
|
|
||||||
|
if (!Thread_WasCreated(<->thread))
|
||||||
|
{
|
||||||
|
lt->func = ThreadFunc;
|
||||||
|
lt->param = t;
|
||||||
|
|
||||||
|
if (LoopThread_Create(lt) != SZ_OK)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_THREAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
unsigned j;
|
||||||
|
for (i = 0; i < numThreads; i++)
|
||||||
|
{
|
||||||
|
CMtThread *t = &p->threads[i];
|
||||||
|
if (LoopThread_StartSubThread(&t->thread) != SZ_OK)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_THREAD;
|
||||||
|
p->threads[0].stopReading = True;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event_Set(&p->threads[0].canWrite);
|
||||||
|
Event_Set(&p->threads[0].canRead);
|
||||||
|
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
LoopThread_WaitSubThread(&p->threads[j].thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numThreads; i++)
|
||||||
|
CMtThread_CloseEvents(&p->threads[i]);
|
||||||
|
return (res == SZ_OK) ? p->res : res;
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/* MtCoder.h -- Multi-thread Coder
|
||||||
|
2009-11-19 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __MT_CODER_H
|
||||||
|
#define __MT_CODER_H
|
||||||
|
|
||||||
|
#include "Threads.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CThread thread;
|
||||||
|
CAutoResetEvent startEvent;
|
||||||
|
CAutoResetEvent finishedEvent;
|
||||||
|
int stop;
|
||||||
|
|
||||||
|
THREAD_FUNC_TYPE func;
|
||||||
|
LPVOID param;
|
||||||
|
THREAD_FUNC_RET_TYPE res;
|
||||||
|
} CLoopThread;
|
||||||
|
|
||||||
|
void LoopThread_Construct(CLoopThread *p);
|
||||||
|
void LoopThread_Close(CLoopThread *p);
|
||||||
|
WRes LoopThread_Create(CLoopThread *p);
|
||||||
|
WRes LoopThread_StopAndWait(CLoopThread *p);
|
||||||
|
WRes LoopThread_StartSubThread(CLoopThread *p);
|
||||||
|
WRes LoopThread_WaitSubThread(CLoopThread *p);
|
||||||
|
|
||||||
|
#ifndef _7ZIP_ST
|
||||||
|
#define NUM_MT_CODER_THREADS_MAX 32
|
||||||
|
#else
|
||||||
|
#define NUM_MT_CODER_THREADS_MAX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt64 totalInSize;
|
||||||
|
UInt64 totalOutSize;
|
||||||
|
ICompressProgress *progress;
|
||||||
|
SRes res;
|
||||||
|
CCriticalSection cs;
|
||||||
|
UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];
|
||||||
|
UInt64 outSizes[NUM_MT_CODER_THREADS_MAX];
|
||||||
|
} CMtProgress;
|
||||||
|
|
||||||
|
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);
|
||||||
|
|
||||||
|
struct _CMtCoder;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct _CMtCoder *mtCoder;
|
||||||
|
Byte *outBuf;
|
||||||
|
size_t outBufSize;
|
||||||
|
Byte *inBuf;
|
||||||
|
size_t inBufSize;
|
||||||
|
unsigned index;
|
||||||
|
CLoopThread thread;
|
||||||
|
|
||||||
|
Bool stopReading;
|
||||||
|
Bool stopWriting;
|
||||||
|
CAutoResetEvent canRead;
|
||||||
|
CAutoResetEvent canWrite;
|
||||||
|
} CMtThread;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize,
|
||||||
|
const Byte *src, size_t srcSize, int finished);
|
||||||
|
} IMtCoderCallback;
|
||||||
|
|
||||||
|
typedef struct _CMtCoder
|
||||||
|
{
|
||||||
|
size_t blockSize;
|
||||||
|
size_t destBlockSize;
|
||||||
|
unsigned numThreads;
|
||||||
|
|
||||||
|
ISeqInStream *inStream;
|
||||||
|
ISeqOutStream *outStream;
|
||||||
|
ICompressProgress *progress;
|
||||||
|
ISzAlloc *alloc;
|
||||||
|
|
||||||
|
IMtCoderCallback *mtCallback;
|
||||||
|
CCriticalSection cs;
|
||||||
|
SRes res;
|
||||||
|
|
||||||
|
CMtProgress mtProgress;
|
||||||
|
CMtThread threads[NUM_MT_CODER_THREADS_MAX];
|
||||||
|
} CMtCoder;
|
||||||
|
|
||||||
|
void MtCoder_Construct(CMtCoder* p);
|
||||||
|
void MtCoder_Destruct(CMtCoder* p);
|
||||||
|
SRes MtCoder_Code(CMtCoder *p);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* Ppmd.h -- PPMD codec common code
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain
|
||||||
|
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||||
|
|
||||||
|
#ifndef __PPMD_H
|
||||||
|
#define __PPMD_H
|
||||||
|
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#ifdef MY_CPU_32BIT
|
||||||
|
#define PPMD_32BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PPMD_INT_BITS 7
|
||||||
|
#define PPMD_PERIOD_BITS 7
|
||||||
|
#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
|
||||||
|
|
||||||
|
#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
|
||||||
|
#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
|
||||||
|
#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
|
||||||
|
#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
|
||||||
|
|
||||||
|
#define PPMD_N1 4
|
||||||
|
#define PPMD_N2 4
|
||||||
|
#define PPMD_N3 4
|
||||||
|
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
|
||||||
|
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */
|
||||||
|
|
||||||
|
/* SEE-contexts for PPM-contexts with masked symbols */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt16 Summ; /* Freq */
|
||||||
|
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
|
||||||
|
Byte Count; /* Count to next change of Shift */
|
||||||
|
} CPpmd_See;
|
||||||
|
|
||||||
|
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
|
||||||
|
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte Symbol;
|
||||||
|
Byte Freq;
|
||||||
|
UInt16 SuccessorLow;
|
||||||
|
UInt16 SuccessorHigh;
|
||||||
|
} CPpmd_State;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
typedef
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
CPpmd_State *
|
||||||
|
#else
|
||||||
|
UInt32
|
||||||
|
#endif
|
||||||
|
CPpmd_State_Ref;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
void *
|
||||||
|
#else
|
||||||
|
UInt32
|
||||||
|
#endif
|
||||||
|
CPpmd_Void_Ref;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
Byte *
|
||||||
|
#else
|
||||||
|
UInt32
|
||||||
|
#endif
|
||||||
|
CPpmd_Byte_Ref;
|
||||||
|
|
||||||
|
#define PPMD_SetAllBitsIn256Bytes(p) \
|
||||||
|
{ unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
|
||||||
|
p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,710 @@
|
||||||
|
/* Ppmd7.c -- PPMdH codec
|
||||||
|
2010-03-12 : Igor Pavlov : Public domain
|
||||||
|
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
#include "Ppmd7.h"
|
||||||
|
|
||||||
|
const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
|
||||||
|
static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
|
||||||
|
|
||||||
|
#define MAX_FREQ 124
|
||||||
|
#define UNIT_SIZE 12
|
||||||
|
|
||||||
|
#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
|
||||||
|
#define U2I(nu) (p->Units2Indx[(nu) - 1])
|
||||||
|
#define I2U(indx) (p->Indx2Units[indx])
|
||||||
|
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
#define REF(ptr) (ptr)
|
||||||
|
#else
|
||||||
|
#define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
|
||||||
|
|
||||||
|
#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
|
||||||
|
#define STATS(ctx) Ppmd7_GetStats(p, ctx)
|
||||||
|
#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
|
||||||
|
#define SUFFIX(ctx) CTX((ctx)->Suffix)
|
||||||
|
|
||||||
|
typedef CPpmd7_Context * CTX_PTR;
|
||||||
|
|
||||||
|
struct CPpmd7_Node_;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
struct CPpmd7_Node_ *
|
||||||
|
#else
|
||||||
|
UInt32
|
||||||
|
#endif
|
||||||
|
CPpmd7_Node_Ref;
|
||||||
|
|
||||||
|
typedef struct CPpmd7_Node_
|
||||||
|
{
|
||||||
|
UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
|
||||||
|
UInt16 NU;
|
||||||
|
CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
|
||||||
|
CPpmd7_Node_Ref Prev;
|
||||||
|
} CPpmd7_Node;
|
||||||
|
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
#define NODE(ptr) (ptr)
|
||||||
|
#else
|
||||||
|
#define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Ppmd7_Construct(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
unsigned i, k, m;
|
||||||
|
|
||||||
|
p->Base = 0;
|
||||||
|
|
||||||
|
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
|
||||||
|
{
|
||||||
|
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
|
||||||
|
do { p->Units2Indx[k++] = (Byte)i; } while(--step);
|
||||||
|
p->Indx2Units[i] = (Byte)k;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->NS2BSIndx[0] = (0 << 1);
|
||||||
|
p->NS2BSIndx[1] = (1 << 1);
|
||||||
|
memset(p->NS2BSIndx + 2, (2 << 1), 9);
|
||||||
|
memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
p->NS2Indx[i] = (Byte)i;
|
||||||
|
for (m = i, k = 1; i < 256; i++)
|
||||||
|
{
|
||||||
|
p->NS2Indx[i] = (Byte)m;
|
||||||
|
if (--k == 0)
|
||||||
|
k = (++m) - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(p->HB2Flag, 0, 0x40);
|
||||||
|
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->Base);
|
||||||
|
p->Size = 0;
|
||||||
|
p->Base = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
if (p->Base == 0 || p->Size != size)
|
||||||
|
{
|
||||||
|
Ppmd7_Free(p, alloc);
|
||||||
|
p->AlignOffset =
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
(4 - size) & 3;
|
||||||
|
#else
|
||||||
|
4 - (size & 3);
|
||||||
|
#endif
|
||||||
|
if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
|
||||||
|
#ifndef PPMD_32BIT
|
||||||
|
+ UNIT_SIZE
|
||||||
|
#endif
|
||||||
|
)) == 0)
|
||||||
|
return False;
|
||||||
|
p->Size = size;
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
|
||||||
|
{
|
||||||
|
*((CPpmd_Void_Ref *)node) = p->FreeList[indx];
|
||||||
|
p->FreeList[indx] = REF(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *RemoveNode(CPpmd7 *p, unsigned indx)
|
||||||
|
{
|
||||||
|
CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
|
||||||
|
p->FreeList[indx] = *node;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
|
||||||
|
{
|
||||||
|
unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
|
||||||
|
ptr = (Byte *)ptr + U2B(I2U(newIndx));
|
||||||
|
if (I2U(i = U2I(nu)) != nu)
|
||||||
|
{
|
||||||
|
unsigned k = I2U(--i);
|
||||||
|
InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
|
||||||
|
}
|
||||||
|
InsertNode(p, ptr, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GlueFreeBlocks(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
CPpmd7_Node headItem;
|
||||||
|
CPpmd7_Node_Ref head = &headItem;
|
||||||
|
#else
|
||||||
|
CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CPpmd7_Node_Ref n = head;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
p->GlueCount = 255;
|
||||||
|
|
||||||
|
/* create doubly-linked list of free blocks */
|
||||||
|
for (i = 0; i < PPMD_NUM_INDEXES; i++)
|
||||||
|
{
|
||||||
|
UInt16 nu = I2U(i);
|
||||||
|
CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
|
||||||
|
p->FreeList[i] = 0;
|
||||||
|
while (next != 0)
|
||||||
|
{
|
||||||
|
CPpmd7_Node *node = NODE(next);
|
||||||
|
node->Next = n;
|
||||||
|
n = NODE(n)->Prev = next;
|
||||||
|
next = *(const CPpmd7_Node_Ref *)node;
|
||||||
|
node->Stamp = 0;
|
||||||
|
node->NU = (UInt16)nu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NODE(head)->Stamp = 1;
|
||||||
|
NODE(head)->Next = n;
|
||||||
|
NODE(n)->Prev = head;
|
||||||
|
if (p->LoUnit != p->HiUnit)
|
||||||
|
((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
|
||||||
|
|
||||||
|
/* Glue free blocks */
|
||||||
|
while (n != head)
|
||||||
|
{
|
||||||
|
CPpmd7_Node *node = NODE(n);
|
||||||
|
UInt32 nu = (UInt32)node->NU;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
CPpmd7_Node *node2 = NODE(n) + nu;
|
||||||
|
nu += node2->NU;
|
||||||
|
if (node2->Stamp != 0 || nu >= 0x10000)
|
||||||
|
break;
|
||||||
|
NODE(node2->Prev)->Next = node2->Next;
|
||||||
|
NODE(node2->Next)->Prev = node2->Prev;
|
||||||
|
node->NU = (UInt16)nu;
|
||||||
|
}
|
||||||
|
n = node->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill lists of free blocks */
|
||||||
|
for (n = NODE(head)->Next; n != head;)
|
||||||
|
{
|
||||||
|
CPpmd7_Node *node = NODE(n);
|
||||||
|
unsigned nu;
|
||||||
|
CPpmd7_Node_Ref next = node->Next;
|
||||||
|
for (nu = node->NU; nu > 128; nu -= 128, node += 128)
|
||||||
|
InsertNode(p, node, PPMD_NUM_INDEXES - 1);
|
||||||
|
if (I2U(i = U2I(nu)) != nu)
|
||||||
|
{
|
||||||
|
unsigned k = I2U(--i);
|
||||||
|
InsertNode(p, node + k, nu - k - 1);
|
||||||
|
}
|
||||||
|
InsertNode(p, node, i);
|
||||||
|
n = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
void *retVal;
|
||||||
|
if (p->GlueCount == 0)
|
||||||
|
{
|
||||||
|
GlueFreeBlocks(p);
|
||||||
|
if (p->FreeList[indx] != 0)
|
||||||
|
return RemoveNode(p, indx);
|
||||||
|
}
|
||||||
|
i = indx;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (++i == PPMD_NUM_INDEXES)
|
||||||
|
{
|
||||||
|
UInt32 numBytes = U2B(I2U(indx));
|
||||||
|
p->GlueCount--;
|
||||||
|
return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (p->FreeList[i] == 0);
|
||||||
|
retVal = RemoveNode(p, i);
|
||||||
|
SplitBlock(p, retVal, i, indx);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *AllocUnits(CPpmd7 *p, unsigned indx)
|
||||||
|
{
|
||||||
|
UInt32 numBytes;
|
||||||
|
if (p->FreeList[indx] != 0)
|
||||||
|
return RemoveNode(p, indx);
|
||||||
|
numBytes = U2B(I2U(indx));
|
||||||
|
if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
|
||||||
|
{
|
||||||
|
void *retVal = p->LoUnit;
|
||||||
|
p->LoUnit += numBytes;
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
return AllocUnitsRare(p, indx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MyMem12Cpy(dest, src, num) \
|
||||||
|
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
|
||||||
|
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
|
||||||
|
|
||||||
|
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
|
||||||
|
{
|
||||||
|
unsigned i0 = U2I(oldNU);
|
||||||
|
unsigned i1 = U2I(newNU);
|
||||||
|
if (i0 == i1)
|
||||||
|
return oldPtr;
|
||||||
|
if (p->FreeList[i1] != 0)
|
||||||
|
{
|
||||||
|
void *ptr = RemoveNode(p, i1);
|
||||||
|
MyMem12Cpy(ptr, oldPtr, newNU);
|
||||||
|
InsertNode(p, oldPtr, i0);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
SplitBlock(p, oldPtr, i0, i1);
|
||||||
|
return oldPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
|
||||||
|
|
||||||
|
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
|
||||||
|
{
|
||||||
|
(p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
|
||||||
|
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RestartModel(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
unsigned i, k, m;
|
||||||
|
|
||||||
|
memset(p->FreeList, 0, sizeof(p->FreeList));
|
||||||
|
p->Text = p->Base + p->AlignOffset;
|
||||||
|
p->HiUnit = p->Text + p->Size;
|
||||||
|
p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
|
||||||
|
p->GlueCount = 0;
|
||||||
|
|
||||||
|
p->OrderFall = p->MaxOrder;
|
||||||
|
p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
|
||||||
|
p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
|
||||||
|
p->MinContext->Suffix = 0;
|
||||||
|
p->MinContext->NumStats = 256;
|
||||||
|
p->MinContext->SummFreq = 256 + 1;
|
||||||
|
p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
|
||||||
|
p->LoUnit += U2B(256 / 2);
|
||||||
|
p->MinContext->Stats = REF(p->FoundState);
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
CPpmd_State *s = &p->FoundState[i];
|
||||||
|
s->Symbol = (Byte)i;
|
||||||
|
s->Freq = 1;
|
||||||
|
SetSuccessor(s, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 128; i++)
|
||||||
|
for (k = 0; k < 8; k++)
|
||||||
|
{
|
||||||
|
UInt16 *dest = p->BinSumm[i] + k;
|
||||||
|
UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
|
||||||
|
for (m = 0; m < 64; m += 8)
|
||||||
|
dest[m] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 25; i++)
|
||||||
|
for (k = 0; k < 16; k++)
|
||||||
|
{
|
||||||
|
CPpmd_See *s = &p->See[i][k];
|
||||||
|
s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
|
||||||
|
s->Count = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
|
||||||
|
{
|
||||||
|
p->MaxOrder = maxOrder;
|
||||||
|
RestartModel(p);
|
||||||
|
p->DummySee.Shift = PPMD_PERIOD_BITS;
|
||||||
|
p->DummySee.Summ = 0; /* unused */
|
||||||
|
p->DummySee.Count = 64; /* unused */
|
||||||
|
}
|
||||||
|
|
||||||
|
static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
|
||||||
|
{
|
||||||
|
CPpmd_State upState;
|
||||||
|
CTX_PTR c = p->MinContext;
|
||||||
|
CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
|
||||||
|
CPpmd_State *ps[PPMD7_MAX_ORDER];
|
||||||
|
unsigned numPs = 0;
|
||||||
|
|
||||||
|
if (!skip)
|
||||||
|
ps[numPs++] = p->FoundState;
|
||||||
|
|
||||||
|
while (c->Suffix)
|
||||||
|
{
|
||||||
|
CPpmd_Void_Ref successor;
|
||||||
|
CPpmd_State *s;
|
||||||
|
c = SUFFIX(c);
|
||||||
|
if (c->NumStats != 1)
|
||||||
|
{
|
||||||
|
for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s = ONE_STATE(c);
|
||||||
|
successor = SUCCESSOR(s);
|
||||||
|
if (successor != upBranch)
|
||||||
|
{
|
||||||
|
c = CTX(successor);
|
||||||
|
if (numPs == 0)
|
||||||
|
return c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ps[numPs++] = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
|
||||||
|
SetSuccessor(&upState, upBranch + 1);
|
||||||
|
|
||||||
|
if (c->NumStats == 1)
|
||||||
|
upState.Freq = ONE_STATE(c)->Freq;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UInt32 cf, s0;
|
||||||
|
CPpmd_State *s;
|
||||||
|
for (s = STATS(c); s->Symbol != upState.Symbol; s++);
|
||||||
|
cf = s->Freq - 1;
|
||||||
|
s0 = c->SummFreq - c->NumStats - cf;
|
||||||
|
upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Create Child */
|
||||||
|
CTX_PTR c1; /* = AllocContext(p); */
|
||||||
|
if (p->HiUnit != p->LoUnit)
|
||||||
|
c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
|
||||||
|
else if (p->FreeList[0] != 0)
|
||||||
|
c1 = (CTX_PTR)RemoveNode(p, 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c1 = (CTX_PTR)AllocUnitsRare(p, 0);
|
||||||
|
if (!c1)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
c1->NumStats = 1;
|
||||||
|
*ONE_STATE(c1) = upState;
|
||||||
|
c1->Suffix = REF(c);
|
||||||
|
SetSuccessor(ps[--numPs], REF(c1));
|
||||||
|
c = c1;
|
||||||
|
}
|
||||||
|
while (numPs != 0);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
|
||||||
|
{
|
||||||
|
CPpmd_State tmp = *t1;
|
||||||
|
*t1 = *t2;
|
||||||
|
*t2 = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UpdateModel(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
|
||||||
|
CTX_PTR c;
|
||||||
|
unsigned s0, ns;
|
||||||
|
|
||||||
|
if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
|
||||||
|
{
|
||||||
|
c = SUFFIX(p->MinContext);
|
||||||
|
|
||||||
|
if (c->NumStats == 1)
|
||||||
|
{
|
||||||
|
CPpmd_State *s = ONE_STATE(c);
|
||||||
|
if (s->Freq < 32)
|
||||||
|
s->Freq++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPpmd_State *s = STATS(c);
|
||||||
|
if (s->Symbol != p->FoundState->Symbol)
|
||||||
|
{
|
||||||
|
do { s++; } while (s->Symbol != p->FoundState->Symbol);
|
||||||
|
if (s[0].Freq >= s[-1].Freq)
|
||||||
|
{
|
||||||
|
SwapStates(&s[0], &s[-1]);
|
||||||
|
s--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s->Freq < MAX_FREQ - 9)
|
||||||
|
{
|
||||||
|
s->Freq += 2;
|
||||||
|
c->SummFreq += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->OrderFall == 0)
|
||||||
|
{
|
||||||
|
p->MinContext = p->MaxContext = CreateSuccessors(p, True);
|
||||||
|
if (p->MinContext == 0)
|
||||||
|
{
|
||||||
|
RestartModel(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SetSuccessor(p->FoundState, REF(p->MinContext));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p->Text++ = p->FoundState->Symbol;
|
||||||
|
successor = REF(p->Text);
|
||||||
|
if (p->Text >= p->UnitsStart)
|
||||||
|
{
|
||||||
|
RestartModel(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fSuccessor)
|
||||||
|
{
|
||||||
|
if (fSuccessor <= successor)
|
||||||
|
{
|
||||||
|
CTX_PTR cs = CreateSuccessors(p, False);
|
||||||
|
if (cs == NULL)
|
||||||
|
{
|
||||||
|
RestartModel(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fSuccessor = REF(cs);
|
||||||
|
}
|
||||||
|
if (--p->OrderFall == 0)
|
||||||
|
{
|
||||||
|
successor = fSuccessor;
|
||||||
|
p->Text -= (p->MaxContext != p->MinContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetSuccessor(p->FoundState, successor);
|
||||||
|
fSuccessor = REF(p->MinContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
|
||||||
|
|
||||||
|
for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
|
||||||
|
{
|
||||||
|
unsigned ns1;
|
||||||
|
UInt32 cf, sf;
|
||||||
|
if ((ns1 = c->NumStats) != 1)
|
||||||
|
{
|
||||||
|
if ((ns1 & 1) == 0)
|
||||||
|
{
|
||||||
|
/* Expand for one UNIT */
|
||||||
|
unsigned oldNU = ns1 >> 1;
|
||||||
|
unsigned i = U2I(oldNU);
|
||||||
|
if (i != U2I(oldNU + 1))
|
||||||
|
{
|
||||||
|
void *ptr = AllocUnits(p, i + 1);
|
||||||
|
void *oldPtr;
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
RestartModel(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
oldPtr = STATS(c);
|
||||||
|
MyMem12Cpy(ptr, oldPtr, oldNU);
|
||||||
|
InsertNode(p, oldPtr, i);
|
||||||
|
c->Stats = STATS_REF(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
|
||||||
|
if (!s)
|
||||||
|
{
|
||||||
|
RestartModel(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*s = *ONE_STATE(c);
|
||||||
|
c->Stats = REF(s);
|
||||||
|
if (s->Freq < MAX_FREQ / 4 - 1)
|
||||||
|
s->Freq <<= 1;
|
||||||
|
else
|
||||||
|
s->Freq = MAX_FREQ - 4;
|
||||||
|
c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
|
||||||
|
}
|
||||||
|
cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
|
||||||
|
sf = (UInt32)s0 + c->SummFreq;
|
||||||
|
if (cf < 6 * sf)
|
||||||
|
{
|
||||||
|
cf = 1 + (cf > sf) + (cf >= 4 * sf);
|
||||||
|
c->SummFreq += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
|
||||||
|
c->SummFreq = (UInt16)(c->SummFreq + cf);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CPpmd_State *s = STATS(c) + ns1;
|
||||||
|
SetSuccessor(s, successor);
|
||||||
|
s->Symbol = p->FoundState->Symbol;
|
||||||
|
s->Freq = (Byte)cf;
|
||||||
|
c->NumStats = (UInt16)(ns1 + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->MaxContext = p->MinContext = CTX(fSuccessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Rescale(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
unsigned i, adder, sumFreq, escFreq;
|
||||||
|
CPpmd_State *stats = STATS(p->MinContext);
|
||||||
|
CPpmd_State *s = p->FoundState;
|
||||||
|
{
|
||||||
|
CPpmd_State tmp = *s;
|
||||||
|
for (; s != stats; s--)
|
||||||
|
s[0] = s[-1];
|
||||||
|
*s = tmp;
|
||||||
|
}
|
||||||
|
escFreq = p->MinContext->SummFreq - s->Freq;
|
||||||
|
s->Freq += 4;
|
||||||
|
adder = (p->OrderFall != 0);
|
||||||
|
s->Freq = (Byte)((s->Freq + adder) >> 1);
|
||||||
|
sumFreq = s->Freq;
|
||||||
|
|
||||||
|
i = p->MinContext->NumStats - 1;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
escFreq -= (++s)->Freq;
|
||||||
|
s->Freq = (Byte)((s->Freq + adder) >> 1);
|
||||||
|
sumFreq += s->Freq;
|
||||||
|
if (s[0].Freq > s[-1].Freq)
|
||||||
|
{
|
||||||
|
CPpmd_State *s1 = s;
|
||||||
|
CPpmd_State tmp = *s1;
|
||||||
|
do
|
||||||
|
s1[0] = s1[-1];
|
||||||
|
while (--s1 != stats && tmp.Freq > s1[-1].Freq);
|
||||||
|
*s1 = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (--i);
|
||||||
|
|
||||||
|
if (s->Freq == 0)
|
||||||
|
{
|
||||||
|
unsigned numStats = p->MinContext->NumStats;
|
||||||
|
unsigned n0, n1;
|
||||||
|
do { i++; } while ((--s)->Freq == 0);
|
||||||
|
escFreq += i;
|
||||||
|
p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
|
||||||
|
if (p->MinContext->NumStats == 1)
|
||||||
|
{
|
||||||
|
CPpmd_State tmp = *stats;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
|
||||||
|
escFreq >>= 1;
|
||||||
|
}
|
||||||
|
while (escFreq > 1);
|
||||||
|
InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
|
||||||
|
*(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
n0 = (numStats + 1) >> 1;
|
||||||
|
n1 = (p->MinContext->NumStats + 1) >> 1;
|
||||||
|
if (n0 != n1)
|
||||||
|
p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
|
||||||
|
}
|
||||||
|
p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
|
||||||
|
p->FoundState = STATS(p->MinContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
|
||||||
|
{
|
||||||
|
CPpmd_See *see;
|
||||||
|
unsigned nonMasked = p->MinContext->NumStats - numMasked;
|
||||||
|
if (p->MinContext->NumStats != 256)
|
||||||
|
{
|
||||||
|
see = p->See[p->NS2Indx[nonMasked - 1]] +
|
||||||
|
(nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
|
||||||
|
2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
|
||||||
|
4 * (numMasked > nonMasked) +
|
||||||
|
p->HiBitsFlag;
|
||||||
|
{
|
||||||
|
unsigned r = (see->Summ >> see->Shift);
|
||||||
|
see->Summ = (UInt16)(see->Summ - r);
|
||||||
|
*escFreq = r + (r == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
see = &p->DummySee;
|
||||||
|
*escFreq = 1;
|
||||||
|
}
|
||||||
|
return see;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void NextContext(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
|
||||||
|
if (p->OrderFall == 0 && (Byte *)c > p->Text)
|
||||||
|
p->MinContext = p->MaxContext = c;
|
||||||
|
else
|
||||||
|
UpdateModel(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ppmd7_Update1(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
CPpmd_State *s = p->FoundState;
|
||||||
|
s->Freq += 4;
|
||||||
|
p->MinContext->SummFreq += 4;
|
||||||
|
if (s[0].Freq > s[-1].Freq)
|
||||||
|
{
|
||||||
|
SwapStates(&s[0], &s[-1]);
|
||||||
|
p->FoundState = --s;
|
||||||
|
if (s->Freq > MAX_FREQ)
|
||||||
|
Rescale(p);
|
||||||
|
}
|
||||||
|
NextContext(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ppmd7_Update1_0(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
|
||||||
|
p->RunLength += p->PrevSuccess;
|
||||||
|
p->MinContext->SummFreq += 4;
|
||||||
|
if ((p->FoundState->Freq += 4) > MAX_FREQ)
|
||||||
|
Rescale(p);
|
||||||
|
NextContext(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ppmd7_UpdateBin(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
|
||||||
|
p->PrevSuccess = 1;
|
||||||
|
p->RunLength++;
|
||||||
|
NextContext(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ppmd7_Update2(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
p->MinContext->SummFreq += 4;
|
||||||
|
if ((p->FoundState->Freq += 4) > MAX_FREQ)
|
||||||
|
Rescale(p);
|
||||||
|
p->RunLength = p->InitRL;
|
||||||
|
UpdateModel(p);
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
/* Ppmd7.h -- PPMdH compression codec
|
||||||
|
2010-03-12 : Igor Pavlov : Public domain
|
||||||
|
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||||
|
|
||||||
|
/* This code supports virtual RangeDecoder and includes the implementation
|
||||||
|
of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
|
||||||
|
If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
|
||||||
|
|
||||||
|
#ifndef __PPMD7_H
|
||||||
|
#define __PPMD7_H
|
||||||
|
|
||||||
|
#include "Ppmd.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define PPMD7_MIN_ORDER 2
|
||||||
|
#define PPMD7_MAX_ORDER 64
|
||||||
|
|
||||||
|
#define PPMD7_MIN_MEM_SIZE (1 << 11)
|
||||||
|
#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
|
||||||
|
|
||||||
|
struct CPpmd7_Context_;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
struct CPpmd7_Context_ *
|
||||||
|
#else
|
||||||
|
UInt32
|
||||||
|
#endif
|
||||||
|
CPpmd7_Context_Ref;
|
||||||
|
|
||||||
|
typedef struct CPpmd7_Context_
|
||||||
|
{
|
||||||
|
UInt16 NumStats;
|
||||||
|
UInt16 SummFreq;
|
||||||
|
CPpmd_State_Ref Stats;
|
||||||
|
CPpmd7_Context_Ref Suffix;
|
||||||
|
} CPpmd7_Context;
|
||||||
|
|
||||||
|
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CPpmd7_Context *MinContext, *MaxContext;
|
||||||
|
CPpmd_State *FoundState;
|
||||||
|
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
|
||||||
|
Int32 RunLength, InitRL; /* must be 32-bit at least */
|
||||||
|
|
||||||
|
UInt32 Size;
|
||||||
|
UInt32 GlueCount;
|
||||||
|
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
|
||||||
|
UInt32 AlignOffset;
|
||||||
|
|
||||||
|
Byte Indx2Units[PPMD_NUM_INDEXES];
|
||||||
|
Byte Units2Indx[128];
|
||||||
|
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
|
||||||
|
Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
|
||||||
|
CPpmd_See DummySee, See[25][16];
|
||||||
|
UInt16 BinSumm[128][64];
|
||||||
|
} CPpmd7;
|
||||||
|
|
||||||
|
void Ppmd7_Construct(CPpmd7 *p);
|
||||||
|
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
|
||||||
|
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc);
|
||||||
|
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
|
||||||
|
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Internal Functions ---------- */
|
||||||
|
|
||||||
|
extern const Byte PPMD7_kExpEscape[16];
|
||||||
|
|
||||||
|
#ifdef PPMD_32BIT
|
||||||
|
#define Ppmd7_GetPtr(p, ptr) (ptr)
|
||||||
|
#define Ppmd7_GetContext(p, ptr) (ptr)
|
||||||
|
#define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
|
||||||
|
#else
|
||||||
|
#define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
|
||||||
|
#define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
|
||||||
|
#define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Ppmd7_Update1(CPpmd7 *p);
|
||||||
|
void Ppmd7_Update1_0(CPpmd7 *p);
|
||||||
|
void Ppmd7_Update2(CPpmd7 *p);
|
||||||
|
void Ppmd7_UpdateBin(CPpmd7 *p);
|
||||||
|
|
||||||
|
#define Ppmd7_GetBinSumm(p) \
|
||||||
|
&p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
|
||||||
|
p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
|
||||||
|
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
|
||||||
|
2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
|
||||||
|
((p->RunLength >> 26) & 0x20)]
|
||||||
|
|
||||||
|
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Decode ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt32 (*GetThreshold)(void *p, UInt32 total);
|
||||||
|
void (*Decode)(void *p, UInt32 start, UInt32 size);
|
||||||
|
UInt32 (*DecodeBit)(void *p, UInt32 size0);
|
||||||
|
} IPpmd7_RangeDec;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
IPpmd7_RangeDec p;
|
||||||
|
UInt32 Range;
|
||||||
|
UInt32 Code;
|
||||||
|
IByteIn *Stream;
|
||||||
|
} CPpmd7z_RangeDec;
|
||||||
|
|
||||||
|
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
|
||||||
|
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
|
||||||
|
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
||||||
|
|
||||||
|
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Encode ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt64 Low;
|
||||||
|
UInt32 Range;
|
||||||
|
Byte Cache;
|
||||||
|
UInt64 CacheSize;
|
||||||
|
IByteOut *Stream;
|
||||||
|
} CPpmd7z_RangeEnc;
|
||||||
|
|
||||||
|
void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p);
|
||||||
|
void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p);
|
||||||
|
|
||||||
|
void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,189 @@
|
||||||
|
/* Ppmd7Dec.c -- PPMdH Decoder
|
||||||
|
2010-03-12 : Igor Pavlov : Public domain
|
||||||
|
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Ppmd7.h"
|
||||||
|
|
||||||
|
#define kTopValue (1 << 24)
|
||||||
|
|
||||||
|
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
p->Code = 0;
|
||||||
|
p->Range = 0xFFFFFFFF;
|
||||||
|
if (p->Stream->Read((void *)p->Stream) != 0)
|
||||||
|
return False;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
|
||||||
|
return (p->Code < 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UInt32 Range_GetThreshold(void *pp, UInt32 total)
|
||||||
|
{
|
||||||
|
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
|
||||||
|
return (p->Code) / (p->Range /= total);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Range_Normalize(CPpmd7z_RangeDec *p)
|
||||||
|
{
|
||||||
|
if (p->Range < kTopValue)
|
||||||
|
{
|
||||||
|
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
|
||||||
|
p->Range <<= 8;
|
||||||
|
if (p->Range < kTopValue)
|
||||||
|
{
|
||||||
|
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
|
||||||
|
p->Range <<= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Range_Decode(void *pp, UInt32 start, UInt32 size)
|
||||||
|
{
|
||||||
|
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
|
||||||
|
p->Code -= start * p->Range;
|
||||||
|
p->Range *= size;
|
||||||
|
Range_Normalize(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
|
||||||
|
{
|
||||||
|
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
|
||||||
|
UInt32 newBound = (p->Range >> 14) * size0;
|
||||||
|
UInt32 symbol;
|
||||||
|
if (p->Code < newBound)
|
||||||
|
{
|
||||||
|
symbol = 0;
|
||||||
|
p->Range = newBound;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
symbol = 1;
|
||||||
|
p->Code -= newBound;
|
||||||
|
p->Range -= newBound;
|
||||||
|
}
|
||||||
|
Range_Normalize(p);
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
|
||||||
|
{
|
||||||
|
p->p.GetThreshold = Range_GetThreshold;
|
||||||
|
p->p.Decode = Range_Decode;
|
||||||
|
p->p.DecodeBit = Range_DecodeBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MASK(sym) ((signed char *)charMask)[sym]
|
||||||
|
|
||||||
|
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
|
||||||
|
{
|
||||||
|
size_t charMask[256 / sizeof(size_t)];
|
||||||
|
if (p->MinContext->NumStats != 1)
|
||||||
|
{
|
||||||
|
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
unsigned i;
|
||||||
|
UInt32 count, hiCnt;
|
||||||
|
if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
|
||||||
|
{
|
||||||
|
Byte symbol;
|
||||||
|
rc->Decode(rc, 0, s->Freq);
|
||||||
|
p->FoundState = s;
|
||||||
|
symbol = s->Symbol;
|
||||||
|
Ppmd7_Update1_0(p);
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
i = p->MinContext->NumStats - 1;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((hiCnt += (++s)->Freq) > count)
|
||||||
|
{
|
||||||
|
Byte symbol;
|
||||||
|
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
|
||||||
|
p->FoundState = s;
|
||||||
|
symbol = s->Symbol;
|
||||||
|
Ppmd7_Update1(p);
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (--i);
|
||||||
|
if (count >= p->MinContext->SummFreq)
|
||||||
|
return -2;
|
||||||
|
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
|
||||||
|
rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
|
||||||
|
PPMD_SetAllBitsIn256Bytes(charMask);
|
||||||
|
MASK(s->Symbol) = 0;
|
||||||
|
i = p->MinContext->NumStats - 1;
|
||||||
|
do { MASK((--s)->Symbol) = 0; } while (--i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UInt16 *prob = Ppmd7_GetBinSumm(p);
|
||||||
|
if (rc->DecodeBit(rc, *prob) == 0)
|
||||||
|
{
|
||||||
|
Byte symbol;
|
||||||
|
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
|
||||||
|
symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
|
||||||
|
Ppmd7_UpdateBin(p);
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
|
||||||
|
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
|
||||||
|
PPMD_SetAllBitsIn256Bytes(charMask);
|
||||||
|
MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
}
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
CPpmd_State *ps[256], *s;
|
||||||
|
UInt32 freqSum, count, hiCnt;
|
||||||
|
CPpmd_See *see;
|
||||||
|
unsigned i, num, numMasked = p->MinContext->NumStats;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p->OrderFall++;
|
||||||
|
if (!p->MinContext->Suffix)
|
||||||
|
return -1;
|
||||||
|
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
|
||||||
|
}
|
||||||
|
while (p->MinContext->NumStats == numMasked);
|
||||||
|
hiCnt = 0;
|
||||||
|
s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
i = 0;
|
||||||
|
num = p->MinContext->NumStats - numMasked;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int k = (int)(MASK(s->Symbol));
|
||||||
|
hiCnt += (s->Freq & k);
|
||||||
|
ps[i] = s++;
|
||||||
|
i -= k;
|
||||||
|
}
|
||||||
|
while (i != num);
|
||||||
|
|
||||||
|
see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
|
||||||
|
freqSum += hiCnt;
|
||||||
|
count = rc->GetThreshold(rc, freqSum);
|
||||||
|
|
||||||
|
if (count < hiCnt)
|
||||||
|
{
|
||||||
|
Byte symbol;
|
||||||
|
CPpmd_State **pps = ps;
|
||||||
|
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
|
||||||
|
s = *pps;
|
||||||
|
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
|
||||||
|
Ppmd_See_Update(see);
|
||||||
|
p->FoundState = s;
|
||||||
|
symbol = s->Symbol;
|
||||||
|
Ppmd7_Update2(p);
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
if (count >= freqSum)
|
||||||
|
return -2;
|
||||||
|
rc->Decode(rc, hiCnt, freqSum - hiCnt);
|
||||||
|
see->Summ = (UInt16)(see->Summ + freqSum);
|
||||||
|
do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
/* Ppmd7Enc.c -- PPMdH Encoder
|
||||||
|
2010-03-12 : Igor Pavlov : Public domain
|
||||||
|
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Ppmd7.h"
|
||||||
|
|
||||||
|
#define kTopValue (1 << 24)
|
||||||
|
|
||||||
|
void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)
|
||||||
|
{
|
||||||
|
p->Low = 0;
|
||||||
|
p->Range = 0xFFFFFFFF;
|
||||||
|
p->Cache = 0;
|
||||||
|
p->CacheSize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
|
||||||
|
{
|
||||||
|
if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)
|
||||||
|
{
|
||||||
|
Byte temp = p->Cache;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
|
||||||
|
temp = 0xFF;
|
||||||
|
}
|
||||||
|
while(--p->CacheSize != 0);
|
||||||
|
p->Cache = (Byte)((UInt32)p->Low >> 24);
|
||||||
|
}
|
||||||
|
p->CacheSize++;
|
||||||
|
p->Low = (UInt32)p->Low << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
|
||||||
|
{
|
||||||
|
p->Low += start * (p->Range /= total);
|
||||||
|
p->Range *= size;
|
||||||
|
while (p->Range < kTopValue)
|
||||||
|
{
|
||||||
|
p->Range <<= 8;
|
||||||
|
RangeEnc_ShiftLow(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)
|
||||||
|
{
|
||||||
|
p->Range = (p->Range >> 14) * size0;
|
||||||
|
while (p->Range < kTopValue)
|
||||||
|
{
|
||||||
|
p->Range <<= 8;
|
||||||
|
RangeEnc_ShiftLow(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)
|
||||||
|
{
|
||||||
|
UInt32 newBound = (p->Range >> 14) * size0;
|
||||||
|
p->Low += newBound;
|
||||||
|
p->Range -= newBound;
|
||||||
|
while (p->Range < kTopValue)
|
||||||
|
{
|
||||||
|
p->Range <<= 8;
|
||||||
|
RangeEnc_ShiftLow(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
RangeEnc_ShiftLow(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MASK(sym) ((signed char *)charMask)[sym]
|
||||||
|
|
||||||
|
void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)
|
||||||
|
{
|
||||||
|
size_t charMask[256 / sizeof(size_t)];
|
||||||
|
if (p->MinContext->NumStats != 1)
|
||||||
|
{
|
||||||
|
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
UInt32 sum;
|
||||||
|
unsigned i;
|
||||||
|
if (s->Symbol == symbol)
|
||||||
|
{
|
||||||
|
RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);
|
||||||
|
p->FoundState = s;
|
||||||
|
Ppmd7_Update1_0(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
sum = s->Freq;
|
||||||
|
i = p->MinContext->NumStats - 1;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((++s)->Symbol == symbol)
|
||||||
|
{
|
||||||
|
RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);
|
||||||
|
p->FoundState = s;
|
||||||
|
Ppmd7_Update1(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sum += s->Freq;
|
||||||
|
}
|
||||||
|
while (--i);
|
||||||
|
|
||||||
|
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
|
||||||
|
PPMD_SetAllBitsIn256Bytes(charMask);
|
||||||
|
MASK(s->Symbol) = 0;
|
||||||
|
i = p->MinContext->NumStats - 1;
|
||||||
|
do { MASK((--s)->Symbol) = 0; } while (--i);
|
||||||
|
RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UInt16 *prob = Ppmd7_GetBinSumm(p);
|
||||||
|
CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
|
||||||
|
if (s->Symbol == symbol)
|
||||||
|
{
|
||||||
|
RangeEnc_EncodeBit_0(rc, *prob);
|
||||||
|
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
|
||||||
|
p->FoundState = s;
|
||||||
|
Ppmd7_UpdateBin(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RangeEnc_EncodeBit_1(rc, *prob);
|
||||||
|
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
|
||||||
|
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
|
||||||
|
PPMD_SetAllBitsIn256Bytes(charMask);
|
||||||
|
MASK(s->Symbol) = 0;
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UInt32 escFreq;
|
||||||
|
CPpmd_See *see;
|
||||||
|
CPpmd_State *s;
|
||||||
|
UInt32 sum;
|
||||||
|
unsigned i, numMasked = p->MinContext->NumStats;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p->OrderFall++;
|
||||||
|
if (!p->MinContext->Suffix)
|
||||||
|
return; /* EndMarker (symbol = -1) */
|
||||||
|
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
|
||||||
|
}
|
||||||
|
while (p->MinContext->NumStats == numMasked);
|
||||||
|
|
||||||
|
see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);
|
||||||
|
s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
sum = 0;
|
||||||
|
i = p->MinContext->NumStats;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int cur = s->Symbol;
|
||||||
|
if (cur == symbol)
|
||||||
|
{
|
||||||
|
UInt32 low = sum;
|
||||||
|
CPpmd_State *s1 = s;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
sum += (s->Freq & (int)(MASK(s->Symbol)));
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
while (--i);
|
||||||
|
RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);
|
||||||
|
Ppmd_See_Update(see);
|
||||||
|
p->FoundState = s1;
|
||||||
|
Ppmd7_Update2(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sum += (s->Freq & (int)(MASK(cur)));
|
||||||
|
MASK(cur) = 0;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
while (--i);
|
||||||
|
|
||||||
|
RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);
|
||||||
|
see->Summ = (UInt16)(see->Summ + sum + escFreq);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* Precomp.h -- StdAfx
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_PRECOMP_H
|
||||||
|
#define __7Z_PRECOMP_H
|
||||||
|
|
||||||
|
#include "Compiler.h"
|
||||||
|
/* #include "7zTypes.h" */
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* RotateDefs.h -- Rotate functions
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __ROTATE_DEFS_H
|
||||||
|
#define __ROTATE_DEFS_H
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// #if (_MSC_VER >= 1200)
|
||||||
|
#pragma intrinsic(_rotl)
|
||||||
|
#pragma intrinsic(_rotr)
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
#define rotlFixed(x, n) _rotl((x), (n))
|
||||||
|
#define rotrFixed(x, n) _rotr((x), (n))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||||
|
#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,206 @@
|
||||||
|
/* Crypto/Sha256.c -- SHA-256 Hash
|
||||||
|
2010-06-11 : Igor Pavlov : Public domain
|
||||||
|
This code is based on public domain code from Wei Dai's Crypto++ library. */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "RotateDefs.h"
|
||||||
|
#include "Sha256.h"
|
||||||
|
|
||||||
|
/* define it for speed optimization */
|
||||||
|
/* #define _SHA256_UNROLL */
|
||||||
|
/* #define _SHA256_UNROLL2 */
|
||||||
|
|
||||||
|
void Sha256_Init(CSha256 *p)
|
||||||
|
{
|
||||||
|
p->state[0] = 0x6a09e667;
|
||||||
|
p->state[1] = 0xbb67ae85;
|
||||||
|
p->state[2] = 0x3c6ef372;
|
||||||
|
p->state[3] = 0xa54ff53a;
|
||||||
|
p->state[4] = 0x510e527f;
|
||||||
|
p->state[5] = 0x9b05688c;
|
||||||
|
p->state[6] = 0x1f83d9ab;
|
||||||
|
p->state[7] = 0x5be0cd19;
|
||||||
|
p->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22))
|
||||||
|
#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25))
|
||||||
|
#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3))
|
||||||
|
#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10))
|
||||||
|
|
||||||
|
#define blk0(i) (W[i] = data[i])
|
||||||
|
#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15]))
|
||||||
|
|
||||||
|
#define Ch(x,y,z) (z^(x&(y^z)))
|
||||||
|
#define Maj(x,y,z) ((x&y)|(z&(x|y)))
|
||||||
|
|
||||||
|
#define a(i) T[(0-(i))&7]
|
||||||
|
#define b(i) T[(1-(i))&7]
|
||||||
|
#define c(i) T[(2-(i))&7]
|
||||||
|
#define d(i) T[(3-(i))&7]
|
||||||
|
#define e(i) T[(4-(i))&7]
|
||||||
|
#define f(i) T[(5-(i))&7]
|
||||||
|
#define g(i) T[(6-(i))&7]
|
||||||
|
#define h(i) T[(7-(i))&7]
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _SHA256_UNROLL2
|
||||||
|
|
||||||
|
#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\
|
||||||
|
d += h; h += S0(a) + Maj(a, b, c)
|
||||||
|
|
||||||
|
#define RX_8(i) \
|
||||||
|
R(a,b,c,d,e,f,g,h, i); \
|
||||||
|
R(h,a,b,c,d,e,f,g, i+1); \
|
||||||
|
R(g,h,a,b,c,d,e,f, i+2); \
|
||||||
|
R(f,g,h,a,b,c,d,e, i+3); \
|
||||||
|
R(e,f,g,h,a,b,c,d, i+4); \
|
||||||
|
R(d,e,f,g,h,a,b,c, i+5); \
|
||||||
|
R(c,d,e,f,g,h,a,b, i+6); \
|
||||||
|
R(b,c,d,e,f,g,h,a, i+7)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\
|
||||||
|
d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
|
||||||
|
|
||||||
|
#ifdef _SHA256_UNROLL
|
||||||
|
|
||||||
|
#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const UInt32 K[64] = {
|
||||||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||||
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||||
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||||
|
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||||
|
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||||
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||||
|
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||||
|
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||||
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||||
|
};
|
||||||
|
|
||||||
|
static void Sha256_Transform(UInt32 *state, const UInt32 *data)
|
||||||
|
{
|
||||||
|
UInt32 W[16];
|
||||||
|
unsigned j;
|
||||||
|
#ifdef _SHA256_UNROLL2
|
||||||
|
UInt32 a,b,c,d,e,f,g,h;
|
||||||
|
a = state[0];
|
||||||
|
b = state[1];
|
||||||
|
c = state[2];
|
||||||
|
d = state[3];
|
||||||
|
e = state[4];
|
||||||
|
f = state[5];
|
||||||
|
g = state[6];
|
||||||
|
h = state[7];
|
||||||
|
#else
|
||||||
|
UInt32 T[8];
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
T[j] = state[j];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (j = 0; j < 64; j += 16)
|
||||||
|
{
|
||||||
|
#if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2)
|
||||||
|
RX_8(0); RX_8(8);
|
||||||
|
#else
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < 16; i++) { R(i); }
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _SHA256_UNROLL2
|
||||||
|
state[0] += a;
|
||||||
|
state[1] += b;
|
||||||
|
state[2] += c;
|
||||||
|
state[3] += d;
|
||||||
|
state[4] += e;
|
||||||
|
state[5] += f;
|
||||||
|
state[6] += g;
|
||||||
|
state[7] += h;
|
||||||
|
#else
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
state[j] += T[j];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Wipe variables */
|
||||||
|
/* memset(W, 0, sizeof(W)); */
|
||||||
|
/* memset(T, 0, sizeof(T)); */
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef S0
|
||||||
|
#undef S1
|
||||||
|
#undef s0
|
||||||
|
#undef s1
|
||||||
|
|
||||||
|
static void Sha256_WriteByteBlock(CSha256 *p)
|
||||||
|
{
|
||||||
|
UInt32 data32[16];
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
data32[i] =
|
||||||
|
((UInt32)(p->buffer[i * 4 ]) << 24) +
|
||||||
|
((UInt32)(p->buffer[i * 4 + 1]) << 16) +
|
||||||
|
((UInt32)(p->buffer[i * 4 + 2]) << 8) +
|
||||||
|
((UInt32)(p->buffer[i * 4 + 3]));
|
||||||
|
Sha256_Transform(p->state, data32);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
|
||||||
|
{
|
||||||
|
UInt32 curBufferPos = (UInt32)p->count & 0x3F;
|
||||||
|
while (size > 0)
|
||||||
|
{
|
||||||
|
p->buffer[curBufferPos++] = *data++;
|
||||||
|
p->count++;
|
||||||
|
size--;
|
||||||
|
if (curBufferPos == 64)
|
||||||
|
{
|
||||||
|
curBufferPos = 0;
|
||||||
|
Sha256_WriteByteBlock(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sha256_Final(CSha256 *p, Byte *digest)
|
||||||
|
{
|
||||||
|
UInt64 lenInBits = (p->count << 3);
|
||||||
|
UInt32 curBufferPos = (UInt32)p->count & 0x3F;
|
||||||
|
unsigned i;
|
||||||
|
p->buffer[curBufferPos++] = 0x80;
|
||||||
|
while (curBufferPos != (64 - 8))
|
||||||
|
{
|
||||||
|
curBufferPos &= 0x3F;
|
||||||
|
if (curBufferPos == 0)
|
||||||
|
Sha256_WriteByteBlock(p);
|
||||||
|
p->buffer[curBufferPos++] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56);
|
||||||
|
lenInBits <<= 8;
|
||||||
|
}
|
||||||
|
Sha256_WriteByteBlock(p);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
*digest++ = (Byte)(p->state[i] >> 24);
|
||||||
|
*digest++ = (Byte)(p->state[i] >> 16);
|
||||||
|
*digest++ = (Byte)(p->state[i] >> 8);
|
||||||
|
*digest++ = (Byte)(p->state[i]);
|
||||||
|
}
|
||||||
|
Sha256_Init(p);
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* Sha256.h -- SHA-256 Hash
|
||||||
|
2013-01-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __CRYPTO_SHA256_H
|
||||||
|
#define __CRYPTO_SHA256_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define SHA256_DIGEST_SIZE 32
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt32 state[8];
|
||||||
|
UInt64 count;
|
||||||
|
Byte buffer[64];
|
||||||
|
} CSha256;
|
||||||
|
|
||||||
|
void Sha256_Init(CSha256 *p);
|
||||||
|
void Sha256_Update(CSha256 *p, const Byte *data, size_t size);
|
||||||
|
void Sha256_Final(CSha256 *p, Byte *digest);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,141 @@
|
||||||
|
/* Sort.c -- Sort functions
|
||||||
|
2014-04-05 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Sort.h"
|
||||||
|
|
||||||
|
#define HeapSortDown(p, k, size, temp) \
|
||||||
|
{ for (;;) { \
|
||||||
|
size_t s = (k << 1); \
|
||||||
|
if (s > size) break; \
|
||||||
|
if (s < size && p[s + 1] > p[s]) s++; \
|
||||||
|
if (temp >= p[s]) break; \
|
||||||
|
p[k] = p[s]; k = s; \
|
||||||
|
} p[k] = temp; }
|
||||||
|
|
||||||
|
void HeapSort(UInt32 *p, size_t size)
|
||||||
|
{
|
||||||
|
if (size <= 1)
|
||||||
|
return;
|
||||||
|
p--;
|
||||||
|
{
|
||||||
|
size_t i = size / 2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
UInt32 temp = p[i];
|
||||||
|
size_t k = i;
|
||||||
|
HeapSortDown(p, k, size, temp)
|
||||||
|
}
|
||||||
|
while (--i != 0);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
do
|
||||||
|
{
|
||||||
|
size_t k = 1;
|
||||||
|
UInt32 temp = p[size];
|
||||||
|
p[size--] = p[1];
|
||||||
|
HeapSortDown(p, k, size, temp)
|
||||||
|
}
|
||||||
|
while (size > 1);
|
||||||
|
*/
|
||||||
|
while (size > 3)
|
||||||
|
{
|
||||||
|
UInt32 temp = p[size];
|
||||||
|
size_t k = (p[3] > p[2]) ? 3 : 2;
|
||||||
|
p[size--] = p[1];
|
||||||
|
p[1] = p[k];
|
||||||
|
HeapSortDown(p, k, size, temp)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
UInt32 temp = p[size];
|
||||||
|
p[size] = p[1];
|
||||||
|
if (size > 2 && p[2] < temp)
|
||||||
|
{
|
||||||
|
p[1] = p[2];
|
||||||
|
p[2] = temp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p[1] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeapSort64(UInt64 *p, size_t size)
|
||||||
|
{
|
||||||
|
if (size <= 1)
|
||||||
|
return;
|
||||||
|
p--;
|
||||||
|
{
|
||||||
|
size_t i = size / 2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
UInt64 temp = p[i];
|
||||||
|
size_t k = i;
|
||||||
|
HeapSortDown(p, k, size, temp)
|
||||||
|
}
|
||||||
|
while (--i != 0);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
do
|
||||||
|
{
|
||||||
|
size_t k = 1;
|
||||||
|
UInt64 temp = p[size];
|
||||||
|
p[size--] = p[1];
|
||||||
|
HeapSortDown(p, k, size, temp)
|
||||||
|
}
|
||||||
|
while (size > 1);
|
||||||
|
*/
|
||||||
|
while (size > 3)
|
||||||
|
{
|
||||||
|
UInt64 temp = p[size];
|
||||||
|
size_t k = (p[3] > p[2]) ? 3 : 2;
|
||||||
|
p[size--] = p[1];
|
||||||
|
p[1] = p[k];
|
||||||
|
HeapSortDown(p, k, size, temp)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
UInt64 temp = p[size];
|
||||||
|
p[size] = p[1];
|
||||||
|
if (size > 2 && p[2] < temp)
|
||||||
|
{
|
||||||
|
p[1] = p[2];
|
||||||
|
p[2] = temp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p[1] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define HeapSortRefDown(p, vals, n, size, temp) \
|
||||||
|
{ size_t k = n; UInt32 val = vals[temp]; for (;;) { \
|
||||||
|
size_t s = (k << 1); \
|
||||||
|
if (s > size) break; \
|
||||||
|
if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \
|
||||||
|
if (val >= vals[p[s]]) break; \
|
||||||
|
p[k] = p[s]; k = s; \
|
||||||
|
} p[k] = temp; }
|
||||||
|
|
||||||
|
void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size)
|
||||||
|
{
|
||||||
|
if (size <= 1)
|
||||||
|
return;
|
||||||
|
p--;
|
||||||
|
{
|
||||||
|
size_t i = size / 2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
UInt32 temp = p[i];
|
||||||
|
HeapSortRefDown(p, vals, i, size, temp);
|
||||||
|
}
|
||||||
|
while (--i != 0);
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
UInt32 temp = p[size];
|
||||||
|
p[size--] = p[1];
|
||||||
|
HeapSortRefDown(p, vals, 1, size, temp);
|
||||||
|
}
|
||||||
|
while (size > 1);
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* Sort.h -- Sort functions
|
||||||
|
2014-04-05 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_SORT_H
|
||||||
|
#define __7Z_SORT_H
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
void HeapSort(UInt32 *p, size_t size);
|
||||||
|
void HeapSort64(UInt64 *p, size_t size);
|
||||||
|
|
||||||
|
/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,93 @@
|
||||||
|
/* Threads.c -- multithreading library
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32_WCE
|
||||||
|
#include <process.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Threads.h"
|
||||||
|
|
||||||
|
static WRes GetError()
|
||||||
|
{
|
||||||
|
DWORD res = GetLastError();
|
||||||
|
return (res) ? (WRes)(res) : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
|
||||||
|
WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
|
||||||
|
|
||||||
|
WRes HandlePtr_Close(HANDLE *p)
|
||||||
|
{
|
||||||
|
if (*p != NULL)
|
||||||
|
if (!CloseHandle(*p))
|
||||||
|
return GetError();
|
||||||
|
*p = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }
|
||||||
|
|
||||||
|
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||||
|
{
|
||||||
|
/* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||||
|
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
|
||||||
|
DWORD threadId;
|
||||||
|
*p = CreateThread(0, 0, func, param, 0, &threadId);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
unsigned threadId;
|
||||||
|
*p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
||||||
|
return HandleToWRes(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
|
||||||
|
{
|
||||||
|
*p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
|
||||||
|
return HandleToWRes(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }
|
||||||
|
WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }
|
||||||
|
|
||||||
|
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }
|
||||||
|
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }
|
||||||
|
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }
|
||||||
|
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }
|
||||||
|
|
||||||
|
|
||||||
|
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
|
||||||
|
{
|
||||||
|
*p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
|
||||||
|
return HandleToWRes(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
|
||||||
|
{ return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
|
||||||
|
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
|
||||||
|
{ return Semaphore_Release(p, (LONG)num, NULL); }
|
||||||
|
WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
|
||||||
|
|
||||||
|
WRes CriticalSection_Init(CCriticalSection *p)
|
||||||
|
{
|
||||||
|
/* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
__try
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
InitializeCriticalSection(p);
|
||||||
|
/* InitializeCriticalSectionAndSpinCount(p, 0); */
|
||||||
|
}
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* Threads.h -- multithreading library
|
||||||
|
2013-11-12 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_THREADS_H
|
||||||
|
#define __7Z_THREADS_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "7zTypes.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
WRes HandlePtr_Close(HANDLE *h);
|
||||||
|
WRes Handle_WaitObject(HANDLE h);
|
||||||
|
|
||||||
|
typedef HANDLE CThread;
|
||||||
|
#define Thread_Construct(p) *(p) = NULL
|
||||||
|
#define Thread_WasCreated(p) (*(p) != NULL)
|
||||||
|
#define Thread_Close(p) HandlePtr_Close(p)
|
||||||
|
#define Thread_Wait(p) Handle_WaitObject(*(p))
|
||||||
|
|
||||||
|
typedef
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
DWORD
|
||||||
|
#else
|
||||||
|
unsigned
|
||||||
|
#endif
|
||||||
|
THREAD_FUNC_RET_TYPE;
|
||||||
|
|
||||||
|
#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
|
||||||
|
#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
|
||||||
|
typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
|
||||||
|
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
|
||||||
|
|
||||||
|
typedef HANDLE CEvent;
|
||||||
|
typedef CEvent CAutoResetEvent;
|
||||||
|
typedef CEvent CManualResetEvent;
|
||||||
|
#define Event_Construct(p) *(p) = NULL
|
||||||
|
#define Event_IsCreated(p) (*(p) != NULL)
|
||||||
|
#define Event_Close(p) HandlePtr_Close(p)
|
||||||
|
#define Event_Wait(p) Handle_WaitObject(*(p))
|
||||||
|
WRes Event_Set(CEvent *p);
|
||||||
|
WRes Event_Reset(CEvent *p);
|
||||||
|
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
|
||||||
|
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
|
||||||
|
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
|
||||||
|
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
|
||||||
|
|
||||||
|
typedef HANDLE CSemaphore;
|
||||||
|
#define Semaphore_Construct(p) (*p) = NULL
|
||||||
|
#define Semaphore_Close(p) HandlePtr_Close(p)
|
||||||
|
#define Semaphore_Wait(p) Handle_WaitObject(*(p))
|
||||||
|
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
|
||||||
|
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
|
||||||
|
WRes Semaphore_Release1(CSemaphore *p);
|
||||||
|
|
||||||
|
typedef CRITICAL_SECTION CCriticalSection;
|
||||||
|
WRes CriticalSection_Init(CCriticalSection *p);
|
||||||
|
#define CriticalSection_Delete(p) DeleteCriticalSection(p)
|
||||||
|
#define CriticalSection_Enter(p) EnterCriticalSection(p)
|
||||||
|
#define CriticalSection_Leave(p) LeaveCriticalSection(p)
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,229 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=7z - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "7z.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "7z - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /Yu"Precomp.h" /FD /c
|
||||||
|
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7zDec.exe" /opt:NOWIN98
|
||||||
|
# SUBTRACT LINK32 /pdb:none
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7zDec.exe" /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "7z - Win32 Release"
|
||||||
|
# Name "7z - Win32 Debug"
|
||||||
|
# Begin Group "Common"
|
||||||
|
|
||||||
|
# PROP Default_Filter ""
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7z.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zAlloc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zAlloc.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zArcIn.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zBuf.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zBuf.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zCrc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zCrc.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zCrcOpt.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zDec.c
|
||||||
|
# ADD CPP /D "_7ZIP_PPMD_SUPPPORT"
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zFile.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zFile.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zStream.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zTypes.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bcj2.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bcj2.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bra.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bra.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bra86.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\CpuArch.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\CpuArch.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Lzma2Dec.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Lzma2Dec.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaDec.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaDec.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Ppmd.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Ppmd7.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Ppmd7.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Ppmd7Dec.c
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Spec"
|
||||||
|
|
||||||
|
# PROP Default_Filter ""
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Compiler.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Precomp.c
|
||||||
|
# ADD CPP /Yc"Precomp.h"
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Precomp.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\7zMain.c
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
|
@ -0,0 +1,29 @@
|
||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "7z"=.\7z.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
|
@ -0,0 +1,546 @@
|
||||||
|
/* 7zMain.c - Test application for 7z Decoder
|
||||||
|
2015-01-02 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../../7z.h"
|
||||||
|
#include "../../7zAlloc.h"
|
||||||
|
#include "../../7zBuf.h"
|
||||||
|
#include "../../7zCrc.h"
|
||||||
|
#include "../../7zFile.h"
|
||||||
|
#include "../../7zVersion.h"
|
||||||
|
|
||||||
|
#ifndef USE_WINDOWS_FILE
|
||||||
|
/* for mkdir */
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <direct.h>
|
||||||
|
#else
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||||
|
|
||||||
|
static int Buf_EnsureSize(CBuf *dest, size_t size)
|
||||||
|
{
|
||||||
|
if (dest->size >= size)
|
||||||
|
return 1;
|
||||||
|
Buf_Free(dest, &g_Alloc);
|
||||||
|
return Buf_Create(dest, size, &g_Alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
|
||||||
|
static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||||
|
|
||||||
|
static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen)
|
||||||
|
{
|
||||||
|
size_t destPos = 0, srcPos = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
unsigned numAdds;
|
||||||
|
UInt32 value;
|
||||||
|
if (srcPos == srcLen)
|
||||||
|
{
|
||||||
|
*destLen = destPos;
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
value = src[srcPos++];
|
||||||
|
if (value < 0x80)
|
||||||
|
{
|
||||||
|
if (dest)
|
||||||
|
dest[destPos] = (char)value;
|
||||||
|
destPos++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (value >= 0xD800 && value < 0xE000)
|
||||||
|
{
|
||||||
|
UInt32 c2;
|
||||||
|
if (value >= 0xDC00 || srcPos == srcLen)
|
||||||
|
break;
|
||||||
|
c2 = src[srcPos++];
|
||||||
|
if (c2 < 0xDC00 || c2 >= 0xE000)
|
||||||
|
break;
|
||||||
|
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
|
||||||
|
}
|
||||||
|
for (numAdds = 1; numAdds < 5; numAdds++)
|
||||||
|
if (value < (((UInt32)1) << (numAdds * 5 + 6)))
|
||||||
|
break;
|
||||||
|
if (dest)
|
||||||
|
dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
|
||||||
|
destPos++;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
numAdds--;
|
||||||
|
if (dest)
|
||||||
|
dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
|
||||||
|
destPos++;
|
||||||
|
}
|
||||||
|
while (numAdds != 0);
|
||||||
|
}
|
||||||
|
*destLen = destPos;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)
|
||||||
|
{
|
||||||
|
size_t destLen = 0;
|
||||||
|
Bool res;
|
||||||
|
Utf16_To_Utf8(NULL, &destLen, src, srcLen);
|
||||||
|
destLen += 1;
|
||||||
|
if (!Buf_EnsureSize(dest, destLen))
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen);
|
||||||
|
dest->data[destLen] = 0;
|
||||||
|
return res ? SZ_OK : SZ_ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s
|
||||||
|
#ifdef _WIN32
|
||||||
|
, UINT codePage
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
unsigned len = 0;
|
||||||
|
for (len = 0; s[len] != 0; len++);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
{
|
||||||
|
unsigned size = len * 3 + 100;
|
||||||
|
if (!Buf_EnsureSize(buf, size))
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
{
|
||||||
|
buf->data[0] = 0;
|
||||||
|
if (len != 0)
|
||||||
|
{
|
||||||
|
char defaultChar = '_';
|
||||||
|
BOOL defUsed;
|
||||||
|
unsigned numChars = 0;
|
||||||
|
numChars = WideCharToMultiByte(codePage, 0, s, len, (char *)buf->data, size, &defaultChar, &defUsed);
|
||||||
|
if (numChars == 0 || numChars >= size)
|
||||||
|
return SZ_ERROR_FAIL;
|
||||||
|
buf->data[numChars] = 0;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return Utf16_To_Utf8Buf(buf, s, len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef USE_WINDOWS_FILE
|
||||||
|
static UINT g_FileCodePage = CP_ACP;
|
||||||
|
#endif
|
||||||
|
#define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage
|
||||||
|
#else
|
||||||
|
#define MY_FILE_CODE_PAGE_PARAM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static WRes MyCreateDir(const UInt16 *name)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
|
||||||
|
return CreateDirectoryW(name, NULL) ? 0 : GetLastError();
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
CBuf buf;
|
||||||
|
WRes res;
|
||||||
|
Buf_Init(&buf);
|
||||||
|
RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM));
|
||||||
|
|
||||||
|
res =
|
||||||
|
#ifdef _WIN32
|
||||||
|
_mkdir((const char *)buf.data)
|
||||||
|
#else
|
||||||
|
mkdir((const char *)buf.data, 0777)
|
||||||
|
#endif
|
||||||
|
== 0 ? 0 : errno;
|
||||||
|
Buf_Free(&buf, &g_Alloc);
|
||||||
|
return res;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
return OutFile_OpenW(p, name);
|
||||||
|
#else
|
||||||
|
CBuf buf;
|
||||||
|
WRes res;
|
||||||
|
Buf_Init(&buf);
|
||||||
|
RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM));
|
||||||
|
res = OutFile_Open(p, (const char *)buf.data);
|
||||||
|
Buf_Free(&buf, &g_Alloc);
|
||||||
|
return res;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes PrintString(const UInt16 *s)
|
||||||
|
{
|
||||||
|
CBuf buf;
|
||||||
|
SRes res;
|
||||||
|
Buf_Init(&buf);
|
||||||
|
res = Utf16_To_Char(&buf, s
|
||||||
|
#ifdef _WIN32
|
||||||
|
, CP_OEMCP
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
fputs((const char *)buf.data, stdout);
|
||||||
|
Buf_Free(&buf, &g_Alloc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UInt64ToStr(UInt64 value, char *s)
|
||||||
|
{
|
||||||
|
char temp[32];
|
||||||
|
int pos = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
temp[pos++] = (char)('0' + (unsigned)(value % 10));
|
||||||
|
value /= 10;
|
||||||
|
}
|
||||||
|
while (value != 0);
|
||||||
|
do
|
||||||
|
*s++ = temp[--pos];
|
||||||
|
while (pos);
|
||||||
|
*s = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *UIntToStr(char *s, unsigned value, int numDigits)
|
||||||
|
{
|
||||||
|
char temp[16];
|
||||||
|
int pos = 0;
|
||||||
|
do
|
||||||
|
temp[pos++] = (char)('0' + (value % 10));
|
||||||
|
while (value /= 10);
|
||||||
|
for (numDigits -= pos; numDigits > 0; numDigits--)
|
||||||
|
*s++ = '0';
|
||||||
|
do
|
||||||
|
*s++ = temp[--pos];
|
||||||
|
while (pos);
|
||||||
|
*s = '\0';
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UIntToStr_2(char *s, unsigned value)
|
||||||
|
{
|
||||||
|
s[0] = (char)('0' + (value / 10));
|
||||||
|
s[1] = (char)('0' + (value % 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PERIOD_4 (4 * 365 + 1)
|
||||||
|
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
||||||
|
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
||||||
|
|
||||||
|
static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s)
|
||||||
|
{
|
||||||
|
unsigned year, mon, hour, min, sec;
|
||||||
|
Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||||
|
unsigned t;
|
||||||
|
UInt32 v;
|
||||||
|
UInt64 v64 = nt->Low | ((UInt64)nt->High << 32);
|
||||||
|
v64 /= 10000000;
|
||||||
|
sec = (unsigned)(v64 % 60); v64 /= 60;
|
||||||
|
min = (unsigned)(v64 % 60); v64 /= 60;
|
||||||
|
hour = (unsigned)(v64 % 24); v64 /= 24;
|
||||||
|
|
||||||
|
v = (UInt32)v64;
|
||||||
|
|
||||||
|
year = (unsigned)(1601 + v / PERIOD_400 * 400);
|
||||||
|
v %= PERIOD_400;
|
||||||
|
|
||||||
|
t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100;
|
||||||
|
t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4;
|
||||||
|
t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365;
|
||||||
|
|
||||||
|
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
|
||||||
|
ms[1] = 29;
|
||||||
|
for (mon = 0;; mon++)
|
||||||
|
{
|
||||||
|
unsigned s = ms[mon];
|
||||||
|
if (v < s)
|
||||||
|
break;
|
||||||
|
v -= s;
|
||||||
|
}
|
||||||
|
s = UIntToStr(s, year, 4); *s++ = '-';
|
||||||
|
UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3;
|
||||||
|
UIntToStr_2(s, (unsigned)v + 1); s[2] = ' '; s += 3;
|
||||||
|
UIntToStr_2(s, hour); s[2] = ':'; s += 3;
|
||||||
|
UIntToStr_2(s, min); s[2] = ':'; s += 3;
|
||||||
|
UIntToStr_2(s, sec); s[2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintError(const char *sz)
|
||||||
|
{
|
||||||
|
printf("\nERROR: %s\n", sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
static void GetAttribString(UInt32 wa, Bool isDir, char *s)
|
||||||
|
{
|
||||||
|
s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.');
|
||||||
|
s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.');
|
||||||
|
s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.');
|
||||||
|
s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.');
|
||||||
|
s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.');
|
||||||
|
s[5] = '\0';
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void GetAttribString(UInt32, Bool, char *s)
|
||||||
|
{
|
||||||
|
s[0] = '\0';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// #define NUM_PARENTS_MAX 128
|
||||||
|
|
||||||
|
int MY_CDECL main(int numargs, char *args[])
|
||||||
|
{
|
||||||
|
CFileInStream archiveStream;
|
||||||
|
CLookToRead lookStream;
|
||||||
|
CSzArEx db;
|
||||||
|
SRes res;
|
||||||
|
ISzAlloc allocImp;
|
||||||
|
ISzAlloc allocTempImp;
|
||||||
|
UInt16 *temp = NULL;
|
||||||
|
size_t tempSize = 0;
|
||||||
|
// UInt32 parents[NUM_PARENTS_MAX];
|
||||||
|
|
||||||
|
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");
|
||||||
|
if (numargs == 1)
|
||||||
|
{
|
||||||
|
printf(
|
||||||
|
"Usage: 7zDec <command> <archive_name>\n\n"
|
||||||
|
"<Commands>\n"
|
||||||
|
" e: Extract files from archive (without using directory names)\n"
|
||||||
|
" l: List contents of archive\n"
|
||||||
|
" t: Test integrity of archive\n"
|
||||||
|
" x: eXtract files with full paths\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (numargs < 3)
|
||||||
|
{
|
||||||
|
PrintError("incorrect command");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE)
|
||||||
|
g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
allocImp.Alloc = SzAlloc;
|
||||||
|
allocImp.Free = SzFree;
|
||||||
|
|
||||||
|
allocTempImp.Alloc = SzAllocTemp;
|
||||||
|
allocTempImp.Free = SzFreeTemp;
|
||||||
|
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
if (InFile_OpenW(&archiveStream.file, L"\test.7z"))
|
||||||
|
#else
|
||||||
|
if (InFile_Open(&archiveStream.file, args[2]))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
PrintError("can not open input file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInStream_CreateVTable(&archiveStream);
|
||||||
|
LookToRead_CreateVTable(&lookStream, False);
|
||||||
|
|
||||||
|
lookStream.realStream = &archiveStream.s;
|
||||||
|
LookToRead_Init(&lookStream);
|
||||||
|
|
||||||
|
CrcGenerateTable();
|
||||||
|
|
||||||
|
SzArEx_Init(&db);
|
||||||
|
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
char *command = args[1];
|
||||||
|
int listCommand = 0, testCommand = 0, fullPaths = 0;
|
||||||
|
if (strcmp(command, "l") == 0) listCommand = 1;
|
||||||
|
else if (strcmp(command, "t") == 0) testCommand = 1;
|
||||||
|
else if (strcmp(command, "e") == 0) { }
|
||||||
|
else if (strcmp(command, "x") == 0) { fullPaths = 1; }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintError("incorrect command");
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if you need cache, use these 3 variables.
|
||||||
|
if you use external function, you can make these variable as static.
|
||||||
|
*/
|
||||||
|
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
|
||||||
|
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
||||||
|
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
||||||
|
|
||||||
|
for (i = 0; i < db.NumFiles; i++)
|
||||||
|
{
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t outSizeProcessed = 0;
|
||||||
|
// const CSzFileItem *f = db.Files + i;
|
||||||
|
size_t len;
|
||||||
|
int isDir = SzArEx_IsDir(&db, i);
|
||||||
|
if (listCommand == 0 && isDir && !fullPaths)
|
||||||
|
continue;
|
||||||
|
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
|
||||||
|
// len = SzArEx_GetFullNameLen(&db, i);
|
||||||
|
|
||||||
|
if (len > tempSize)
|
||||||
|
{
|
||||||
|
SzFree(NULL, temp);
|
||||||
|
tempSize = len;
|
||||||
|
temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));
|
||||||
|
if (!temp)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_MEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SzArEx_GetFileNameUtf16(&db, i, temp);
|
||||||
|
/*
|
||||||
|
if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (listCommand)
|
||||||
|
{
|
||||||
|
char attr[8], s[32], t[32];
|
||||||
|
UInt64 fileSize;
|
||||||
|
|
||||||
|
GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr);
|
||||||
|
|
||||||
|
fileSize = SzArEx_GetFileSize(&db, i);
|
||||||
|
UInt64ToStr(fileSize, s);
|
||||||
|
if (SzBitWithVals_Check(&db.MTime, i))
|
||||||
|
ConvertFileTimeToString(&db.MTime.Vals[i], t);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t j;
|
||||||
|
for (j = 0; j < 19; j++)
|
||||||
|
t[j] = ' ';
|
||||||
|
t[j] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s %s %10s ", t, attr, s);
|
||||||
|
res = PrintString(temp);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (isDir)
|
||||||
|
printf("/");
|
||||||
|
printf("\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fputs(testCommand ?
|
||||||
|
"Testing ":
|
||||||
|
"Extracting ",
|
||||||
|
stdout);
|
||||||
|
res = PrintString(temp);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (isDir)
|
||||||
|
printf("/");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = SzArEx_Extract(&db, &lookStream.s, i,
|
||||||
|
&blockIndex, &outBuffer, &outBufferSize,
|
||||||
|
&offset, &outSizeProcessed,
|
||||||
|
&allocImp, &allocTempImp);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!testCommand)
|
||||||
|
{
|
||||||
|
CSzFile outFile;
|
||||||
|
size_t processedSize;
|
||||||
|
size_t j;
|
||||||
|
UInt16 *name = (UInt16 *)temp;
|
||||||
|
const UInt16 *destPath = (const UInt16 *)name;
|
||||||
|
for (j = 0; name[j] != 0; j++)
|
||||||
|
if (name[j] == '/')
|
||||||
|
{
|
||||||
|
if (fullPaths)
|
||||||
|
{
|
||||||
|
name[j] = 0;
|
||||||
|
MyCreateDir(name);
|
||||||
|
name[j] = CHAR_PATH_SEPARATOR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
destPath = name + j + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDir)
|
||||||
|
{
|
||||||
|
MyCreateDir(destPath);
|
||||||
|
printf("\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (OutFile_OpenUtf16(&outFile, destPath))
|
||||||
|
{
|
||||||
|
PrintError("can not open output file");
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
processedSize = outSizeProcessed;
|
||||||
|
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)
|
||||||
|
{
|
||||||
|
PrintError("can not write output file");
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (File_Close(&outFile))
|
||||||
|
{
|
||||||
|
PrintError("can not close output file");
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
if (SzBitWithVals_Check(&db.Attribs, i))
|
||||||
|
SetFileAttributesW(destPath, db.Attribs.Vals[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
IAlloc_Free(&allocImp, outBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SzArEx_Free(&db, &allocImp);
|
||||||
|
SzFree(NULL, temp);
|
||||||
|
|
||||||
|
File_Close(&archiveStream.file);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
printf("\nEverything is Ok\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (res == SZ_ERROR_UNSUPPORTED)
|
||||||
|
PrintError("decoder doesn't support this archive");
|
||||||
|
else if (res == SZ_ERROR_MEM)
|
||||||
|
PrintError("can not allocate memory");
|
||||||
|
else if (res == SZ_ERROR_CRC)
|
||||||
|
PrintError("CRC error");
|
||||||
|
else
|
||||||
|
printf("\nERROR #%d\n", res);
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
/* Precomp.c -- StdAfx
|
||||||
|
2013-01-21 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* Precomp.h -- StdAfx
|
||||||
|
2013-06-16 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_PRECOMP_H
|
||||||
|
#define __7Z_PRECOMP_H
|
||||||
|
|
||||||
|
#include "../../Compiler.h"
|
||||||
|
#include "../../7zTypes.h"
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,39 @@
|
||||||
|
# MY_STATIC_LINK=1
|
||||||
|
CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT
|
||||||
|
|
||||||
|
PROG = 7zDec.exe
|
||||||
|
|
||||||
|
C_OBJS = \
|
||||||
|
$O\7zAlloc.obj \
|
||||||
|
$O\7zBuf.obj \
|
||||||
|
$O\7zCrc.obj \
|
||||||
|
$O\7zCrcOpt.obj \
|
||||||
|
$O\7zFile.obj \
|
||||||
|
$O\7zDec.obj \
|
||||||
|
$O\7zArcIn.obj \
|
||||||
|
$O\7zStream.obj \
|
||||||
|
$O\Bcj2.obj \
|
||||||
|
$O\Bra.obj \
|
||||||
|
$O\Bra86.obj \
|
||||||
|
$O\CpuArch.obj \
|
||||||
|
$O\Lzma2Dec.obj \
|
||||||
|
$O\LzmaDec.obj \
|
||||||
|
$O\Ppmd7.obj \
|
||||||
|
$O\Ppmd7Dec.obj \
|
||||||
|
|
||||||
|
7Z_OBJS = \
|
||||||
|
$O\7zMain.obj \
|
||||||
|
|
||||||
|
OBJS = \
|
||||||
|
$O\Precomp.obj \
|
||||||
|
$(7Z_OBJS) \
|
||||||
|
$(C_OBJS) \
|
||||||
|
|
||||||
|
!include "../../../CPP/Build.mak"
|
||||||
|
|
||||||
|
$(7Z_OBJS): $(*B).c
|
||||||
|
$(CCOMPL_USE)
|
||||||
|
$(C_OBJS): ../../$(*B).c
|
||||||
|
$(CCOMPL_USE)
|
||||||
|
$O\Precomp.obj: Precomp.c
|
||||||
|
$(CCOMPL_PCH)
|
|
@ -0,0 +1,70 @@
|
||||||
|
PROG = 7zDec
|
||||||
|
CXX = g++
|
||||||
|
LIB =
|
||||||
|
RM = rm -f
|
||||||
|
CFLAGS = -c -O2 -Wall
|
||||||
|
|
||||||
|
OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
|
||||||
|
$(PROG): $(OBJS)
|
||||||
|
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
|
||||||
|
|
||||||
|
7zMain.o: 7zMain.c
|
||||||
|
$(CXX) $(CFLAGS) 7zMain.c
|
||||||
|
|
||||||
|
7zAlloc.o: ../../7zAlloc.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zAlloc.c
|
||||||
|
|
||||||
|
7zArcIn.o: ../../7zArcIn.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zArcIn.c
|
||||||
|
|
||||||
|
7zBuf.o: ../../7zBuf.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zBuf.c
|
||||||
|
|
||||||
|
7zBuf2.o: ../../7zBuf2.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zBuf2.c
|
||||||
|
|
||||||
|
7zCrc.o: ../../7zCrc.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zCrc.c
|
||||||
|
|
||||||
|
7zCrcOpt.o: ../../7zCrc.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zCrcOpt.c
|
||||||
|
|
||||||
|
7zDec.o: ../../7zDec.c
|
||||||
|
$(CXX) $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT ../../7zDec.c
|
||||||
|
|
||||||
|
CpuArch.o: ../../CpuArch.c
|
||||||
|
$(CXX) $(CFLAGS) ../../CpuArch.c
|
||||||
|
|
||||||
|
LzmaDec.o: ../../LzmaDec.c
|
||||||
|
$(CXX) $(CFLAGS) ../../LzmaDec.c
|
||||||
|
|
||||||
|
Lzma2Dec.o: ../../Lzma2Dec.c
|
||||||
|
$(CXX) $(CFLAGS) ../../Lzma2Dec.c
|
||||||
|
|
||||||
|
Bra.o: ../../Bra.c
|
||||||
|
$(CXX) $(CFLAGS) ../../Bra.c
|
||||||
|
|
||||||
|
Bra86.o: ../../Bra86.c
|
||||||
|
$(CXX) $(CFLAGS) ../../Bra86.c
|
||||||
|
|
||||||
|
Bcj2.o: ../../Bcj2.c
|
||||||
|
$(CXX) $(CFLAGS) ../../Bcj2.c
|
||||||
|
|
||||||
|
Ppmd7.o: ../../Ppmd7.c
|
||||||
|
$(CXX) $(CFLAGS) ../../Ppmd7.c
|
||||||
|
|
||||||
|
Ppmd7Dec.o: ../../Ppmd7Dec.c
|
||||||
|
$(CXX) $(CFLAGS) ../../Ppmd7Dec.c
|
||||||
|
|
||||||
|
7zFile.o: ../../7zFile.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zFile.c
|
||||||
|
|
||||||
|
7zStream.o: ../../7zStream.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zStream.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-$(RM) $(PROG) $(OBJS)
|
||||||
|
|
|
@ -0,0 +1,254 @@
|
||||||
|
/* LzmaUtil.c -- Test application for LZMA compression
|
||||||
|
2014-12-31 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "../../Precomp.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../../Alloc.h"
|
||||||
|
#include "../../7zFile.h"
|
||||||
|
#include "../../7zVersion.h"
|
||||||
|
#include "../../LzmaDec.h"
|
||||||
|
#include "../../LzmaEnc.h"
|
||||||
|
|
||||||
|
const char *kCantReadMessage = "Can not read input file";
|
||||||
|
const char *kCantWriteMessage = "Can not write output file";
|
||||||
|
const char *kCantAllocateMessage = "Can not allocate memory";
|
||||||
|
const char *kDataErrorMessage = "Data error";
|
||||||
|
|
||||||
|
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||||
|
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||||
|
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||||
|
|
||||||
|
void PrintHelp(char *buffer)
|
||||||
|
{
|
||||||
|
strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
|
||||||
|
"\nUsage: lzma <e|d> inputFile outputFile\n"
|
||||||
|
" e: encode file\n"
|
||||||
|
" d: decode file\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int PrintError(char *buffer, const char *message)
|
||||||
|
{
|
||||||
|
strcat(buffer, "\nError: ");
|
||||||
|
strcat(buffer, message);
|
||||||
|
strcat(buffer, "\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PrintErrorNumber(char *buffer, SRes val)
|
||||||
|
{
|
||||||
|
sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PrintUserError(char *buffer)
|
||||||
|
{
|
||||||
|
return PrintError(buffer, "Incorrect command");
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IN_BUF_SIZE (1 << 16)
|
||||||
|
#define OUT_BUF_SIZE (1 << 16)
|
||||||
|
|
||||||
|
static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||||
|
UInt64 unpackSize)
|
||||||
|
{
|
||||||
|
int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
|
||||||
|
Byte inBuf[IN_BUF_SIZE];
|
||||||
|
Byte outBuf[OUT_BUF_SIZE];
|
||||||
|
size_t inPos = 0, inSize = 0, outPos = 0;
|
||||||
|
LzmaDec_Init(state);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (inPos == inSize)
|
||||||
|
{
|
||||||
|
inSize = IN_BUF_SIZE;
|
||||||
|
RINOK(inStream->Read(inStream, inBuf, &inSize));
|
||||||
|
inPos = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
SRes res;
|
||||||
|
SizeT inProcessed = inSize - inPos;
|
||||||
|
SizeT outProcessed = OUT_BUF_SIZE - outPos;
|
||||||
|
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
|
||||||
|
ELzmaStatus status;
|
||||||
|
if (thereIsSize && outProcessed > unpackSize)
|
||||||
|
{
|
||||||
|
outProcessed = (SizeT)unpackSize;
|
||||||
|
finishMode = LZMA_FINISH_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
|
||||||
|
inBuf + inPos, &inProcessed, finishMode, &status);
|
||||||
|
inPos += inProcessed;
|
||||||
|
outPos += outProcessed;
|
||||||
|
unpackSize -= outProcessed;
|
||||||
|
|
||||||
|
if (outStream)
|
||||||
|
if (outStream->Write(outStream, outBuf, outPos) != outPos)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
|
||||||
|
outPos = 0;
|
||||||
|
|
||||||
|
if (res != SZ_OK || (thereIsSize && unpackSize == 0))
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (inProcessed == 0 && outProcessed == 0)
|
||||||
|
{
|
||||||
|
if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
|
||||||
|
{
|
||||||
|
UInt64 unpackSize;
|
||||||
|
int i;
|
||||||
|
SRes res = 0;
|
||||||
|
|
||||||
|
CLzmaDec state;
|
||||||
|
|
||||||
|
/* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
|
||||||
|
unsigned char header[LZMA_PROPS_SIZE + 8];
|
||||||
|
|
||||||
|
/* Read and parse header */
|
||||||
|
|
||||||
|
RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
|
||||||
|
|
||||||
|
unpackSize = 0;
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
|
||||||
|
|
||||||
|
LzmaDec_Construct(&state);
|
||||||
|
RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
|
||||||
|
res = Decode2(&state, outStream, inStream, unpackSize);
|
||||||
|
LzmaDec_Free(&state, &g_Alloc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
|
||||||
|
{
|
||||||
|
CLzmaEncHandle enc;
|
||||||
|
SRes res;
|
||||||
|
CLzmaEncProps props;
|
||||||
|
|
||||||
|
rs = rs;
|
||||||
|
|
||||||
|
enc = LzmaEnc_Create(&g_Alloc);
|
||||||
|
if (enc == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
|
||||||
|
LzmaEncProps_Init(&props);
|
||||||
|
res = LzmaEnc_SetProps(enc, &props);
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
Byte header[LZMA_PROPS_SIZE + 8];
|
||||||
|
size_t headerSize = LZMA_PROPS_SIZE;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
res = LzmaEnc_WriteProperties(enc, header, &headerSize);
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
header[headerSize++] = (Byte)(fileSize >> (8 * i));
|
||||||
|
if (outStream->Write(outStream, header, headerSize) != headerSize)
|
||||||
|
res = SZ_ERROR_WRITE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (res == SZ_OK)
|
||||||
|
res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main2(int numArgs, const char *args[], char *rs)
|
||||||
|
{
|
||||||
|
CFileSeqInStream inStream;
|
||||||
|
CFileOutStream outStream;
|
||||||
|
char c;
|
||||||
|
int res;
|
||||||
|
int encodeMode;
|
||||||
|
Bool useOutFile = False;
|
||||||
|
|
||||||
|
FileSeqInStream_CreateVTable(&inStream);
|
||||||
|
File_Construct(&inStream.file);
|
||||||
|
|
||||||
|
FileOutStream_CreateVTable(&outStream);
|
||||||
|
File_Construct(&outStream.file);
|
||||||
|
|
||||||
|
if (numArgs == 1)
|
||||||
|
{
|
||||||
|
PrintHelp(rs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
|
||||||
|
return PrintUserError(rs);
|
||||||
|
|
||||||
|
c = args[1][0];
|
||||||
|
encodeMode = (c == 'e' || c == 'E');
|
||||||
|
if (!encodeMode && c != 'd' && c != 'D')
|
||||||
|
return PrintUserError(rs);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t t4 = sizeof(UInt32);
|
||||||
|
size_t t8 = sizeof(UInt64);
|
||||||
|
if (t4 != 4 || t8 != 8)
|
||||||
|
return PrintError(rs, "Incorrect UInt32 or UInt64");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InFile_Open(&inStream.file, args[2]) != 0)
|
||||||
|
return PrintError(rs, "Can not open input file");
|
||||||
|
|
||||||
|
if (numArgs > 3)
|
||||||
|
{
|
||||||
|
useOutFile = True;
|
||||||
|
if (OutFile_Open(&outStream.file, args[3]) != 0)
|
||||||
|
return PrintError(rs, "Can not open output file");
|
||||||
|
}
|
||||||
|
else if (encodeMode)
|
||||||
|
PrintUserError(rs);
|
||||||
|
|
||||||
|
if (encodeMode)
|
||||||
|
{
|
||||||
|
UInt64 fileSize;
|
||||||
|
File_GetLength(&inStream.file, &fileSize);
|
||||||
|
res = Encode(&outStream.s, &inStream.s, fileSize, rs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useOutFile)
|
||||||
|
File_Close(&outStream.file);
|
||||||
|
File_Close(&inStream.file);
|
||||||
|
|
||||||
|
if (res != SZ_OK)
|
||||||
|
{
|
||||||
|
if (res == SZ_ERROR_MEM)
|
||||||
|
return PrintError(rs, kCantAllocateMessage);
|
||||||
|
else if (res == SZ_ERROR_DATA)
|
||||||
|
return PrintError(rs, kDataErrorMessage);
|
||||||
|
else if (res == SZ_ERROR_WRITE)
|
||||||
|
return PrintError(rs, kCantWriteMessage);
|
||||||
|
else if (res == SZ_ERROR_READ)
|
||||||
|
return PrintError(rs, kCantReadMessage);
|
||||||
|
return PrintErrorNumber(rs, res);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MY_CDECL main(int numArgs, const char *args[])
|
||||||
|
{
|
||||||
|
char rs[800] = { 0 };
|
||||||
|
int res = main2(numArgs, args, rs);
|
||||||
|
fputs(rs, stdout);
|
||||||
|
return res;
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=LzmaUtil - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "LzmaUtil.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "LzmaUtil - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MT /W4 /WX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
|
||||||
|
# SUBTRACT CPP /YX
|
||||||
|
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7lzma.exe"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MTd /W4 /WX /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /YX
|
||||||
|
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7lzma.exe" /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "LzmaUtil - Win32 Release"
|
||||||
|
# Name "LzmaUtil - Win32 Debug"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zFile.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zFile.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zStream.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zVersion.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Alloc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Alloc.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\CpuArch.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzFind.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzFind.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzFindMt.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzFindMt.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzHash.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaDec.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaDec.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaEnc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaEnc.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\LzmaUtil.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Threads.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Threads.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Types.h
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
|
@ -0,0 +1,29 @@
|
||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# MY_STATIC_LINK=1
|
||||||
|
PROG = LZMAc.exe
|
||||||
|
|
||||||
|
CFLAGS = $(CFLAGS) \
|
||||||
|
|
||||||
|
LIB_OBJS = \
|
||||||
|
$O\LzmaUtil.obj \
|
||||||
|
|
||||||
|
C_OBJS = \
|
||||||
|
$O\Alloc.obj \
|
||||||
|
$O\LzFind.obj \
|
||||||
|
$O\LzFindMt.obj \
|
||||||
|
$O\LzmaDec.obj \
|
||||||
|
$O\LzmaEnc.obj \
|
||||||
|
$O\7zFile.obj \
|
||||||
|
$O\7zStream.obj \
|
||||||
|
$O\Threads.obj \
|
||||||
|
|
||||||
|
OBJS = \
|
||||||
|
$(LIB_OBJS) \
|
||||||
|
$(C_OBJS) \
|
||||||
|
|
||||||
|
!include "../../../CPP/Build.mak"
|
||||||
|
|
||||||
|
$(LIB_OBJS): $(*B).c
|
||||||
|
$(COMPL_O2)
|
||||||
|
$(C_OBJS): ../../$(*B).c
|
||||||
|
$(COMPL_O2)
|
|
@ -0,0 +1,44 @@
|
||||||
|
PROG = lzma
|
||||||
|
CXX = g++
|
||||||
|
LIB =
|
||||||
|
RM = rm -f
|
||||||
|
CFLAGS = -c -O2 -Wall -D_7ZIP_ST
|
||||||
|
|
||||||
|
OBJS = \
|
||||||
|
LzmaUtil.o \
|
||||||
|
Alloc.o \
|
||||||
|
LzFind.o \
|
||||||
|
LzmaDec.o \
|
||||||
|
LzmaEnc.o \
|
||||||
|
7zFile.o \
|
||||||
|
7zStream.o \
|
||||||
|
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
|
||||||
|
$(PROG): $(OBJS)
|
||||||
|
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
|
||||||
|
|
||||||
|
LzmaUtil.o: LzmaUtil.c
|
||||||
|
$(CXX) $(CFLAGS) LzmaUtil.c
|
||||||
|
|
||||||
|
Alloc.o: ../../Alloc.c
|
||||||
|
$(CXX) $(CFLAGS) ../../Alloc.c
|
||||||
|
|
||||||
|
LzFind.o: ../../LzFind.c
|
||||||
|
$(CXX) $(CFLAGS) ../../LzFind.c
|
||||||
|
|
||||||
|
LzmaDec.o: ../../LzmaDec.c
|
||||||
|
$(CXX) $(CFLAGS) ../../LzmaDec.c
|
||||||
|
|
||||||
|
LzmaEnc.o: ../../LzmaEnc.c
|
||||||
|
$(CXX) $(CFLAGS) ../../LzmaEnc.c
|
||||||
|
|
||||||
|
7zFile.o: ../../7zFile.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zFile.c
|
||||||
|
|
||||||
|
7zStream.o: ../../7zStream.c
|
||||||
|
$(CXX) $(CFLAGS) ../../7zStream.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-$(RM) $(PROG) $(OBJS)
|
|
@ -0,0 +1,4 @@
|
||||||
|
EXPORTS
|
||||||
|
LzmaCompress
|
||||||
|
LzmaUncompress
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
|
||||||
|
CFG=LzmaLib - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "LzmaLib.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "LzmaLib - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /FD /c
|
||||||
|
# SUBTRACT CPP /YX
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98
|
||||||
|
# SUBTRACT LINK32 /pdb:none
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /YX
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "LzmaLib - Win32 Release"
|
||||||
|
# Name "LzmaLib - Win32 Debug"
|
||||||
|
# Begin Group "Spec"
|
||||||
|
|
||||||
|
# PROP Default_Filter ""
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\LzmaLib.def
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\LzmaLibExports.c
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zTypes.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Alloc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Alloc.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\IStream.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzFind.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzFind.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzFindMt.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzFindMt.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzHash.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaDec.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaDec.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaEnc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaEnc.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaLib.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaLib.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\resource.rc
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Threads.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Threads.h
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
|
@ -0,0 +1,29 @@
|
||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/* LzmaLibExports.c -- LZMA library DLL Entry point
|
||||||
|
2008-10-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
|
||||||
|
{
|
||||||
|
hInstance = hInstance;
|
||||||
|
dwReason = dwReason;
|
||||||
|
lpReserved = lpReserved;
|
||||||
|
return TRUE;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
MY_STATIC_LINK=1
|
||||||
|
SLIB = sLZMA.lib
|
||||||
|
PROG = LZMA.dll
|
||||||
|
SLIBPATH = $O\$(SLIB)
|
||||||
|
|
||||||
|
DEF_FILE = LzmaLib.def
|
||||||
|
CFLAGS = $(CFLAGS) \
|
||||||
|
|
||||||
|
LIB_OBJS = \
|
||||||
|
$O\LzmaLibExports.obj \
|
||||||
|
|
||||||
|
C_OBJS = \
|
||||||
|
$O\Alloc.obj \
|
||||||
|
$O\LzFind.obj \
|
||||||
|
$O\LzFindMt.obj \
|
||||||
|
$O\LzmaDec.obj \
|
||||||
|
$O\LzmaEnc.obj \
|
||||||
|
$O\LzmaLib.obj \
|
||||||
|
$O\Threads.obj \
|
||||||
|
|
||||||
|
OBJS = \
|
||||||
|
$(LIB_OBJS) \
|
||||||
|
$(C_OBJS) \
|
||||||
|
$O\resource.res
|
||||||
|
|
||||||
|
!include "../../../CPP/Build.mak"
|
||||||
|
|
||||||
|
$(SLIBPATH): $O $(OBJS)
|
||||||
|
lib -out:$(SLIBPATH) $(OBJS) $(LIBS)
|
||||||
|
|
||||||
|
$(LIB_OBJS): $(*B).c
|
||||||
|
$(COMPL_O2)
|
||||||
|
$(C_OBJS): ../../$(*B).c
|
||||||
|
$(COMPL_O2)
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "../../7zVersion.rc"
|
||||||
|
|
||||||
|
MY_VERSION_INFO_DLL("LZMA library", "LZMA")
|
|
@ -0,0 +1,4 @@
|
||||||
|
/* Precomp.c -- StdAfx
|
||||||
|
2013-01-21 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* Precomp.h -- StdAfx
|
||||||
|
2013-06-16 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __7Z_PRECOMP_H
|
||||||
|
#define __7Z_PRECOMP_H
|
||||||
|
|
||||||
|
#include "../../Compiler.h"
|
||||||
|
#include "../../7zTypes.h"
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,617 @@
|
||||||
|
/* SfxSetup.c - 7z SFX Setup
|
||||||
|
2014-12-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#ifndef UNICODE
|
||||||
|
#define UNICODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _UNICODE
|
||||||
|
#define _UNICODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _CONSOLE
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../../7z.h"
|
||||||
|
#include "../../7zAlloc.h"
|
||||||
|
#include "../../7zCrc.h"
|
||||||
|
#include "../../7zFile.h"
|
||||||
|
#include "../../CpuArch.h"
|
||||||
|
|
||||||
|
#define k_EXE_ExtIndex 2
|
||||||
|
|
||||||
|
static const char *kExts[] =
|
||||||
|
{
|
||||||
|
"bat"
|
||||||
|
, "cmd"
|
||||||
|
, "exe"
|
||||||
|
, "inf"
|
||||||
|
, "msi"
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
, "cab"
|
||||||
|
#endif
|
||||||
|
, "html"
|
||||||
|
, "htm"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *kNames[] =
|
||||||
|
{
|
||||||
|
"setup"
|
||||||
|
, "install"
|
||||||
|
, "run"
|
||||||
|
, "start"
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned FindExt(const wchar_t *s, unsigned *extLen)
|
||||||
|
{
|
||||||
|
unsigned len = (unsigned)wcslen(s);
|
||||||
|
unsigned i;
|
||||||
|
for (i = len; i > 0; i--)
|
||||||
|
{
|
||||||
|
if (s[i - 1] == '.')
|
||||||
|
{
|
||||||
|
*extLen = len - i;
|
||||||
|
return i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*extLen = 0;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))
|
||||||
|
|
||||||
|
static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
const char *item = items[i];
|
||||||
|
unsigned itemLen = (unsigned)strlen(item);
|
||||||
|
unsigned j;
|
||||||
|
if (len != itemLen)
|
||||||
|
continue;
|
||||||
|
for (j = 0; j < len; j++)
|
||||||
|
{
|
||||||
|
unsigned c = item[j];
|
||||||
|
if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j == len)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _CONSOLE
|
||||||
|
static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
|
||||||
|
{
|
||||||
|
ctrlType = ctrlType;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void PrintErrorMessage(const char *message)
|
||||||
|
{
|
||||||
|
#ifdef _CONSOLE
|
||||||
|
printf("\n7-Zip Error: %s\n", message);
|
||||||
|
#else
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
WCHAR messageW[256 + 4];
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < 256 && message[i] != 0; i++)
|
||||||
|
messageW[i] = message[i];
|
||||||
|
messageW[i] = 0;
|
||||||
|
MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR);
|
||||||
|
#else
|
||||||
|
MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static WRes MyCreateDir(const WCHAR *name)
|
||||||
|
{
|
||||||
|
return CreateDirectoryW(name, NULL) ? 0 : GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
#define kBufferSize (1 << 13)
|
||||||
|
#else
|
||||||
|
#define kBufferSize (1 << 15)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define kSignatureSearchLimit (1 << 22)
|
||||||
|
|
||||||
|
static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
|
||||||
|
{
|
||||||
|
Byte buf[kBufferSize];
|
||||||
|
size_t numPrevBytes = 0;
|
||||||
|
*resPos = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
size_t processed, pos;
|
||||||
|
if (*resPos > kSignatureSearchLimit)
|
||||||
|
return False;
|
||||||
|
processed = kBufferSize - numPrevBytes;
|
||||||
|
if (File_Read(stream, buf + numPrevBytes, &processed) != 0)
|
||||||
|
return False;
|
||||||
|
processed += numPrevBytes;
|
||||||
|
if (processed < k7zStartHeaderSize ||
|
||||||
|
(processed == k7zStartHeaderSize && numPrevBytes != 0))
|
||||||
|
return False;
|
||||||
|
processed -= k7zStartHeaderSize;
|
||||||
|
for (pos = 0; pos <= processed; pos++)
|
||||||
|
{
|
||||||
|
for (; buf[pos] != '7' && pos <= processed; pos++);
|
||||||
|
if (pos > processed)
|
||||||
|
break;
|
||||||
|
if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)
|
||||||
|
if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8))
|
||||||
|
{
|
||||||
|
*resPos += pos;
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*resPos += processed;
|
||||||
|
numPrevBytes = k7zStartHeaderSize;
|
||||||
|
memmove(buf, buf + processed, k7zStartHeaderSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool DoesFileOrDirExist(const WCHAR *path)
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATAW fd;
|
||||||
|
HANDLE handle;
|
||||||
|
handle = FindFirstFileW(path, &fd);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
return False;
|
||||||
|
FindClose(handle);
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WRes RemoveDirWithSubItems(WCHAR *path)
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATAW fd;
|
||||||
|
HANDLE handle;
|
||||||
|
WRes res = 0;
|
||||||
|
size_t len = wcslen(path);
|
||||||
|
wcscpy(path + len, L"*");
|
||||||
|
handle = FindFirstFileW(path, &fd);
|
||||||
|
path[len] = L'\0';
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
return GetLastError();
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (wcscmp(fd.cFileName, L".") != 0 &&
|
||||||
|
wcscmp(fd.cFileName, L"..") != 0)
|
||||||
|
{
|
||||||
|
wcscpy(path + len, fd.cFileName);
|
||||||
|
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||||
|
{
|
||||||
|
wcscat(path, WSTRING_PATH_SEPARATOR);
|
||||||
|
res = RemoveDirWithSubItems(path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetFileAttributesW(path, 0);
|
||||||
|
if (DeleteFileW(path) == 0)
|
||||||
|
res = GetLastError();
|
||||||
|
}
|
||||||
|
if (res != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!FindNextFileW(handle, &fd))
|
||||||
|
{
|
||||||
|
res = GetLastError();
|
||||||
|
if (res == ERROR_NO_MORE_FILES)
|
||||||
|
res = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path[len] = L'\0';
|
||||||
|
FindClose(handle);
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
if (!RemoveDirectoryW(path))
|
||||||
|
res = GetLastError();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _CONSOLE
|
||||||
|
int MY_CDECL main()
|
||||||
|
#else
|
||||||
|
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
LPWSTR
|
||||||
|
#else
|
||||||
|
LPSTR
|
||||||
|
#endif
|
||||||
|
lpCmdLine, int nCmdShow)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
CFileInStream archiveStream;
|
||||||
|
CLookToRead lookStream;
|
||||||
|
CSzArEx db;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
ISzAlloc allocImp;
|
||||||
|
ISzAlloc allocTempImp;
|
||||||
|
WCHAR sfxPath[MAX_PATH + 2];
|
||||||
|
WCHAR path[MAX_PATH * 3 + 2];
|
||||||
|
#ifndef UNDER_CE
|
||||||
|
WCHAR workCurDir[MAX_PATH + 32];
|
||||||
|
#endif
|
||||||
|
size_t pathLen;
|
||||||
|
DWORD winRes;
|
||||||
|
const wchar_t *cmdLineParams;
|
||||||
|
const char *errorMessage = NULL;
|
||||||
|
Bool useShellExecute = True;
|
||||||
|
|
||||||
|
#ifdef _CONSOLE
|
||||||
|
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
|
||||||
|
#else
|
||||||
|
hInstance = hInstance;
|
||||||
|
hPrevInstance = hPrevInstance;
|
||||||
|
lpCmdLine = lpCmdLine;
|
||||||
|
nCmdShow = nCmdShow;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CrcGenerateTable();
|
||||||
|
|
||||||
|
allocImp.Alloc = SzAlloc;
|
||||||
|
allocImp.Free = SzFree;
|
||||||
|
|
||||||
|
allocTempImp.Alloc = SzAllocTemp;
|
||||||
|
allocTempImp.Free = SzFreeTemp;
|
||||||
|
|
||||||
|
FileInStream_CreateVTable(&archiveStream);
|
||||||
|
LookToRead_CreateVTable(&lookStream, False);
|
||||||
|
|
||||||
|
winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH);
|
||||||
|
if (winRes == 0 || winRes > MAX_PATH)
|
||||||
|
return 1;
|
||||||
|
{
|
||||||
|
cmdLineParams = GetCommandLineW();
|
||||||
|
#ifndef UNDER_CE
|
||||||
|
{
|
||||||
|
Bool quoteMode = False;
|
||||||
|
for (;; cmdLineParams++)
|
||||||
|
{
|
||||||
|
wchar_t c = *cmdLineParams;
|
||||||
|
if (c == L'\"')
|
||||||
|
quoteMode = !quoteMode;
|
||||||
|
else if (c == 0 || (c == L' ' && !quoteMode))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
DWORD d;
|
||||||
|
winRes = GetTempPathW(MAX_PATH, path);
|
||||||
|
if (winRes == 0 || winRes > MAX_PATH)
|
||||||
|
return 1;
|
||||||
|
pathLen = wcslen(path);
|
||||||
|
d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();
|
||||||
|
|
||||||
|
for (i = 0;; i++, d += GetTickCount())
|
||||||
|
{
|
||||||
|
if (i >= 100)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wcscpy(path + pathLen, L"7z");
|
||||||
|
|
||||||
|
{
|
||||||
|
wchar_t *s = path + wcslen(path);
|
||||||
|
UInt32 value = d;
|
||||||
|
unsigned k;
|
||||||
|
for (k = 0; k < 8; k++)
|
||||||
|
{
|
||||||
|
unsigned t = value & 0xF;
|
||||||
|
value >>= 4;
|
||||||
|
s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
|
||||||
|
}
|
||||||
|
s[k] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DoesFileOrDirExist(path))
|
||||||
|
continue;
|
||||||
|
if (CreateDirectoryW(path, NULL))
|
||||||
|
{
|
||||||
|
wcscat(path, WSTRING_PATH_SEPARATOR);
|
||||||
|
pathLen = wcslen(path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (GetLastError() != ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef UNDER_CE
|
||||||
|
wcscpy(workCurDir, path);
|
||||||
|
#endif
|
||||||
|
if (res != SZ_OK)
|
||||||
|
errorMessage = "Can't create temp folder";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != SZ_OK)
|
||||||
|
{
|
||||||
|
if (!errorMessage)
|
||||||
|
errorMessage = "Error";
|
||||||
|
PrintErrorMessage(errorMessage);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InFile_OpenW(&archiveStream.file, sfxPath) != 0)
|
||||||
|
{
|
||||||
|
errorMessage = "can not open input file";
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UInt64 pos = 0;
|
||||||
|
if (!FindSignature(&archiveStream.file, &pos))
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0)
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
if (res != 0)
|
||||||
|
errorMessage = "Can't find 7z archive";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
lookStream.realStream = &archiveStream.s;
|
||||||
|
LookToRead_Init(&lookStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
SzArEx_Init(&db);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
UInt32 executeFileIndex = (UInt32)(Int32)-1;
|
||||||
|
UInt32 minPrice = 1 << 30;
|
||||||
|
UInt32 i;
|
||||||
|
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
|
||||||
|
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
||||||
|
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
||||||
|
|
||||||
|
for (i = 0; i < db.NumFiles; i++)
|
||||||
|
{
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t outSizeProcessed = 0;
|
||||||
|
size_t len;
|
||||||
|
WCHAR *temp;
|
||||||
|
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
|
||||||
|
|
||||||
|
if (len >= MAX_PATH)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = path + pathLen;
|
||||||
|
|
||||||
|
SzArEx_GetFileNameUtf16(&db, i, temp);
|
||||||
|
{
|
||||||
|
res = SzArEx_Extract(&db, &lookStream.s, i,
|
||||||
|
&blockIndex, &outBuffer, &outBufferSize,
|
||||||
|
&offset, &outSizeProcessed,
|
||||||
|
&allocImp, &allocTempImp);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CSzFile outFile;
|
||||||
|
size_t processedSize;
|
||||||
|
size_t j;
|
||||||
|
size_t nameStartPos = 0;
|
||||||
|
for (j = 0; temp[j] != 0; j++)
|
||||||
|
{
|
||||||
|
if (temp[j] == '/')
|
||||||
|
{
|
||||||
|
temp[j] = 0;
|
||||||
|
MyCreateDir(path);
|
||||||
|
temp[j] = CHAR_PATH_SEPARATOR;
|
||||||
|
nameStartPos = j + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SzArEx_IsDir(&db, i))
|
||||||
|
{
|
||||||
|
MyCreateDir(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned extLen;
|
||||||
|
const WCHAR *name = temp + nameStartPos;
|
||||||
|
unsigned len = (unsigned)wcslen(name);
|
||||||
|
unsigned nameLen = FindExt(temp + nameStartPos, &extLen);
|
||||||
|
unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen);
|
||||||
|
unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen);
|
||||||
|
|
||||||
|
unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12));
|
||||||
|
if (minPrice > price)
|
||||||
|
{
|
||||||
|
minPrice = price;
|
||||||
|
executeFileIndex = i;
|
||||||
|
useShellExecute = (extPrice != k_EXE_ExtIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DoesFileOrDirExist(path))
|
||||||
|
{
|
||||||
|
errorMessage = "Duplicate file";
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (OutFile_OpenW(&outFile, path))
|
||||||
|
{
|
||||||
|
errorMessage = "Can't open output file";
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processedSize = outSizeProcessed;
|
||||||
|
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)
|
||||||
|
{
|
||||||
|
errorMessage = "Can't write output file";
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
if (SzBitWithVals_Check(&db.MTime, i))
|
||||||
|
{
|
||||||
|
const CNtfsFileTime *t = db.MTime.Vals + i;
|
||||||
|
FILETIME mTime;
|
||||||
|
mTime.dwLowDateTime = t->Low;
|
||||||
|
mTime.dwHighDateTime = t->High;
|
||||||
|
SetFileTime(outFile.handle, NULL, NULL, &mTime);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
SRes res2 = File_Close(&outFile);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (res2 != SZ_OK)
|
||||||
|
{
|
||||||
|
res = res2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
if (SzBitWithVals_Check(&db.Attribs, i))
|
||||||
|
SetFileAttributesW(path, db.Attribs.Vals[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
if (executeFileIndex == (UInt32)(Int32)-1)
|
||||||
|
{
|
||||||
|
errorMessage = "There is no file to execute";
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WCHAR *temp = path + pathLen;
|
||||||
|
UInt32 j;
|
||||||
|
SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp);
|
||||||
|
for (j = 0; temp[j] != 0; j++)
|
||||||
|
if (temp[j] == '/')
|
||||||
|
temp[j] = CHAR_PATH_SEPARATOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IAlloc_Free(&allocImp, outBuffer);
|
||||||
|
}
|
||||||
|
SzArEx_Free(&db, &allocImp);
|
||||||
|
|
||||||
|
File_Close(&archiveStream.file);
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
HANDLE hProcess = 0;
|
||||||
|
|
||||||
|
#ifndef UNDER_CE
|
||||||
|
WCHAR oldCurDir[MAX_PATH + 2];
|
||||||
|
oldCurDir[0] = 0;
|
||||||
|
{
|
||||||
|
DWORD needLen = GetCurrentDirectory(MAX_PATH + 1, oldCurDir);
|
||||||
|
if (needLen == 0 || needLen > MAX_PATH)
|
||||||
|
oldCurDir[0] = 0;
|
||||||
|
SetCurrentDirectory(workCurDir);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (useShellExecute)
|
||||||
|
{
|
||||||
|
SHELLEXECUTEINFO ei;
|
||||||
|
UINT32 executeRes;
|
||||||
|
BOOL success;
|
||||||
|
|
||||||
|
memset(&ei, 0, sizeof(ei));
|
||||||
|
ei.cbSize = sizeof(ei);
|
||||||
|
ei.lpFile = path;
|
||||||
|
ei.fMask = SEE_MASK_NOCLOSEPROCESS
|
||||||
|
#ifndef UNDER_CE
|
||||||
|
| SEE_MASK_FLAG_DDEWAIT
|
||||||
|
#endif
|
||||||
|
/* | SEE_MASK_NO_CONSOLE */
|
||||||
|
;
|
||||||
|
if (wcslen(cmdLineParams) != 0)
|
||||||
|
ei.lpParameters = cmdLineParams;
|
||||||
|
ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */
|
||||||
|
success = ShellExecuteEx(&ei);
|
||||||
|
executeRes = (UINT32)(UINT_PTR)ei.hInstApp;
|
||||||
|
if (!success || (executeRes <= 32 && executeRes != 0)) /* executeRes = 0 in Windows CE */
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
else
|
||||||
|
hProcess = ei.hProcess;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STARTUPINFOW si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
WCHAR cmdLine[MAX_PATH * 3];
|
||||||
|
|
||||||
|
wcscpy(cmdLine, path);
|
||||||
|
wcscat(cmdLine, cmdLineParams);
|
||||||
|
memset(&si, 0, sizeof(si));
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0)
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CloseHandle(pi.hThread);
|
||||||
|
hProcess = pi.hProcess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hProcess != 0)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(hProcess, INFINITE);
|
||||||
|
CloseHandle(hProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef UNDER_CE
|
||||||
|
SetCurrentDirectory(oldCurDir);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
path[pathLen] = L'\0';
|
||||||
|
RemoveDirWithSubItems(path);
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
if (res == SZ_ERROR_UNSUPPORTED)
|
||||||
|
errorMessage = "Decoder doesn't support this archive";
|
||||||
|
else if (res == SZ_ERROR_MEM)
|
||||||
|
errorMessage = "Can't allocate required memory";
|
||||||
|
else if (res == SZ_ERROR_CRC)
|
||||||
|
errorMessage = "CRC error";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!errorMessage)
|
||||||
|
errorMessage = "ERROR";
|
||||||
|
}
|
||||||
|
if (errorMessage)
|
||||||
|
PrintErrorMessage(errorMessage);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,211 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="SfxSetup" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||||
|
|
||||||
|
CFG=SfxSetup - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "SfxSetup.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "SfxSetup.mak" CFG="SfxSetup - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "SfxSetup - Win32 Release" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE "SfxSetup - Win32 Debug" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "SfxSetup - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "SfxSetup - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "SfxSetup - Win32 Release"
|
||||||
|
# Name "SfxSetup - Win32 Debug"
|
||||||
|
# Begin Group "Common"
|
||||||
|
|
||||||
|
# PROP Default_Filter ""
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7z.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zAlloc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zAlloc.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zArcIn.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zBuf.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zBuf.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zCrc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zCrc.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zCrcOpt.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zDec.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zFile.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zFile.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zStream.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\7zTypes.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bcj2.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bcj2.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bra.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bra.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Bra86.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\CpuArch.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\CpuArch.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Lzma2Dec.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Lzma2Dec.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaDec.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\LzmaDec.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Spec"
|
||||||
|
|
||||||
|
# PROP Default_Filter ""
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Precomp.c
|
||||||
|
# ADD CPP /Yc"Precomp.h"
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Precomp.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\SfxSetup.c
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
|
@ -0,0 +1,29 @@
|
||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "SfxSetup"=.\SfxSetup.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
PROG = 7zS2.sfx
|
||||||
|
|
||||||
|
C_OBJS = \
|
||||||
|
$O\7zAlloc.obj \
|
||||||
|
$O\7zArcIn.obj \
|
||||||
|
$O\7zBuf.obj \
|
||||||
|
$O\7zBuf2.obj \
|
||||||
|
$O\7zCrc.obj \
|
||||||
|
$O\7zCrcOpt.obj \
|
||||||
|
$O\7zFile.obj \
|
||||||
|
$O\7zDec.obj \
|
||||||
|
$O\7zStream.obj \
|
||||||
|
$O\Bcj2.obj \
|
||||||
|
$O\Bra.obj \
|
||||||
|
$O\Bra86.obj \
|
||||||
|
$O\CpuArch.obj \
|
||||||
|
$O\Lzma2Dec.obj \
|
||||||
|
$O\LzmaDec.obj \
|
||||||
|
|
||||||
|
7Z_OBJS = \
|
||||||
|
$O\SfxSetup.obj \
|
||||||
|
|
||||||
|
OBJS = \
|
||||||
|
$(7Z_OBJS) \
|
||||||
|
$(C_OBJS) \
|
||||||
|
$O\resource.res
|
||||||
|
|
||||||
|
!include "../../../CPP/Build.mak"
|
||||||
|
|
||||||
|
$(7Z_OBJS): $(*B).c
|
||||||
|
$(COMPL_O1)
|
||||||
|
$(C_OBJS): ../../$(*B).c
|
||||||
|
$(COMPL_O1)
|
|
@ -0,0 +1,34 @@
|
||||||
|
PROG = 7zS2con.sfx
|
||||||
|
CFLAGS = $(CFLAGS) -D_CONSOLE
|
||||||
|
|
||||||
|
C_OBJS = \
|
||||||
|
$O\7zAlloc.obj \
|
||||||
|
$O\7zArcIn.obj \
|
||||||
|
$O\7zBuf.obj \
|
||||||
|
$O\7zBuf2.obj \
|
||||||
|
$O\7zCrc.obj \
|
||||||
|
$O\7zCrcOpt.obj \
|
||||||
|
$O\7zFile.obj \
|
||||||
|
$O\7zDec.obj \
|
||||||
|
$O\7zStream.obj \
|
||||||
|
$O\Bcj2.obj \
|
||||||
|
$O\Bra.obj \
|
||||||
|
$O\Bra86.obj \
|
||||||
|
$O\CpuArch.obj \
|
||||||
|
$O\Lzma2Dec.obj \
|
||||||
|
$O\LzmaDec.obj \
|
||||||
|
|
||||||
|
7Z_OBJS = \
|
||||||
|
$O\SfxSetup.obj \
|
||||||
|
|
||||||
|
OBJS = \
|
||||||
|
$(7Z_OBJS) \
|
||||||
|
$(C_OBJS) \
|
||||||
|
$O\resource.res
|
||||||
|
|
||||||
|
!include "../../../CPP/Build.mak"
|
||||||
|
|
||||||
|
$(7Z_OBJS): $(*B).c
|
||||||
|
$(COMPL_O1)
|
||||||
|
$(C_OBJS): ../../$(*B).c
|
||||||
|
$(COMPL_O1)
|
|
@ -0,0 +1,5 @@
|
||||||
|
#include "../../7zVersion.rc"
|
||||||
|
|
||||||
|
MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx")
|
||||||
|
|
||||||
|
1 ICON "setup.ico"
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,90 @@
|
||||||
|
/* Xz.c - Xz
|
||||||
|
2009-04-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "7zCrc.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
#include "Xz.h"
|
||||||
|
#include "XzCrc64.h"
|
||||||
|
|
||||||
|
Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };
|
||||||
|
Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };
|
||||||
|
|
||||||
|
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
buf[i++] = (Byte)((v & 0x7F) | 0x80);
|
||||||
|
v >>= 7;
|
||||||
|
}
|
||||||
|
while (v != 0);
|
||||||
|
buf[i - 1] &= 0x7F;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Xz_Construct(CXzStream *p)
|
||||||
|
{
|
||||||
|
p->numBlocks = p->numBlocksAllocated = 0;
|
||||||
|
p->blocks = 0;
|
||||||
|
p->flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Xz_Free(CXzStream *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->blocks);
|
||||||
|
p->numBlocks = p->numBlocksAllocated = 0;
|
||||||
|
p->blocks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned XzFlags_GetCheckSize(CXzStreamFlags f)
|
||||||
|
{
|
||||||
|
int t = XzFlags_GetCheckType(f);
|
||||||
|
return (t == 0) ? 0 : (4 << ((t - 1) / 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void XzCheck_Init(CXzCheck *p, int mode)
|
||||||
|
{
|
||||||
|
p->mode = mode;
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break;
|
||||||
|
case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break;
|
||||||
|
case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XzCheck_Update(CXzCheck *p, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
switch (p->mode)
|
||||||
|
{
|
||||||
|
case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break;
|
||||||
|
case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break;
|
||||||
|
case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int XzCheck_Final(CXzCheck *p, Byte *digest)
|
||||||
|
{
|
||||||
|
switch (p->mode)
|
||||||
|
{
|
||||||
|
case XZ_CHECK_CRC32:
|
||||||
|
SetUi32(digest, CRC_GET_DIGEST(p->crc));
|
||||||
|
break;
|
||||||
|
case XZ_CHECK_CRC64:
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
UInt64 v = CRC64_GET_DIGEST(p->crc64);
|
||||||
|
for (i = 0; i < 8; i++, v >>= 8)
|
||||||
|
digest[i] = (Byte)(v & 0xFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XZ_CHECK_SHA256:
|
||||||
|
Sha256_Final(&p->sha, digest);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,275 @@
|
||||||
|
/* Xz.h - Xz interface
|
||||||
|
2014-12-30 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __XZ_H
|
||||||
|
#define __XZ_H
|
||||||
|
|
||||||
|
#include "Sha256.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define XZ_ID_Subblock 1
|
||||||
|
#define XZ_ID_Delta 3
|
||||||
|
#define XZ_ID_X86 4
|
||||||
|
#define XZ_ID_PPC 5
|
||||||
|
#define XZ_ID_IA64 6
|
||||||
|
#define XZ_ID_ARM 7
|
||||||
|
#define XZ_ID_ARMT 8
|
||||||
|
#define XZ_ID_SPARC 9
|
||||||
|
#define XZ_ID_LZMA2 0x21
|
||||||
|
|
||||||
|
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);
|
||||||
|
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v);
|
||||||
|
|
||||||
|
/* ---------- xz block ---------- */
|
||||||
|
|
||||||
|
#define XZ_BLOCK_HEADER_SIZE_MAX 1024
|
||||||
|
|
||||||
|
#define XZ_NUM_FILTERS_MAX 4
|
||||||
|
#define XZ_BF_NUM_FILTERS_MASK 3
|
||||||
|
#define XZ_BF_PACK_SIZE (1 << 6)
|
||||||
|
#define XZ_BF_UNPACK_SIZE (1 << 7)
|
||||||
|
|
||||||
|
#define XZ_FILTER_PROPS_SIZE_MAX 20
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt64 id;
|
||||||
|
UInt32 propsSize;
|
||||||
|
Byte props[XZ_FILTER_PROPS_SIZE_MAX];
|
||||||
|
} CXzFilter;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt64 packSize;
|
||||||
|
UInt64 unpackSize;
|
||||||
|
Byte flags;
|
||||||
|
CXzFilter filters[XZ_NUM_FILTERS_MAX];
|
||||||
|
} CXzBlock;
|
||||||
|
|
||||||
|
#define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)
|
||||||
|
#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0)
|
||||||
|
#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)
|
||||||
|
|
||||||
|
SRes XzBlock_Parse(CXzBlock *p, const Byte *header);
|
||||||
|
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes);
|
||||||
|
|
||||||
|
/* ---------- xz stream ---------- */
|
||||||
|
|
||||||
|
#define XZ_SIG_SIZE 6
|
||||||
|
#define XZ_FOOTER_SIG_SIZE 2
|
||||||
|
|
||||||
|
extern Byte XZ_SIG[XZ_SIG_SIZE];
|
||||||
|
extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
|
||||||
|
|
||||||
|
#define XZ_STREAM_FLAGS_SIZE 2
|
||||||
|
#define XZ_STREAM_CRC_SIZE 4
|
||||||
|
|
||||||
|
#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)
|
||||||
|
#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)
|
||||||
|
|
||||||
|
#define XZ_CHECK_MASK 0xF
|
||||||
|
#define XZ_CHECK_NO 0
|
||||||
|
#define XZ_CHECK_CRC32 1
|
||||||
|
#define XZ_CHECK_CRC64 4
|
||||||
|
#define XZ_CHECK_SHA256 10
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int mode;
|
||||||
|
UInt32 crc;
|
||||||
|
UInt64 crc64;
|
||||||
|
CSha256 sha;
|
||||||
|
} CXzCheck;
|
||||||
|
|
||||||
|
void XzCheck_Init(CXzCheck *p, int mode);
|
||||||
|
void XzCheck_Update(CXzCheck *p, const void *data, size_t size);
|
||||||
|
int XzCheck_Final(CXzCheck *p, Byte *digest);
|
||||||
|
|
||||||
|
typedef UInt16 CXzStreamFlags;
|
||||||
|
|
||||||
|
#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)
|
||||||
|
#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)
|
||||||
|
#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)
|
||||||
|
unsigned XzFlags_GetCheckSize(CXzStreamFlags f);
|
||||||
|
|
||||||
|
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf);
|
||||||
|
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt64 unpackSize;
|
||||||
|
UInt64 totalSize;
|
||||||
|
} CXzBlockSizes;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CXzStreamFlags flags;
|
||||||
|
size_t numBlocks;
|
||||||
|
size_t numBlocksAllocated;
|
||||||
|
CXzBlockSizes *blocks;
|
||||||
|
UInt64 startOffset;
|
||||||
|
} CXzStream;
|
||||||
|
|
||||||
|
void Xz_Construct(CXzStream *p);
|
||||||
|
void Xz_Free(CXzStream *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)
|
||||||
|
|
||||||
|
UInt64 Xz_GetUnpackSize(const CXzStream *p);
|
||||||
|
UInt64 Xz_GetPackSize(const CXzStream *p);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t num;
|
||||||
|
size_t numAllocated;
|
||||||
|
CXzStream *streams;
|
||||||
|
} CXzs;
|
||||||
|
|
||||||
|
void Xzs_Construct(CXzs *p);
|
||||||
|
void Xzs_Free(CXzs *p, ISzAlloc *alloc);
|
||||||
|
SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
UInt64 Xzs_GetNumBlocks(const CXzs *p);
|
||||||
|
UInt64 Xzs_GetUnpackSize(const CXzs *p);
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||||
|
CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||||
|
CODER_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||||
|
CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */
|
||||||
|
} ECoderStatus;
|
||||||
|
|
||||||
|
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, ISzAlloc *alloc);
|
||||||
|
SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);
|
||||||
|
void (*Init)(void *p);
|
||||||
|
SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished);
|
||||||
|
} IStateCoder;
|
||||||
|
|
||||||
|
#define MIXCODER_NUM_FILTERS_MAX 4
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISzAlloc *alloc;
|
||||||
|
Byte *buf;
|
||||||
|
int numCoders;
|
||||||
|
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];
|
||||||
|
IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];
|
||||||
|
} CMixCoder;
|
||||||
|
|
||||||
|
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);
|
||||||
|
void MixCoder_Free(CMixCoder *p);
|
||||||
|
void MixCoder_Init(CMixCoder *p);
|
||||||
|
SRes MixCoder_SetFromMethod(CMixCoder *p, int 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
|
||||||
|
{
|
||||||
|
XZ_STATE_STREAM_HEADER,
|
||||||
|
XZ_STATE_STREAM_INDEX,
|
||||||
|
XZ_STATE_STREAM_INDEX_CRC,
|
||||||
|
XZ_STATE_STREAM_FOOTER,
|
||||||
|
XZ_STATE_STREAM_PADDING,
|
||||||
|
XZ_STATE_BLOCK_HEADER,
|
||||||
|
XZ_STATE_BLOCK,
|
||||||
|
XZ_STATE_BLOCK_FOOTER
|
||||||
|
} EXzState;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
EXzState state;
|
||||||
|
UInt32 pos;
|
||||||
|
unsigned alignPos;
|
||||||
|
unsigned indexPreSize;
|
||||||
|
|
||||||
|
CXzStreamFlags streamFlags;
|
||||||
|
|
||||||
|
UInt32 blockHeaderSize;
|
||||||
|
UInt64 packSize;
|
||||||
|
UInt64 unpackSize;
|
||||||
|
|
||||||
|
UInt64 numBlocks;
|
||||||
|
UInt64 indexSize;
|
||||||
|
UInt64 indexPos;
|
||||||
|
UInt64 padSize;
|
||||||
|
|
||||||
|
UInt64 numStartedStreams;
|
||||||
|
UInt64 numFinishedStreams;
|
||||||
|
UInt64 numTotalBlocks;
|
||||||
|
|
||||||
|
UInt32 crc;
|
||||||
|
CMixCoder decoder;
|
||||||
|
CXzBlock block;
|
||||||
|
CXzCheck check;
|
||||||
|
CSha256 sha;
|
||||||
|
Byte shaDigest[SHA256_DIGEST_SIZE];
|
||||||
|
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
|
||||||
|
} CXzUnpacker;
|
||||||
|
|
||||||
|
void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc);
|
||||||
|
void XzUnpacker_Init(CXzUnpacker *p);
|
||||||
|
void XzUnpacker_Free(CXzUnpacker *p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
finishMode:
|
||||||
|
It has meaning only if the decoding reaches output limit (*destLen).
|
||||||
|
CODER_FINISH_ANY - use smallest number of input bytes
|
||||||
|
CODER_FINISH_END - read EndOfStream marker after decoding
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
status:
|
||||||
|
CODER_STATUS_NOT_FINISHED,
|
||||||
|
CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams,
|
||||||
|
call XzUnpacker_IsStreamWasFinished to check that current stream was finished
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_DATA - Data error
|
||||||
|
SZ_ERROR_UNSUPPORTED - Unsupported method or method properties
|
||||||
|
SZ_ERROR_CRC - CRC error
|
||||||
|
// SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||||
|
|
||||||
|
SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons:
|
||||||
|
- xz Stream Signature failure
|
||||||
|
- CRC32 of xz Stream Header is failed
|
||||||
|
- The size of Stream padding is not multiple of four bytes.
|
||||||
|
It's possible to get that error, if xz stream was finished and the stream
|
||||||
|
contains some another data. In that case you can call XzUnpacker_GetExtraSize()
|
||||||
|
function to get real size of xz stream.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode,
|
||||||
|
ECoderStatus *status);
|
||||||
|
|
||||||
|
Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Call XzUnpacker_GetExtraSize after XzUnpacker_Code function to detect real size of
|
||||||
|
xz stream in two cases:
|
||||||
|
XzUnpacker_Code() returns:
|
||||||
|
res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT
|
||||||
|
res == SZ_ERROR_NO_ARCHIVE
|
||||||
|
*/
|
||||||
|
|
||||||
|
UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,90 @@
|
||||||
|
/* XzCrc64.c -- CRC64 calculation
|
||||||
|
2011-06-28 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "XzCrc64.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
|
#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE
|
||||||
|
#define CRC_NUM_TABLES 4
|
||||||
|
#else
|
||||||
|
#define CRC_NUM_TABLES 5
|
||||||
|
#define CRC_UINT64_SWAP(v) \
|
||||||
|
((v >> 56) | \
|
||||||
|
((v >> 40) & ((UInt64)0xFF << 8)) | \
|
||||||
|
((v >> 24) & ((UInt64)0xFF << 16)) | \
|
||||||
|
((v >> 8) & ((UInt64)0xFF << 24)) | \
|
||||||
|
((v << 8) & ((UInt64)0xFF << 32)) | \
|
||||||
|
((v << 24) & ((UInt64)0xFF << 40)) | \
|
||||||
|
((v << 40) & ((UInt64)0xFF << 48)) | \
|
||||||
|
(v << 56))
|
||||||
|
UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MY_CPU_BE
|
||||||
|
UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef UInt64 (MY_FAST_CALL *CRC_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table);
|
||||||
|
|
||||||
|
static CRC_FUNC g_Crc64Update;
|
||||||
|
UInt64 g_Crc64Table[256 * CRC_NUM_TABLES];
|
||||||
|
|
||||||
|
UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
return g_Crc64Update(v, data, size, g_Crc64Table);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size)
|
||||||
|
{
|
||||||
|
return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MY_FAST_CALL Crc64GenerateTable()
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
UInt64 r = i;
|
||||||
|
unsigned j;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
r = (r >> 1) ^ (kCrc64Poly & ~((r & 1) - 1));
|
||||||
|
g_Crc64Table[i] = r;
|
||||||
|
}
|
||||||
|
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||||
|
{
|
||||||
|
UInt64 r = g_Crc64Table[i - 256];
|
||||||
|
g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE
|
||||||
|
|
||||||
|
g_Crc64Update = XzCrc64UpdateT4;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
#ifndef MY_CPU_BE
|
||||||
|
UInt32 k = 1;
|
||||||
|
if (*(const Byte *)&k == 1)
|
||||||
|
g_Crc64Update = XzCrc64UpdateT4;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
|
||||||
|
{
|
||||||
|
UInt64 x = g_Crc64Table[i - 256];
|
||||||
|
g_Crc64Table[i] = CRC_UINT64_SWAP(x);
|
||||||
|
}
|
||||||
|
g_Crc64Update = XzCrc64UpdateT1_BeT4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue