Update 7z_C to 2409 and update extractor
This commit is contained in:
parent
3cd82d1f24
commit
e64a8b695a
|
@ -1,128 +1,159 @@
|
||||||
/* 7z.h -- 7z interface
|
/* 7z.h -- 7z interface
|
||||||
2010-03-11 : Igor Pavlov : Public domain */
|
2023-04-02 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_H
|
#ifndef ZIP7_INC_7Z_H
|
||||||
#define __7Z_H
|
#define ZIP7_INC_7Z_H
|
||||||
|
|
||||||
#include "7zBuf.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
#define k7zStartHeaderSize 0x20
|
#define k7zStartHeaderSize 0x20
|
||||||
#define k7zSignatureSize 6
|
#define k7zSignatureSize 6
|
||||||
extern Byte k7zSignature[k7zSignatureSize];
|
|
||||||
#define k7zMajorVersion 0
|
|
||||||
|
|
||||||
enum EIdEnum {
|
extern const Byte k7zSignature[k7zSignatureSize];
|
||||||
k7zIdEnd,
|
|
||||||
k7zIdHeader,
|
|
||||||
k7zIdArchiveProperties,
|
|
||||||
k7zIdAdditionalStreamsInfo,
|
|
||||||
k7zIdMainStreamsInfo,
|
|
||||||
k7zIdFilesInfo,
|
|
||||||
k7zIdPackInfo,
|
|
||||||
k7zIdUnpackInfo,
|
|
||||||
k7zIdSubStreamsInfo,
|
|
||||||
k7zIdSize,
|
|
||||||
k7zIdCRC,
|
|
||||||
k7zIdFolder,
|
|
||||||
k7zIdCodersUnpackSize,
|
|
||||||
k7zIdNumUnpackStream,
|
|
||||||
k7zIdEmptyStream,
|
|
||||||
k7zIdEmptyFile,
|
|
||||||
k7zIdAnti,
|
|
||||||
k7zIdName,
|
|
||||||
k7zIdCTime,
|
|
||||||
k7zIdATime,
|
|
||||||
k7zIdMTime,
|
|
||||||
k7zIdWinAttributes,
|
|
||||||
k7zIdComment,
|
|
||||||
k7zIdEncodedHeader,
|
|
||||||
k7zIdStartPos,
|
|
||||||
k7zIdDummy
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 NumInStreams;
|
const Byte *Data;
|
||||||
UInt32 NumOutStreams;
|
size_t Size;
|
||||||
UInt64 MethodID;
|
} CSzData;
|
||||||
CBuf Props;
|
|
||||||
|
/* CSzCoderInfo & CSzFolder support only default methods */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t PropsOffset;
|
||||||
|
UInt32 MethodID;
|
||||||
|
Byte NumStreams;
|
||||||
|
Byte PropsSize;
|
||||||
} CSzCoderInfo;
|
} CSzCoderInfo;
|
||||||
|
|
||||||
void SzCoderInfo_Init(CSzCoderInfo* p);
|
typedef struct
|
||||||
void SzCoderInfo_Free(CSzCoderInfo* p, ISzAlloc* alloc);
|
{
|
||||||
|
UInt32 InIndex;
|
||||||
|
UInt32 OutIndex;
|
||||||
|
} CSzBond;
|
||||||
|
|
||||||
|
#define SZ_NUM_CODERS_IN_FOLDER_MAX 4
|
||||||
|
#define SZ_NUM_BONDS_IN_FOLDER_MAX 3
|
||||||
|
#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 InIndex;
|
UInt32 NumCoders;
|
||||||
UInt32 OutIndex;
|
UInt32 NumBonds;
|
||||||
} CSzBindPair;
|
UInt32 NumPackStreams;
|
||||||
|
UInt32 UnpackStream;
|
||||||
typedef struct
|
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
|
||||||
{
|
CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
|
||||||
CSzCoderInfo* Coders;
|
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
|
||||||
CSzBindPair* BindPairs;
|
|
||||||
UInt32* PackStreams;
|
|
||||||
UInt64* UnpackSizes;
|
|
||||||
UInt32 NumCoders;
|
|
||||||
UInt32 NumBindPairs;
|
|
||||||
UInt32 NumPackStreams;
|
|
||||||
int UnpackCRCDefined;
|
|
||||||
UInt32 UnpackCRC;
|
|
||||||
|
|
||||||
UInt32 NumUnpackStreams;
|
|
||||||
} CSzFolder;
|
} CSzFolder;
|
||||||
|
|
||||||
void SzFolder_Init(CSzFolder* p);
|
|
||||||
UInt64 SzFolder_GetUnpackSize(CSzFolder* p);
|
|
||||||
int SzFolder_FindBindPairForInStream(CSzFolder* p, UInt32 inStreamIndex);
|
|
||||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder* p);
|
|
||||||
UInt64 SzFolder_GetUnpackSize(CSzFolder* p);
|
|
||||||
|
|
||||||
SRes SzFolder_Decode(const CSzFolder* folder, const UInt64* packSizes,
|
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
|
||||||
ILookInStream* stream, UInt64 startPos,
|
|
||||||
Byte* outBuffer, size_t outSize, ISzAlloc* allocMain);
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 Low;
|
UInt32 Low;
|
||||||
UInt32 High;
|
UInt32 High;
|
||||||
} CNtfsFileTime;
|
} CNtfsFileTime;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CNtfsFileTime MTime;
|
Byte *Defs; /* MSB 0 bit numbering */
|
||||||
UInt64 Size;
|
UInt32 *Vals;
|
||||||
UInt32 Crc;
|
} CSzBitUi32s;
|
||||||
UInt32 Attrib;
|
|
||||||
Byte HasStream;
|
|
||||||
Byte IsDir;
|
|
||||||
Byte IsAnti;
|
|
||||||
Byte CrcDefined;
|
|
||||||
Byte MTimeDefined;
|
|
||||||
Byte AttribDefined;
|
|
||||||
} CSzFileItem;
|
|
||||||
|
|
||||||
void SzFile_Init(CSzFileItem* p);
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt64* PackSizes;
|
Byte *Defs; /* MSB 0 bit numbering */
|
||||||
Byte* PackCRCsDefined;
|
// UInt64 *Vals;
|
||||||
UInt32* PackCRCs;
|
CNtfsFileTime *Vals;
|
||||||
CSzFolder* Folders;
|
} CSzBitUi64s;
|
||||||
CSzFileItem* Files;
|
|
||||||
UInt32 NumPackStreams;
|
#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||||
UInt32 NumFolders;
|
|
||||||
UInt32 NumFiles;
|
#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; // NumFolders
|
||||||
|
|
||||||
|
size_t *FoCodersOffsets; // NumFolders + 1
|
||||||
|
UInt32 *FoStartPackStreamIndex; // NumFolders + 1
|
||||||
|
UInt32 *FoToCoderUnpackSizes; // NumFolders + 1
|
||||||
|
Byte *FoToMainUnpackSizeIndex; // NumFolders
|
||||||
|
UInt64 *CoderUnpackSizes; // for all coders in all folders
|
||||||
|
|
||||||
|
Byte *CodersData;
|
||||||
|
|
||||||
|
UInt64 RangeLimit;
|
||||||
} CSzAr;
|
} CSzAr;
|
||||||
|
|
||||||
void SzAr_Init(CSzAr* p);
|
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
|
||||||
void SzAr_Free(CSzAr* p, ISzAlloc* alloc);
|
|
||||||
|
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
|
||||||
|
ILookInStreamPtr stream, UInt64 startPos,
|
||||||
|
Byte *outBuffer, size_t outSize,
|
||||||
|
ISzAllocPtr allocMain);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CSzAr db;
|
||||||
|
|
||||||
|
UInt64 startPosAfterHeader;
|
||||||
|
UInt64 dataPos;
|
||||||
|
|
||||||
|
UInt32 NumFiles;
|
||||||
|
|
||||||
|
UInt64 *UnpackPositions; // NumFiles + 1
|
||||||
|
// Byte *IsEmptyFiles;
|
||||||
|
Byte *IsDirs;
|
||||||
|
CSzBitUi32s CRCs;
|
||||||
|
|
||||||
|
CSzBitUi32s Attribs;
|
||||||
|
// CSzBitUi32s Parents;
|
||||||
|
CSzBitUi64s MTime;
|
||||||
|
CSzBitUi64s CTime;
|
||||||
|
|
||||||
|
UInt32 *FolderToFile; // NumFolders + 1
|
||||||
|
UInt32 *FileToFolder; // NumFiles
|
||||||
|
|
||||||
|
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, ISzAllocPtr alloc);
|
||||||
|
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||||
|
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SzExtract extracts file from archive
|
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);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
SzArEx_Extract extracts file from archive
|
||||||
|
|
||||||
*outBuffer must be 0 before first call for each new archive.
|
*outBuffer must be 0 before first call for each new archive.
|
||||||
|
|
||||||
|
@ -141,46 +172,18 @@ void SzAr_Free(CSzAr* p, ISzAlloc* alloc);
|
||||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
CSzAr db;
|
|
||||||
|
|
||||||
UInt64 startPosAfterHeader;
|
|
||||||
UInt64 dataPos;
|
|
||||||
|
|
||||||
UInt32* FolderStartPackStreamIndex;
|
|
||||||
UInt64* PackStreamStartPositions;
|
|
||||||
UInt32* FolderStartFileIndex;
|
|
||||||
UInt32* FileIndexToFolderIndexMap;
|
|
||||||
|
|
||||||
size_t* FileNameOffsets; /* in 2-byte steps */
|
|
||||||
CBuf FileNames; /* UTF-16-LE */
|
|
||||||
} CSzArEx;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
SRes SzArEx_Extract(
|
SRes SzArEx_Extract(
|
||||||
const CSzArEx* db,
|
const CSzArEx *db,
|
||||||
ILookInStream* inStream,
|
ILookInStreamPtr inStream,
|
||||||
UInt32 fileIndex, /* index of file */
|
UInt32 fileIndex, /* index of file */
|
||||||
UInt32* blockIndex, /* index of solid block */
|
UInt32 *blockIndex, /* index of solid block */
|
||||||
Byte** outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||||
size_t* outBufferSize, /* buffer size for output buffer */
|
size_t *outBufferSize, /* buffer size for output buffer */
|
||||||
size_t* offset, /* offset of stream for required file in *outBuffer */
|
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||||
size_t* outSizeProcessed, /* size of file in *outBuffer */
|
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||||
ISzAlloc* allocMain,
|
ISzAllocPtr allocMain,
|
||||||
ISzAlloc* allocTemp);
|
ISzAllocPtr allocTemp);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SzArEx_Open Errors:
|
SzArEx_Open Errors:
|
||||||
|
@ -193,7 +196,8 @@ SZ_ERROR_INPUT_EOF
|
||||||
SZ_ERROR_FAIL
|
SZ_ERROR_FAIL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes SzArEx_Open(CSzArEx* p, ILookInStream* inStream, ISzAlloc* allocMain, ISzAlloc* allocTemp);
|
SRes SzArEx_Open(CSzArEx *p, ILookInStreamPtr inStream,
|
||||||
|
ISzAllocPtr allocMain, ISzAllocPtr allocTemp);
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
|
|
||||||
|
|
|
@ -1,74 +1,89 @@
|
||||||
/* 7zAlloc.c -- Allocation functions
|
/* 7zAlloc.c -- Allocation functions for 7z processing
|
||||||
2010-10-29 : Igor Pavlov : Public domain */
|
2023-03-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "7zAlloc.h"
|
#include "7zAlloc.h"
|
||||||
|
|
||||||
/* #define _SZ_ALLOC_DEBUG */
|
/* #define SZ_ALLOC_DEBUG */
|
||||||
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
/* use SZ_ALLOC_DEBUG to debug alloc/free operations */
|
||||||
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef SZ_ALLOC_DEBUG
|
||||||
|
|
||||||
|
/*
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include "7zWindows.h"
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
int g_allocCount = 0;
|
static int g_allocCount = 0;
|
||||||
int g_allocCountTemp = 0;
|
static int g_allocCountTemp = 0;
|
||||||
|
|
||||||
#endif
|
static void Print_Alloc(const char *s, size_t size, int *counter)
|
||||||
|
|
||||||
void* SzAlloc(void* p, size_t size)
|
|
||||||
{
|
{
|
||||||
(void)p; // unused param
|
const unsigned size2 = (unsigned)size;
|
||||||
if (size == 0)
|
fprintf(stderr, "\n%s count = %10d : %10u bytes; ", s, *counter, size2);
|
||||||
return 0;
|
(*counter)++;
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
}
|
||||||
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
|
static void Print_Free(const char *s, int *counter)
|
||||||
g_allocCount++;
|
{
|
||||||
|
(*counter)--;
|
||||||
|
fprintf(stderr, "\n%s count = %10d", s, *counter);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return malloc(size);
|
|
||||||
|
void *SzAlloc(ISzAllocPtr p, size_t size)
|
||||||
|
{
|
||||||
|
UNUSED_VAR(p)
|
||||||
|
if (size == 0)
|
||||||
|
return 0;
|
||||||
|
#ifdef SZ_ALLOC_DEBUG
|
||||||
|
Print_Alloc("Alloc", size, &g_allocCount);
|
||||||
|
#endif
|
||||||
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzFree(void* p, void* address)
|
void SzFree(ISzAllocPtr p, void *address)
|
||||||
{
|
{
|
||||||
(void)p; // unused param
|
UNUSED_VAR(p)
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef SZ_ALLOC_DEBUG
|
||||||
if (address != 0) {
|
if (address)
|
||||||
g_allocCount--;
|
Print_Free("Free ", &g_allocCount);
|
||||||
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
|
#endif
|
||||||
}
|
free(address);
|
||||||
#endif
|
|
||||||
free(address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* SzAllocTemp(void* p, size_t size)
|
void *SzAllocTemp(ISzAllocPtr p, size_t size)
|
||||||
{
|
{
|
||||||
(void)p; // unused param
|
UNUSED_VAR(p)
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef SZ_ALLOC_DEBUG
|
||||||
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
|
Print_Alloc("Alloc_temp", size, &g_allocCountTemp);
|
||||||
g_allocCountTemp++;
|
/*
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return HeapAlloc(GetProcessHeap(), 0, size);
|
return HeapAlloc(GetProcessHeap(), 0, size);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
*/
|
||||||
return malloc(size);
|
#endif
|
||||||
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzFreeTemp(void* p, void* address)
|
void SzFreeTemp(ISzAllocPtr p, void *address)
|
||||||
{
|
{
|
||||||
(void)p; // unused param
|
UNUSED_VAR(p)
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef SZ_ALLOC_DEBUG
|
||||||
if (address != 0) {
|
if (address)
|
||||||
g_allocCountTemp--;
|
Print_Free("Free_temp ", &g_allocCountTemp);
|
||||||
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
|
/*
|
||||||
}
|
#ifdef _WIN32
|
||||||
#ifdef _WIN32
|
HeapFree(GetProcessHeap(), 0, address);
|
||||||
HeapFree(GetProcessHeap(), 0, address);
|
return;
|
||||||
return;
|
#endif
|
||||||
#endif
|
*/
|
||||||
#endif
|
#endif
|
||||||
free(address);
|
free(address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
/* 7zAlloc.h -- Allocation functions
|
/* 7zAlloc.h -- Allocation functions
|
||||||
2010-10-29 : Igor Pavlov : Public domain */
|
2023-03-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_ALLOC_H
|
#ifndef ZIP7_INC_7Z_ALLOC_H
|
||||||
#define __7Z_ALLOC_H
|
#define ZIP7_INC_7Z_ALLOC_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include "7zTypes.h"
|
||||||
|
|
||||||
void* SzAlloc(void* p, size_t size);
|
EXTERN_C_BEGIN
|
||||||
void SzFree(void* p, void* address);
|
|
||||||
|
|
||||||
void* SzAllocTemp(void* p, size_t size);
|
void *SzAlloc(ISzAllocPtr p, size_t size);
|
||||||
void SzFreeTemp(void* p, void* address);
|
void SzFree(ISzAllocPtr p, void *address);
|
||||||
|
|
||||||
|
void *SzAllocTemp(ISzAllocPtr p, size_t size);
|
||||||
|
void SzFreeTemp(ISzAllocPtr p, void *address);
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,34 +1,36 @@
|
||||||
/* 7zBuf.c -- Byte Buffer
|
/* 7zBuf.c -- Byte Buffer
|
||||||
2008-03-28
|
2017-04-03 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include "7zBuf.h"
|
#include "7zBuf.h"
|
||||||
|
|
||||||
void Buf_Init(CBuf* p)
|
void Buf_Init(CBuf *p)
|
||||||
{
|
{
|
||||||
p->data = 0;
|
p->data = 0;
|
||||||
p->size = 0;
|
p->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Buf_Create(CBuf* p, size_t size, ISzAlloc* alloc)
|
int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc)
|
||||||
{
|
{
|
||||||
p->size = 0;
|
p->size = 0;
|
||||||
if (size == 0) {
|
if (size == 0)
|
||||||
p->data = 0;
|
{
|
||||||
return 1;
|
p->data = 0;
|
||||||
}
|
return 1;
|
||||||
p->data = (Byte*)alloc->Alloc(alloc, size);
|
}
|
||||||
if (p->data != 0) {
|
p->data = (Byte *)ISzAlloc_Alloc(alloc, size);
|
||||||
p->size = size;
|
if (p->data)
|
||||||
return 1;
|
{
|
||||||
}
|
p->size = size;
|
||||||
return 0;
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buf_Free(CBuf* p, ISzAlloc* alloc)
|
void Buf_Free(CBuf *p, ISzAllocPtr alloc)
|
||||||
{
|
{
|
||||||
alloc->Free(alloc, p->data);
|
ISzAlloc_Free(alloc, p->data);
|
||||||
p->data = 0;
|
p->data = 0;
|
||||||
p->size = 0;
|
p->size = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,35 @@
|
||||||
/* 7zBuf.h -- Byte Buffer
|
/* 7zBuf.h -- Byte Buffer
|
||||||
2009-02-07 : Igor Pavlov : Public domain */
|
2023-03-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_BUF_H
|
#ifndef ZIP7_INC_7Z_BUF_H
|
||||||
#define __7Z_BUF_H
|
#define ZIP7_INC_7Z_BUF_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
EXTERN_C_BEGIN
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Byte* data;
|
Byte *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
} CBuf;
|
} CBuf;
|
||||||
|
|
||||||
void Buf_Init(CBuf* p);
|
void Buf_Init(CBuf *p);
|
||||||
int Buf_Create(CBuf* p, size_t size, ISzAlloc* alloc);
|
int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc);
|
||||||
void Buf_Free(CBuf* p, ISzAlloc* alloc);
|
void Buf_Free(CBuf *p, ISzAllocPtr alloc);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Byte* data;
|
Byte *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t pos;
|
size_t pos;
|
||||||
} CDynBuf;
|
} CDynBuf;
|
||||||
|
|
||||||
void DynBuf_Construct(CDynBuf* p);
|
void DynBuf_Construct(CDynBuf *p);
|
||||||
void DynBuf_SeekToBeg(CDynBuf* p);
|
void DynBuf_SeekToBeg(CDynBuf *p);
|
||||||
int DynBuf_Write(CDynBuf* p, const Byte* buf, size_t size, ISzAlloc* alloc);
|
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc);
|
||||||
void DynBuf_Free(CDynBuf* p, ISzAlloc* alloc);
|
void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
EXTERN_C_END
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* 7zBuf2.c -- Byte Buffer
|
||||||
|
2017-04-03 : 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, ISzAllocPtr alloc)
|
||||||
|
{
|
||||||
|
if (size > p->size - p->pos)
|
||||||
|
{
|
||||||
|
size_t newSize = p->pos + size;
|
||||||
|
Byte *data;
|
||||||
|
newSize += newSize / 4;
|
||||||
|
data = (Byte *)ISzAlloc_Alloc(alloc, newSize);
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
p->size = newSize;
|
||||||
|
if (p->pos != 0)
|
||||||
|
memcpy(data, p->data, p->pos);
|
||||||
|
ISzAlloc_Free(alloc, p->data);
|
||||||
|
p->data = data;
|
||||||
|
}
|
||||||
|
if (size != 0)
|
||||||
|
{
|
||||||
|
memcpy(p->data + p->pos, buf, size);
|
||||||
|
p->pos += size;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc)
|
||||||
|
{
|
||||||
|
ISzAlloc_Free(alloc, p->data);
|
||||||
|
p->data = 0;
|
||||||
|
p->size = 0;
|
||||||
|
p->pos = 0;
|
||||||
|
}
|
|
@ -1,80 +1,420 @@
|
||||||
/* 7zCrc.c -- CRC32 init
|
/* 7zCrc.c -- CRC32 calculation and init
|
||||||
2010-12-01 : Igor Pavlov : Public domain */
|
2024-03-01 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include "7zCrc.h"
|
#include "7zCrc.h"
|
||||||
#include "CpuArch.h"
|
#include "CpuArch.h"
|
||||||
|
|
||||||
#define kCrcPoly 0xEDB88320
|
// for debug:
|
||||||
|
// #define __ARM_FEATURE_CRC32 1
|
||||||
|
|
||||||
#ifdef MY_CPU_X86_OR_AMD64
|
#ifdef __ARM_FEATURE_CRC32
|
||||||
#define CRC_NUM_TABLES 8
|
// #pragma message("__ARM_FEATURE_CRC32")
|
||||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void* data, size_t size, const UInt32* table);
|
#define Z7_CRC_HW_FORCE
|
||||||
#elif defined(MY_CPU_LE)
|
#endif
|
||||||
#define CRC_NUM_TABLES 4
|
|
||||||
|
// #define Z7_CRC_DEBUG_BE
|
||||||
|
#ifdef Z7_CRC_DEBUG_BE
|
||||||
|
#undef MY_CPU_LE
|
||||||
|
#define MY_CPU_BE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Z7_CRC_HW_FORCE
|
||||||
|
#define Z7_CRC_NUM_TABLES_USE 1
|
||||||
#else
|
#else
|
||||||
#define CRC_NUM_TABLES 5
|
#ifdef Z7_CRC_NUM_TABLES
|
||||||
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
#define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES
|
||||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void* data, size_t size, const UInt32* table);
|
#else
|
||||||
|
#define Z7_CRC_NUM_TABLES_USE 12
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE < 1
|
||||||
|
#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_LE) || (Z7_CRC_NUM_TABLES_USE == 1)
|
||||||
|
#define Z7_CRC_NUM_TABLES_TOTAL Z7_CRC_NUM_TABLES_USE
|
||||||
|
#else
|
||||||
|
#define Z7_CRC_NUM_TABLES_TOTAL (Z7_CRC_NUM_TABLES_USE + 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Z7_CRC_HW_FORCE
|
||||||
|
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE == 1 \
|
||||||
|
|| (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
|
||||||
|
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||||
|
#define Z7_CRC_UPDATE_T1_FUNC_NAME CrcUpdateGT1
|
||||||
|
static UInt32 Z7_FASTCALL Z7_CRC_UPDATE_T1_FUNC_NAME(UInt32 v, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
const UInt32 *table = g_CrcTable;
|
||||||
|
const Byte *p = (const Byte *)data;
|
||||||
|
const Byte *lim = p + size;
|
||||||
|
for (; p != lim; p++)
|
||||||
|
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE != 1
|
||||||
#ifndef MY_CPU_BE
|
#ifndef MY_CPU_BE
|
||||||
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void* data, size_t size, const UInt32* table);
|
#define FUNC_NAME_LE_2(s) CrcUpdateT ## s
|
||||||
|
#define FUNC_NAME_LE_1(s) FUNC_NAME_LE_2(s)
|
||||||
|
#define FUNC_NAME_LE FUNC_NAME_LE_1(Z7_CRC_NUM_TABLES_USE)
|
||||||
|
UInt32 Z7_FASTCALL FUNC_NAME_LE (UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||||
|
#endif
|
||||||
|
#ifndef MY_CPU_LE
|
||||||
|
#define FUNC_NAME_BE_2(s) CrcUpdateT1_BeT ## s
|
||||||
|
#define FUNC_NAME_BE_1(s) FUNC_NAME_BE_2(s)
|
||||||
|
#define FUNC_NAME_BE FUNC_NAME_BE_1(Z7_CRC_NUM_TABLES_USE)
|
||||||
|
UInt32 Z7_FASTCALL FUNC_NAME_BE (UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef UInt32(MY_FAST_CALL* CRC_FUNC)(UInt32 v, const void* data, size_t size, const UInt32* table);
|
#endif // Z7_CRC_HW_FORCE
|
||||||
|
|
||||||
static CRC_FUNC g_CrcUpdate;
|
/* ---------- hardware CRC ---------- */
|
||||||
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
|
#ifdef MY_CPU_LE
|
||||||
|
|
||||||
g_CrcUpdate = CrcUpdateT4;
|
#if defined(MY_CPU_ARM_OR_ARM64)
|
||||||
|
// #pragma message("ARM*")
|
||||||
|
|
||||||
#if CRC_NUM_TABLES == 8
|
#if (defined(__clang__) && (__clang_major__ >= 3)) \
|
||||||
if (!CPU_Is_InOrder())
|
|| defined(__GNUC__) && (__GNUC__ >= 6) && defined(MY_CPU_ARM64) \
|
||||||
g_CrcUpdate = CrcUpdateT8;
|
|| defined(__GNUC__) && (__GNUC__ >= 8)
|
||||||
|
#if !defined(__ARM_FEATURE_CRC32)
|
||||||
|
// #pragma message("!defined(__ARM_FEATURE_CRC32)")
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#define __ARM_FEATURE_CRC32 1
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#define Z7_ARM_FEATURE_CRC32_WAS_SET
|
||||||
|
#if defined(__clang__)
|
||||||
|
#if defined(MY_CPU_ARM64)
|
||||||
|
#define ATTRIB_CRC __attribute__((__target__("crc")))
|
||||||
|
#else
|
||||||
|
#define ATTRIB_CRC __attribute__((__target__("armv8-a,crc")))
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(MY_CPU_ARM64)
|
||||||
|
#if !defined(Z7_GCC_VERSION) || (Z7_GCC_VERSION >= 60000)
|
||||||
|
#define ATTRIB_CRC __attribute__((__target__("+crc")))
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
#if !defined(Z7_GCC_VERSION) || (__GNUC__ >= 8)
|
||||||
|
#if defined(__ARM_FP) && __GNUC__ >= 8
|
||||||
|
// for -mfloat-abi=hard: similar to <arm_acle.h>
|
||||||
|
#define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc+simd")))
|
||||||
#else
|
#else
|
||||||
|
#define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc")))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if defined(__ARM_FEATURE_CRC32)
|
||||||
|
// #pragma message("<arm_acle.h>")
|
||||||
|
/*
|
||||||
|
arm_acle.h (GGC):
|
||||||
|
before Nov 17, 2017:
|
||||||
|
#ifdef __ARM_FEATURE_CRC32
|
||||||
|
|
||||||
|
Nov 17, 2017: gcc10.0 (gcc 9.2.0) checked"
|
||||||
|
#if __ARM_ARCH >= 8
|
||||||
|
#pragma GCC target ("arch=armv8-a+crc")
|
||||||
|
|
||||||
|
Aug 22, 2019: GCC 8.4?, 9.2.1, 10.1:
|
||||||
|
#ifdef __ARM_FEATURE_CRC32
|
||||||
|
#ifdef __ARM_FP
|
||||||
|
#pragma GCC target ("arch=armv8-a+crc+simd")
|
||||||
|
#else
|
||||||
|
#pragma GCC target ("arch=armv8-a+crc")
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
#if defined(__ARM_ARCH) && __ARM_ARCH < 8
|
||||||
|
#if defined(Z7_GCC_VERSION) && (__GNUC__ == 8) && (Z7_GCC_VERSION < 80400) \
|
||||||
|
|| defined(Z7_GCC_VERSION) && (__GNUC__ == 9) && (Z7_GCC_VERSION < 90201) \
|
||||||
|
|| defined(Z7_GCC_VERSION) && (__GNUC__ == 10) && (Z7_GCC_VERSION < 100100)
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
|
||||||
|
// #pragma message("#define __ARM_ARCH 8")
|
||||||
|
#undef __ARM_ARCH
|
||||||
|
#define __ARM_ARCH 8
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#define Z7_CRC_HW_USE
|
||||||
|
#include <arm_acle.h>
|
||||||
|
#endif
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#if defined(MY_CPU_ARM64)
|
||||||
|
#if (_MSC_VER >= 1910)
|
||||||
|
#ifdef __clang__
|
||||||
|
// #define Z7_CRC_HW_USE
|
||||||
|
// #include <arm_acle.h>
|
||||||
|
#else
|
||||||
|
#define Z7_CRC_HW_USE
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else // non-ARM*
|
||||||
|
|
||||||
|
// #define Z7_CRC_HW_USE // for debug : we can test HW-branch of code
|
||||||
|
#ifdef Z7_CRC_HW_USE
|
||||||
|
#include "7zCrcEmu.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // non-ARM*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(Z7_CRC_HW_USE)
|
||||||
|
|
||||||
|
// #pragma message("USE ARM HW CRC")
|
||||||
|
|
||||||
|
#ifdef MY_CPU_64BIT
|
||||||
|
#define CRC_HW_WORD_TYPE UInt64
|
||||||
|
#define CRC_HW_WORD_FUNC __crc32d
|
||||||
|
#else
|
||||||
|
#define CRC_HW_WORD_TYPE UInt32
|
||||||
|
#define CRC_HW_WORD_FUNC __crc32w
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CRC_HW_UNROLL_BYTES (sizeof(CRC_HW_WORD_TYPE) * 4)
|
||||||
|
|
||||||
|
#ifdef ATTRIB_CRC
|
||||||
|
ATTRIB_CRC
|
||||||
|
#endif
|
||||||
|
Z7_NO_INLINE
|
||||||
|
#ifdef Z7_CRC_HW_FORCE
|
||||||
|
UInt32 Z7_FASTCALL CrcUpdate
|
||||||
|
#else
|
||||||
|
static UInt32 Z7_FASTCALL CrcUpdate_HW
|
||||||
|
#endif
|
||||||
|
(UInt32 v, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
const Byte *p = (const Byte *)data;
|
||||||
|
for (; size != 0 && ((unsigned)(ptrdiff_t)p & (CRC_HW_UNROLL_BYTES - 1)) != 0; size--)
|
||||||
|
v = __crc32b(v, *p++);
|
||||||
|
if (size >= CRC_HW_UNROLL_BYTES)
|
||||||
|
{
|
||||||
|
const Byte *lim = p + size;
|
||||||
|
size &= CRC_HW_UNROLL_BYTES - 1;
|
||||||
|
lim -= size;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
#ifndef MY_CPU_BE
|
v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));
|
||||||
UInt32 k = 1;
|
v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));
|
||||||
if (*(const Byte*)&k == 1)
|
p += 2 * sizeof(CRC_HW_WORD_TYPE);
|
||||||
g_CrcUpdate = CrcUpdateT4;
|
v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));
|
||||||
else
|
v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));
|
||||||
#endif
|
p += 2 * sizeof(CRC_HW_WORD_TYPE);
|
||||||
{
|
|
||||||
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
|
while (p != lim);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; size != 0; size--)
|
||||||
|
v = __crc32b(v, *p++);
|
||||||
|
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Z7_ARM_FEATURE_CRC32_WAS_SET
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#undef __ARM_FEATURE_CRC32
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#undef Z7_ARM_FEATURE_CRC32_WAS_SET
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // defined(Z7_CRC_HW_USE)
|
||||||
|
#endif // MY_CPU_LE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef Z7_CRC_HW_FORCE
|
||||||
|
|
||||||
|
#if defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
|
||||||
|
/*
|
||||||
|
typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_WITH_TABLE_FUNC)
|
||||||
|
(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||||
|
Z7_CRC_UPDATE_WITH_TABLE_FUNC g_CrcUpdate;
|
||||||
|
*/
|
||||||
|
static unsigned g_Crc_Algo;
|
||||||
|
#if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
|
||||||
|
static unsigned g_Crc_Be;
|
||||||
|
#endif
|
||||||
|
#endif // defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Z7_NO_INLINE
|
||||||
|
#ifdef Z7_CRC_HW_USE
|
||||||
|
static UInt32 Z7_FASTCALL CrcUpdate_Base
|
||||||
|
#else
|
||||||
|
UInt32 Z7_FASTCALL CrcUpdate
|
||||||
|
#endif
|
||||||
|
(UInt32 crc, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE == 1
|
||||||
|
return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);
|
||||||
|
#else // Z7_CRC_NUM_TABLES_USE != 1
|
||||||
|
#ifdef Z7_CRC_UPDATE_T1_FUNC_NAME
|
||||||
|
if (g_Crc_Algo == 1)
|
||||||
|
return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE
|
||||||
|
return FUNC_NAME_LE(crc, data, size, g_CrcTable);
|
||||||
|
#elif defined(MY_CPU_BE)
|
||||||
|
return FUNC_NAME_BE(crc, data, size, g_CrcTable);
|
||||||
|
#else
|
||||||
|
if (g_Crc_Be)
|
||||||
|
return FUNC_NAME_BE(crc, data, size, g_CrcTable);
|
||||||
|
else
|
||||||
|
return FUNC_NAME_LE(crc, data, size, g_CrcTable);
|
||||||
|
#endif
|
||||||
|
#endif // Z7_CRC_NUM_TABLES_USE != 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Z7_CRC_HW_USE
|
||||||
|
Z7_NO_INLINE
|
||||||
|
UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
if (g_Crc_Algo == 0)
|
||||||
|
return CrcUpdate_HW(crc, data, size);
|
||||||
|
return CrcUpdate_Base(crc, data, size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // !defined(Z7_CRC_HW_FORCE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)
|
||||||
|
{
|
||||||
|
return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MY_ALIGN(64)
|
||||||
|
UInt32 g_CrcTable[256 * Z7_CRC_NUM_TABLES_TOTAL];
|
||||||
|
|
||||||
|
|
||||||
|
void Z7_FASTCALL CrcGenerateTable(void)
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
#if defined(Z7_CRC_HW_FORCE)
|
||||||
|
g_CrcTable[i] = __crc32b(i, 0);
|
||||||
|
#else
|
||||||
|
#define kCrcPoly 0xEDB88320
|
||||||
|
UInt32 r = i;
|
||||||
|
unsigned j;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
|
||||||
|
g_CrcTable[i] = r;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
for (i = 256; i < 256 * Z7_CRC_NUM_TABLES_USE; i++)
|
||||||
|
{
|
||||||
|
const UInt32 r = g_CrcTable[(size_t)i - 256];
|
||||||
|
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(Z7_CRC_HW_FORCE) && \
|
||||||
|
(defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME) || defined(MY_CPU_BE))
|
||||||
|
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE <= 1
|
||||||
|
g_Crc_Algo = 1;
|
||||||
|
#else // Z7_CRC_NUM_TABLES_USE <= 1
|
||||||
|
|
||||||
|
#if defined(MY_CPU_LE)
|
||||||
|
g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
|
||||||
|
#else // !defined(MY_CPU_LE)
|
||||||
|
{
|
||||||
|
#ifndef MY_CPU_BE
|
||||||
|
UInt32 k = 0x01020304;
|
||||||
|
const Byte *p = (const Byte *)&k;
|
||||||
|
if (p[0] == 4 && p[1] == 3)
|
||||||
|
g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
|
||||||
|
else if (p[0] != 1 || p[1] != 2)
|
||||||
|
g_Crc_Algo = 1;
|
||||||
|
else
|
||||||
|
#endif // MY_CPU_BE
|
||||||
|
{
|
||||||
|
for (i = 256 * Z7_CRC_NUM_TABLES_TOTAL - 1; i >= 256; i--)
|
||||||
|
{
|
||||||
|
const UInt32 x = g_CrcTable[(size_t)i - 256];
|
||||||
|
g_CrcTable[i] = Z7_BSWAP32(x);
|
||||||
|
}
|
||||||
|
#if defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
|
||||||
|
g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
|
||||||
|
#endif
|
||||||
|
#if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
|
||||||
|
g_Crc_Be = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // !defined(MY_CPU_LE)
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE
|
||||||
|
#ifdef Z7_CRC_HW_USE
|
||||||
|
if (CPU_IsSupported_CRC32())
|
||||||
|
g_Crc_Algo = 0;
|
||||||
|
#endif // Z7_CRC_HW_USE
|
||||||
|
#endif // MY_CPU_LE
|
||||||
|
|
||||||
|
#endif // Z7_CRC_NUM_TABLES_USE <= 1
|
||||||
|
#endif // g_Crc_Algo was declared
|
||||||
|
}
|
||||||
|
|
||||||
|
Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo)
|
||||||
|
{
|
||||||
|
if (algo == 0)
|
||||||
|
return &CrcUpdate;
|
||||||
|
|
||||||
|
#if defined(Z7_CRC_HW_USE)
|
||||||
|
if (algo == sizeof(CRC_HW_WORD_TYPE) * 8)
|
||||||
|
{
|
||||||
|
#ifdef Z7_CRC_HW_FORCE
|
||||||
|
return &CrcUpdate;
|
||||||
|
#else
|
||||||
|
if (g_Crc_Algo == 0)
|
||||||
|
return &CrcUpdate_HW;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Z7_CRC_HW_FORCE
|
||||||
|
if (algo == Z7_CRC_NUM_TABLES_USE)
|
||||||
|
return
|
||||||
|
#ifdef Z7_CRC_HW_USE
|
||||||
|
&CrcUpdate_Base;
|
||||||
|
#else
|
||||||
|
&CrcUpdate;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef kCrcPoly
|
||||||
|
#undef Z7_CRC_NUM_TABLES_USE
|
||||||
|
#undef Z7_CRC_NUM_TABLES_TOTAL
|
||||||
|
#undef CRC_UPDATE_BYTE_2
|
||||||
|
#undef FUNC_NAME_LE_2
|
||||||
|
#undef FUNC_NAME_LE_1
|
||||||
|
#undef FUNC_NAME_LE
|
||||||
|
#undef FUNC_NAME_BE_2
|
||||||
|
#undef FUNC_NAME_BE_1
|
||||||
|
#undef FUNC_NAME_BE
|
||||||
|
|
||||||
|
#undef CRC_HW_UNROLL_BYTES
|
||||||
|
#undef CRC_HW_WORD_FUNC
|
||||||
|
#undef CRC_HW_WORD_TYPE
|
||||||
|
|
|
@ -1,24 +1,27 @@
|
||||||
/* 7zCrc.h -- CRC32 calculation
|
/* 7zCrc.h -- CRC32 calculation
|
||||||
2009-11-21 : Igor Pavlov : Public domain */
|
2024-01-22 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_CRC_H
|
#ifndef ZIP7_INC_7Z_CRC_H
|
||||||
#define __7Z_CRC_H
|
#define ZIP7_INC_7Z_CRC_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
extern UInt32 g_CrcTable[];
|
extern UInt32 g_CrcTable[];
|
||||||
|
|
||||||
/* Call CrcGenerateTable one time before other CRC functions */
|
/* Call CrcGenerateTable one time before other CRC functions */
|
||||||
void MY_FAST_CALL CrcGenerateTable(void);
|
void Z7_FASTCALL CrcGenerateTable(void);
|
||||||
|
|
||||||
#define CRC_INIT_VAL 0xFFFFFFFF
|
#define CRC_INIT_VAL 0xFFFFFFFF
|
||||||
#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
|
#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
|
||||||
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
#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 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size);
|
||||||
UInt32 MY_FAST_CALL CrcCalc(const void* data, size_t size);
|
UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size);
|
||||||
|
|
||||||
|
typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_FUNC)(UInt32 v, const void *data, size_t size);
|
||||||
|
Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo);
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
|
|
||||||
|
|
|
@ -1,53 +1,199 @@
|
||||||
/* 7zCrcOpt.c -- CRC32 calculation
|
/* 7zCrcOpt.c -- CRC32 calculation (optimized functions)
|
||||||
2010-12-01 : Igor Pavlov : Public domain */
|
2023-12-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include "CpuArch.h"
|
#include "CpuArch.h"
|
||||||
|
|
||||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
#if !defined(Z7_CRC_NUM_TABLES) || Z7_CRC_NUM_TABLES > 1
|
||||||
|
|
||||||
|
// for debug only : define Z7_CRC_DEBUG_BE to test big-endian code in little-endian cpu
|
||||||
|
// #define Z7_CRC_DEBUG_BE
|
||||||
|
#ifdef Z7_CRC_DEBUG_BE
|
||||||
|
#undef MY_CPU_LE
|
||||||
|
#define MY_CPU_BE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// the value Z7_CRC_NUM_TABLES_USE must be defined to same value as in 7zCrc.c
|
||||||
|
#ifdef Z7_CRC_NUM_TABLES
|
||||||
|
#define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES
|
||||||
|
#else
|
||||||
|
#define Z7_CRC_NUM_TABLES_USE 12
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE % 4 || \
|
||||||
|
Z7_CRC_NUM_TABLES_USE < 4 * 1 || \
|
||||||
|
Z7_CRC_NUM_TABLES_USE > 4 * 6
|
||||||
|
#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef MY_CPU_BE
|
#ifndef MY_CPU_BE
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void* data, size_t size, const UInt32* table)
|
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||||
|
|
||||||
|
#define Q(n, d) \
|
||||||
|
( (table + ((n) * 4 + 3) * 0x100)[(Byte)(d)] \
|
||||||
|
^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \
|
||||||
|
^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \
|
||||||
|
^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )
|
||||||
|
|
||||||
|
#define R(a) *((const UInt32 *)(const void *)p + (a))
|
||||||
|
|
||||||
|
#define CRC_FUNC_PRE_LE2(step) \
|
||||||
|
UInt32 Z7_FASTCALL CrcUpdateT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||||
|
|
||||||
|
#define CRC_FUNC_PRE_LE(step) \
|
||||||
|
CRC_FUNC_PRE_LE2(step); \
|
||||||
|
CRC_FUNC_PRE_LE2(step)
|
||||||
|
|
||||||
|
CRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE)
|
||||||
{
|
{
|
||||||
const Byte* p = (const Byte*)data;
|
const Byte *p = (const Byte *)data;
|
||||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
const Byte *lim;
|
||||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
|
||||||
for (; size >= 4; size -= 4, p += 4) {
|
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||||
v ^= *(const UInt32*)p;
|
lim = p + size;
|
||||||
v = table[0x300 + (v & 0xFF)] ^ table[0x200 + ((v >> 8) & 0xFF)] ^ table[0x100 + ((v >> 16) & 0xFF)] ^ table[0x000 + ((v >> 24))];
|
if (size >= Z7_CRC_NUM_TABLES_USE)
|
||||||
|
{
|
||||||
|
lim -= Z7_CRC_NUM_TABLES_USE;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
v ^= R(0);
|
||||||
|
{
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE == 1 * 4
|
||||||
|
v = Q(0, v);
|
||||||
|
#else
|
||||||
|
#define U2(r, op) \
|
||||||
|
{ d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
|
||||||
|
UInt32 d, x;
|
||||||
|
U2(1, =)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 3 * 4
|
||||||
|
#define U(r) U2(r, ^=)
|
||||||
|
U(2)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 4 * 4
|
||||||
|
U(3)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 5 * 4
|
||||||
|
U(4)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 6 * 4
|
||||||
|
U(5)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 7 * 4
|
||||||
|
#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#undef U
|
||||||
|
#undef U2
|
||||||
|
v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
p += Z7_CRC_NUM_TABLES_USE;
|
||||||
}
|
}
|
||||||
for (; size > 0; size--, p++)
|
while (p <= lim);
|
||||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
lim += Z7_CRC_NUM_TABLES_USE;
|
||||||
return v;
|
}
|
||||||
|
for (; p < lim; 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)
|
#undef CRC_UPDATE_BYTE_2
|
||||||
{
|
#undef R
|
||||||
return CrcUpdateT4(v, data, size, table);
|
#undef Q
|
||||||
}
|
#undef CRC_FUNC_PRE_LE
|
||||||
|
#undef CRC_FUNC_PRE_LE2
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef MY_CPU_LE
|
#ifndef MY_CPU_LE
|
||||||
|
|
||||||
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 24) ^ (b)] ^ ((crc) << 8))
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void* data, size_t size, const UInt32* table)
|
#define Q(n, d) \
|
||||||
|
( (table + ((n) * 4 + 0) * 0x100)[((d)) & 0xFF] \
|
||||||
|
^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \
|
||||||
|
^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \
|
||||||
|
^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] )
|
||||||
|
|
||||||
|
#ifdef Z7_CRC_DEBUG_BE
|
||||||
|
#define R(a) GetBe32a((const UInt32 *)(const void *)p + (a))
|
||||||
|
#else
|
||||||
|
#define R(a) *((const UInt32 *)(const void *)p + (a))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define CRC_FUNC_PRE_BE2(step) \
|
||||||
|
UInt32 Z7_FASTCALL CrcUpdateT1_BeT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||||
|
|
||||||
|
#define CRC_FUNC_PRE_BE(step) \
|
||||||
|
CRC_FUNC_PRE_BE2(step); \
|
||||||
|
CRC_FUNC_PRE_BE2(step)
|
||||||
|
|
||||||
|
CRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE)
|
||||||
{
|
{
|
||||||
const Byte* p = (const Byte*)data;
|
const Byte *p = (const Byte *)data;
|
||||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
const Byte *lim;
|
||||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
table += 0x100;
|
||||||
v = CRC_UINT32_SWAP(v);
|
v = Z7_BSWAP32(v);
|
||||||
table += 0x100;
|
for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
|
||||||
for (; size >= 4; size -= 4, p += 4) {
|
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||||
v ^= *(const UInt32*)p;
|
lim = p + size;
|
||||||
v = table[0x000 + (v & 0xFF)] ^ table[0x100 + ((v >> 8) & 0xFF)] ^ table[0x200 + ((v >> 16) & 0xFF)] ^ table[0x300 + ((v >> 24))];
|
if (size >= Z7_CRC_NUM_TABLES_USE)
|
||||||
|
{
|
||||||
|
lim -= Z7_CRC_NUM_TABLES_USE;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
v ^= R(0);
|
||||||
|
{
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE == 1 * 4
|
||||||
|
v = Q(0, v);
|
||||||
|
#else
|
||||||
|
#define U2(r, op) \
|
||||||
|
{ d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
|
||||||
|
UInt32 d, x;
|
||||||
|
U2(1, =)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 3 * 4
|
||||||
|
#define U(r) U2(r, ^=)
|
||||||
|
U(2)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 4 * 4
|
||||||
|
U(3)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 5 * 4
|
||||||
|
U(4)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 6 * 4
|
||||||
|
U(5)
|
||||||
|
#if Z7_CRC_NUM_TABLES_USE >= 7 * 4
|
||||||
|
#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#undef U
|
||||||
|
#undef U2
|
||||||
|
v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
p += Z7_CRC_NUM_TABLES_USE;
|
||||||
}
|
}
|
||||||
table -= 0x100;
|
while (p <= lim);
|
||||||
v = CRC_UINT32_SWAP(v);
|
lim += Z7_CRC_NUM_TABLES_USE;
|
||||||
for (; size > 0; size--, p++)
|
}
|
||||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
for (; p < lim; p++)
|
||||||
return v;
|
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||||
|
return Z7_BSWAP32(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef CRC_UPDATE_BYTE_2_BE
|
||||||
|
#undef R
|
||||||
|
#undef Q
|
||||||
|
#undef CRC_FUNC_PRE_BE
|
||||||
|
#undef CRC_FUNC_PRE_BE2
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#undef Z7_CRC_NUM_TABLES_USE
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,163 +1,199 @@
|
||||||
/* 7zStream.c -- 7z Stream functions
|
/* 7zStream.c -- 7z Stream functions
|
||||||
2010-03-11 : Igor Pavlov : Public domain */
|
2023-04-02 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "Types.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
SRes SeqInStream_Read2(ISeqInStream* stream, void* buf, size_t size, SRes errorType)
|
|
||||||
|
SRes SeqInStream_ReadMax(ISeqInStreamPtr stream, void *buf, size_t *processedSize)
|
||||||
{
|
{
|
||||||
while (size != 0) {
|
size_t size = *processedSize;
|
||||||
size_t processed = size;
|
*processedSize = 0;
|
||||||
RINOK(stream->Read(stream, buf, &processed));
|
while (size != 0)
|
||||||
if (processed == 0)
|
{
|
||||||
return errorType;
|
size_t cur = size;
|
||||||
buf = (void*)((Byte*)buf + processed);
|
const SRes res = ISeqInStream_Read(stream, buf, &cur);
|
||||||
size -= processed;
|
*processedSize += cur;
|
||||||
}
|
buf = (void *)((Byte *)buf + cur);
|
||||||
|
size -= cur;
|
||||||
|
if (res != SZ_OK)
|
||||||
|
return res;
|
||||||
|
if (cur == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SRes SeqInStream_Read2(ISeqInStreamPtr stream, void *buf, size_t size, SRes errorType)
|
||||||
|
{
|
||||||
|
while (size != 0)
|
||||||
|
{
|
||||||
|
size_t processed = size;
|
||||||
|
RINOK(ISeqInStream_Read(stream, buf, &processed))
|
||||||
|
if (processed == 0)
|
||||||
|
return errorType;
|
||||||
|
buf = (void *)((Byte *)buf + processed);
|
||||||
|
size -= processed;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes SeqInStream_Read(ISeqInStreamPtr stream, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
SRes SeqInStream_ReadByte(ISeqInStreamPtr stream, Byte *buf)
|
||||||
|
{
|
||||||
|
size_t processed = 1;
|
||||||
|
RINOK(ISeqInStream_Read(stream, buf, &processed))
|
||||||
|
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SRes LookInStream_SeekTo(ILookInStreamPtr stream, UInt64 offset)
|
||||||
|
{
|
||||||
|
Int64 t = (Int64)offset;
|
||||||
|
return ILookInStream_Seek(stream, &t, SZ_SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LookInStream_LookRead(ILookInStreamPtr stream, void *buf, size_t *size)
|
||||||
|
{
|
||||||
|
const void *lookBuf;
|
||||||
|
if (*size == 0)
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
|
RINOK(ILookInStream_Look(stream, &lookBuf, size))
|
||||||
|
memcpy(buf, lookBuf, *size);
|
||||||
|
return ILookInStream_Skip(stream, *size);
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes SeqInStream_Read(ISeqInStream* stream, void* buf, size_t size)
|
SRes LookInStream_Read2(ILookInStreamPtr stream, void *buf, size_t size, SRes errorType)
|
||||||
{
|
{
|
||||||
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
while (size != 0)
|
||||||
|
{
|
||||||
|
size_t processed = size;
|
||||||
|
RINOK(ILookInStream_Read(stream, buf, &processed))
|
||||||
|
if (processed == 0)
|
||||||
|
return errorType;
|
||||||
|
buf = (void *)((Byte *)buf + processed);
|
||||||
|
size -= processed;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes SeqInStream_ReadByte(ISeqInStream* stream, Byte* buf)
|
SRes LookInStream_Read(ILookInStreamPtr stream, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
size_t processed = 1;
|
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||||
RINOK(stream->Read(stream, buf, &processed));
|
|
||||||
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes LookInStream_SeekTo(ILookInStream* stream, UInt64 offset)
|
|
||||||
|
|
||||||
|
#define GET_LookToRead2 Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLookToRead2)
|
||||||
|
|
||||||
|
static SRes LookToRead2_Look_Lookahead(ILookInStreamPtr pp, const void **buf, size_t *size)
|
||||||
{
|
{
|
||||||
Int64 t = offset;
|
SRes res = SZ_OK;
|
||||||
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
GET_LookToRead2
|
||||||
|
size_t size2 = p->size - p->pos;
|
||||||
|
if (size2 == 0 && *size != 0)
|
||||||
|
{
|
||||||
|
p->pos = 0;
|
||||||
|
p->size = 0;
|
||||||
|
size2 = p->bufSize;
|
||||||
|
res = ISeekInStream_Read(p->realStream, p->buf, &size2);
|
||||||
|
p->size = size2;
|
||||||
|
}
|
||||||
|
if (*size > size2)
|
||||||
|
*size = size2;
|
||||||
|
*buf = p->buf + p->pos;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes LookInStream_LookRead(ILookInStream* stream, void* buf, size_t* size)
|
static SRes LookToRead2_Look_Exact(ILookInStreamPtr pp, const void **buf, size_t *size)
|
||||||
{
|
{
|
||||||
const void* lookBuf;
|
SRes res = SZ_OK;
|
||||||
if (*size == 0)
|
GET_LookToRead2
|
||||||
return SZ_OK;
|
size_t size2 = p->size - p->pos;
|
||||||
RINOK(stream->Look(stream, &lookBuf, size));
|
if (size2 == 0 && *size != 0)
|
||||||
memcpy(buf, lookBuf, *size);
|
{
|
||||||
return stream->Skip(stream, *size);
|
p->pos = 0;
|
||||||
|
p->size = 0;
|
||||||
|
if (*size > p->bufSize)
|
||||||
|
*size = p->bufSize;
|
||||||
|
res = ISeekInStream_Read(p->realStream, p->buf, size);
|
||||||
|
size2 = p->size = *size;
|
||||||
|
}
|
||||||
|
if (*size > size2)
|
||||||
|
*size = size2;
|
||||||
|
*buf = p->buf + p->pos;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes LookInStream_Read2(ILookInStream* stream, void* buf, size_t size, SRes errorType)
|
static SRes LookToRead2_Skip(ILookInStreamPtr pp, size_t offset)
|
||||||
{
|
{
|
||||||
while (size != 0) {
|
GET_LookToRead2
|
||||||
size_t processed = size;
|
p->pos += offset;
|
||||||
RINOK(stream->Read(stream, buf, &processed));
|
return SZ_OK;
|
||||||
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)
|
static SRes LookToRead2_Read(ILookInStreamPtr pp, void *buf, size_t *size)
|
||||||
{
|
{
|
||||||
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
GET_LookToRead2
|
||||||
|
size_t rem = p->size - p->pos;
|
||||||
|
if (rem == 0)
|
||||||
|
return ISeekInStream_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_Look_Lookahead(void* pp, const void** buf, size_t* size)
|
static SRes LookToRead2_Seek(ILookInStreamPtr pp, Int64 *pos, ESzSeek origin)
|
||||||
{
|
{
|
||||||
SRes res = SZ_OK;
|
GET_LookToRead2
|
||||||
CLookToRead* p = (CLookToRead*)pp;
|
p->pos = p->size = 0;
|
||||||
size_t size2 = p->size - p->pos;
|
return ISeekInStream_Seek(p->realStream, pos, origin);
|
||||||
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)
|
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead)
|
||||||
{
|
{
|
||||||
SRes res = SZ_OK;
|
p->vt.Look = lookahead ?
|
||||||
CLookToRead* p = (CLookToRead*)pp;
|
LookToRead2_Look_Lookahead :
|
||||||
size_t size2 = p->size - p->pos;
|
LookToRead2_Look_Exact;
|
||||||
if (size2 == 0 && *size > 0) {
|
p->vt.Skip = LookToRead2_Skip;
|
||||||
p->pos = 0;
|
p->vt.Read = LookToRead2_Read;
|
||||||
if (*size > LookToRead_BUF_SIZE)
|
p->vt.Seek = LookToRead2_Seek;
|
||||||
*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)
|
|
||||||
|
|
||||||
|
static SRes SecToLook_Read(ISeqInStreamPtr pp, void *buf, size_t *size)
|
||||||
{
|
{
|
||||||
CLookToRead* p = (CLookToRead*)pp;
|
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToLook)
|
||||||
p->pos += offset;
|
return LookInStream_LookRead(p->realStream, buf, size);
|
||||||
return SZ_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes LookToRead_Read(void* pp, void* buf, size_t* size)
|
void SecToLook_CreateVTable(CSecToLook *p)
|
||||||
{
|
{
|
||||||
CLookToRead* p = (CLookToRead*)pp;
|
p->vt.Read = SecToLook_Read;
|
||||||
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)
|
static SRes SecToRead_Read(ISeqInStreamPtr pp, void *buf, size_t *size)
|
||||||
{
|
{
|
||||||
CLookToRead* p = (CLookToRead*)pp;
|
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToRead)
|
||||||
p->pos = p->size = 0;
|
return ILookInStream_Read(p->realStream, buf, size);
|
||||||
return p->realStream->Seek(p->realStream, pos, origin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LookToRead_CreateVTable(CLookToRead* p, int lookahead)
|
void SecToRead_CreateVTable(CSecToRead *p)
|
||||||
{
|
{
|
||||||
p->s.Look = lookahead ? LookToRead_Look_Lookahead : LookToRead_Look_Exact;
|
p->vt.Read = SecToRead_Read;
|
||||||
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,597 @@
|
||||||
|
/* 7zTypes.h -- Basic types
|
||||||
|
2024-01-24 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef ZIP7_7Z_TYPES_H
|
||||||
|
#define ZIP7_7Z_TYPES_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* #include <windows.h> */
|
||||||
|
#else
|
||||||
|
#include <errno.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 _MSC_VER
|
||||||
|
#if _MSC_VER > 1200
|
||||||
|
#define MY_ALIGN(n) __declspec(align(n))
|
||||||
|
#else
|
||||||
|
#define MY_ALIGN(n)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
// C11/C++11:
|
||||||
|
#include <stdalign.h>
|
||||||
|
#define MY_ALIGN(n) alignas(n)
|
||||||
|
*/
|
||||||
|
#define MY_ALIGN(n) __attribute__ ((aligned(n)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
/* typedef DWORD WRes; */
|
||||||
|
typedef unsigned WRes;
|
||||||
|
#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
|
||||||
|
|
||||||
|
// #define MY_HRES_ERROR_INTERNAL_ERROR MY_SRes_HRESULT_FROM_WRes(ERROR_INTERNAL_ERROR)
|
||||||
|
|
||||||
|
#else // _WIN32
|
||||||
|
|
||||||
|
// #define ENV_HAVE_LSTAT
|
||||||
|
typedef int WRes;
|
||||||
|
|
||||||
|
// (FACILITY_ERRNO = 0x800) is 7zip's FACILITY constant to represent (errno) errors in HRESULT
|
||||||
|
#define MY_FACILITY_ERRNO 0x800
|
||||||
|
#define MY_FACILITY_WIN32 7
|
||||||
|
#define MY_FACILITY_WRes MY_FACILITY_ERRNO
|
||||||
|
|
||||||
|
#define MY_HRESULT_FROM_errno_CONST_ERROR(x) ((HRESULT)( \
|
||||||
|
( (HRESULT)(x) & 0x0000FFFF) \
|
||||||
|
| (MY_FACILITY_WRes << 16) \
|
||||||
|
| (HRESULT)0x80000000 ))
|
||||||
|
|
||||||
|
#define MY_SRes_HRESULT_FROM_WRes(x) \
|
||||||
|
((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : MY_HRESULT_FROM_errno_CONST_ERROR(x))
|
||||||
|
|
||||||
|
// we call macro HRESULT_FROM_WIN32 for system errors (WRes) that are (errno)
|
||||||
|
#define HRESULT_FROM_WIN32(x) MY_SRes_HRESULT_FROM_WRes(x)
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define ERROR_FILE_NOT_FOUND 2L
|
||||||
|
#define ERROR_ACCESS_DENIED 5L
|
||||||
|
#define ERROR_NO_MORE_FILES 18L
|
||||||
|
#define ERROR_LOCK_VIOLATION 33L
|
||||||
|
#define ERROR_FILE_EXISTS 80L
|
||||||
|
#define ERROR_DISK_FULL 112L
|
||||||
|
#define ERROR_NEGATIVE_SEEK 131L
|
||||||
|
#define ERROR_ALREADY_EXISTS 183L
|
||||||
|
#define ERROR_DIRECTORY 267L
|
||||||
|
#define ERROR_TOO_MANY_POSTS 298L
|
||||||
|
|
||||||
|
#define ERROR_INTERNAL_ERROR 1359L
|
||||||
|
#define ERROR_INVALID_REPARSE_DATA 4392L
|
||||||
|
#define ERROR_REPARSE_TAG_INVALID 4393L
|
||||||
|
#define ERROR_REPARSE_TAG_MISMATCH 4394L
|
||||||
|
*/
|
||||||
|
|
||||||
|
// we use errno equivalents for some WIN32 errors:
|
||||||
|
|
||||||
|
#define ERROR_INVALID_PARAMETER EINVAL
|
||||||
|
#define ERROR_INVALID_FUNCTION EINVAL
|
||||||
|
#define ERROR_ALREADY_EXISTS EEXIST
|
||||||
|
#define ERROR_FILE_EXISTS EEXIST
|
||||||
|
#define ERROR_PATH_NOT_FOUND ENOENT
|
||||||
|
#define ERROR_FILE_NOT_FOUND ENOENT
|
||||||
|
#define ERROR_DISK_FULL ENOSPC
|
||||||
|
// #define ERROR_INVALID_HANDLE EBADF
|
||||||
|
|
||||||
|
// we use FACILITY_WIN32 for errors that has no errno equivalent
|
||||||
|
// Too many posts were made to a semaphore.
|
||||||
|
#define ERROR_TOO_MANY_POSTS ((HRESULT)0x8007012AL)
|
||||||
|
#define ERROR_INVALID_REPARSE_DATA ((HRESULT)0x80071128L)
|
||||||
|
#define ERROR_REPARSE_TAG_INVALID ((HRESULT)0x80071129L)
|
||||||
|
|
||||||
|
// if (MY_FACILITY_WRes != FACILITY_WIN32),
|
||||||
|
// we use FACILITY_WIN32 for COM errors:
|
||||||
|
#define E_OUTOFMEMORY ((HRESULT)0x8007000EL)
|
||||||
|
#define E_INVALIDARG ((HRESULT)0x80070057L)
|
||||||
|
#define MY_E_ERROR_NEGATIVE_SEEK ((HRESULT)0x80070083L)
|
||||||
|
|
||||||
|
/*
|
||||||
|
// we can use FACILITY_ERRNO for some COM errors, that have errno equivalents:
|
||||||
|
#define E_OUTOFMEMORY MY_HRESULT_FROM_errno_CONST_ERROR(ENOMEM)
|
||||||
|
#define E_INVALIDARG MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL)
|
||||||
|
#define MY_E_ERROR_NEGATIVE_SEEK MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TEXT(quote) quote
|
||||||
|
|
||||||
|
#define FILE_ATTRIBUTE_READONLY 0x0001
|
||||||
|
#define FILE_ATTRIBUTE_HIDDEN 0x0002
|
||||||
|
#define FILE_ATTRIBUTE_SYSTEM 0x0004
|
||||||
|
#define FILE_ATTRIBUTE_DIRECTORY 0x0010
|
||||||
|
#define FILE_ATTRIBUTE_ARCHIVE 0x0020
|
||||||
|
#define FILE_ATTRIBUTE_DEVICE 0x0040
|
||||||
|
#define FILE_ATTRIBUTE_NORMAL 0x0080
|
||||||
|
#define FILE_ATTRIBUTE_TEMPORARY 0x0100
|
||||||
|
#define FILE_ATTRIBUTE_SPARSE_FILE 0x0200
|
||||||
|
#define FILE_ATTRIBUTE_REPARSE_POINT 0x0400
|
||||||
|
#define FILE_ATTRIBUTE_COMPRESSED 0x0800
|
||||||
|
#define FILE_ATTRIBUTE_OFFLINE 0x1000
|
||||||
|
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x2000
|
||||||
|
#define FILE_ATTRIBUTE_ENCRYPTED 0x4000
|
||||||
|
|
||||||
|
#define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000 /* trick for Unix */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef RINOK
|
||||||
|
#define RINOK(x) { const int _result_ = (x); if (_result_ != 0) return _result_; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RINOK_WRes
|
||||||
|
#define RINOK_WRes(x) { const WRes _result_ = (x); if (_result_ != 0) return _result_; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char Byte;
|
||||||
|
typedef short Int16;
|
||||||
|
typedef unsigned short UInt16;
|
||||||
|
|
||||||
|
#ifdef Z7_DECL_Int32_AS_long
|
||||||
|
typedef long Int32;
|
||||||
|
typedef unsigned long UInt32;
|
||||||
|
#else
|
||||||
|
typedef int Int32;
|
||||||
|
typedef unsigned int UInt32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
|
||||||
|
typedef int INT;
|
||||||
|
typedef Int32 INT32;
|
||||||
|
typedef unsigned int UINT;
|
||||||
|
typedef UInt32 UINT32;
|
||||||
|
typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit for _WIN32 compatibility
|
||||||
|
typedef UINT32 ULONG;
|
||||||
|
|
||||||
|
#undef DWORD
|
||||||
|
typedef UINT32 DWORD;
|
||||||
|
|
||||||
|
#define VOID void
|
||||||
|
|
||||||
|
#define HRESULT LONG
|
||||||
|
|
||||||
|
typedef void *LPVOID;
|
||||||
|
// typedef void VOID;
|
||||||
|
// typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
|
||||||
|
// gcc / clang on Unix : sizeof(long==sizeof(void*) in 32 or 64 bits)
|
||||||
|
typedef long INT_PTR;
|
||||||
|
typedef unsigned long UINT_PTR;
|
||||||
|
typedef long LONG_PTR;
|
||||||
|
typedef unsigned long DWORD_PTR;
|
||||||
|
|
||||||
|
typedef size_t SIZE_T;
|
||||||
|
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
|
||||||
|
#define MY_HRES_ERROR_INTERNAL_ERROR ((HRESULT)0x8007054FL)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Z7_DECL_Int64_AS_long
|
||||||
|
|
||||||
|
typedef long Int64;
|
||||||
|
typedef unsigned long UInt64;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__clang__)
|
||||||
|
typedef __int64 Int64;
|
||||||
|
typedef unsigned __int64 UInt64;
|
||||||
|
#else
|
||||||
|
#if defined(__clang__) || defined(__GNUC__)
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int64_t Int64;
|
||||||
|
typedef uint64_t UInt64;
|
||||||
|
#else
|
||||||
|
typedef long long int Int64;
|
||||||
|
typedef unsigned long long int UInt64;
|
||||||
|
// #define UINT64_CONST(n) n ## ULL
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UINT64_CONST(n) n
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Z7_DECL_SizeT_AS_unsigned_int
|
||||||
|
typedef unsigned int SizeT;
|
||||||
|
#else
|
||||||
|
typedef size_t SizeT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if (defined(_MSC_VER) && _MSC_VER <= 1200)
|
||||||
|
typedef size_t MY_uintptr_t;
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef uintptr_t MY_uintptr_t;
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef int BoolInt;
|
||||||
|
/* typedef BoolInt Bool; */
|
||||||
|
#define True 1
|
||||||
|
#define False 0
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define Z7_STDCALL __stdcall
|
||||||
|
#else
|
||||||
|
#define Z7_STDCALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1300
|
||||||
|
#define Z7_NO_INLINE __declspec(noinline)
|
||||||
|
#else
|
||||||
|
#define Z7_NO_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Z7_FORCE_INLINE __forceinline
|
||||||
|
|
||||||
|
#define Z7_CDECL __cdecl
|
||||||
|
#define Z7_FASTCALL __fastcall
|
||||||
|
|
||||||
|
#else // _MSC_VER
|
||||||
|
|
||||||
|
#if (defined(__GNUC__) && (__GNUC__ >= 4)) \
|
||||||
|
|| (defined(__clang__) && (__clang_major__ >= 4)) \
|
||||||
|
|| defined(__INTEL_COMPILER) \
|
||||||
|
|| defined(__xlC__)
|
||||||
|
#define Z7_NO_INLINE __attribute__((noinline))
|
||||||
|
#define Z7_FORCE_INLINE __attribute__((always_inline)) inline
|
||||||
|
#else
|
||||||
|
#define Z7_NO_INLINE
|
||||||
|
#define Z7_FORCE_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Z7_CDECL
|
||||||
|
|
||||||
|
#if defined(_M_IX86) \
|
||||||
|
|| defined(__i386__)
|
||||||
|
// #define Z7_FASTCALL __attribute__((fastcall))
|
||||||
|
// #define Z7_FASTCALL __attribute__((cdecl))
|
||||||
|
#define Z7_FASTCALL
|
||||||
|
#elif defined(MY_CPU_AMD64)
|
||||||
|
// #define Z7_FASTCALL __attribute__((ms_abi))
|
||||||
|
#define Z7_FASTCALL
|
||||||
|
#else
|
||||||
|
#define Z7_FASTCALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
|
||||||
|
/* The following interfaces use first parameter as pointer to structure */
|
||||||
|
|
||||||
|
// #define Z7_C_IFACE_CONST_QUAL
|
||||||
|
#define Z7_C_IFACE_CONST_QUAL const
|
||||||
|
|
||||||
|
#define Z7_C_IFACE_DECL(a) \
|
||||||
|
struct a ## _; \
|
||||||
|
typedef Z7_C_IFACE_CONST_QUAL struct a ## _ * a ## Ptr; \
|
||||||
|
typedef struct a ## _ a; \
|
||||||
|
struct a ## _
|
||||||
|
|
||||||
|
|
||||||
|
Z7_C_IFACE_DECL (IByteIn)
|
||||||
|
{
|
||||||
|
Byte (*Read)(IByteInPtr p); /* reads one byte, returns 0 in case of EOF or error */
|
||||||
|
};
|
||||||
|
#define IByteIn_Read(p) (p)->Read(p)
|
||||||
|
|
||||||
|
|
||||||
|
Z7_C_IFACE_DECL (IByteOut)
|
||||||
|
{
|
||||||
|
void (*Write)(IByteOutPtr p, Byte b);
|
||||||
|
};
|
||||||
|
#define IByteOut_Write(p, b) (p)->Write(p, b)
|
||||||
|
|
||||||
|
|
||||||
|
Z7_C_IFACE_DECL (ISeqInStream)
|
||||||
|
{
|
||||||
|
SRes (*Read)(ISeqInStreamPtr p, void *buf, size_t *size);
|
||||||
|
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||||
|
(output(*size) < input(*size)) is allowed */
|
||||||
|
};
|
||||||
|
#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||||
|
|
||||||
|
/* try to read as much as avail in stream and limited by (*processedSize) */
|
||||||
|
SRes SeqInStream_ReadMax(ISeqInStreamPtr stream, void *buf, size_t *processedSize);
|
||||||
|
/* it can return SZ_ERROR_INPUT_EOF */
|
||||||
|
// SRes SeqInStream_Read(ISeqInStreamPtr stream, void *buf, size_t size);
|
||||||
|
// SRes SeqInStream_Read2(ISeqInStreamPtr stream, void *buf, size_t size, SRes errorType);
|
||||||
|
SRes SeqInStream_ReadByte(ISeqInStreamPtr stream, Byte *buf);
|
||||||
|
|
||||||
|
|
||||||
|
Z7_C_IFACE_DECL (ISeqOutStream)
|
||||||
|
{
|
||||||
|
size_t (*Write)(ISeqOutStreamPtr p, const void *buf, size_t size);
|
||||||
|
/* Returns: result - the number of actually written bytes.
|
||||||
|
(result < size) means error */
|
||||||
|
};
|
||||||
|
#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SZ_SEEK_SET = 0,
|
||||||
|
SZ_SEEK_CUR = 1,
|
||||||
|
SZ_SEEK_END = 2
|
||||||
|
} ESzSeek;
|
||||||
|
|
||||||
|
|
||||||
|
Z7_C_IFACE_DECL (ISeekInStream)
|
||||||
|
{
|
||||||
|
SRes (*Read)(ISeekInStreamPtr p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||||
|
SRes (*Seek)(ISeekInStreamPtr p, Int64 *pos, ESzSeek origin);
|
||||||
|
};
|
||||||
|
#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||||
|
#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
|
||||||
|
|
||||||
|
|
||||||
|
Z7_C_IFACE_DECL (ILookInStream)
|
||||||
|
{
|
||||||
|
SRes (*Look)(ILookInStreamPtr 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)(ILookInStreamPtr p, size_t offset);
|
||||||
|
/* offset must be <= output(*size) of Look */
|
||||||
|
SRes (*Read)(ILookInStreamPtr p, void *buf, size_t *size);
|
||||||
|
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
||||||
|
SRes (*Seek)(ILookInStreamPtr p, Int64 *pos, ESzSeek origin);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size)
|
||||||
|
#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset)
|
||||||
|
#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||||
|
#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
|
||||||
|
|
||||||
|
|
||||||
|
SRes LookInStream_LookRead(ILookInStreamPtr stream, void *buf, size_t *size);
|
||||||
|
SRes LookInStream_SeekTo(ILookInStreamPtr stream, UInt64 offset);
|
||||||
|
|
||||||
|
/* reads via ILookInStream::Read */
|
||||||
|
SRes LookInStream_Read2(ILookInStreamPtr stream, void *buf, size_t size, SRes errorType);
|
||||||
|
SRes LookInStream_Read(ILookInStreamPtr stream, void *buf, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ILookInStream vt;
|
||||||
|
ISeekInStreamPtr realStream;
|
||||||
|
|
||||||
|
size_t pos;
|
||||||
|
size_t size; /* it's data size */
|
||||||
|
|
||||||
|
/* the following variables must be set outside */
|
||||||
|
Byte *buf;
|
||||||
|
size_t bufSize;
|
||||||
|
} CLookToRead2;
|
||||||
|
|
||||||
|
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);
|
||||||
|
|
||||||
|
#define LookToRead2_INIT(p) { (p)->pos = (p)->size = 0; }
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream vt;
|
||||||
|
ILookInStreamPtr realStream;
|
||||||
|
} CSecToLook;
|
||||||
|
|
||||||
|
void SecToLook_CreateVTable(CSecToLook *p);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream vt;
|
||||||
|
ILookInStreamPtr realStream;
|
||||||
|
} CSecToRead;
|
||||||
|
|
||||||
|
void SecToRead_CreateVTable(CSecToRead *p);
|
||||||
|
|
||||||
|
|
||||||
|
Z7_C_IFACE_DECL (ICompressProgress)
|
||||||
|
{
|
||||||
|
SRes (*Progress)(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize);
|
||||||
|
/* Returns: result. (result != SZ_OK) means break.
|
||||||
|
Value (UInt64)(Int64)-1 for size means unknown value. */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ISzAlloc ISzAlloc;
|
||||||
|
typedef const ISzAlloc * ISzAllocPtr;
|
||||||
|
|
||||||
|
struct ISzAlloc
|
||||||
|
{
|
||||||
|
void *(*Alloc)(ISzAllocPtr p, size_t size);
|
||||||
|
void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)
|
||||||
|
#define ISzAlloc_Free(p, a) (p)->Free(p, a)
|
||||||
|
|
||||||
|
/* deprecated */
|
||||||
|
#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)
|
||||||
|
#define IAlloc_Free(p, a) ISzAlloc_Free(p, a)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MY_offsetof
|
||||||
|
#ifdef offsetof
|
||||||
|
#define MY_offsetof(type, m) offsetof(type, m)
|
||||||
|
/*
|
||||||
|
#define MY_offsetof(type, m) FIELD_OFFSET(type, m)
|
||||||
|
*/
|
||||||
|
#else
|
||||||
|
#define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef Z7_container_of
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define Z7_container_of(ptr, type, m) container_of(ptr, type, m)
|
||||||
|
#define Z7_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)
|
||||||
|
#define Z7_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))
|
||||||
|
#define Z7_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly"
|
||||||
|
GCC 3.4.4 : classes with constructor
|
||||||
|
GCC 4.8.1 : classes with non-public variable members"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define Z7_container_of(ptr, type, m) \
|
||||||
|
((type *)(void *)((char *)(void *) \
|
||||||
|
(1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m)))
|
||||||
|
|
||||||
|
#define Z7_container_of_CONST(ptr, type, m) \
|
||||||
|
((const type *)(const void *)((const char *)(const void *) \
|
||||||
|
(1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define Z7_container_of_NON_CONST_FROM_CONST(ptr, type, m) \
|
||||||
|
((type *)(void *)(const void *)((const char *)(const void *) \
|
||||||
|
(1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m)))
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(void *)(ptr))
|
||||||
|
|
||||||
|
// #define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
|
||||||
|
#define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_container_of(ptr, type, m)
|
||||||
|
// #define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_container_of_NON_CONST_FROM_CONST(ptr, type, m)
|
||||||
|
|
||||||
|
#define Z7_CONTAINER_FROM_VTBL_CONST(ptr, type, m) Z7_container_of_CONST(ptr, type, m)
|
||||||
|
|
||||||
|
#define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
|
||||||
|
/*
|
||||||
|
#define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL(ptr, type, m)
|
||||||
|
*/
|
||||||
|
#if defined (__clang__) || defined(__GNUC__)
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL \
|
||||||
|
_Pragma("GCC diagnostic pop")
|
||||||
|
#else
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(ptr, type, m, p) \
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \
|
||||||
|
type *p = Z7_CONTAINER_FROM_VTBL(ptr, type, m); \
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL
|
||||||
|
|
||||||
|
#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(type) \
|
||||||
|
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(pp, type, vt, p)
|
||||||
|
|
||||||
|
|
||||||
|
// #define ZIP7_DECLARE_HANDLE(name) typedef void *name;
|
||||||
|
#define Z7_DECLARE_HANDLE(name) struct name##_dummy{int unused;}; typedef struct name##_dummy *name;
|
||||||
|
|
||||||
|
|
||||||
|
#define Z7_memset_0_ARRAY(a) memset((a), 0, sizeof(a))
|
||||||
|
|
||||||
|
#ifndef Z7_ARRAY_SIZE
|
||||||
|
#define Z7_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#define k_PropVar_TimePrec_0 0
|
||||||
|
#define k_PropVar_TimePrec_Unix 1
|
||||||
|
#define k_PropVar_TimePrec_DOS 2
|
||||||
|
#define k_PropVar_TimePrec_HighPrec 3
|
||||||
|
#define k_PropVar_TimePrec_Base 16
|
||||||
|
#define k_PropVar_TimePrec_100ns (k_PropVar_TimePrec_Base + 7)
|
||||||
|
#define k_PropVar_TimePrec_1ns (k_PropVar_TimePrec_Base + 9)
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
#ifndef Z7_ST
|
||||||
|
#ifdef _7ZIP_ST
|
||||||
|
#define Z7_ST
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
*/
|
|
@ -1,153 +1,290 @@
|
||||||
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2023-03-01 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include "Bcj2.h"
|
#include "Bcj2.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
#define kTopValue ((UInt32)1 << 24)
|
||||||
#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 kNumBitModelTotalBits 11
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||||
#define kNumMoveBits 5
|
#define kNumMoveBits 5
|
||||||
|
|
||||||
#define RC_READ_BYTE (*buffer++)
|
// UInt32 bcj2_stats[256 + 2][2];
|
||||||
#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 \
|
void Bcj2Dec_Init(CBcj2Dec *p)
|
||||||
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];
|
unsigned i;
|
||||||
SizeT inPos = 0, outPos = 0;
|
p->state = BCJ2_STREAM_RC; // BCJ2_DEC_STATE_OK;
|
||||||
|
p->ip = 0;
|
||||||
const Byte *buffer, *bufferLim;
|
p->temp = 0;
|
||||||
UInt32 range, code;
|
p->range = 0;
|
||||||
Byte prevByte = 0;
|
p->code = 0;
|
||||||
|
for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
|
||||||
unsigned int _i;
|
p->probs[i] = kBitModelTotal >> 1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
||||||
|
{
|
||||||
|
UInt32 v = p->temp;
|
||||||
|
// const Byte *src;
|
||||||
|
if (p->range <= 5)
|
||||||
|
{
|
||||||
|
UInt32 code = p->code;
|
||||||
|
p->state = BCJ2_DEC_STATE_ERROR; /* for case if we return SZ_ERROR_DATA; */
|
||||||
|
for (; p->range != 5; p->range++)
|
||||||
|
{
|
||||||
|
if (p->range == 1 && code != 0)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||||
|
{
|
||||||
|
p->state = BCJ2_STREAM_RC;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
code = (code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||||
|
p->code = code;
|
||||||
|
}
|
||||||
|
if (code == 0xffffffff)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
p->range = 0xffffffff;
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
{
|
||||||
|
unsigned state = p->state;
|
||||||
|
// we check BCJ2_IS_32BIT_STREAM() here instead of check in the main loop
|
||||||
|
if (BCJ2_IS_32BIT_STREAM(state))
|
||||||
|
{
|
||||||
|
const Byte *cur = p->bufs[state];
|
||||||
|
if (cur == p->lims[state])
|
||||||
|
return SZ_OK;
|
||||||
|
p->bufs[state] = cur + 4;
|
||||||
|
{
|
||||||
|
const UInt32 ip = p->ip + 4;
|
||||||
|
v = GetBe32a(cur) - ip;
|
||||||
|
p->ip = ip;
|
||||||
|
}
|
||||||
|
state = BCJ2_DEC_STATE_ORIG_0;
|
||||||
|
}
|
||||||
|
if ((unsigned)(state - BCJ2_DEC_STATE_ORIG_0) < 4)
|
||||||
|
{
|
||||||
|
Byte *dest = p->dest;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (dest == p->destLim)
|
||||||
|
{
|
||||||
|
p->state = state;
|
||||||
|
p->temp = v;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
*dest++ = (Byte)v;
|
||||||
|
p->dest = dest;
|
||||||
|
if (++state == BCJ2_DEC_STATE_ORIG_3 + 1)
|
||||||
|
break;
|
||||||
|
v >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// src = p->bufs[BCJ2_STREAM_MAIN];
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if (BCJ2_IS_32BIT_STREAM(p->state))
|
||||||
|
p->state = BCJ2_DEC_STATE_OK;
|
||||||
|
else
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if (p->range < kTopValue)
|
||||||
|
{
|
||||||
|
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||||
|
{
|
||||||
|
p->state = BCJ2_STREAM_RC;
|
||||||
|
p->temp = v;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
p->range <<= 8;
|
||||||
|
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
|
||||||
|
const Byte *srcLim;
|
||||||
|
Byte *dest = p->dest;
|
||||||
|
{
|
||||||
|
const SizeT rem = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src);
|
||||||
|
SizeT num = (SizeT)(p->destLim - dest);
|
||||||
|
if (num >= rem)
|
||||||
|
num = rem;
|
||||||
|
#define NUM_ITERS 4
|
||||||
|
#if (NUM_ITERS & (NUM_ITERS - 1)) == 0
|
||||||
|
num &= ~((SizeT)NUM_ITERS - 1); // if (NUM_ITERS == (1 << x))
|
||||||
|
#else
|
||||||
|
num -= num % NUM_ITERS; // if (NUM_ITERS != (1 << x))
|
||||||
|
#endif
|
||||||
|
srcLim = src + num;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NUM_SHIFT_BITS 24
|
||||||
|
#define ONE_ITER(indx) { \
|
||||||
|
const unsigned b = src[indx]; \
|
||||||
|
*dest++ = (Byte)b; \
|
||||||
|
v = (v << NUM_SHIFT_BITS) | b; \
|
||||||
|
if (((b + (0x100 - 0xe8)) & 0xfe) == 0) break; \
|
||||||
|
if (((v - (((UInt32)0x0f << (NUM_SHIFT_BITS)) + 0x80)) & \
|
||||||
|
((((UInt32)1 << (4 + NUM_SHIFT_BITS)) - 0x1) << 4)) == 0) break; \
|
||||||
|
/* ++dest */; /* v = b; */ }
|
||||||
|
|
||||||
|
if (src != srcLim)
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* The dependency chain of 2-cycle for (v) calculation is not big problem here.
|
||||||
|
But we can remove dependency chain with v = b in the end of loop. */
|
||||||
|
ONE_ITER(0)
|
||||||
|
#if (NUM_ITERS > 1)
|
||||||
|
ONE_ITER(1)
|
||||||
|
#if (NUM_ITERS > 2)
|
||||||
|
ONE_ITER(2)
|
||||||
|
#if (NUM_ITERS > 3)
|
||||||
|
ONE_ITER(3)
|
||||||
|
#if (NUM_ITERS > 4)
|
||||||
|
ONE_ITER(4)
|
||||||
|
#if (NUM_ITERS > 5)
|
||||||
|
ONE_ITER(5)
|
||||||
|
#if (NUM_ITERS > 6)
|
||||||
|
ONE_ITER(6)
|
||||||
|
#if (NUM_ITERS > 7)
|
||||||
|
ONE_ITER(7)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
src += NUM_ITERS;
|
||||||
|
if (src == srcLim)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src == srcLim)
|
||||||
|
#if (NUM_ITERS > 1)
|
||||||
|
for (;;)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if (NUM_ITERS > 1)
|
||||||
|
if (src == p->lims[BCJ2_STREAM_MAIN] || dest == p->destLim)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
const SizeT num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]);
|
||||||
|
p->bufs[BCJ2_STREAM_MAIN] = src;
|
||||||
|
p->dest = dest;
|
||||||
|
p->ip += (UInt32)num;
|
||||||
|
/* state BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */
|
||||||
|
p->state =
|
||||||
|
src == p->lims[BCJ2_STREAM_MAIN] ?
|
||||||
|
(unsigned)BCJ2_STREAM_MAIN :
|
||||||
|
(unsigned)BCJ2_DEC_STATE_ORIG;
|
||||||
|
p->temp = v;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
#if (NUM_ITERS > 1)
|
||||||
|
ONE_ITER(0)
|
||||||
|
src++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const SizeT num = (SizeT)(dest - p->dest);
|
||||||
|
p->dest = dest; // p->dest += num;
|
||||||
|
p->bufs[BCJ2_STREAM_MAIN] += num; // = src;
|
||||||
|
p->ip += (UInt32)num;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
UInt32 bound, ttt;
|
||||||
|
CBcj2Prob *prob; // unsigned index;
|
||||||
|
/*
|
||||||
|
prob = p->probs + (unsigned)((Byte)v == 0xe8 ?
|
||||||
|
2 + (Byte)(v >> 8) :
|
||||||
|
((v >> 5) & 1)); // ((Byte)v < 0xe8 ? 0 : 1));
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
const unsigned c = ((v + 0x17) >> 6) & 1;
|
||||||
|
prob = p->probs + (unsigned)
|
||||||
|
(((0 - c) & (Byte)(v >> NUM_SHIFT_BITS)) + c + ((v >> 5) & 1));
|
||||||
|
// (Byte)
|
||||||
|
// 8x->0 : e9->1 : xxe8->xx+2
|
||||||
|
// 8x->0x100 : e9->0x101 : xxe8->xx
|
||||||
|
// (((0x100 - (e & ~v)) & (0x100 | (v >> 8))) + (e & v));
|
||||||
|
// (((0x101 + (~e | v)) & (0x100 | (v >> 8))) + (e & v));
|
||||||
|
}
|
||||||
|
ttt = *prob;
|
||||||
|
bound = (p->range >> kNumBitModelTotalBits) * ttt;
|
||||||
|
if (p->code < bound)
|
||||||
|
{
|
||||||
|
// bcj2_stats[prob - p->probs][0]++;
|
||||||
|
p->range = bound;
|
||||||
|
*prob = (CBcj2Prob)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// bcj2_stats[prob - p->probs][1]++;
|
||||||
|
p->range -= bound;
|
||||||
|
p->code -= bound;
|
||||||
|
*prob = (CBcj2Prob)(ttt - (ttt >> kNumMoveBits));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* (v == 0xe8 ? 0 : 1) uses setcc instruction with additional zero register usage in x64 MSVC. */
|
||||||
|
// const unsigned cj = ((Byte)v == 0xe8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
|
||||||
|
const unsigned cj = (((v + 0x57) >> 6) & 1) + BCJ2_STREAM_CALL;
|
||||||
|
const Byte *cur = p->bufs[cj];
|
||||||
|
Byte *dest;
|
||||||
|
SizeT rem;
|
||||||
|
if (cur == p->lims[cj])
|
||||||
|
{
|
||||||
|
p->state = cj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v = GetBe32a(cur);
|
||||||
|
p->bufs[cj] = cur + 4;
|
||||||
|
{
|
||||||
|
const UInt32 ip = p->ip + 4;
|
||||||
|
v -= ip;
|
||||||
|
p->ip = ip;
|
||||||
|
}
|
||||||
|
dest = p->dest;
|
||||||
|
rem = (SizeT)(p->destLim - dest);
|
||||||
|
if (rem < 4)
|
||||||
|
{
|
||||||
|
if ((unsigned)rem > 0) { dest[0] = (Byte)v; v >>= 8;
|
||||||
|
if ((unsigned)rem > 1) { dest[1] = (Byte)v; v >>= 8;
|
||||||
|
if ((unsigned)rem > 2) { dest[2] = (Byte)v; v >>= 8; }}}
|
||||||
|
p->temp = v;
|
||||||
|
p->dest = dest + rem;
|
||||||
|
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SetUi32(dest, v)
|
||||||
|
v >>= 24;
|
||||||
|
p->dest = dest + 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
|
||||||
|
{
|
||||||
|
p->range <<= 8;
|
||||||
|
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef NUM_ITERS
|
||||||
|
#undef ONE_ITER
|
||||||
|
#undef NUM_SHIFT_BITS
|
||||||
|
#undef kTopValue
|
||||||
|
#undef kNumBitModelTotalBits
|
||||||
|
#undef kBitModelTotal
|
||||||
|
#undef kNumMoveBits
|
||||||
|
|
|
@ -1,38 +1,332 @@
|
||||||
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
/* Bcj2.h -- BCJ2 converter for x86 code (Branch CALL/JUMP variant2)
|
||||||
2009-02-07 : Igor Pavlov : Public domain */
|
2023-03-02 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __BCJ2_H
|
#ifndef ZIP7_INC_BCJ2_H
|
||||||
#define __BCJ2_H
|
#define ZIP7_INC_BCJ2_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
EXTERN_C_BEGIN
|
||||||
extern "C" {
|
|
||||||
#endif
|
#define BCJ2_NUM_STREAMS 4
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
BCJ2_STREAM_MAIN,
|
||||||
|
BCJ2_STREAM_CALL,
|
||||||
|
BCJ2_STREAM_JUMP,
|
||||||
|
BCJ2_STREAM_RC
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,
|
||||||
|
BCJ2_DEC_STATE_ORIG_1,
|
||||||
|
BCJ2_DEC_STATE_ORIG_2,
|
||||||
|
BCJ2_DEC_STATE_ORIG_3,
|
||||||
|
|
||||||
|
BCJ2_DEC_STATE_ORIG,
|
||||||
|
BCJ2_DEC_STATE_ERROR /* after detected data error */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,
|
||||||
|
BCJ2_ENC_STATE_FINISHED /* it's state after fully encoded stream */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* #define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) */
|
||||||
|
#define BCJ2_IS_32BIT_STREAM(s) ((unsigned)((unsigned)(s) - (unsigned)BCJ2_STREAM_CALL) < 2)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Conditions:
|
CBcj2Dec / CBcj2Enc
|
||||||
outSize <= FullOutputSize,
|
bufs sizes:
|
||||||
where FullOutputSize is full size of output stream of x86_2 filter.
|
BUF_SIZE(n) = lims[n] - bufs[n]
|
||||||
|
bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be multiply of 4:
|
||||||
If buf0 overlaps outBuf, there are two required conditions:
|
(BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
|
||||||
1) (buf0 >= outBuf)
|
(BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
|
||||||
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
SZ_OK
|
|
||||||
SZ_ERROR_DATA - Data error
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int Bcj2_Decode(
|
// typedef UInt32 CBcj2Prob;
|
||||||
const Byte* buf0, SizeT size0,
|
typedef UInt16 CBcj2Prob;
|
||||||
const Byte* buf1, SizeT size1,
|
|
||||||
const Byte* buf2, SizeT size2,
|
|
||||||
const Byte* buf3, SizeT size3,
|
|
||||||
Byte* outBuf, SizeT outSize);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
/*
|
||||||
}
|
BCJ2 encoder / decoder internal requirements:
|
||||||
#endif
|
- If last bytes of stream contain marker (e8/e8/0f8x), then
|
||||||
|
there is also encoded symbol (0 : no conversion) in RC stream.
|
||||||
|
- One case of overlapped instructions is supported,
|
||||||
|
if last byte of converted instruction is (0f) and next byte is (8x):
|
||||||
|
marker [xx xx xx 0f] 8x
|
||||||
|
then the pair (0f 8x) is treated as marker.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------- BCJ2 Decoder ---------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
CBcj2Dec:
|
||||||
|
(dest) is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:
|
||||||
|
bufs[BCJ2_STREAM_MAIN] >= dest &&
|
||||||
|
bufs[BCJ2_STREAM_MAIN] - dest >=
|
||||||
|
BUF_SIZE(BCJ2_STREAM_CALL) +
|
||||||
|
BUF_SIZE(BCJ2_STREAM_JUMP)
|
||||||
|
reserve = bufs[BCJ2_STREAM_MAIN] - dest -
|
||||||
|
( BUF_SIZE(BCJ2_STREAM_CALL) +
|
||||||
|
BUF_SIZE(BCJ2_STREAM_JUMP) )
|
||||||
|
and additional conditions:
|
||||||
|
if (it's first call of Bcj2Dec_Decode() after Bcj2Dec_Init())
|
||||||
|
{
|
||||||
|
(reserve != 1) : if (ver < v23.00)
|
||||||
|
}
|
||||||
|
else // if there are more than one calls of Bcj2Dec_Decode() after Bcj2Dec_Init())
|
||||||
|
{
|
||||||
|
(reserve >= 6) : if (ver < v23.00)
|
||||||
|
(reserve >= 4) : if (ver >= v23.00)
|
||||||
|
We need that (reserve) because after first call of Bcj2Dec_Decode(),
|
||||||
|
CBcj2Dec::temp can contain up to 4 bytes for writing to (dest).
|
||||||
|
}
|
||||||
|
(reserve == 0) is allowed, if we decode full stream via single call of Bcj2Dec_Decode().
|
||||||
|
(reserve == 0) also is allowed in case of multi-call, if we use fixed buffers,
|
||||||
|
and (reserve) is calculated from full (final) sizes of all streams before first call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const Byte *bufs[BCJ2_NUM_STREAMS];
|
||||||
|
const Byte *lims[BCJ2_NUM_STREAMS];
|
||||||
|
Byte *dest;
|
||||||
|
const Byte *destLim;
|
||||||
|
|
||||||
|
unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */
|
||||||
|
|
||||||
|
UInt32 ip; /* property of starting base for decoding */
|
||||||
|
UInt32 temp; /* Byte temp[4]; */
|
||||||
|
UInt32 range;
|
||||||
|
UInt32 code;
|
||||||
|
CBcj2Prob probs[2 + 256];
|
||||||
|
} CBcj2Dec;
|
||||||
|
|
||||||
|
|
||||||
|
/* Note:
|
||||||
|
Bcj2Dec_Init() sets (CBcj2Dec::ip = 0)
|
||||||
|
if (ip != 0) property is required, the caller must set CBcj2Dec::ip after Bcj2Dec_Init()
|
||||||
|
*/
|
||||||
|
void Bcj2Dec_Init(CBcj2Dec *p);
|
||||||
|
|
||||||
|
|
||||||
|
/* Bcj2Dec_Decode():
|
||||||
|
returns:
|
||||||
|
SZ_OK
|
||||||
|
SZ_ERROR_DATA : if data in 5 starting bytes of BCJ2_STREAM_RC stream are not correct
|
||||||
|
*/
|
||||||
|
SRes Bcj2Dec_Decode(CBcj2Dec *p);
|
||||||
|
|
||||||
|
/* To check that decoding was finished you can compare
|
||||||
|
sizes of processed streams with sizes known from another sources.
|
||||||
|
You must do at least one mandatory check from the two following options:
|
||||||
|
- the check for size of processed output (ORIG) stream.
|
||||||
|
- the check for size of processed input (MAIN) stream.
|
||||||
|
additional optional checks:
|
||||||
|
- the checks for processed sizes of all input streams (MAIN, CALL, JUMP, RC)
|
||||||
|
- the checks Bcj2Dec_IsMaybeFinished*()
|
||||||
|
also before actual decoding you can check that the
|
||||||
|
following condition is met for stream sizes:
|
||||||
|
( size(ORIG) == size(MAIN) + size(CALL) + size(JUMP) )
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* (state == BCJ2_STREAM_MAIN) means that decoder is ready for
|
||||||
|
additional input data in BCJ2_STREAM_MAIN stream.
|
||||||
|
Note that (state == BCJ2_STREAM_MAIN) is allowed for non-finished decoding.
|
||||||
|
*/
|
||||||
|
#define Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) ((_p_)->state == BCJ2_STREAM_MAIN)
|
||||||
|
|
||||||
|
/* if the stream decoding was finished correctly, then range decoder
|
||||||
|
part of CBcj2Dec also was finished, and then (CBcj2Dec::code == 0).
|
||||||
|
Note that (CBcj2Dec::code == 0) is allowed for non-finished decoding.
|
||||||
|
*/
|
||||||
|
#define Bcj2Dec_IsMaybeFinished_code(_p_) ((_p_)->code == 0)
|
||||||
|
|
||||||
|
/* use Bcj2Dec_IsMaybeFinished() only as additional check
|
||||||
|
after at least one mandatory check from the two following options:
|
||||||
|
- the check for size of processed output (ORIG) stream.
|
||||||
|
- the check for size of processed input (MAIN) stream.
|
||||||
|
*/
|
||||||
|
#define Bcj2Dec_IsMaybeFinished(_p_) ( \
|
||||||
|
Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) && \
|
||||||
|
Bcj2Dec_IsMaybeFinished_code(_p_))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- BCJ2 Encoder ---------- */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BCJ2_ENC_FINISH_MODE_CONTINUE,
|
||||||
|
BCJ2_ENC_FINISH_MODE_END_BLOCK,
|
||||||
|
BCJ2_ENC_FINISH_MODE_END_STREAM
|
||||||
|
} EBcj2Enc_FinishMode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
BCJ2_ENC_FINISH_MODE_CONTINUE:
|
||||||
|
process non finished encoding.
|
||||||
|
It notifies the encoder that additional further calls
|
||||||
|
can provide more input data (src) than provided by current call.
|
||||||
|
In that case the CBcj2Enc encoder still can move (src) pointer
|
||||||
|
up to (srcLim), but CBcj2Enc encoder can store some of the last
|
||||||
|
processed bytes (up to 4 bytes) from src to internal CBcj2Enc::temp[] buffer.
|
||||||
|
at return:
|
||||||
|
(CBcj2Enc::src will point to position that includes
|
||||||
|
processed data and data copied to (temp[]) buffer)
|
||||||
|
That data from (temp[]) buffer will be used in further calls.
|
||||||
|
|
||||||
|
BCJ2_ENC_FINISH_MODE_END_BLOCK:
|
||||||
|
finish encoding of current block (ended at srcLim) without RC flushing.
|
||||||
|
at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_ORIG) &&
|
||||||
|
CBcj2Enc::src == CBcj2Enc::srcLim)
|
||||||
|
: it shows that block encoding was finished. And the encoder is
|
||||||
|
ready for new (src) data or for stream finish operation.
|
||||||
|
finished block means
|
||||||
|
{
|
||||||
|
CBcj2Enc has completed block encoding up to (srcLim).
|
||||||
|
(1 + 4 bytes) or (2 + 4 bytes) CALL/JUMP cortages will
|
||||||
|
not cross block boundary at (srcLim).
|
||||||
|
temporary CBcj2Enc buffer for (ORIG) src data is empty.
|
||||||
|
3 output uncompressed streams (MAIN, CALL, JUMP) were flushed.
|
||||||
|
RC stream was not flushed. And RC stream will cross block boundary.
|
||||||
|
}
|
||||||
|
Note: some possible implementation of BCJ2 encoder could
|
||||||
|
write branch marker (e8/e8/0f8x) in one call of Bcj2Enc_Encode(),
|
||||||
|
and it could calculate symbol for RC in another call of Bcj2Enc_Encode().
|
||||||
|
BCJ2 encoder uses ip/fileIp/fileSize/relatLimit values to calculate RC symbol.
|
||||||
|
And these CBcj2Enc variables can have different values in different Bcj2Enc_Encode() calls.
|
||||||
|
So caller must finish each block with BCJ2_ENC_FINISH_MODE_END_BLOCK
|
||||||
|
to ensure that RC symbol is calculated and written in proper block.
|
||||||
|
|
||||||
|
BCJ2_ENC_FINISH_MODE_END_STREAM
|
||||||
|
finish encoding of stream (ended at srcLim) fully including RC flushing.
|
||||||
|
at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_FINISHED)
|
||||||
|
: it shows that stream encoding was finished fully,
|
||||||
|
and all output streams were flushed fully.
|
||||||
|
also Bcj2Enc_IsFinished() can be called.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
32-bit relative offset in JUMP/CALL commands is
|
||||||
|
- (mod 4 GiB) for 32-bit x86 code
|
||||||
|
- signed Int32 for 64-bit x86-64 code
|
||||||
|
BCJ2 encoder also does internal relative to absolute address conversions.
|
||||||
|
And there are 2 possible ways to do it:
|
||||||
|
before v23: we used 32-bit variables and (mod 4 GiB) conversion
|
||||||
|
since v23: we use 64-bit variables and (signed Int32 offset) conversion.
|
||||||
|
The absolute address condition for conversion in v23:
|
||||||
|
((UInt64)((Int64)ip64 - (Int64)fileIp64 + 5 + (Int32)offset) < (UInt64)fileSize64)
|
||||||
|
note that if (fileSize64 > 2 GiB). there is difference between
|
||||||
|
old (mod 4 GiB) way (v22) and new (signed Int32 offset) way (v23).
|
||||||
|
And new (v23) way is more suitable to encode 64-bit x86-64 code for (fileSize64 > 2 GiB) cases.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
// for old (v22) way for conversion:
|
||||||
|
typedef UInt32 CBcj2Enc_ip_unsigned;
|
||||||
|
typedef Int32 CBcj2Enc_ip_signed;
|
||||||
|
#define BCJ2_ENC_FileSize_MAX ((UInt32)1 << 31)
|
||||||
|
*/
|
||||||
|
typedef UInt64 CBcj2Enc_ip_unsigned;
|
||||||
|
typedef Int64 CBcj2Enc_ip_signed;
|
||||||
|
|
||||||
|
/* maximum size of file that can be used for conversion condition */
|
||||||
|
#define BCJ2_ENC_FileSize_MAX ((CBcj2Enc_ip_unsigned)0 - 2)
|
||||||
|
|
||||||
|
/* default value of fileSize64_minus1 variable that means
|
||||||
|
that absolute address limitation will not be used */
|
||||||
|
#define BCJ2_ENC_FileSizeField_UNLIMITED ((CBcj2Enc_ip_unsigned)0 - 1)
|
||||||
|
|
||||||
|
/* calculate value that later can be set to CBcj2Enc::fileSize64_minus1 */
|
||||||
|
#define BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize) \
|
||||||
|
((CBcj2Enc_ip_unsigned)(fileSize) - 1)
|
||||||
|
|
||||||
|
/* set CBcj2Enc::fileSize64_minus1 variable from size of file */
|
||||||
|
#define Bcj2Enc_SET_FileSize(p, fileSize) \
|
||||||
|
(p)->fileSize64_minus1 = BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Byte *bufs[BCJ2_NUM_STREAMS];
|
||||||
|
const Byte *lims[BCJ2_NUM_STREAMS];
|
||||||
|
const Byte *src;
|
||||||
|
const Byte *srcLim;
|
||||||
|
|
||||||
|
unsigned state;
|
||||||
|
EBcj2Enc_FinishMode finishMode;
|
||||||
|
|
||||||
|
Byte context;
|
||||||
|
Byte flushRem;
|
||||||
|
Byte isFlushState;
|
||||||
|
|
||||||
|
Byte cache;
|
||||||
|
UInt32 range;
|
||||||
|
UInt64 low;
|
||||||
|
UInt64 cacheSize;
|
||||||
|
|
||||||
|
// UInt32 context; // for marker version, it can include marker flag.
|
||||||
|
|
||||||
|
/* (ip64) and (fileIp64) correspond to virtual source stream position
|
||||||
|
that doesn't include data in temp[] */
|
||||||
|
CBcj2Enc_ip_unsigned ip64; /* current (ip) position */
|
||||||
|
CBcj2Enc_ip_unsigned fileIp64; /* start (ip) position of current file */
|
||||||
|
CBcj2Enc_ip_unsigned fileSize64_minus1; /* size of current file (for conversion limitation) */
|
||||||
|
UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)) : 0 means disable_conversion */
|
||||||
|
// UInt32 relatExcludeBits;
|
||||||
|
|
||||||
|
UInt32 tempTarget;
|
||||||
|
unsigned tempPos; /* the number of bytes that were copied to temp[] buffer
|
||||||
|
(tempPos <= 4) outside of Bcj2Enc_Encode() */
|
||||||
|
// Byte temp[4]; // for marker version
|
||||||
|
Byte temp[8];
|
||||||
|
CBcj2Prob probs[2 + 256];
|
||||||
|
} CBcj2Enc;
|
||||||
|
|
||||||
|
void Bcj2Enc_Init(CBcj2Enc *p);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Bcj2Enc_Encode(): at exit:
|
||||||
|
p->State < BCJ2_NUM_STREAMS : we need more buffer space for output stream
|
||||||
|
(bufs[p->State] == lims[p->State])
|
||||||
|
p->State == BCJ2_ENC_STATE_ORIG : we need more data in input src stream
|
||||||
|
(src == srcLim)
|
||||||
|
p->State == BCJ2_ENC_STATE_FINISHED : after fully encoded stream
|
||||||
|
*/
|
||||||
|
void Bcj2Enc_Encode(CBcj2Enc *p);
|
||||||
|
|
||||||
|
/* Bcj2Enc encoder can look ahead for up 4 bytes of source stream.
|
||||||
|
CBcj2Enc::tempPos : is the number of bytes that were copied from input stream to temp[] buffer.
|
||||||
|
(CBcj2Enc::src) after Bcj2Enc_Encode() is starting position after
|
||||||
|
fully processed data and after data copied to temp buffer.
|
||||||
|
So if the caller needs to get real number of fully processed input
|
||||||
|
bytes (without look ahead data in temp buffer),
|
||||||
|
the caller must subtruct (CBcj2Enc::tempPos) value from processed size
|
||||||
|
value that is calculated based on current (CBcj2Enc::src):
|
||||||
|
cur_processed_pos = Calc_Big_Processed_Pos(enc.src)) -
|
||||||
|
Bcj2Enc_Get_AvailInputSize_in_Temp(&enc);
|
||||||
|
*/
|
||||||
|
/* get the size of input data that was stored in temp[] buffer: */
|
||||||
|
#define Bcj2Enc_Get_AvailInputSize_in_Temp(p) ((p)->tempPos)
|
||||||
|
|
||||||
|
#define Bcj2Enc_IsFinished(p) ((p)->flushRem == 0)
|
||||||
|
|
||||||
|
/* Note : the decoder supports overlapping of marker (0f 80).
|
||||||
|
But we can eliminate such overlapping cases by setting
|
||||||
|
the limit for relative offset conversion as
|
||||||
|
CBcj2Enc::relatLimit <= (0x0f << 24) == (240 MiB)
|
||||||
|
*/
|
||||||
|
/* default value for CBcj2Enc::relatLimit */
|
||||||
|
#define BCJ2_ENC_RELAT_LIMIT_DEFAULT ((UInt32)0x0f << 24)
|
||||||
|
#define BCJ2_ENC_RELAT_LIMIT_MAX ((UInt32)1 << 31)
|
||||||
|
// #define BCJ2_RELAT_EXCLUDE_NUM_BITS 5
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,112 +1,709 @@
|
||||||
/* Bra.c -- Converters for RISC code
|
/* Bra.c -- Branch converters for RISC code
|
||||||
2010-04-16 : Igor Pavlov : Public domain */
|
2024-01-20 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include "Bra.h"
|
#include "Bra.h"
|
||||||
|
#include "RotateDefs.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
SizeT ARM_Convert(Byte* data, SizeT size, UInt32 ip, int encoding)
|
#if defined(MY_CPU_SIZEOF_POINTER) \
|
||||||
|
&& ( MY_CPU_SIZEOF_POINTER == 4 \
|
||||||
|
|| MY_CPU_SIZEOF_POINTER == 8)
|
||||||
|
#define BR_CONV_USE_OPT_PC_PTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BR_CONV_USE_OPT_PC_PTR
|
||||||
|
#define BR_PC_INIT pc -= (UInt32)(SizeT)p;
|
||||||
|
#define BR_PC_GET (pc + (UInt32)(SizeT)p)
|
||||||
|
#else
|
||||||
|
#define BR_PC_INIT pc += (UInt32)size;
|
||||||
|
#define BR_PC_GET (pc - (UInt32)(SizeT)(lim - p))
|
||||||
|
// #define BR_PC_INIT
|
||||||
|
// #define BR_PC_GET (pc + (UInt32)(SizeT)(p - data))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c;
|
||||||
|
// #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c;
|
||||||
|
|
||||||
|
#define Z7_BRANCH_CONV(name) z7_ ## name
|
||||||
|
|
||||||
|
#define Z7_BRANCH_FUNC_MAIN(name) \
|
||||||
|
static \
|
||||||
|
Z7_FORCE_INLINE \
|
||||||
|
Z7_ATTRIB_NO_VECTOR \
|
||||||
|
Byte *Z7_BRANCH_CONV(name)(Byte *p, SizeT size, UInt32 pc, int encoding)
|
||||||
|
|
||||||
|
#define Z7_BRANCH_FUNC_IMP(name, m, encoding) \
|
||||||
|
Z7_NO_INLINE \
|
||||||
|
Z7_ATTRIB_NO_VECTOR \
|
||||||
|
Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \
|
||||||
|
{ return Z7_BRANCH_CONV(name)(data, size, pc, encoding); } \
|
||||||
|
|
||||||
|
#ifdef Z7_EXTRACT_ONLY
|
||||||
|
#define Z7_BRANCH_FUNCS_IMP(name) \
|
||||||
|
Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0)
|
||||||
|
#else
|
||||||
|
#define Z7_BRANCH_FUNCS_IMP(name) \
|
||||||
|
Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) \
|
||||||
|
Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC_2, 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define BR_EXTERNAL_FOR
|
||||||
|
#define BR_NEXT_ITERATION continue;
|
||||||
|
#else
|
||||||
|
#define BR_EXTERNAL_FOR for (;;)
|
||||||
|
#define BR_NEXT_ITERATION break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__clang__) && (__clang_major__ >= 8) \
|
||||||
|
|| defined(__GNUC__) && (__GNUC__ >= 1000) \
|
||||||
|
// GCC is not good for __builtin_expect() here
|
||||||
|
/* || defined(_MSC_VER) && (_MSC_VER >= 1920) */
|
||||||
|
// #define Z7_unlikely [[unlikely]]
|
||||||
|
// #define Z7_LIKELY(x) (__builtin_expect((x), 1))
|
||||||
|
#define Z7_UNLIKELY(x) (__builtin_expect((x), 0))
|
||||||
|
// #define Z7_likely [[likely]]
|
||||||
|
#else
|
||||||
|
// #define Z7_LIKELY(x) (x)
|
||||||
|
#define Z7_UNLIKELY(x) (x)
|
||||||
|
// #define Z7_likely
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
Z7_BRANCH_FUNC_MAIN(BranchConv_ARM64)
|
||||||
{
|
{
|
||||||
SizeT i;
|
// Byte *p = data;
|
||||||
if (size < 4)
|
const Byte *lim;
|
||||||
return 0;
|
const UInt32 flag = (UInt32)1 << (24 - 4);
|
||||||
size -= 4;
|
const UInt32 mask = ((UInt32)1 << 24) - (flag << 1);
|
||||||
ip += 8;
|
size &= ~(SizeT)3;
|
||||||
for (i = 0; i <= size; i += 4) {
|
// if (size == 0) return p;
|
||||||
if (data[i + 3] == 0xEB) {
|
lim = p + size;
|
||||||
UInt32 dest;
|
BR_PC_INIT
|
||||||
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);
|
pc -= 4; // because (p) will point to next instruction
|
||||||
src <<= 2;
|
|
||||||
if (encoding)
|
BR_EXTERNAL_FOR
|
||||||
dest = ip + (UInt32)i + src;
|
{
|
||||||
else
|
// Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
|
||||||
dest = src - (ip + (UInt32)i);
|
for (;;)
|
||||||
dest >>= 2;
|
{
|
||||||
data[i + 2] = (Byte)(dest >> 16);
|
UInt32 v;
|
||||||
data[i + 1] = (Byte)(dest >> 8);
|
if Z7_UNLIKELY(p == lim)
|
||||||
data[i + 0] = (Byte)dest;
|
return p;
|
||||||
}
|
v = GetUi32a(p);
|
||||||
|
p += 4;
|
||||||
|
if Z7_UNLIKELY(((v - 0x94000000) & 0xfc000000) == 0)
|
||||||
|
{
|
||||||
|
UInt32 c = BR_PC_GET >> 2;
|
||||||
|
BR_CONVERT_VAL(v, c)
|
||||||
|
v &= 0x03ffffff;
|
||||||
|
v |= 0x94000000;
|
||||||
|
SetUi32a(p - 4, v)
|
||||||
|
BR_NEXT_ITERATION
|
||||||
|
}
|
||||||
|
// v = rotlFixed(v, 8); v += (flag << 8) - 0x90; if Z7_UNLIKELY((v & ((mask << 8) + 0x9f)) == 0)
|
||||||
|
v -= 0x90000000; if Z7_UNLIKELY((v & 0x9f000000) == 0)
|
||||||
|
{
|
||||||
|
UInt32 z, c;
|
||||||
|
// v = rotrFixed(v, 8);
|
||||||
|
v += flag; if Z7_UNLIKELY(v & mask) continue;
|
||||||
|
z = (v & 0xffffffe0) | (v >> 26);
|
||||||
|
c = (BR_PC_GET >> (12 - 3)) & ~(UInt32)7;
|
||||||
|
BR_CONVERT_VAL(z, c)
|
||||||
|
v &= 0x1f;
|
||||||
|
v |= 0x90000000;
|
||||||
|
v |= z << 26;
|
||||||
|
v |= 0x00ffffe0 & ((z & (((flag << 1) - 1))) - flag);
|
||||||
|
SetUi32a(p - 4, v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return i;
|
}
|
||||||
|
}
|
||||||
|
Z7_BRANCH_FUNCS_IMP(BranchConv_ARM64)
|
||||||
|
|
||||||
|
|
||||||
|
Z7_BRANCH_FUNC_MAIN(BranchConv_ARM)
|
||||||
|
{
|
||||||
|
// Byte *p = data;
|
||||||
|
const Byte *lim;
|
||||||
|
size &= ~(SizeT)3;
|
||||||
|
lim = p + size;
|
||||||
|
BR_PC_INIT
|
||||||
|
/* in ARM: branch offset is relative to the +2 instructions from current instruction.
|
||||||
|
(p) will point to next instruction */
|
||||||
|
pc += 8 - 4;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break;
|
||||||
|
if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
UInt32 v = GetUi32a(p - 4);
|
||||||
|
UInt32 c = BR_PC_GET >> 2;
|
||||||
|
BR_CONVERT_VAL(v, c)
|
||||||
|
v &= 0x00ffffff;
|
||||||
|
v |= 0xeb000000;
|
||||||
|
SetUi32a(p - 4, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Z7_BRANCH_FUNCS_IMP(BranchConv_ARM)
|
||||||
|
|
||||||
|
|
||||||
|
Z7_BRANCH_FUNC_MAIN(BranchConv_PPC)
|
||||||
|
{
|
||||||
|
// Byte *p = data;
|
||||||
|
const Byte *lim;
|
||||||
|
size &= ~(SizeT)3;
|
||||||
|
lim = p + size;
|
||||||
|
BR_PC_INIT
|
||||||
|
pc -= 4; // because (p) will point to next instruction
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UInt32 v;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if Z7_UNLIKELY(p == lim)
|
||||||
|
return p;
|
||||||
|
// v = GetBe32a(p);
|
||||||
|
v = *(UInt32 *)(void *)p;
|
||||||
|
p += 4;
|
||||||
|
// if ((v & 0xfc000003) == 0x48000001) break;
|
||||||
|
// if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) break;
|
||||||
|
if Z7_UNLIKELY(
|
||||||
|
((v - Z7_CONV_BE_TO_NATIVE_CONST32(0x48000001))
|
||||||
|
& Z7_CONV_BE_TO_NATIVE_CONST32(0xfc000003)) == 0) break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
v = Z7_CONV_NATIVE_TO_BE_32(v);
|
||||||
|
{
|
||||||
|
UInt32 c = BR_PC_GET;
|
||||||
|
BR_CONVERT_VAL(v, c)
|
||||||
|
}
|
||||||
|
v &= 0x03ffffff;
|
||||||
|
v |= 0x48000000;
|
||||||
|
SetBe32a(p - 4, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Z7_BRANCH_FUNCS_IMP(BranchConv_PPC)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Z7_CPU_FAST_ROTATE_SUPPORTED
|
||||||
|
#define BR_SPARC_USE_ROTATE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Z7_BRANCH_FUNC_MAIN(BranchConv_SPARC)
|
||||||
|
{
|
||||||
|
// Byte *p = data;
|
||||||
|
const Byte *lim;
|
||||||
|
const UInt32 flag = (UInt32)1 << 22;
|
||||||
|
size &= ~(SizeT)3;
|
||||||
|
lim = p + size;
|
||||||
|
BR_PC_INIT
|
||||||
|
pc -= 4; // because (p) will point to next instruction
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UInt32 v;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if Z7_UNLIKELY(p == lim)
|
||||||
|
return p;
|
||||||
|
/* // the code without GetBe32a():
|
||||||
|
{ const UInt32 v = GetUi16a(p) & 0xc0ff; p += 4; if (v == 0x40 || v == 0xc07f) break; }
|
||||||
|
*/
|
||||||
|
v = GetBe32a(p);
|
||||||
|
p += 4;
|
||||||
|
#ifdef BR_SPARC_USE_ROTATE
|
||||||
|
v = rotlFixed(v, 2);
|
||||||
|
v += (flag << 2) - 1;
|
||||||
|
if Z7_UNLIKELY((v & (3 - (flag << 3))) == 0)
|
||||||
|
#else
|
||||||
|
v += (UInt32)5 << 29;
|
||||||
|
v ^= (UInt32)7 << 29;
|
||||||
|
v += flag;
|
||||||
|
if Z7_UNLIKELY((v & (0 - (flag << 1))) == 0)
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// UInt32 v = GetBe32a(p - 4);
|
||||||
|
#ifndef BR_SPARC_USE_ROTATE
|
||||||
|
v <<= 2;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
UInt32 c = BR_PC_GET;
|
||||||
|
BR_CONVERT_VAL(v, c)
|
||||||
|
}
|
||||||
|
v &= (flag << 3) - 1;
|
||||||
|
#ifdef BR_SPARC_USE_ROTATE
|
||||||
|
v -= (flag << 2) - 1;
|
||||||
|
v = rotrFixed(v, 2);
|
||||||
|
#else
|
||||||
|
v -= (flag << 2);
|
||||||
|
v >>= 2;
|
||||||
|
v |= (UInt32)1 << 30;
|
||||||
|
#endif
|
||||||
|
SetBe32a(p - 4, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Z7_BRANCH_FUNCS_IMP(BranchConv_SPARC)
|
||||||
|
|
||||||
|
|
||||||
|
Z7_BRANCH_FUNC_MAIN(BranchConv_ARMT)
|
||||||
|
{
|
||||||
|
// Byte *p = data;
|
||||||
|
Byte *lim;
|
||||||
|
size &= ~(SizeT)1;
|
||||||
|
// if (size == 0) return p;
|
||||||
|
if (size <= 2) return p;
|
||||||
|
size -= 2;
|
||||||
|
lim = p + size;
|
||||||
|
BR_PC_INIT
|
||||||
|
/* in ARM: branch offset is relative to the +2 instructions from current instruction.
|
||||||
|
(p) will point to the +2 instructions from current instruction */
|
||||||
|
// pc += 4 - 4;
|
||||||
|
// if (encoding) pc -= 0xf800 << 1; else pc += 0xf800 << 1;
|
||||||
|
// #define ARMT_TAIL_PROC { goto armt_tail; }
|
||||||
|
#define ARMT_TAIL_PROC { return p; }
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* in MSVC 32-bit x86 compilers:
|
||||||
|
UInt32 version : it loads value from memory with movzx
|
||||||
|
Byte version : it loads value to 8-bit register (AL/CL)
|
||||||
|
movzx version is slightly faster in some cpus
|
||||||
|
*/
|
||||||
|
unsigned b1;
|
||||||
|
// Byte / unsigned
|
||||||
|
b1 = p[1];
|
||||||
|
// optimized version to reduce one (p >= lim) check:
|
||||||
|
// unsigned a1 = p[1]; b1 = p[3]; p += 2; if Z7_LIKELY((b1 & (a1 ^ 8)) < 0xf8)
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
unsigned b3; // Byte / UInt32
|
||||||
|
/* (Byte)(b3) normalization can use low byte computations in MSVC.
|
||||||
|
It gives smaller code, and no loss of speed in some compilers/cpus.
|
||||||
|
But new MSVC 32-bit x86 compilers use more slow load
|
||||||
|
from memory to low byte register in that case.
|
||||||
|
So we try to use full 32-bit computations for faster code.
|
||||||
|
*/
|
||||||
|
// if (p >= lim) { ARMT_TAIL_PROC } b3 = b1 + 8; b1 = p[3]; p += 2; if ((b3 & b1) >= 0xf8) break;
|
||||||
|
if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b3 = p[3]; p += 2; if Z7_UNLIKELY((b3 & (b1 ^ 8)) >= 0xf8) break;
|
||||||
|
if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b1 = p[3]; p += 2; if Z7_UNLIKELY((b1 & (b3 ^ 8)) >= 0xf8) break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* we can adjust pc for (0xf800) to rid of (& 0x7FF) operation.
|
||||||
|
But gcc/clang for arm64 can use bfi instruction for full code here */
|
||||||
|
UInt32 v =
|
||||||
|
((UInt32)GetUi16a(p - 2) << 11) |
|
||||||
|
((UInt32)GetUi16a(p) & 0x7FF);
|
||||||
|
/*
|
||||||
|
UInt32 v =
|
||||||
|
((UInt32)p[1 - 2] << 19)
|
||||||
|
+ (((UInt32)p[1] & 0x7) << 8)
|
||||||
|
+ (((UInt32)p[-2] << 11))
|
||||||
|
+ (p[0]);
|
||||||
|
*/
|
||||||
|
p += 2;
|
||||||
|
{
|
||||||
|
UInt32 c = BR_PC_GET >> 1;
|
||||||
|
BR_CONVERT_VAL(v, c)
|
||||||
|
}
|
||||||
|
SetUi16a(p - 4, (UInt16)(((v >> 11) & 0x7ff) | 0xf000))
|
||||||
|
SetUi16a(p - 2, (UInt16)(v | 0xf800))
|
||||||
|
/*
|
||||||
|
p[-4] = (Byte)(v >> 11);
|
||||||
|
p[-3] = (Byte)(0xf0 | ((v >> 19) & 0x7));
|
||||||
|
p[-2] = (Byte)v;
|
||||||
|
p[-1] = (Byte)(0xf8 | (v >> 8));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (p < lim);
|
||||||
|
return p;
|
||||||
|
// armt_tail:
|
||||||
|
// if ((Byte)((lim[1] & 0xf8)) != 0xf0) { lim += 2; } return lim;
|
||||||
|
// return (Byte *)(lim + ((Byte)((lim[1] ^ 0xf0) & 0xf8) == 0 ? 0 : 2));
|
||||||
|
// return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2));
|
||||||
|
// return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2));
|
||||||
|
}
|
||||||
|
Z7_BRANCH_FUNCS_IMP(BranchConv_ARMT)
|
||||||
|
|
||||||
|
|
||||||
|
// #define BR_IA64_NO_INLINE
|
||||||
|
|
||||||
|
Z7_BRANCH_FUNC_MAIN(BranchConv_IA64)
|
||||||
|
{
|
||||||
|
// Byte *p = data;
|
||||||
|
const Byte *lim;
|
||||||
|
size &= ~(SizeT)15;
|
||||||
|
lim = p + size;
|
||||||
|
pc -= 1 << 4;
|
||||||
|
pc >>= 4 - 1;
|
||||||
|
// pc -= 1 << 1;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
unsigned m;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if Z7_UNLIKELY(p == lim)
|
||||||
|
return p;
|
||||||
|
m = (unsigned)((UInt32)0x334b0000 >> (*p & 0x1e));
|
||||||
|
p += 16;
|
||||||
|
pc += 1 << 1;
|
||||||
|
if (m &= 3)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
p += (ptrdiff_t)m * 5 - 20; // negative value is expected here.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const UInt32 t =
|
||||||
|
#if defined(MY_CPU_X86_OR_AMD64)
|
||||||
|
// we use 32-bit load here to reduce code size on x86:
|
||||||
|
GetUi32(p);
|
||||||
|
#else
|
||||||
|
GetUi16(p);
|
||||||
|
#endif
|
||||||
|
UInt32 z = GetUi32(p + 1) >> m;
|
||||||
|
p += 5;
|
||||||
|
if (((t >> m) & (0x70 << 1)) == 0
|
||||||
|
&& ((z - (0x5000000 << 1)) & (0xf000000 << 1)) == 0)
|
||||||
|
{
|
||||||
|
UInt32 v = (UInt32)((0x8fffff << 1) | 1) & z;
|
||||||
|
z ^= v;
|
||||||
|
#ifdef BR_IA64_NO_INLINE
|
||||||
|
v |= (v & ((UInt32)1 << (23 + 1))) >> 3;
|
||||||
|
{
|
||||||
|
UInt32 c = pc;
|
||||||
|
BR_CONVERT_VAL(v, c)
|
||||||
|
}
|
||||||
|
v &= (0x1fffff << 1) | 1;
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
if (encoding)
|
||||||
|
{
|
||||||
|
// pc &= ~(0xc00000 << 1); // we just need to clear at least 2 bits
|
||||||
|
pc &= (0x1fffff << 1) | 1;
|
||||||
|
v += pc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// pc |= 0xc00000 << 1; // we need to set at least 2 bits
|
||||||
|
pc |= ~(UInt32)((0x1fffff << 1) | 1);
|
||||||
|
v -= pc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v &= ~(UInt32)(0x600000 << 1);
|
||||||
|
#endif
|
||||||
|
v += (0x700000 << 1);
|
||||||
|
v &= (0x8fffff << 1) | 1;
|
||||||
|
z |= v;
|
||||||
|
z <<= m;
|
||||||
|
SetUi32(p + 1 - 5, z)
|
||||||
|
}
|
||||||
|
m++;
|
||||||
|
}
|
||||||
|
while (m &= 3); // while (m < 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Z7_BRANCH_FUNCS_IMP(BranchConv_IA64)
|
||||||
|
|
||||||
|
|
||||||
|
#define BR_CONVERT_VAL_ENC(v) v += BR_PC_GET;
|
||||||
|
#define BR_CONVERT_VAL_DEC(v) v -= BR_PC_GET;
|
||||||
|
|
||||||
|
#if 1 && defined(MY_CPU_LE_UNALIGN)
|
||||||
|
#define RISCV_USE_UNALIGNED_LOAD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RISCV_USE_UNALIGNED_LOAD
|
||||||
|
#define RISCV_GET_UI32(p) GetUi32(p)
|
||||||
|
#define RISCV_SET_UI32(p, v) { SetUi32(p, v) }
|
||||||
|
#else
|
||||||
|
#define RISCV_GET_UI32(p) \
|
||||||
|
((UInt32)GetUi16a(p) + \
|
||||||
|
((UInt32)GetUi16a((p) + 2) << 16))
|
||||||
|
#define RISCV_SET_UI32(p, v) { \
|
||||||
|
SetUi16a(p, (UInt16)(v)) \
|
||||||
|
SetUi16a((p) + 2, (UInt16)(v >> 16)) }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1 && defined(MY_CPU_LE)
|
||||||
|
#define RISCV_USE_16BIT_LOAD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RISCV_USE_16BIT_LOAD
|
||||||
|
#define RISCV_LOAD_VAL(p) GetUi16a(p)
|
||||||
|
#else
|
||||||
|
#define RISCV_LOAD_VAL(p) (*(p))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RISCV_INSTR_SIZE 2
|
||||||
|
#define RISCV_STEP_1 (4 + RISCV_INSTR_SIZE)
|
||||||
|
#define RISCV_STEP_2 4
|
||||||
|
#define RISCV_REG_VAL (2 << 7)
|
||||||
|
#define RISCV_CMD_VAL 3
|
||||||
|
#if 1
|
||||||
|
// for code size optimization:
|
||||||
|
#define RISCV_DELTA_7F 0x7f
|
||||||
|
#else
|
||||||
|
#define RISCV_DELTA_7F 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RISCV_CHECK_1(v, b) \
|
||||||
|
(((((b) - RISCV_CMD_VAL) ^ ((v) << 8)) & (0xf8000 + RISCV_CMD_VAL)) == 0)
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#define RISCV_CHECK_2(v, r) \
|
||||||
|
((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL | 8)) \
|
||||||
|
<< 18) \
|
||||||
|
< ((r) & 0x1d))
|
||||||
|
#else
|
||||||
|
// this branch gives larger code, because
|
||||||
|
// compilers generate larger code for big constants.
|
||||||
|
#define RISCV_CHECK_2(v, r) \
|
||||||
|
((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
|
||||||
|
& ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
|
||||||
|
< ((r) & 0x1d))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define RISCV_SCAN_LOOP \
|
||||||
|
Byte *lim; \
|
||||||
|
size &= ~(SizeT)(RISCV_INSTR_SIZE - 1); \
|
||||||
|
if (size <= 6) return p; \
|
||||||
|
size -= 6; \
|
||||||
|
lim = p + size; \
|
||||||
|
BR_PC_INIT \
|
||||||
|
for (;;) \
|
||||||
|
{ \
|
||||||
|
UInt32 a, v; \
|
||||||
|
/* Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE */ \
|
||||||
|
for (;;) \
|
||||||
|
{ \
|
||||||
|
if Z7_UNLIKELY(p >= lim) { return p; } \
|
||||||
|
a = (RISCV_LOAD_VAL(p) ^ 0x10u) + 1; \
|
||||||
|
if ((a & 0x77) == 0) break; \
|
||||||
|
a = (RISCV_LOAD_VAL(p + RISCV_INSTR_SIZE) ^ 0x10u) + 1; \
|
||||||
|
p += RISCV_INSTR_SIZE * 2; \
|
||||||
|
if ((a & 0x77) == 0) \
|
||||||
|
{ \
|
||||||
|
p -= RISCV_INSTR_SIZE; \
|
||||||
|
if Z7_UNLIKELY(p >= lim) { return p; } \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
// (xx6f ^ 10) + 1 = xx7f + 1 = xx80 : JAL
|
||||||
|
// (xxef ^ 10) + 1 = xxff + 1 = xx00 + 100 : JAL
|
||||||
|
// (xx17 ^ 10) + 1 = xx07 + 1 = xx08 : AUIPC
|
||||||
|
// (xx97 ^ 10) + 1 = xx87 + 1 = xx88 : AUIPC
|
||||||
|
|
||||||
|
Byte * Z7_BRANCH_CONV_ENC(RISCV)(Byte *p, SizeT size, UInt32 pc)
|
||||||
|
{
|
||||||
|
RISCV_SCAN_LOOP
|
||||||
|
v = a;
|
||||||
|
a = RISCV_GET_UI32(p);
|
||||||
|
#ifndef RISCV_USE_16BIT_LOAD
|
||||||
|
v += (UInt32)p[1] << 8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((v & 8) == 0) // JAL
|
||||||
|
{
|
||||||
|
if ((v - (0x100 /* - RISCV_DELTA_7F */)) & 0xd80)
|
||||||
|
{
|
||||||
|
p += RISCV_INSTR_SIZE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
v = ((a & 1u << 31) >> 11)
|
||||||
|
| ((a & 0x3ff << 21) >> 20)
|
||||||
|
| ((a & 1 << 20) >> 9)
|
||||||
|
| (a & 0xff << 12);
|
||||||
|
BR_CONVERT_VAL_ENC(v)
|
||||||
|
// ((v & 1) == 0)
|
||||||
|
// v: bits [1 : 20] contain offset bits
|
||||||
|
#if 0 && defined(RISCV_USE_UNALIGNED_LOAD)
|
||||||
|
a &= 0xfff;
|
||||||
|
a |= ((UInt32)(v << 23))
|
||||||
|
| ((UInt32)(v << 7) & ((UInt32)0xff << 16))
|
||||||
|
| ((UInt32)(v >> 5) & ((UInt32)0xf0 << 8));
|
||||||
|
RISCV_SET_UI32(p, a)
|
||||||
|
#else // aligned
|
||||||
|
#if 0
|
||||||
|
SetUi16a(p, (UInt16)(((v >> 5) & 0xf000) | (a & 0xfff)))
|
||||||
|
#else
|
||||||
|
p[1] = (Byte)(((v >> 13) & 0xf0) | ((a >> 8) & 0xf));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
|
||||||
|
v <<= 15;
|
||||||
|
v = Z7_BSWAP32(v);
|
||||||
|
SetUi16a(p + 2, (UInt16)v)
|
||||||
|
#else
|
||||||
|
p[2] = (Byte)(v >> 9);
|
||||||
|
p[3] = (Byte)(v >> 1);
|
||||||
|
#endif
|
||||||
|
#endif // aligned
|
||||||
|
}
|
||||||
|
p += 4;
|
||||||
|
continue;
|
||||||
|
} // JAL
|
||||||
|
|
||||||
|
{
|
||||||
|
// AUIPC
|
||||||
|
if (v & 0xe80) // (not x0) and (not x2)
|
||||||
|
{
|
||||||
|
const UInt32 b = RISCV_GET_UI32(p + 4);
|
||||||
|
if (RISCV_CHECK_1(v, b))
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const UInt32 temp = (b << 12) | (0x17 + RISCV_REG_VAL);
|
||||||
|
RISCV_SET_UI32(p, temp)
|
||||||
|
}
|
||||||
|
a &= 0xfffff000;
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
const int t = -1 >> 1;
|
||||||
|
if (t != -1)
|
||||||
|
a += (b >> 20) - ((b >> 19) & 0x1000); // arithmetic right shift emulation
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
a += (UInt32)((Int32)b >> 20); // arithmetic right shift (sign-extension).
|
||||||
|
}
|
||||||
|
BR_CONVERT_VAL_ENC(a)
|
||||||
|
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
|
||||||
|
a = Z7_BSWAP32(a);
|
||||||
|
RISCV_SET_UI32(p + 4, a)
|
||||||
|
#else
|
||||||
|
SetBe32(p + 4, a)
|
||||||
|
#endif
|
||||||
|
p += 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p += RISCV_STEP_1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UInt32 r = a >> 27;
|
||||||
|
if (RISCV_CHECK_2(v, r))
|
||||||
|
{
|
||||||
|
v = RISCV_GET_UI32(p + 4);
|
||||||
|
r = (r << 7) + 0x17 + (v & 0xfffff000);
|
||||||
|
a = (a >> 12) | (v << 20);
|
||||||
|
RISCV_SET_UI32(p, r)
|
||||||
|
RISCV_SET_UI32(p + 4, a)
|
||||||
|
p += 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p += RISCV_STEP_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // for
|
||||||
}
|
}
|
||||||
|
|
||||||
SizeT ARMT_Convert(Byte* data, SizeT size, UInt32 ip, int encoding)
|
|
||||||
|
Byte * Z7_BRANCH_CONV_DEC(RISCV)(Byte *p, SizeT size, UInt32 pc)
|
||||||
{
|
{
|
||||||
SizeT i;
|
RISCV_SCAN_LOOP
|
||||||
if (size < 4)
|
#ifdef RISCV_USE_16BIT_LOAD
|
||||||
return 0;
|
if ((a & 8) == 0)
|
||||||
size -= 4;
|
{
|
||||||
ip += 4;
|
#else
|
||||||
for (i = 0; i <= size; i += 2) {
|
v = a;
|
||||||
if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) {
|
a += (UInt32)p[1] << 8;
|
||||||
UInt32 dest;
|
if ((v & 8) == 0)
|
||||||
UInt32 src = (((UInt32)data[i + 1] & 0x7) << 19) | ((UInt32)data[i + 0] << 11) | (((UInt32)data[i + 3] & 0x7) << 8) | (data[i + 2]);
|
{
|
||||||
|
#endif
|
||||||
|
// JAL
|
||||||
|
a -= 0x100 - RISCV_DELTA_7F;
|
||||||
|
if (a & 0xd80)
|
||||||
|
{
|
||||||
|
p += RISCV_INSTR_SIZE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const UInt32 a_old = (a + (0xef - RISCV_DELTA_7F)) & 0xfff;
|
||||||
|
#if 0 // unaligned
|
||||||
|
a = GetUi32(p);
|
||||||
|
v = (UInt32)(a >> 23) & ((UInt32)0xff << 1)
|
||||||
|
| (UInt32)(a >> 7) & ((UInt32)0xff << 9)
|
||||||
|
#elif 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
|
||||||
|
v = GetUi16a(p + 2);
|
||||||
|
v = Z7_BSWAP32(v) >> 15
|
||||||
|
#else
|
||||||
|
v = (UInt32)p[3] << 1
|
||||||
|
| (UInt32)p[2] << 9
|
||||||
|
#endif
|
||||||
|
| (UInt32)((a & 0xf000) << 5);
|
||||||
|
BR_CONVERT_VAL_DEC(v)
|
||||||
|
a = a_old
|
||||||
|
| (v << 11 & 1u << 31)
|
||||||
|
| (v << 20 & 0x3ff << 21)
|
||||||
|
| (v << 9 & 1 << 20)
|
||||||
|
| (v & 0xff << 12);
|
||||||
|
RISCV_SET_UI32(p, a)
|
||||||
|
}
|
||||||
|
p += 4;
|
||||||
|
continue;
|
||||||
|
} // JAL
|
||||||
|
|
||||||
src <<= 1;
|
{
|
||||||
if (encoding)
|
// AUIPC
|
||||||
dest = ip + (UInt32)i + src;
|
v = a;
|
||||||
else
|
#if 1 && defined(RISCV_USE_UNALIGNED_LOAD)
|
||||||
dest = src - (ip + (UInt32)i);
|
a = GetUi32(p);
|
||||||
dest >>= 1;
|
#else
|
||||||
|
a |= (UInt32)GetUi16a(p + 2) << 16;
|
||||||
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
|
#endif
|
||||||
data[i + 0] = (Byte)(dest >> 11);
|
if ((v & 0xe80) == 0) // x0/x2
|
||||||
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
|
{
|
||||||
data[i + 2] = (Byte)dest;
|
const UInt32 r = a >> 27;
|
||||||
i += 2;
|
if (RISCV_CHECK_2(v, r))
|
||||||
|
{
|
||||||
|
UInt32 b;
|
||||||
|
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
|
||||||
|
b = RISCV_GET_UI32(p + 4);
|
||||||
|
b = Z7_BSWAP32(b);
|
||||||
|
#else
|
||||||
|
b = GetBe32(p + 4);
|
||||||
|
#endif
|
||||||
|
v = a >> 12;
|
||||||
|
BR_CONVERT_VAL_DEC(b)
|
||||||
|
a = (r << 7) + 0x17;
|
||||||
|
a += (b + 0x800) & 0xfffff000;
|
||||||
|
v |= b << 20;
|
||||||
|
RISCV_SET_UI32(p, a)
|
||||||
|
RISCV_SET_UI32(p + 4, v)
|
||||||
|
p += 8;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
return i;
|
p += RISCV_STEP_2;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
SizeT PPC_Convert(Byte* data, SizeT size, UInt32 ip, int encoding)
|
{
|
||||||
{
|
const UInt32 b = RISCV_GET_UI32(p + 4);
|
||||||
SizeT i;
|
if (!RISCV_CHECK_1(v, b))
|
||||||
if (size < 4)
|
p += RISCV_STEP_1;
|
||||||
return 0;
|
else
|
||||||
size -= 4;
|
{
|
||||||
for (i = 0; i <= size; i += 4) {
|
v = (a & 0xfffff000) | (b >> 20);
|
||||||
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) {
|
a = (b << 12) | (0x17 + RISCV_REG_VAL);
|
||||||
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3] & (~3));
|
RISCV_SET_UI32(p, a)
|
||||||
|
RISCV_SET_UI32(p + 4, v)
|
||||||
UInt32 dest;
|
p += 8;
|
||||||
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;
|
} // for
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,71 +1,105 @@
|
||||||
/* Bra.h -- Branch converters for executables
|
/* Bra.h -- Branch converters for executables
|
||||||
2009-02-07 : Igor Pavlov : Public domain */
|
2024-01-20 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __BRA_H
|
#ifndef ZIP7_INC_BRA_H
|
||||||
#define __BRA_H
|
#define ZIP7_INC_BRA_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
EXTERN_C_BEGIN
|
||||||
extern "C" {
|
|
||||||
#endif
|
/* #define PPC BAD_PPC_11 // for debug */
|
||||||
|
|
||||||
|
#define Z7_BRANCH_CONV_DEC_2(name) z7_ ## name ## _Dec
|
||||||
|
#define Z7_BRANCH_CONV_ENC_2(name) z7_ ## name ## _Enc
|
||||||
|
#define Z7_BRANCH_CONV_DEC(name) Z7_BRANCH_CONV_DEC_2(BranchConv_ ## name)
|
||||||
|
#define Z7_BRANCH_CONV_ENC(name) Z7_BRANCH_CONV_ENC_2(BranchConv_ ## name)
|
||||||
|
#define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec
|
||||||
|
#define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc
|
||||||
|
|
||||||
|
#define Z7_BRANCH_CONV_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc)
|
||||||
|
#define Z7_BRANCH_CONV_ST_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc, UInt32 *state)
|
||||||
|
|
||||||
|
typedef Z7_BRANCH_CONV_DECL( (*z7_Func_BranchConv));
|
||||||
|
typedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt));
|
||||||
|
|
||||||
|
#define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0
|
||||||
|
Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_DEC(X86));
|
||||||
|
Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_ENC(X86));
|
||||||
|
|
||||||
|
#define Z7_BRANCH_FUNCS_DECL(name) \
|
||||||
|
Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_DEC_2(name)); \
|
||||||
|
Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_ENC_2(name));
|
||||||
|
|
||||||
|
Z7_BRANCH_FUNCS_DECL (BranchConv_ARM64)
|
||||||
|
Z7_BRANCH_FUNCS_DECL (BranchConv_ARM)
|
||||||
|
Z7_BRANCH_FUNCS_DECL (BranchConv_ARMT)
|
||||||
|
Z7_BRANCH_FUNCS_DECL (BranchConv_PPC)
|
||||||
|
Z7_BRANCH_FUNCS_DECL (BranchConv_SPARC)
|
||||||
|
Z7_BRANCH_FUNCS_DECL (BranchConv_IA64)
|
||||||
|
Z7_BRANCH_FUNCS_DECL (BranchConv_RISCV)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These functions convert relative addresses to absolute addresses
|
These functions convert data that contain CPU instructions.
|
||||||
in CALL instructions to increase the compression ratio.
|
Each such function converts relative addresses to absolute addresses in some
|
||||||
|
branch instructions: CALL (in all converters) and JUMP (X86 converter only).
|
||||||
|
Such conversion allows to increase compression ratio, if we compress that data.
|
||||||
|
|
||||||
In:
|
There are 2 types of converters:
|
||||||
data - data buffer
|
Byte * Conv_RISC (Byte *data, SizeT size, UInt32 pc);
|
||||||
size - size of data
|
Byte * ConvSt_X86(Byte *data, SizeT size, UInt32 pc, UInt32 *state);
|
||||||
ip - current virtual Instruction Pinter (IP) value
|
Each Converter supports 2 versions: one for encoding
|
||||||
state - state variable for x86 converter
|
and one for decoding (_Enc/_Dec postfixes in function name).
|
||||||
encoding - 0 (for decoding), 1 (for encoding)
|
|
||||||
|
|
||||||
Out:
|
In params:
|
||||||
state - state variable for x86 converter
|
data : data buffer
|
||||||
|
size : size of data
|
||||||
|
pc : current virtual Program Counter (Instruction Pointer) value
|
||||||
|
In/Out param:
|
||||||
|
state : pointer to state variable (for X86 converter only)
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
The number of processed bytes. If you call these functions with multiple calls,
|
The pointer to position in (data) buffer after last byte that was processed.
|
||||||
you must start next call with first byte after block of processed bytes.
|
If the caller calls converter again, it must call it starting with that position.
|
||||||
|
But the caller is allowed to move data in buffer. So pointer to
|
||||||
|
current processed position also will be changed for next call.
|
||||||
|
Also the caller must increase internal (pc) value for next call.
|
||||||
|
|
||||||
|
Each converter has some characteristics: Endian, Alignment, LookAhead.
|
||||||
Type Endian Alignment LookAhead
|
Type Endian Alignment LookAhead
|
||||||
|
|
||||||
x86 little 1 4
|
X86 little 1 4
|
||||||
ARMT little 2 2
|
ARMT little 2 2
|
||||||
|
RISCV little 2 6
|
||||||
ARM little 4 0
|
ARM little 4 0
|
||||||
|
ARM64 little 4 0
|
||||||
PPC big 4 0
|
PPC big 4 0
|
||||||
SPARC big 4 0
|
SPARC big 4 0
|
||||||
IA64 little 16 0
|
IA64 little 16 0
|
||||||
|
|
||||||
size must be >= Alignment + LookAhead, if it's not last block.
|
(data) must be aligned for (Alignment).
|
||||||
If (size < Alignment + LookAhead), converter returns 0.
|
processed size can be calculated as:
|
||||||
|
SizeT processed = Conv(data, size, pc) - data;
|
||||||
|
if (processed == 0)
|
||||||
|
it means that converter needs more data for processing.
|
||||||
|
If (size < Alignment + LookAhead)
|
||||||
|
then (processed == 0) is allowed.
|
||||||
|
|
||||||
Example:
|
Example code for conversion in loop:
|
||||||
|
UInt32 pc = 0;
|
||||||
UInt32 ip = 0;
|
size = 0;
|
||||||
for ()
|
for (;;)
|
||||||
{
|
{
|
||||||
; size must be >= Alignment + LookAhead, if it's not last block
|
size += Load_more_input_data(data + size);
|
||||||
SizeT processed = Convert(data, size, ip, 1);
|
SizeT processed = Conv(data, size, pc) - data;
|
||||||
data += processed;
|
if (processed == 0 && no_more_input_data_after_size)
|
||||||
size -= processed;
|
break; // we stop convert loop
|
||||||
ip += processed;
|
data += processed;
|
||||||
}
|
size -= processed;
|
||||||
|
pc += processed;
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define x86_Convert_Init(state) \
|
EXTERN_C_END
|
||||||
{ \
|
|
||||||
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);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,77 +1,187 @@
|
||||||
/* Bra86.c -- Converter for x86 code (BCJ)
|
/* Bra86.c -- Branch converter for X86 code (BCJ)
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2023-04-02 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include "Bra.h"
|
#include "Bra.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
|
|
||||||
|
|
||||||
const Byte kMaskToAllowedStatus[8] = { 1, 1, 1, 0, 1, 0, 0, 0 };
|
#if defined(MY_CPU_SIZEOF_POINTER) \
|
||||||
const Byte kMaskToBitNumber[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
|
&& ( MY_CPU_SIZEOF_POINTER == 4 \
|
||||||
|
|| MY_CPU_SIZEOF_POINTER == 8)
|
||||||
|
#define BR_CONV_USE_OPT_PC_PTR
|
||||||
|
#endif
|
||||||
|
|
||||||
SizeT x86_Convert(Byte* data, SizeT size, UInt32 ip, UInt32* state, int encoding)
|
#ifdef BR_CONV_USE_OPT_PC_PTR
|
||||||
|
#define BR_PC_INIT pc -= (UInt32)(SizeT)p; // (MY_uintptr_t)
|
||||||
|
#define BR_PC_GET (pc + (UInt32)(SizeT)p)
|
||||||
|
#else
|
||||||
|
#define BR_PC_INIT pc += (UInt32)size;
|
||||||
|
#define BR_PC_GET (pc - (UInt32)(SizeT)(lim - p))
|
||||||
|
// #define BR_PC_INIT
|
||||||
|
// #define BR_PC_GET (pc + (UInt32)(SizeT)(p - data))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c;
|
||||||
|
// #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c;
|
||||||
|
|
||||||
|
#define Z7_BRANCH_CONV_ST(name) z7_BranchConvSt_ ## name
|
||||||
|
|
||||||
|
#define BR86_NEED_CONV_FOR_MS_BYTE(b) ((((b) + 1) & 0xfe) == 0)
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE_UNALIGN
|
||||||
|
#define BR86_PREPARE_BCJ_SCAN const UInt32 v = GetUi32(p) ^ 0xe8e8e8e8;
|
||||||
|
#define BR86_IS_BCJ_BYTE(n) ((v & ((UInt32)0xfe << (n) * 8)) == 0)
|
||||||
|
#else
|
||||||
|
#define BR86_PREPARE_BCJ_SCAN
|
||||||
|
// bad for MSVC X86 (partial write to byte reg):
|
||||||
|
#define BR86_IS_BCJ_BYTE(n) ((p[n - 4] & 0xfe) == 0xe8)
|
||||||
|
// bad for old MSVC (partial write to byte reg):
|
||||||
|
// #define BR86_IS_BCJ_BYTE(n) (((*p ^ 0xe8) & 0xfe) == 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static
|
||||||
|
Z7_FORCE_INLINE
|
||||||
|
Z7_ATTRIB_NO_VECTOR
|
||||||
|
Byte *Z7_BRANCH_CONV_ST(X86)(Byte *p, SizeT size, UInt32 pc, UInt32 *state, int encoding)
|
||||||
{
|
{
|
||||||
SizeT bufferPos = 0, prevPosT;
|
if (size < 5)
|
||||||
UInt32 prevMask = *state & 0x7;
|
return p;
|
||||||
if (size < 5)
|
{
|
||||||
return 0;
|
// Byte *p = data;
|
||||||
ip += 5;
|
const Byte *lim = p + size - 4;
|
||||||
prevPosT = (SizeT)0 - 1;
|
unsigned mask = (unsigned)*state; // & 7;
|
||||||
|
#ifdef BR_CONV_USE_OPT_PC_PTR
|
||||||
|
/* if BR_CONV_USE_OPT_PC_PTR is defined: we need to adjust (pc) for (+4),
|
||||||
|
because call/jump offset is relative to the next instruction.
|
||||||
|
if BR_CONV_USE_OPT_PC_PTR is not defined : we don't need to adjust (pc) for (+4),
|
||||||
|
because BR_PC_GET uses (pc - (lim - p)), and lim was adjusted for (-4) before.
|
||||||
|
*/
|
||||||
|
pc += 4;
|
||||||
|
#endif
|
||||||
|
BR_PC_INIT
|
||||||
|
goto start;
|
||||||
|
|
||||||
for (;;) {
|
for (;; mask |= 4)
|
||||||
Byte* p = data + bufferPos;
|
{
|
||||||
Byte* limit = data + size - 4;
|
// cont: mask |= 4;
|
||||||
for (; p < limit; p++)
|
start:
|
||||||
if ((*p & 0xFE) == 0xE8)
|
if (p >= lim)
|
||||||
break;
|
goto fin;
|
||||||
bufferPos = (SizeT)(p - data);
|
{
|
||||||
if (p >= limit)
|
BR86_PREPARE_BCJ_SCAN
|
||||||
break;
|
p += 4;
|
||||||
prevPosT = bufferPos - prevPosT;
|
if (BR86_IS_BCJ_BYTE(0)) { goto m0; } mask >>= 1;
|
||||||
if (prevPosT > 3)
|
if (BR86_IS_BCJ_BYTE(1)) { goto m1; } mask >>= 1;
|
||||||
prevMask = 0;
|
if (BR86_IS_BCJ_BYTE(2)) { goto m2; } mask = 0;
|
||||||
else {
|
if (BR86_IS_BCJ_BYTE(3)) { goto a3; }
|
||||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
|
||||||
if (prevMask != 0) {
|
|
||||||
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
|
||||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) {
|
|
||||||
prevPosT = bufferPos;
|
|
||||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
|
||||||
bufferPos++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prevPosT = bufferPos;
|
|
||||||
|
|
||||||
if (Test86MSByte(p[4])) {
|
|
||||||
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
|
||||||
UInt32 dest;
|
|
||||||
for (;;) {
|
|
||||||
Byte b;
|
|
||||||
int index;
|
|
||||||
if (encoding)
|
|
||||||
dest = (ip + (UInt32)bufferPos) + src;
|
|
||||||
else
|
|
||||||
dest = src - (ip + (UInt32)bufferPos);
|
|
||||||
if (prevMask == 0)
|
|
||||||
break;
|
|
||||||
index = kMaskToBitNumber[prevMask] * 8;
|
|
||||||
b = (Byte)(dest >> (24 - index));
|
|
||||||
if (!Test86MSByte(b))
|
|
||||||
break;
|
|
||||||
src = dest ^ ((1 << (32 - index)) - 1);
|
|
||||||
}
|
|
||||||
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
|
||||||
p[3] = (Byte)(dest >> 16);
|
|
||||||
p[2] = (Byte)(dest >> 8);
|
|
||||||
p[1] = (Byte)dest;
|
|
||||||
bufferPos += 5;
|
|
||||||
} else {
|
|
||||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
|
||||||
bufferPos++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
prevPosT = bufferPos - prevPosT;
|
goto main_loop;
|
||||||
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
|
||||||
return bufferPos;
|
m0: p--;
|
||||||
|
m1: p--;
|
||||||
|
m2: p--;
|
||||||
|
if (mask == 0)
|
||||||
|
goto a3;
|
||||||
|
if (p > lim)
|
||||||
|
goto fin_p;
|
||||||
|
|
||||||
|
// if (((0x17u >> mask) & 1) == 0)
|
||||||
|
if (mask > 4 || mask == 3)
|
||||||
|
{
|
||||||
|
mask >>= 1;
|
||||||
|
continue; // goto cont;
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
if (BR86_NEED_CONV_FOR_MS_BYTE(p[mask]))
|
||||||
|
continue; // goto cont;
|
||||||
|
// if (!BR86_NEED_CONV_FOR_MS_BYTE(p[3])) continue; // goto cont;
|
||||||
|
{
|
||||||
|
UInt32 v = GetUi32(p);
|
||||||
|
UInt32 c;
|
||||||
|
v += (1 << 24); if (v & 0xfe000000) continue; // goto cont;
|
||||||
|
c = BR_PC_GET;
|
||||||
|
BR_CONVERT_VAL(v, c)
|
||||||
|
{
|
||||||
|
mask <<= 3;
|
||||||
|
if (BR86_NEED_CONV_FOR_MS_BYTE(v >> mask))
|
||||||
|
{
|
||||||
|
v ^= (((UInt32)0x100 << mask) - 1);
|
||||||
|
#ifdef MY_CPU_X86
|
||||||
|
// for X86 : we can recalculate (c) to reduce register pressure
|
||||||
|
c = BR_PC_GET;
|
||||||
|
#endif
|
||||||
|
BR_CONVERT_VAL(v, c)
|
||||||
|
}
|
||||||
|
mask = 0;
|
||||||
|
}
|
||||||
|
// v = (v & ((1 << 24) - 1)) - (v & (1 << 24));
|
||||||
|
v &= (1 << 25) - 1; v -= (1 << 24);
|
||||||
|
SetUi32(p, v)
|
||||||
|
p += 4;
|
||||||
|
goto main_loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
main_loop:
|
||||||
|
if (p >= lim)
|
||||||
|
goto fin;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
BR86_PREPARE_BCJ_SCAN
|
||||||
|
p += 4;
|
||||||
|
if (BR86_IS_BCJ_BYTE(0)) { goto a0; }
|
||||||
|
if (BR86_IS_BCJ_BYTE(1)) { goto a1; }
|
||||||
|
if (BR86_IS_BCJ_BYTE(2)) { goto a2; }
|
||||||
|
if (BR86_IS_BCJ_BYTE(3)) { goto a3; }
|
||||||
|
if (p >= lim)
|
||||||
|
goto fin;
|
||||||
|
}
|
||||||
|
|
||||||
|
a0: p--;
|
||||||
|
a1: p--;
|
||||||
|
a2: p--;
|
||||||
|
a3:
|
||||||
|
if (p > lim)
|
||||||
|
goto fin_p;
|
||||||
|
// if (!BR86_NEED_CONV_FOR_MS_BYTE(p[3])) continue; // goto cont;
|
||||||
|
{
|
||||||
|
UInt32 v = GetUi32(p);
|
||||||
|
UInt32 c;
|
||||||
|
v += (1 << 24); if (v & 0xfe000000) continue; // goto cont;
|
||||||
|
c = BR_PC_GET;
|
||||||
|
BR_CONVERT_VAL(v, c)
|
||||||
|
// v = (v & ((1 << 24) - 1)) - (v & (1 << 24));
|
||||||
|
v &= (1 << 25) - 1; v -= (1 << 24);
|
||||||
|
SetUi32(p, v)
|
||||||
|
p += 4;
|
||||||
|
goto main_loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fin_p:
|
||||||
|
p--;
|
||||||
|
fin:
|
||||||
|
// the following processing for tail is optional and can be commented
|
||||||
|
/*
|
||||||
|
lim += 4;
|
||||||
|
for (; p < lim; p++, mask >>= 1)
|
||||||
|
if ((*p & 0xfe) == 0xe8)
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
*state = (UInt32)mask;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define Z7_BRANCH_CONV_ST_FUNC_IMP(name, m, encoding) \
|
||||||
|
Z7_NO_INLINE \
|
||||||
|
Z7_ATTRIB_NO_VECTOR \
|
||||||
|
Byte *m(name)(Byte *data, SizeT size, UInt32 pc, UInt32 *state) \
|
||||||
|
{ return Z7_BRANCH_CONV_ST(name)(data, size, pc, state, encoding); }
|
||||||
|
|
||||||
|
Z7_BRANCH_CONV_ST_FUNC_IMP(X86, Z7_BRANCH_CONV_ST_DEC, 0)
|
||||||
|
#ifndef Z7_EXTRACT_ONLY
|
||||||
|
Z7_BRANCH_CONV_ST_FUNC_IMP(X86, Z7_BRANCH_CONV_ST_ENC, 1)
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
/* Compiler.h : Compiler specific defines and pragmas
|
||||||
|
2024-01-22 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef ZIP7_INC_COMPILER_H
|
||||||
|
#define ZIP7_INC_COMPILER_H
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# define Z7_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
|
||||||
|
#endif
|
||||||
|
#if defined(__clang__) && defined(__apple_build_version__)
|
||||||
|
# define Z7_APPLE_CLANG_VERSION Z7_CLANG_VERSION
|
||||||
|
#elif defined(__clang__)
|
||||||
|
# define Z7_LLVM_CLANG_VERSION Z7_CLANG_VERSION
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
# define Z7_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#if !defined(__clang__) && !defined(__GNUC__)
|
||||||
|
#define Z7_MSC_VER_ORIGINAL _MSC_VER
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||||
|
#define Z7_MINGW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__LCC__) && (defined(__MCST__) || defined(__e2k__))
|
||||||
|
#define Z7_MCST_LCC
|
||||||
|
#define Z7_MCST_LCC_VERSION (__LCC__ * 100 + __LCC_MINOR__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if defined(__AVX2__) \
|
||||||
|
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
|
||||||
|
|| defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \
|
||||||
|
|| defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \
|
||||||
|
|| defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \
|
||||||
|
|| defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)
|
||||||
|
#define Z7_COMPILER_AVX2_SUPPORTED
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
// padding size of '' with 4 bytes to alignment boundary
|
||||||
|
#pragma GCC diagnostic ignored "-Wpadded"
|
||||||
|
|
||||||
|
#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) \
|
||||||
|
&& defined(__FreeBSD__)
|
||||||
|
// freebsd:
|
||||||
|
#pragma GCC diagnostic ignored "-Wexcess-padding"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __clang_major__ >= 16
|
||||||
|
#pragma GCC diagnostic ignored "-Wunsafe-buffer-usage"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __clang_major__ == 13
|
||||||
|
#if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)
|
||||||
|
// cheri
|
||||||
|
#pragma GCC diagnostic ignored "-Wcapability-to-integer-cast"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __clang_major__ == 13
|
||||||
|
// for <arm_neon.h>
|
||||||
|
#pragma GCC diagnostic ignored "-Wreserved-identifier"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __clang__
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(__clang__) && __clang_major__ >= 16
|
||||||
|
// #pragma GCC diagnostic ignored "-Wcast-function-type-strict"
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wcast-function-type-strict\"")
|
||||||
|
#else
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*Z7_void_Function)(void);
|
||||||
|
#if defined(__clang__) || defined(__GNUC__)
|
||||||
|
#define Z7_CAST_FUNC_C (Z7_void_Function)
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER > 1920
|
||||||
|
#define Z7_CAST_FUNC_C (void *)
|
||||||
|
// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'
|
||||||
|
#else
|
||||||
|
#define Z7_CAST_FUNC_C
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__)
|
||||||
|
// #pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40000) && (Z7_GCC_VERSION < 70000)
|
||||||
|
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#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 defined(_MSC_VER) && _MSC_VER >= 1800
|
||||||
|
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// == 1200 : -O1 : for __forceinline
|
||||||
|
// >= 1900 : -O1 : for printf
|
||||||
|
#pragma warning(disable : 4710) // function not inlined
|
||||||
|
|
||||||
|
#if _MSC_VER < 1900
|
||||||
|
// winnt.h: 'Int64ShllMod32'
|
||||||
|
#pragma warning(disable : 4514) // unreferenced inline function has been removed
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if _MSC_VER < 1300
|
||||||
|
// #pragma warning(disable : 4702) // unreachable code
|
||||||
|
// Bra.c : -O1:
|
||||||
|
#pragma warning(disable : 4714) // function marked as __forceinline not inlined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if _MSC_VER > 1400 && _MSC_VER <= 1900
|
||||||
|
// strcat: This function or variable may be unsafe
|
||||||
|
// sysinfoapi.h: kit10: GetVersion was declared deprecated
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if _MSC_VER > 1200
|
||||||
|
// -Wall warnings
|
||||||
|
|
||||||
|
#pragma warning(disable : 4711) // function selected for automatic inline expansion
|
||||||
|
#pragma warning(disable : 4820) // '2' bytes padding added after data member
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1400 && _MSC_VER < 1920
|
||||||
|
// 1400: string.h: _DBG_MEMCPY_INLINE_
|
||||||
|
// 1600 - 191x : smmintrin.h __cplusplus'
|
||||||
|
// is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
|
||||||
|
#pragma warning(disable : 4668)
|
||||||
|
|
||||||
|
// 1400 - 1600 : WinDef.h : 'FARPROC' :
|
||||||
|
// 1900 - 191x : immintrin.h: _readfsbase_u32
|
||||||
|
// no function prototype given : converting '()' to '(void)'
|
||||||
|
#pragma warning(disable : 4255)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if _MSC_VER >= 1914
|
||||||
|
// Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
|
||||||
|
#pragma warning(disable : 5045)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _MSC_VER > 1200
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__clang__) && (__clang_major__ >= 4)
|
||||||
|
#define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \
|
||||||
|
_Pragma("clang loop unroll(disable)") \
|
||||||
|
_Pragma("clang loop vectorize(disable)")
|
||||||
|
#define Z7_ATTRIB_NO_VECTORIZE
|
||||||
|
#elif defined(__GNUC__) && (__GNUC__ >= 5) \
|
||||||
|
&& (!defined(Z7_MCST_LCC_VERSION) || (Z7_MCST_LCC_VERSION >= 12610))
|
||||||
|
#define Z7_ATTRIB_NO_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
|
||||||
|
// __attribute__((optimize("no-unroll-loops")));
|
||||||
|
#define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
|
||||||
|
#elif defined(_MSC_VER) && (_MSC_VER >= 1920)
|
||||||
|
#define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \
|
||||||
|
_Pragma("loop( no_vector )")
|
||||||
|
#define Z7_ATTRIB_NO_VECTORIZE
|
||||||
|
#else
|
||||||
|
#define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
|
||||||
|
#define Z7_ATTRIB_NO_VECTORIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_X86_OR_AMD64) && ( \
|
||||||
|
defined(__clang__) && (__clang_major__ >= 4) \
|
||||||
|
|| defined(__GNUC__) && (__GNUC__ >= 5))
|
||||||
|
#define Z7_ATTRIB_NO_SSE __attribute__((__target__("no-sse")))
|
||||||
|
#else
|
||||||
|
#define Z7_ATTRIB_NO_SSE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Z7_ATTRIB_NO_VECTOR \
|
||||||
|
Z7_ATTRIB_NO_VECTORIZE \
|
||||||
|
Z7_ATTRIB_NO_SSE
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__clang__) && (__clang_major__ >= 8) \
|
||||||
|
|| defined(__GNUC__) && (__GNUC__ >= 1000) \
|
||||||
|
/* || defined(_MSC_VER) && (_MSC_VER >= 1920) */
|
||||||
|
// GCC is not good for __builtin_expect()
|
||||||
|
#define Z7_LIKELY(x) (__builtin_expect((x), 1))
|
||||||
|
#define Z7_UNLIKELY(x) (__builtin_expect((x), 0))
|
||||||
|
// #define Z7_unlikely [[unlikely]]
|
||||||
|
// #define Z7_likely [[likely]]
|
||||||
|
#else
|
||||||
|
#define Z7_LIKELY(x) (x)
|
||||||
|
#define Z7_UNLIKELY(x) (x)
|
||||||
|
// #define Z7_likely
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30600))
|
||||||
|
|
||||||
|
#if (Z7_CLANG_VERSION < 130000)
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wreserved-id-macro\"")
|
||||||
|
#else
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wreserved-macro-identifier\"")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \
|
||||||
|
_Pragma("GCC diagnostic pop")
|
||||||
|
#else
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UNUSED_VAR(x) (void)x;
|
||||||
|
/* #define UNUSED_VAR(x) x=x; */
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,159 +1,678 @@
|
||||||
/* CpuArch.h -- CPU specific code
|
/* CpuArch.h -- CPU specific code
|
||||||
2010-12-01: Igor Pavlov : Public domain */
|
Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __CPU_ARCH_H
|
#ifndef ZIP7_INC_CPU_ARCH_H
|
||||||
#define __CPU_ARCH_H
|
#define ZIP7_INC_CPU_ARCH_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MY_CPU_LE means that CPU is LITTLE ENDIAN.
|
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_BE means that CPU is BIG ENDIAN.
|
||||||
|
If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.
|
||||||
|
|
||||||
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
|
MY_CPU_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.
|
|
||||||
|
MY_CPU_64BIT means that processor can work with 64-bit registers.
|
||||||
|
MY_CPU_64BIT can be used to select fast code branch
|
||||||
|
MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
|
#if !defined(_M_ARM64EC)
|
||||||
#define MY_CPU_AMD64
|
#if defined(_M_X64) \
|
||||||
|
|| defined(_M_AMD64) \
|
||||||
|
|| defined(__x86_64__) \
|
||||||
|
|| defined(__AMD64__) \
|
||||||
|
|| defined(__amd64__)
|
||||||
|
#define MY_CPU_AMD64
|
||||||
|
#ifdef __ILP32__
|
||||||
|
#define MY_CPU_NAME "x32"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 4
|
||||||
|
#else
|
||||||
|
#define MY_CPU_NAME "x64"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 8
|
||||||
|
#endif
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
|
|
||||||
#define MY_CPU_64BIT
|
#if defined(_M_IX86) \
|
||||||
|
|| defined(__i386__)
|
||||||
|
#define MY_CPU_X86
|
||||||
|
#define MY_CPU_NAME "x86"
|
||||||
|
/* #define MY_CPU_32BIT */
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_M_IX86) || defined(__i386__)
|
|
||||||
#define MY_CPU_X86
|
#if defined(_M_ARM64) \
|
||||||
|
|| defined(_M_ARM64EC) \
|
||||||
|
|| defined(__AARCH64EL__) \
|
||||||
|
|| defined(__AARCH64EB__) \
|
||||||
|
|| defined(__aarch64__)
|
||||||
|
#define MY_CPU_ARM64
|
||||||
|
#if defined(__ILP32__) \
|
||||||
|
|| defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)
|
||||||
|
#define MY_CPU_NAME "arm64-32"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 4
|
||||||
|
#elif defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)
|
||||||
|
#define MY_CPU_NAME "arm64-128"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 16
|
||||||
|
#else
|
||||||
|
#if defined(_M_ARM64EC)
|
||||||
|
#define MY_CPU_NAME "arm64ec"
|
||||||
|
#else
|
||||||
|
#define MY_CPU_NAME "arm64"
|
||||||
#endif
|
#endif
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 8
|
||||||
|
#endif
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_M_ARM) \
|
||||||
|
|| defined(_M_ARM_NT) \
|
||||||
|
|| defined(_M_ARMT) \
|
||||||
|
|| defined(__arm__) \
|
||||||
|
|| defined(__thumb__) \
|
||||||
|
|| defined(__ARMEL__) \
|
||||||
|
|| defined(__ARMEB__) \
|
||||||
|
|| defined(__THUMBEL__) \
|
||||||
|
|| defined(__THUMBEB__)
|
||||||
|
#define MY_CPU_ARM
|
||||||
|
|
||||||
|
#if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT)
|
||||||
|
#define MY_CPU_ARMT
|
||||||
|
#define MY_CPU_NAME "armt"
|
||||||
|
#else
|
||||||
|
#define MY_CPU_ARM32
|
||||||
|
#define MY_CPU_NAME "arm"
|
||||||
|
#endif
|
||||||
|
/* #define MY_CPU_32BIT */
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_M_IA64) \
|
||||||
|
|| defined(__ia64__)
|
||||||
|
#define MY_CPU_IA64
|
||||||
|
#define MY_CPU_NAME "ia64"
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__mips64) \
|
||||||
|
|| defined(__mips64__) \
|
||||||
|
|| (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3))
|
||||||
|
#define MY_CPU_NAME "mips64"
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#elif defined(__mips__)
|
||||||
|
#define MY_CPU_NAME "mips"
|
||||||
|
/* #define MY_CPU_32BIT */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__ppc64__) \
|
||||||
|
|| defined(__powerpc64__) \
|
||||||
|
|| defined(__ppc__) \
|
||||||
|
|| defined(__powerpc__) \
|
||||||
|
|| defined(__PPC__) \
|
||||||
|
|| defined(_POWER)
|
||||||
|
|
||||||
|
#define MY_CPU_PPC_OR_PPC64
|
||||||
|
|
||||||
|
#if defined(__ppc64__) \
|
||||||
|
|| defined(__powerpc64__) \
|
||||||
|
|| defined(_LP64) \
|
||||||
|
|| defined(__64BIT__)
|
||||||
|
#ifdef __ILP32__
|
||||||
|
#define MY_CPU_NAME "ppc64-32"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 4
|
||||||
|
#else
|
||||||
|
#define MY_CPU_NAME "ppc64"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 8
|
||||||
|
#endif
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#else
|
||||||
|
#define MY_CPU_NAME "ppc"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 4
|
||||||
|
/* #define MY_CPU_32BIT */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__sparc__) \
|
||||||
|
|| defined(__sparc)
|
||||||
|
#define MY_CPU_SPARC
|
||||||
|
#if defined(__LP64__) \
|
||||||
|
|| defined(_LP64) \
|
||||||
|
|| defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)
|
||||||
|
#define MY_CPU_NAME "sparcv9"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 8
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#elif defined(__sparc_v9__) \
|
||||||
|
|| defined(__sparcv9)
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)
|
||||||
|
#define MY_CPU_NAME "sparcv9-32"
|
||||||
|
#else
|
||||||
|
#define MY_CPU_NAME "sparcv9m"
|
||||||
|
#endif
|
||||||
|
#elif defined(__sparc_v8__) \
|
||||||
|
|| defined(__sparcv8)
|
||||||
|
#define MY_CPU_NAME "sparcv8"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 4
|
||||||
|
#else
|
||||||
|
#define MY_CPU_NAME "sparc"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__riscv) \
|
||||||
|
|| defined(__riscv__)
|
||||||
|
#define MY_CPU_RISCV
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
#define MY_CPU_NAME "riscv32"
|
||||||
|
#elif __riscv_xlen == 64
|
||||||
|
#define MY_CPU_NAME "riscv64"
|
||||||
|
#else
|
||||||
|
#define MY_CPU_NAME "riscv"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__loongarch__)
|
||||||
|
#define MY_CPU_LOONGARCH
|
||||||
|
#if defined(__loongarch64) || defined(__loongarch_grlen) && (__loongarch_grlen == 64)
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#endif
|
||||||
|
#if defined(__loongarch64)
|
||||||
|
#define MY_CPU_NAME "loongarch64"
|
||||||
|
#define MY_CPU_LOONGARCH64
|
||||||
|
#else
|
||||||
|
#define MY_CPU_NAME "loongarch"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// #undef MY_CPU_NAME
|
||||||
|
// #undef MY_CPU_SIZEOF_POINTER
|
||||||
|
// #define __e2k__
|
||||||
|
// #define __SIZEOF_POINTER__ 4
|
||||||
|
#if defined(__e2k__)
|
||||||
|
#define MY_CPU_E2K
|
||||||
|
#if defined(__ILP32__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)
|
||||||
|
#define MY_CPU_NAME "e2k-32"
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 4
|
||||||
|
#else
|
||||||
|
#define MY_CPU_NAME "e2k"
|
||||||
|
#if defined(__LP64__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)
|
||||||
|
#define MY_CPU_SIZEOF_POINTER 8
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#define MY_CPU_64BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
||||||
#define MY_CPU_X86_OR_AMD64
|
#define MY_CPU_X86_OR_AMD64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_X86) || defined(_M_ARM)
|
#if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64)
|
||||||
#define MY_CPU_32BIT
|
#define MY_CPU_ARM_OR_ARM64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(_M_ARM)
|
|
||||||
#define MY_CPU_ARM_LE
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#ifdef MY_CPU_ARM
|
||||||
|
#define MY_CPU_ARM_LE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MY_CPU_ARM64
|
||||||
|
#define MY_CPU_ARM64_LE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _M_IA64
|
||||||
|
#define MY_CPU_IA64_LE
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(_M_IA64)
|
|
||||||
#define MY_CPU_IA64_LE
|
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||||
|
|| defined(MY_CPU_ARM_LE) \
|
||||||
|
|| defined(MY_CPU_ARM64_LE) \
|
||||||
|
|| defined(MY_CPU_IA64_LE) \
|
||||||
|
|| defined(_LITTLE_ENDIAN) \
|
||||||
|
|| defined(__LITTLE_ENDIAN__) \
|
||||||
|
|| defined(__ARMEL__) \
|
||||||
|
|| defined(__THUMBEL__) \
|
||||||
|
|| defined(__AARCH64EL__) \
|
||||||
|
|| defined(__MIPSEL__) \
|
||||||
|
|| defined(__MIPSEL) \
|
||||||
|
|| defined(_MIPSEL) \
|
||||||
|
|| defined(__BFIN__) \
|
||||||
|
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||||
|
#define MY_CPU_LE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_X86_OR_AMD64)
|
#if defined(__BIG_ENDIAN__) \
|
||||||
#define MY_CPU_LE_UNALIGN
|
|| defined(__ARMEB__) \
|
||||||
|
|| defined(__THUMBEB__) \
|
||||||
|
|| defined(__AARCH64EB__) \
|
||||||
|
|| defined(__MIPSEB__) \
|
||||||
|
|| defined(__MIPSEB) \
|
||||||
|
|| defined(_MIPSEB) \
|
||||||
|
|| defined(__m68k__) \
|
||||||
|
|| defined(__s390__) \
|
||||||
|
|| defined(__s390x__) \
|
||||||
|
|| defined(__zarch__) \
|
||||||
|
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||||
|
#define MY_CPU_BE
|
||||||
#endif
|
#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)
|
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
|
||||||
Stop_Compiling_Bad_Endian
|
#error Stop_Compiling_Bad_Endian
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MY_CPU_LE_UNALIGN
|
#if !defined(MY_CPU_LE) && !defined(MY_CPU_BE)
|
||||||
|
#error Stop_Compiling_CPU_ENDIAN_must_be_detected_at_compile_time
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GetUi16(p) (*(const UInt16*)(p))
|
#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT)
|
||||||
#define GetUi32(p) (*(const UInt32*)(p))
|
#error Stop_Compiling_Bad_32_64_BIT
|
||||||
#define GetUi64(p) (*(const UInt64*)(p))
|
#endif
|
||||||
#define SetUi16(p, d) *(UInt16*)(p) = (d);
|
|
||||||
#define SetUi32(p, d) *(UInt32*)(p) = (d);
|
#ifdef __SIZEOF_POINTER__
|
||||||
#define SetUi64(p, d) *(UInt64*)(p) = (d);
|
#ifdef MY_CPU_SIZEOF_POINTER
|
||||||
|
#if MY_CPU_SIZEOF_POINTER != __SIZEOF_POINTER__
|
||||||
|
#error Stop_Compiling_Bad_MY_CPU_PTR_SIZE
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define MY_CPU_SIZEOF_POINTER __SIZEOF_POINTER__
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
|
||||||
|
#if defined (_LP64)
|
||||||
|
#error Stop_Compiling_Bad_MY_CPU_PTR_SIZE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#if _MSC_VER >= 1300
|
||||||
|
#define MY_CPU_pragma_pack_push_1 __pragma(pack(push, 1))
|
||||||
|
#define MY_CPU_pragma_pop __pragma(pack(pop))
|
||||||
|
#else
|
||||||
|
#define MY_CPU_pragma_pack_push_1
|
||||||
|
#define MY_CPU_pragma_pop
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef __xlC__
|
||||||
|
#define MY_CPU_pragma_pack_push_1 _Pragma("pack(1)")
|
||||||
|
#define MY_CPU_pragma_pop _Pragma("pack()")
|
||||||
|
#else
|
||||||
|
#define MY_CPU_pragma_pack_push_1 _Pragma("pack(push, 1)")
|
||||||
|
#define MY_CPU_pragma_pop _Pragma("pack(pop)")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MY_CPU_NAME
|
||||||
|
// #define MY_CPU_IS_UNKNOWN
|
||||||
|
#ifdef MY_CPU_LE
|
||||||
|
#define MY_CPU_NAME "LE"
|
||||||
|
#elif defined(MY_CPU_BE)
|
||||||
|
#define MY_CPU_NAME "BE"
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
#define MY_CPU_NAME ""
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __has_builtin
|
||||||
|
#define Z7_has_builtin(x) __has_builtin(x)
|
||||||
|
#else
|
||||||
|
#define Z7_has_builtin(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define Z7_BSWAP32_CONST(v) \
|
||||||
|
( (((UInt32)(v) << 24) ) \
|
||||||
|
| (((UInt32)(v) << 8) & (UInt32)0xff0000) \
|
||||||
|
| (((UInt32)(v) >> 8) & (UInt32)0xff00 ) \
|
||||||
|
| (((UInt32)(v) >> 24) ))
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Note: these macros will use bswap instruction (486), that is unsupported in 386 cpu */
|
||||||
|
|
||||||
|
#pragma intrinsic(_byteswap_ushort)
|
||||||
|
#pragma intrinsic(_byteswap_ulong)
|
||||||
|
#pragma intrinsic(_byteswap_uint64)
|
||||||
|
|
||||||
|
#define Z7_BSWAP16(v) _byteswap_ushort(v)
|
||||||
|
#define Z7_BSWAP32(v) _byteswap_ulong (v)
|
||||||
|
#define Z7_BSWAP64(v) _byteswap_uint64(v)
|
||||||
|
#define Z7_CPU_FAST_BSWAP_SUPPORTED
|
||||||
|
|
||||||
|
/* GCC can generate slow code that calls function for __builtin_bswap32() for:
|
||||||
|
- GCC for RISCV, if Zbb/XTHeadBb extension is not used.
|
||||||
|
- GCC for SPARC.
|
||||||
|
The code from CLANG for SPARC also is not fastest.
|
||||||
|
So we don't define Z7_CPU_FAST_BSWAP_SUPPORTED in some cases.
|
||||||
|
*/
|
||||||
|
#elif (!defined(MY_CPU_RISCV) || defined (__riscv_zbb) || defined(__riscv_xtheadbb)) \
|
||||||
|
&& !defined(MY_CPU_SPARC) \
|
||||||
|
&& ( \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
|
||||||
|
|| (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define Z7_BSWAP16(v) __builtin_bswap16(v)
|
||||||
|
#define Z7_BSWAP32(v) __builtin_bswap32(v)
|
||||||
|
#define Z7_BSWAP64(v) __builtin_bswap64(v)
|
||||||
|
#define Z7_CPU_FAST_BSWAP_SUPPORTED
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define GetUi16(p) (((const Byte*)(p))[0] | ((UInt16)((const Byte*)(p))[1] << 8))
|
#define Z7_BSWAP16(v) ((UInt16) \
|
||||||
|
( ((UInt32)(v) << 8) \
|
||||||
|
| ((UInt32)(v) >> 8) \
|
||||||
|
))
|
||||||
|
|
||||||
|
#define Z7_BSWAP32(v) Z7_BSWAP32_CONST(v)
|
||||||
|
|
||||||
|
#define Z7_BSWAP64(v) \
|
||||||
|
( ( ( (UInt64)(v) ) << 8 * 7 ) \
|
||||||
|
| ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 1) ) << 8 * 5 ) \
|
||||||
|
| ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 2) ) << 8 * 3 ) \
|
||||||
|
| ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 3) ) << 8 * 1 ) \
|
||||||
|
| ( ( (UInt64)(v) >> 8 * 1 ) & ((UInt32)0xff << 8 * 3) ) \
|
||||||
|
| ( ( (UInt64)(v) >> 8 * 3 ) & ((UInt32)0xff << 8 * 2) ) \
|
||||||
|
| ( ( (UInt64)(v) >> 8 * 5 ) & ((UInt32)0xff << 8 * 1) ) \
|
||||||
|
| ( ( (UInt64)(v) >> 8 * 7 ) ) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE
|
||||||
|
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||||
|
|| defined(MY_CPU_ARM64) \
|
||||||
|
|| defined(MY_CPU_RISCV) && defined(__riscv_misaligned_fast) \
|
||||||
|
|| defined(MY_CPU_E2K) && defined(__iset__) && (__iset__ >= 6)
|
||||||
|
#define MY_CPU_LE_UNALIGN
|
||||||
|
#define MY_CPU_LE_UNALIGN_64
|
||||||
|
#elif defined(__ARM_FEATURE_UNALIGNED)
|
||||||
|
/* === ALIGNMENT on 32-bit arm and LDRD/STRD/LDM/STM instructions.
|
||||||
|
Description of problems:
|
||||||
|
problem-1 : 32-bit ARM architecture:
|
||||||
|
multi-access (pair of 32-bit accesses) instructions (LDRD/STRD/LDM/STM)
|
||||||
|
require 32-bit (WORD) alignment (by 32-bit ARM architecture).
|
||||||
|
So there is "Alignment fault exception", if data is not aligned for 32-bit.
|
||||||
|
|
||||||
|
problem-2 : 32-bit kernels and arm64 kernels:
|
||||||
|
32-bit linux kernels provide fixup for these "paired" instruction "Alignment fault exception".
|
||||||
|
So unaligned paired-access instructions work via exception handler in kernel in 32-bit linux.
|
||||||
|
|
||||||
|
But some arm64 kernels do not handle these faults in 32-bit programs.
|
||||||
|
So we have unhandled exception for such instructions.
|
||||||
|
Probably some new arm64 kernels have fixed it, and unaligned
|
||||||
|
paired-access instructions work in new kernels?
|
||||||
|
|
||||||
|
problem-3 : compiler for 32-bit arm:
|
||||||
|
Compilers use LDRD/STRD/LDM/STM for UInt64 accesses
|
||||||
|
and for another cases where two 32-bit accesses are fused
|
||||||
|
to one multi-access instruction.
|
||||||
|
So UInt64 variables must be aligned for 32-bit, and each
|
||||||
|
32-bit access must be aligned for 32-bit, if we want to
|
||||||
|
avoid "Alignment fault" exception (handled or unhandled).
|
||||||
|
|
||||||
|
problem-4 : performace:
|
||||||
|
Even if unaligned access is handled by kernel, it will be slow.
|
||||||
|
So if we allow unaligned access, we can get fast unaligned
|
||||||
|
single-access, and slow unaligned paired-access.
|
||||||
|
|
||||||
|
We don't allow unaligned access on 32-bit arm, because compiler
|
||||||
|
genarates paired-access instructions that require 32-bit alignment,
|
||||||
|
and some arm64 kernels have no handler for these instructions.
|
||||||
|
Also unaligned paired-access instructions will be slow, if kernel handles them.
|
||||||
|
*/
|
||||||
|
// it must be disabled:
|
||||||
|
// #define MY_CPU_LE_UNALIGN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MY_CPU_LE_UNALIGN
|
||||||
|
|
||||||
|
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
|
||||||
|
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
|
||||||
|
#ifdef MY_CPU_LE_UNALIGN_64
|
||||||
|
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
|
||||||
|
#define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SetUi16(p, v) { *(UInt16 *)(void *)(p) = (v); }
|
||||||
|
#define SetUi32(p, v) { *(UInt32 *)(void *)(p) = (v); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define GetUi16(p) ( (UInt16) ( \
|
||||||
|
((const Byte *)(p))[0] | \
|
||||||
|
((UInt16)((const Byte *)(p))[1] << 8) ))
|
||||||
|
|
||||||
#define GetUi32(p) ( \
|
#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))
|
((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, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||||
|
_ppp_[0] = (Byte)_vvv_; \
|
||||||
|
_ppp_[1] = (Byte)(_vvv_ >> 8); }
|
||||||
|
|
||||||
#define SetUi16(p, d) \
|
#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||||
{ \
|
_ppp_[0] = (Byte)_vvv_; \
|
||||||
UInt32 _x_ = (d); \
|
_ppp_[1] = (Byte)(_vvv_ >> 8); \
|
||||||
((Byte*)(p))[0] = (Byte)_x_; \
|
_ppp_[2] = (Byte)(_vvv_ >> 16); \
|
||||||
((Byte*)(p))[1] = (Byte)(_x_ >> 8); \
|
_ppp_[3] = (Byte)(_vvv_ >> 24); }
|
||||||
}
|
|
||||||
|
|
||||||
#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
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
|
|
||||||
|
|
||||||
#ifndef _M_X64
|
#ifndef GetUi64
|
||||||
#pragma intrinsic(_byteswap_ulong)
|
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||||
#pragma intrinsic(_byteswap_uint64)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GetBe32(p) _byteswap_ulong(*(const UInt32*)(const Byte*)(p))
|
#ifndef SetUi64
|
||||||
#define GetBe64(p) _byteswap_uint64(*(const UInt64*)(const Byte*)(p))
|
#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
|
||||||
|
SetUi32(_ppp2_ , (UInt32)_vvv2_) \
|
||||||
|
SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)) }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED)
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Z7_BSWAP16 can be slow for x86-msvc
|
||||||
|
#define GetBe16_to32(p) (Z7_BSWAP16 (*(const UInt16 *)(const void *)(p)))
|
||||||
|
#else
|
||||||
|
#define GetBe16_to32(p) (Z7_BSWAP32 (*(const UInt16 *)(const void *)(p)) >> 16)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GetBe32(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p))
|
||||||
|
#define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); }
|
||||||
|
|
||||||
|
#if defined(MY_CPU_LE_UNALIGN_64)
|
||||||
|
#define GetBe64(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p))
|
||||||
|
#define SetBe64(p, v) { (*(UInt64 *)(void *)(p)) = Z7_BSWAP64(v); }
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define GetBe32(p) ( \
|
#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])
|
((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))
|
#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||||
|
_ppp_[0] = (Byte)(_vvv_ >> 24); \
|
||||||
|
_ppp_[1] = (Byte)(_vvv_ >> 16); \
|
||||||
|
_ppp_[2] = (Byte)(_vvv_ >> 8); \
|
||||||
|
_ppp_[3] = (Byte)_vvv_; }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GetBe16(p) (((UInt16)((const Byte*)(p))[0] << 8) | ((const Byte*)(p))[1])
|
#ifndef GetBe64
|
||||||
|
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SetBe64
|
||||||
|
#define SetBe64(p, v) { Byte *_ppp_ = (Byte *)(p); UInt64 _vvv_ = (v); \
|
||||||
|
_ppp_[0] = (Byte)(_vvv_ >> 56); \
|
||||||
|
_ppp_[1] = (Byte)(_vvv_ >> 48); \
|
||||||
|
_ppp_[2] = (Byte)(_vvv_ >> 40); \
|
||||||
|
_ppp_[3] = (Byte)(_vvv_ >> 32); \
|
||||||
|
_ppp_[4] = (Byte)(_vvv_ >> 24); \
|
||||||
|
_ppp_[5] = (Byte)(_vvv_ >> 16); \
|
||||||
|
_ppp_[6] = (Byte)(_vvv_ >> 8); \
|
||||||
|
_ppp_[7] = (Byte)_vvv_; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GetBe16
|
||||||
|
#ifdef GetBe16_to32
|
||||||
|
#define GetBe16(p) ( (UInt16) GetBe16_to32(p))
|
||||||
|
#else
|
||||||
|
#define GetBe16(p) ( (UInt16) ( \
|
||||||
|
((UInt16)((const Byte *)(p))[0] << 8) | \
|
||||||
|
((const Byte *)(p))[1] ))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(MY_CPU_BE)
|
||||||
|
#define Z7_CONV_BE_TO_NATIVE_CONST32(v) (v)
|
||||||
|
#define Z7_CONV_LE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v)
|
||||||
|
#define Z7_CONV_NATIVE_TO_BE_32(v) (v)
|
||||||
|
#elif defined(MY_CPU_LE)
|
||||||
|
#define Z7_CONV_BE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v)
|
||||||
|
#define Z7_CONV_LE_TO_NATIVE_CONST32(v) (v)
|
||||||
|
#define Z7_CONV_NATIVE_TO_BE_32(v) Z7_BSWAP32(v)
|
||||||
|
#else
|
||||||
|
#error Stop_Compiling_Unknown_Endian_CONV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(MY_CPU_BE)
|
||||||
|
|
||||||
|
#define GetBe64a(p) (*(const UInt64 *)(const void *)(p))
|
||||||
|
#define GetBe32a(p) (*(const UInt32 *)(const void *)(p))
|
||||||
|
#define GetBe16a(p) (*(const UInt16 *)(const void *)(p))
|
||||||
|
#define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
|
||||||
|
#define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); }
|
||||||
|
|
||||||
|
#define GetUi64a(p) GetUi64(p)
|
||||||
|
#define GetUi32a(p) GetUi32(p)
|
||||||
|
#define GetUi16a(p) GetUi16(p)
|
||||||
|
#define SetUi32a(p, v) SetUi32(p, v)
|
||||||
|
#define SetUi16a(p, v) SetUi16(p, v)
|
||||||
|
|
||||||
|
#elif defined(MY_CPU_LE)
|
||||||
|
|
||||||
|
#define GetUi64a(p) (*(const UInt64 *)(const void *)(p))
|
||||||
|
#define GetUi32a(p) (*(const UInt32 *)(const void *)(p))
|
||||||
|
#define GetUi16a(p) (*(const UInt16 *)(const void *)(p))
|
||||||
|
#define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
|
||||||
|
#define SetUi16a(p, v) { *(UInt16 *)(void *)(p) = (v); }
|
||||||
|
|
||||||
|
#define GetBe64a(p) GetBe64(p)
|
||||||
|
#define GetBe32a(p) GetBe32(p)
|
||||||
|
#define GetBe16a(p) GetBe16(p)
|
||||||
|
#define SetBe32a(p, v) SetBe32(p, v)
|
||||||
|
#define SetBe16a(p, v) SetBe16(p, v)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error Stop_Compiling_Unknown_Endian_CPU_a
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef GetBe16_to32
|
||||||
|
#define GetBe16_to32(p) GetBe16(p)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||||
|
|| defined(MY_CPU_ARM_OR_ARM64) \
|
||||||
|
|| defined(MY_CPU_PPC_OR_PPC64)
|
||||||
|
#define Z7_CPU_FAST_ROTATE_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef MY_CPU_X86_OR_AMD64
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
|
||||||
typedef struct
|
void Z7_FASTCALL z7_x86_cpuid(UInt32 a[4], UInt32 function);
|
||||||
{
|
UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void);
|
||||||
UInt32 maxFunc;
|
#if defined(MY_CPU_AMD64)
|
||||||
UInt32 vendor[3];
|
#define Z7_IF_X86_CPUID_SUPPORTED
|
||||||
UInt32 ver;
|
#else
|
||||||
UInt32 b;
|
#define Z7_IF_X86_CPUID_SUPPORTED if (z7_x86_cpuid_GetMaxFunc())
|
||||||
UInt32 c;
|
#endif
|
||||||
UInt32 d;
|
|
||||||
} Cx86cpuid;
|
|
||||||
|
|
||||||
enum {
|
BoolInt CPU_IsSupported_AES(void);
|
||||||
CPU_FIRM_INTEL,
|
BoolInt CPU_IsSupported_AVX(void);
|
||||||
CPU_FIRM_AMD,
|
BoolInt CPU_IsSupported_AVX2(void);
|
||||||
CPU_FIRM_VIA
|
BoolInt CPU_IsSupported_AVX512F_AVX512VL(void);
|
||||||
};
|
BoolInt CPU_IsSupported_VAES_AVX2(void);
|
||||||
|
BoolInt CPU_IsSupported_CMOV(void);
|
||||||
|
BoolInt CPU_IsSupported_SSE(void);
|
||||||
|
BoolInt CPU_IsSupported_SSE2(void);
|
||||||
|
BoolInt CPU_IsSupported_SSSE3(void);
|
||||||
|
BoolInt CPU_IsSupported_SSE41(void);
|
||||||
|
BoolInt CPU_IsSupported_SHA(void);
|
||||||
|
BoolInt CPU_IsSupported_SHA512(void);
|
||||||
|
BoolInt CPU_IsSupported_PageGB(void);
|
||||||
|
|
||||||
Bool x86cpuid_CheckAndRead(Cx86cpuid* p);
|
#elif defined(MY_CPU_ARM_OR_ARM64)
|
||||||
int x86cpuid_GetFirm(const Cx86cpuid* p);
|
|
||||||
|
|
||||||
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
|
BoolInt CPU_IsSupported_CRC32(void);
|
||||||
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
|
BoolInt CPU_IsSupported_NEON(void);
|
||||||
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
|
|
||||||
|
|
||||||
Bool CPU_Is_InOrder();
|
#if defined(_WIN32)
|
||||||
Bool CPU_Is_Aes_Supported();
|
BoolInt CPU_IsSupported_CRYPTO(void);
|
||||||
|
#define CPU_IsSupported_SHA1 CPU_IsSupported_CRYPTO
|
||||||
|
#define CPU_IsSupported_SHA2 CPU_IsSupported_CRYPTO
|
||||||
|
#define CPU_IsSupported_AES CPU_IsSupported_CRYPTO
|
||||||
|
#else
|
||||||
|
BoolInt CPU_IsSupported_SHA1(void);
|
||||||
|
BoolInt CPU_IsSupported_SHA2(void);
|
||||||
|
BoolInt CPU_IsSupported_AES(void);
|
||||||
|
#endif
|
||||||
|
BoolInt CPU_IsSupported_SHA512(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
int z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize);
|
||||||
|
int z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val);
|
||||||
|
#endif
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
/* Delta.c -- Delta converter
|
||||||
|
2021-02-09 : 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||||
|
{
|
||||||
|
Byte temp[DELTA_STATE_SIZE];
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
do
|
||||||
|
temp[i] = state[i];
|
||||||
|
while (++i != delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size <= delta)
|
||||||
|
{
|
||||||
|
unsigned i = 0, k;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Byte b = *data;
|
||||||
|
*data++ = (Byte)(b - temp[i]);
|
||||||
|
temp[i] = b;
|
||||||
|
}
|
||||||
|
while (++i != size);
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (i == delta)
|
||||||
|
i = 0;
|
||||||
|
state[k] = temp[i++];
|
||||||
|
}
|
||||||
|
while (++k != delta);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Byte *p = data + size - delta;
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
do
|
||||||
|
state[i] = *p++;
|
||||||
|
while (++i != delta);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const Byte *lim = data + delta;
|
||||||
|
ptrdiff_t dif = -(ptrdiff_t)delta;
|
||||||
|
|
||||||
|
if (((ptrdiff_t)size + dif) & 1)
|
||||||
|
{
|
||||||
|
--p; *p = (Byte)(*p - p[dif]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (p != lim)
|
||||||
|
{
|
||||||
|
--p; *p = (Byte)(*p - p[dif]);
|
||||||
|
--p; *p = (Byte)(*p - p[dif]);
|
||||||
|
}
|
||||||
|
|
||||||
|
dif = -dif;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
--p; *p = (Byte)(*p - temp[--dif]);
|
||||||
|
}
|
||||||
|
while (dif != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
const Byte *lim;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
lim = data + size;
|
||||||
|
|
||||||
|
if (size <= delta)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
*data = (Byte)(*data + state[i++]);
|
||||||
|
while (++data != lim);
|
||||||
|
|
||||||
|
for (; delta != i; state++, delta--)
|
||||||
|
*state = state[i];
|
||||||
|
data -= i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
#define B(n) b ## n
|
||||||
|
#define I(n) Byte B(n) = state[n];
|
||||||
|
#define U(n) { B(n) = (Byte)((B(n)) + *data++); data[-1] = (B(n)); }
|
||||||
|
#define F(n) if (data != lim) { U(n) }
|
||||||
|
|
||||||
|
if (delta == 1)
|
||||||
|
{
|
||||||
|
I(0)
|
||||||
|
if ((lim - data) & 1) { U(0) }
|
||||||
|
while (data != lim) { U(0) U(0) }
|
||||||
|
data -= 1;
|
||||||
|
}
|
||||||
|
else if (delta == 2)
|
||||||
|
{
|
||||||
|
I(0) I(1)
|
||||||
|
lim -= 1; while (data < lim) { U(0) U(1) }
|
||||||
|
lim += 1; F(0)
|
||||||
|
data -= 2;
|
||||||
|
}
|
||||||
|
else if (delta == 3)
|
||||||
|
{
|
||||||
|
I(0) I(1) I(2)
|
||||||
|
lim -= 2; while (data < lim) { U(0) U(1) U(2) }
|
||||||
|
lim += 2; F(0) F(1)
|
||||||
|
data -= 3;
|
||||||
|
}
|
||||||
|
else if (delta == 4)
|
||||||
|
{
|
||||||
|
I(0) I(1) I(2) I(3)
|
||||||
|
lim -= 3; while (data < lim) { U(0) U(1) U(2) U(3) }
|
||||||
|
lim += 3; F(0) F(1) F(2)
|
||||||
|
data -= 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*data = (Byte)(*data + state[i++]);
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
while (i != delta);
|
||||||
|
|
||||||
|
{
|
||||||
|
ptrdiff_t dif = -(ptrdiff_t)delta;
|
||||||
|
do
|
||||||
|
*data = (Byte)(*data + data[dif]);
|
||||||
|
while (++data != lim);
|
||||||
|
data += dif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
*state++ = *data;
|
||||||
|
while (++data != lim);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* Delta.h -- Delta converter
|
||||||
|
2023-03-03 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef ZIP7_INC_DELTA_H
|
||||||
|
#define ZIP7_INC_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
|
|
@ -1,8 +1,10 @@
|
||||||
/* Lzma2Dec.c -- LZMA2 Decoder
|
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||||
2010-12-15 : Igor Pavlov : Public domain */
|
2024-03-01 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
/* #define SHOW_DEBUG_INFO */
|
/* #define SHOW_DEBUG_INFO */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#ifdef SHOW_DEBUG_INFO
|
#ifdef SHOW_DEBUG_INFO
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,31 +14,25 @@
|
||||||
#include "Lzma2Dec.h"
|
#include "Lzma2Dec.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
00000000 - EOS
|
00000000 - End of data
|
||||||
00000001 U U - Uncompressed Reset Dic
|
00000001 U U - Uncompressed, reset dic, need reset state and set new prop
|
||||||
00000010 U U - Uncompressed No Reset
|
00000010 U U - Uncompressed, no reset
|
||||||
100uuuuu U U P P - LZMA no reset
|
100uuuuu U U P P - LZMA, no reset
|
||||||
101uuuuu U U P P - LZMA reset state
|
101uuuuu U U P P - LZMA, reset state
|
||||||
110uuuuu U U P P S - LZMA reset state + new prop
|
110uuuuu U U P P S - LZMA, reset state + set new prop
|
||||||
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
|
111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
|
||||||
|
|
||||||
u, U - Unpack Size
|
u, U - Unpack Size
|
||||||
P - Pack Size
|
P - Pack Size
|
||||||
S - Props
|
S - Props
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LZMA2_CONTROL_LZMA (1 << 7)
|
|
||||||
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
|
||||||
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
#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_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 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_LCLP_MAX 4
|
||||||
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p)&1)) << ((p) / 2 + 11))
|
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||||
|
|
||||||
#ifdef SHOW_DEBUG_INFO
|
#ifdef SHOW_DEBUG_INFO
|
||||||
#define PRF(x) x
|
#define PRF(x) x
|
||||||
|
@ -44,284 +40,454 @@
|
||||||
#define PRF(x)
|
#define PRF(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
LZMA2_STATE_CONTROL,
|
{
|
||||||
LZMA2_STATE_UNPACK0,
|
LZMA2_STATE_CONTROL,
|
||||||
LZMA2_STATE_UNPACK1,
|
LZMA2_STATE_UNPACK0,
|
||||||
LZMA2_STATE_PACK0,
|
LZMA2_STATE_UNPACK1,
|
||||||
LZMA2_STATE_PACK1,
|
LZMA2_STATE_PACK0,
|
||||||
LZMA2_STATE_PROP,
|
LZMA2_STATE_PACK1,
|
||||||
LZMA2_STATE_DATA,
|
LZMA2_STATE_PROP,
|
||||||
LZMA2_STATE_DATA_CONT,
|
LZMA2_STATE_DATA,
|
||||||
LZMA2_STATE_FINISHED,
|
LZMA2_STATE_DATA_CONT,
|
||||||
LZMA2_STATE_ERROR
|
LZMA2_STATE_FINISHED,
|
||||||
|
LZMA2_STATE_ERROR
|
||||||
} ELzma2State;
|
} ELzma2State;
|
||||||
|
|
||||||
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte* props)
|
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
|
||||||
{
|
{
|
||||||
UInt32 dicSize;
|
UInt32 dicSize;
|
||||||
if (prop > 40)
|
if (prop > 40)
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||||
props[0] = (Byte)LZMA2_LCLP_MAX;
|
props[0] = (Byte)LZMA2_LCLP_MAX;
|
||||||
props[1] = (Byte)(dicSize);
|
props[1] = (Byte)(dicSize);
|
||||||
props[2] = (Byte)(dicSize >> 8);
|
props[2] = (Byte)(dicSize >> 8);
|
||||||
props[3] = (Byte)(dicSize >> 16);
|
props[3] = (Byte)(dicSize >> 16);
|
||||||
props[4] = (Byte)(dicSize >> 24);
|
props[4] = (Byte)(dicSize >> 24);
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec* p, Byte prop, ISzAlloc* alloc)
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
|
||||||
{
|
{
|
||||||
Byte props[LZMA_PROPS_SIZE];
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
RINOK(Lzma2Dec_GetOldProps(prop, props))
|
||||||
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes Lzma2Dec_Allocate(CLzma2Dec* p, Byte prop, ISzAlloc* alloc)
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
|
||||||
{
|
{
|
||||||
Byte props[LZMA_PROPS_SIZE];
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
RINOK(Lzma2Dec_GetOldProps(prop, props))
|
||||||
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lzma2Dec_Init(CLzma2Dec* p)
|
void Lzma2Dec_Init(CLzma2Dec *p)
|
||||||
{
|
{
|
||||||
p->state = LZMA2_STATE_CONTROL;
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
p->needInitDic = True;
|
p->needInitLevel = 0xE0;
|
||||||
p->needInitState = True;
|
p->isExtraMode = False;
|
||||||
p->needInitProp = True;
|
p->unpackSize = 0;
|
||||||
LzmaDec_Init(&p->decoder);
|
|
||||||
|
// p->decoder.dicPos = 0; // we can use it instead of full init
|
||||||
|
LzmaDec_Init(&p->decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec* p, Byte b)
|
// ELzma2State
|
||||||
|
static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||||
{
|
{
|
||||||
switch (p->state) {
|
switch (p->state)
|
||||||
|
{
|
||||||
case LZMA2_STATE_CONTROL:
|
case LZMA2_STATE_CONTROL:
|
||||||
p->control = b;
|
p->isExtraMode = False;
|
||||||
PRF(printf("\n %4X ", p->decoder.dicPos));
|
p->control = b;
|
||||||
PRF(printf(" %2X", b));
|
PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
|
||||||
if (p->control == 0)
|
PRF(printf(" %02X", (unsigned)b));
|
||||||
return LZMA2_STATE_FINISHED;
|
if (b == 0)
|
||||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p)) {
|
return LZMA2_STATE_FINISHED;
|
||||||
if ((p->control & 0x7F) > 2)
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
return LZMA2_STATE_ERROR;
|
{
|
||||||
p->unpackSize = 0;
|
if (b == LZMA2_CONTROL_COPY_RESET_DIC)
|
||||||
} else
|
p->needInitLevel = 0xC0;
|
||||||
p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
|
else if (b > 2 || p->needInitLevel == 0xE0)
|
||||||
return LZMA2_STATE_UNPACK0;
|
return LZMA2_STATE_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (b < p->needInitLevel)
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
p->needInitLevel = 0;
|
||||||
|
p->unpackSize = (UInt32)(b & 0x1F) << 16;
|
||||||
|
}
|
||||||
|
return LZMA2_STATE_UNPACK0;
|
||||||
|
|
||||||
case LZMA2_STATE_UNPACK0:
|
case LZMA2_STATE_UNPACK0:
|
||||||
p->unpackSize |= (UInt32)b << 8;
|
p->unpackSize |= (UInt32)b << 8;
|
||||||
return LZMA2_STATE_UNPACK1;
|
return LZMA2_STATE_UNPACK1;
|
||||||
|
|
||||||
case LZMA2_STATE_UNPACK1:
|
case LZMA2_STATE_UNPACK1:
|
||||||
p->unpackSize |= (UInt32)b;
|
p->unpackSize |= (UInt32)b;
|
||||||
p->unpackSize++;
|
p->unpackSize++;
|
||||||
PRF(printf(" %8d", p->unpackSize));
|
PRF(printf(" %7u", (unsigned)p->unpackSize));
|
||||||
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||||
|
|
||||||
case LZMA2_STATE_PACK0:
|
case LZMA2_STATE_PACK0:
|
||||||
p->packSize = (UInt32)b << 8;
|
p->packSize = (UInt32)b << 8;
|
||||||
return LZMA2_STATE_PACK1;
|
return LZMA2_STATE_PACK1;
|
||||||
|
|
||||||
case LZMA2_STATE_PACK1:
|
case LZMA2_STATE_PACK1:
|
||||||
p->packSize |= (UInt32)b;
|
p->packSize |= (UInt32)b;
|
||||||
p->packSize++;
|
p->packSize++;
|
||||||
PRF(printf(" %8d", p->packSize));
|
// if (p->packSize < 5) return LZMA2_STATE_ERROR;
|
||||||
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP : (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
PRF(printf(" %5u", (unsigned)p->packSize));
|
||||||
|
return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
|
||||||
|
|
||||||
case LZMA2_STATE_PROP: {
|
case LZMA2_STATE_PROP:
|
||||||
int lc, lp;
|
{
|
||||||
if (b >= (9 * 5 * 5))
|
unsigned lc, lp;
|
||||||
return LZMA2_STATE_ERROR;
|
if (b >= (9 * 5 * 5))
|
||||||
lc = b % 9;
|
return LZMA2_STATE_ERROR;
|
||||||
b /= 9;
|
lc = b % 9;
|
||||||
p->decoder.prop.pb = b / 5;
|
b /= 9;
|
||||||
lp = b % 5;
|
p->decoder.prop.pb = (Byte)(b / 5);
|
||||||
if (lc + lp > LZMA2_LCLP_MAX)
|
lp = b % 5;
|
||||||
return LZMA2_STATE_ERROR;
|
if (lc + lp > LZMA2_LCLP_MAX)
|
||||||
p->decoder.prop.lc = lc;
|
return LZMA2_STATE_ERROR;
|
||||||
p->decoder.prop.lp = lp;
|
p->decoder.prop.lc = (Byte)lc;
|
||||||
p->needInitProp = False;
|
p->decoder.prop.lp = (Byte)lp;
|
||||||
return LZMA2_STATE_DATA;
|
return LZMA2_STATE_DATA;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return LZMA2_STATE_ERROR;
|
default:
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LzmaDec_UpdateWithUncompressed(CLzmaDec* p, const Byte* src, SizeT size)
|
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
|
||||||
{
|
{
|
||||||
memcpy(p->dic + p->dicPos, src, size);
|
memcpy(p->dic + p->dicPos, src, size);
|
||||||
p->dicPos += size;
|
p->dicPos += size;
|
||||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
||||||
p->checkDicSize = p->prop.dicSize;
|
p->checkDicSize = p->prop.dicSize;
|
||||||
p->processedPos += (UInt32)size;
|
p->processedPos += (UInt32)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LzmaDec_InitDicAndState(CLzmaDec* p, Bool initDic, Bool initState);
|
void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
|
||||||
|
|
||||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec* p, SizeT dicLimit,
|
|
||||||
const Byte* src, SizeT* srcLen, ELzmaFinishMode finishMode, ELzmaStatus* status)
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||||
{
|
{
|
||||||
SizeT inSize = *srcLen;
|
SizeT inSize = *srcLen;
|
||||||
*srcLen = 0;
|
*srcLen = 0;
|
||||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
|
||||||
while (p->state != LZMA2_STATE_FINISHED) {
|
while (p->state != LZMA2_STATE_ERROR)
|
||||||
SizeT dicPos = p->decoder.dicPos;
|
{
|
||||||
if (p->state == LZMA2_STATE_ERROR)
|
SizeT dicPos;
|
||||||
return SZ_ERROR_DATA;
|
|
||||||
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) {
|
if (p->state == LZMA2_STATE_FINISHED)
|
||||||
*status = LZMA_STATUS_NOT_FINISHED;
|
{
|
||||||
return SZ_OK;
|
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||||
}
|
return SZ_OK;
|
||||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) {
|
}
|
||||||
if (*srcLen == inSize) {
|
|
||||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
dicPos = p->decoder.dicPos;
|
||||||
return SZ_OK;
|
|
||||||
}
|
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||||
(*srcLen)++;
|
{
|
||||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
*status = LZMA_STATUS_NOT_FINISHED;
|
||||||
continue;
|
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++);
|
||||||
|
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SizeT inCur = inSize - *srcLen;
|
||||||
|
SizeT outCur = dicLimit - dicPos;
|
||||||
|
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||||
|
|
||||||
|
if (outCur >= p->unpackSize)
|
||||||
|
{
|
||||||
|
outCur = (SizeT)p->unpackSize;
|
||||||
|
curFinishMode = LZMA_FINISH_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
|
{
|
||||||
|
if (inCur == 0)
|
||||||
{
|
{
|
||||||
SizeT destSizeCur = dicLimit - dicPos;
|
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
SizeT srcSizeCur = inSize - *srcLen;
|
return SZ_OK;
|
||||||
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)
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
{
|
{
|
||||||
SizeT outSize = *destLen, inSize = *srcLen;
|
BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||||
*srcLen = *destLen = 0;
|
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||||
for (;;) {
|
}
|
||||||
SizeT srcSizeCur = inSize, outSizeCur, dicPos;
|
|
||||||
ELzmaFinishMode curFinishMode;
|
if (inCur > outCur)
|
||||||
|
inCur = outCur;
|
||||||
|
if (inCur == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
|
||||||
|
|
||||||
|
src += inCur;
|
||||||
|
*srcLen += inCur;
|
||||||
|
p->unpackSize -= (UInt32)inCur;
|
||||||
|
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SRes res;
|
SRes res;
|
||||||
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
|
||||||
p->decoder.dicPos = 0;
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
dicPos = p->decoder.dicPos;
|
{
|
||||||
if (outSize > p->decoder.dicBufSize - dicPos) {
|
BoolInt initDic = (p->control >= 0xE0);
|
||||||
outSizeCur = p->decoder.dicBufSize;
|
BoolInt initState = (p->control >= 0xA0);
|
||||||
curFinishMode = LZMA_FINISH_ANY;
|
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||||
} else {
|
p->state = LZMA2_STATE_DATA_CONT;
|
||||||
outSizeCur = dicPos + outSize;
|
|
||||||
curFinishMode = finishMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
|
if (inCur > p->packSize)
|
||||||
src += srcSizeCur;
|
inCur = (SizeT)p->packSize;
|
||||||
inSize -= srcSizeCur;
|
|
||||||
*srcLen += srcSizeCur;
|
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||||
outSizeCur = p->decoder.dicPos - dicPos;
|
|
||||||
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
|
src += inCur;
|
||||||
dest += outSizeCur;
|
*srcLen += inCur;
|
||||||
outSize -= outSizeCur;
|
p->packSize -= (UInt32)inCur;
|
||||||
*destLen += outSizeCur;
|
outCur = p->decoder.dicPos - dicPos;
|
||||||
|
p->unpackSize -= (UInt32)outCur;
|
||||||
|
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
return res;
|
break;
|
||||||
if (outSizeCur == 0 || outSize == 0)
|
|
||||||
return SZ_OK;
|
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||||
|
{
|
||||||
|
if (p->packSize == 0)
|
||||||
|
break;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inCur == 0 && outCur == 0)
|
||||||
|
{
|
||||||
|
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||||
|
|| p->unpackSize != 0
|
||||||
|
|| p->packSize != 0)
|
||||||
|
break;
|
||||||
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
p->state = LZMA2_STATE_ERROR;
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes Lzma2Decode(Byte* dest, SizeT* destLen, const Byte* src, SizeT* srcLen,
|
|
||||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus* status, ISzAlloc* alloc)
|
|
||||||
|
|
||||||
|
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||||
|
SizeT outSize,
|
||||||
|
const Byte *src, SizeT *srcLen,
|
||||||
|
int checkFinishBlock)
|
||||||
{
|
{
|
||||||
CLzma2Dec p;
|
SizeT inSize = *srcLen;
|
||||||
SRes res;
|
*srcLen = 0;
|
||||||
SizeT outSize = *destLen, inSize = *srcLen;
|
|
||||||
*destLen = *srcLen = 0;
|
while (p->state != LZMA2_STATE_ERROR)
|
||||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
{
|
||||||
Lzma2Dec_Construct(&p);
|
if (p->state == LZMA2_STATE_FINISHED)
|
||||||
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
|
return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
|
||||||
p.decoder.dic = dest;
|
|
||||||
p.decoder.dicBufSize = outSize;
|
if (outSize == 0 && !checkFinishBlock)
|
||||||
Lzma2Dec_Init(&p);
|
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||||
*srcLen = inSize;
|
|
||||||
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
|
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||||
*destLen = p.decoder.dicPos;
|
{
|
||||||
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
if (*srcLen == inSize)
|
||||||
res = SZ_ERROR_INPUT_EOF;
|
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
Lzma2Dec_FreeProbs(&p, alloc);
|
(*srcLen)++;
|
||||||
return res;
|
|
||||||
|
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||||
|
|
||||||
|
if (p->state == LZMA2_STATE_UNPACK0)
|
||||||
|
{
|
||||||
|
// if (p->decoder.dicPos != 0)
|
||||||
|
if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
|
||||||
|
return LZMA2_PARSE_STATUS_NEW_BLOCK;
|
||||||
|
// if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following code can be commented.
|
||||||
|
// It's not big problem, if we read additional input bytes.
|
||||||
|
// It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
|
||||||
|
|
||||||
|
if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
|
||||||
|
{
|
||||||
|
// checkFinishBlock is true. So we expect that block must be finished,
|
||||||
|
// We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
|
||||||
|
// break;
|
||||||
|
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
|
return LZMA2_PARSE_STATUS_NEW_CHUNK;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outSize == 0)
|
||||||
|
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||||
|
|
||||||
|
{
|
||||||
|
SizeT inCur = inSize - *srcLen;
|
||||||
|
|
||||||
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
|
{
|
||||||
|
if (inCur == 0)
|
||||||
|
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
if (inCur > p->unpackSize)
|
||||||
|
inCur = p->unpackSize;
|
||||||
|
if (inCur > outSize)
|
||||||
|
inCur = outSize;
|
||||||
|
p->decoder.dicPos += inCur;
|
||||||
|
src += inCur;
|
||||||
|
*srcLen += inCur;
|
||||||
|
outSize -= inCur;
|
||||||
|
p->unpackSize -= (UInt32)inCur;
|
||||||
|
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->isExtraMode = True;
|
||||||
|
|
||||||
|
if (inCur == 0)
|
||||||
|
{
|
||||||
|
if (p->packSize != 0)
|
||||||
|
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
}
|
||||||
|
else if (p->state == LZMA2_STATE_DATA)
|
||||||
|
{
|
||||||
|
p->state = LZMA2_STATE_DATA_CONT;
|
||||||
|
if (*src != 0)
|
||||||
|
{
|
||||||
|
// first byte of lzma chunk must be Zero
|
||||||
|
*srcLen += 1;
|
||||||
|
p->packSize--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inCur > p->packSize)
|
||||||
|
inCur = (SizeT)p->packSize;
|
||||||
|
|
||||||
|
src += inCur;
|
||||||
|
*srcLen += inCur;
|
||||||
|
p->packSize -= (UInt32)inCur;
|
||||||
|
|
||||||
|
if (p->packSize == 0)
|
||||||
|
{
|
||||||
|
SizeT rem = outSize;
|
||||||
|
if (rem > p->unpackSize)
|
||||||
|
rem = p->unpackSize;
|
||||||
|
p->decoder.dicPos += rem;
|
||||||
|
p->unpackSize -= (UInt32)rem;
|
||||||
|
outSize -= rem;
|
||||||
|
if (p->unpackSize == 0)
|
||||||
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p->state = LZMA2_STATE_ERROR;
|
||||||
|
return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||||
|
{
|
||||||
|
SizeT outSize = *destLen, inSize = *srcLen;
|
||||||
|
*srcLen = *destLen = 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
SizeT inCur = inSize, outCur, dicPos;
|
||||||
|
ELzmaFinishMode curFinishMode;
|
||||||
|
SRes res;
|
||||||
|
|
||||||
|
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||||
|
p->decoder.dicPos = 0;
|
||||||
|
dicPos = p->decoder.dicPos;
|
||||||
|
curFinishMode = LZMA_FINISH_ANY;
|
||||||
|
outCur = p->decoder.dicBufSize - dicPos;
|
||||||
|
|
||||||
|
if (outCur >= outSize)
|
||||||
|
{
|
||||||
|
outCur = outSize;
|
||||||
|
curFinishMode = finishMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||||
|
|
||||||
|
src += inCur;
|
||||||
|
inSize -= inCur;
|
||||||
|
*srcLen += inCur;
|
||||||
|
outCur = p->decoder.dicPos - dicPos;
|
||||||
|
memcpy(dest, p->decoder.dic + dicPos, outCur);
|
||||||
|
dest += outCur;
|
||||||
|
outSize -= outCur;
|
||||||
|
*destLen += outCur;
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
if (outCur == 0 || outSize == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
|
||||||
|
{
|
||||||
|
CLzma2Dec p;
|
||||||
|
SRes res;
|
||||||
|
SizeT outSize = *destLen, inSize = *srcLen;
|
||||||
|
*destLen = *srcLen = 0;
|
||||||
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
Lzma2Dec_CONSTRUCT(&p)
|
||||||
|
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc))
|
||||||
|
p.decoder.dic = dest;
|
||||||
|
p.decoder.dicBufSize = outSize;
|
||||||
|
Lzma2Dec_Init(&p);
|
||||||
|
*srcLen = inSize;
|
||||||
|
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
|
||||||
|
*destLen = p.decoder.dicPos;
|
||||||
|
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||||
|
res = SZ_ERROR_INPUT_EOF;
|
||||||
|
Lzma2Dec_FreeProbs(&p, alloc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef PRF
|
||||||
|
|
|
@ -1,36 +1,35 @@
|
||||||
/* Lzma2Dec.h -- LZMA2 Decoder
|
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||||
2009-05-03 : Igor Pavlov : Public domain */
|
2023-03-03 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __LZMA2_DEC_H
|
#ifndef ZIP7_INC_LZMA2_DEC_H
|
||||||
#define __LZMA2_DEC_H
|
#define ZIP7_INC_LZMA2_DEC_H
|
||||||
|
|
||||||
#include "LzmaDec.h"
|
#include "LzmaDec.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
EXTERN_C_BEGIN
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------- State Interface ---------- */
|
/* ---------- State Interface ---------- */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CLzmaDec decoder;
|
unsigned state;
|
||||||
UInt32 packSize;
|
Byte control;
|
||||||
UInt32 unpackSize;
|
Byte needInitLevel;
|
||||||
int state;
|
Byte isExtraMode;
|
||||||
Byte control;
|
Byte _pad_;
|
||||||
Bool needInitDic;
|
UInt32 packSize;
|
||||||
Bool needInitState;
|
UInt32 unpackSize;
|
||||||
Bool needInitProp;
|
CLzmaDec decoder;
|
||||||
} CLzma2Dec;
|
} CLzma2Dec;
|
||||||
|
|
||||||
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
|
#define Lzma2Dec_CONSTRUCT(p) LzmaDec_CONSTRUCT(&(p)->decoder)
|
||||||
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
|
#define Lzma2Dec_Construct(p) Lzma2Dec_CONSTRUCT(p)
|
||||||
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
|
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc)
|
||||||
|
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc)
|
||||||
|
|
||||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec* p, Byte prop, ISzAlloc* alloc);
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||||
SRes Lzma2Dec_Allocate(CLzma2Dec* p, Byte prop, ISzAlloc* alloc);
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||||
void Lzma2Dec_Init(CLzma2Dec* p);
|
void Lzma2Dec_Init(CLzma2Dec *p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
finishMode:
|
finishMode:
|
||||||
|
@ -47,11 +46,53 @@ Returns:
|
||||||
SZ_ERROR_DATA - Data error
|
SZ_ERROR_DATA - Data error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec* p, SizeT dicLimit,
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
const Byte* src, SizeT* srcLen, ELzmaFinishMode finishMode, ELzmaStatus* status);
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- LZMA2 block and chunk parsing ---------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.
|
||||||
|
It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:
|
||||||
|
- LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.
|
||||||
|
- LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.
|
||||||
|
CLzma2Dec::unpackSize contains unpack size of that chunk
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
LZMA_STATUS_NOT_SPECIFIED // data error
|
||||||
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
|
LZMA_STATUS_NOT_FINISHED //
|
||||||
|
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||||
|
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused
|
||||||
|
*/
|
||||||
|
LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,
|
||||||
|
LZMA2_PARSE_STATUS_NEW_CHUNK
|
||||||
|
} ELzma2ParseStatus;
|
||||||
|
|
||||||
|
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||||
|
SizeT outSize, // output size
|
||||||
|
const Byte *src, SizeT *srcLen,
|
||||||
|
int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position.
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
LZMA2 parser doesn't decode LZMA chunks, so we must read
|
||||||
|
full input LZMA chunk to decode some part of LZMA chunk.
|
||||||
|
|
||||||
|
Lzma2Dec_GetUnpackExtra() returns the value that shows
|
||||||
|
max possible number of output bytes that can be output by decoder
|
||||||
|
at current input positon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0)
|
||||||
|
|
||||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec* p, Byte* dest, SizeT* destLen,
|
|
||||||
const Byte* src, SizeT* srcLen, ELzmaFinishMode finishMode, ELzmaStatus* status);
|
|
||||||
|
|
||||||
/* ---------- One Call Interface ---------- */
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
@ -72,11 +113,9 @@ Returns:
|
||||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes Lzma2Decode(Byte* dest, SizeT* destLen, const Byte* src, SizeT* srcLen,
|
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus* status, ISzAlloc* alloc);
|
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
EXTERN_C_END
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,32 +1,37 @@
|
||||||
/* LzmaDec.h -- LZMA Decoder
|
/* LzmaDec.h -- LZMA Decoder
|
||||||
2009-02-07 : Igor Pavlov : Public domain */
|
2023-04-02 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __LZMA_DEC_H
|
#ifndef ZIP7_INC_LZMA_DEC_H
|
||||||
#define __LZMA_DEC_H
|
#define ZIP7_INC_LZMA_DEC_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "7zTypes.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
EXTERN_C_BEGIN
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* #define _LZMA_PROB32 */
|
/* #define Z7_LZMA_PROB32 */
|
||||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
/* Z7_LZMA_PROB32 can increase the speed on some CPUs,
|
||||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
typedef
|
||||||
#define CLzmaProb UInt32
|
#ifdef Z7_LZMA_PROB32
|
||||||
|
UInt32
|
||||||
#else
|
#else
|
||||||
#define CLzmaProb UInt16
|
UInt16
|
||||||
#endif
|
#endif
|
||||||
|
CLzmaProb;
|
||||||
|
|
||||||
|
|
||||||
/* ---------- LZMA Properties ---------- */
|
/* ---------- LZMA Properties ---------- */
|
||||||
|
|
||||||
#define LZMA_PROPS_SIZE 5
|
#define LZMA_PROPS_SIZE 5
|
||||||
|
|
||||||
typedef struct _CLzmaProps {
|
typedef struct
|
||||||
unsigned lc, lp, pb;
|
{
|
||||||
UInt32 dicSize;
|
Byte lc;
|
||||||
|
Byte lp;
|
||||||
|
Byte pb;
|
||||||
|
Byte _pad_;
|
||||||
|
UInt32 dicSize;
|
||||||
} CLzmaProps;
|
} CLzmaProps;
|
||||||
|
|
||||||
/* LzmaProps_Decode - decodes properties
|
/* LzmaProps_Decode - decodes properties
|
||||||
|
@ -35,7 +40,8 @@ Returns:
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaProps_Decode(CLzmaProps* p, const Byte* data, unsigned size);
|
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
||||||
|
|
||||||
|
|
||||||
/* ---------- LZMA Decoder state ---------- */
|
/* ---------- LZMA Decoder state ---------- */
|
||||||
|
|
||||||
|
@ -46,40 +52,40 @@ SRes LzmaProps_Decode(CLzmaProps* p, const Byte* data, unsigned size);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CLzmaProps prop;
|
/* Don't change this structure. ASM code can use it. */
|
||||||
CLzmaProb* probs;
|
CLzmaProps prop;
|
||||||
Byte* dic;
|
CLzmaProb *probs;
|
||||||
const Byte* buf;
|
CLzmaProb *probs_1664;
|
||||||
UInt32 range, code;
|
Byte *dic;
|
||||||
SizeT dicPos;
|
SizeT dicBufSize;
|
||||||
SizeT dicBufSize;
|
SizeT dicPos;
|
||||||
UInt32 processedPos;
|
const Byte *buf;
|
||||||
UInt32 checkDicSize;
|
UInt32 range;
|
||||||
unsigned state;
|
UInt32 code;
|
||||||
UInt32 reps[4];
|
UInt32 processedPos;
|
||||||
unsigned remainLen;
|
UInt32 checkDicSize;
|
||||||
int needFlush;
|
UInt32 reps[4];
|
||||||
int needInitState;
|
UInt32 state;
|
||||||
UInt32 numProbs;
|
UInt32 remainLen;
|
||||||
unsigned tempBufSize;
|
|
||||||
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
UInt32 numProbs;
|
||||||
|
unsigned tempBufSize;
|
||||||
|
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||||
} CLzmaDec;
|
} CLzmaDec;
|
||||||
|
|
||||||
#define LzmaDec_Construct(p) \
|
#define LzmaDec_CONSTRUCT(p) { (p)->dic = NULL; (p)->probs = NULL; }
|
||||||
{ \
|
#define LzmaDec_Construct(p) LzmaDec_CONSTRUCT(p)
|
||||||
(p)->dic = 0; \
|
|
||||||
(p)->probs = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
void LzmaDec_Init(CLzmaDec* p);
|
void LzmaDec_Init(CLzmaDec *p);
|
||||||
|
|
||||||
/* There are two types of LZMA streams:
|
/* There are two types of LZMA streams:
|
||||||
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
- Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||||
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
- Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
LZMA_FINISH_ANY, /* finish at any point */
|
{
|
||||||
LZMA_FINISH_END /* block must be finished at the end */
|
LZMA_FINISH_ANY, /* finish at any point */
|
||||||
|
LZMA_FINISH_END /* block must be finished at the end */
|
||||||
} ELzmaFinishMode;
|
} ELzmaFinishMode;
|
||||||
|
|
||||||
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
||||||
|
@ -97,16 +103,18 @@ typedef enum {
|
||||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||||
You must use correct finish mode in that case. */
|
You must use correct finish mode in that case. */
|
||||||
|
|
||||||
typedef enum {
|
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_SPECIFIED, /* use main error code instead */
|
||||||
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||||
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
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;
|
||||||
|
|
||||||
/* ELzmaStatus is used only as output value for function call */
|
/* ELzmaStatus is used only as output value for function call */
|
||||||
|
|
||||||
|
|
||||||
/* ---------- Interfaces ---------- */
|
/* ---------- Interfaces ---------- */
|
||||||
|
|
||||||
/* There are 3 levels of interfaces:
|
/* There are 3 levels of interfaces:
|
||||||
|
@ -116,6 +124,7 @@ typedef enum {
|
||||||
You can select any of these interfaces, but don't mix functions from different
|
You can select any of these interfaces, but don't mix functions from different
|
||||||
groups for same object. */
|
groups for same object. */
|
||||||
|
|
||||||
|
|
||||||
/* There are two variants to allocate state for Dictionary Interface:
|
/* There are two variants to allocate state for Dictionary Interface:
|
||||||
1) LzmaDec_Allocate / LzmaDec_Free
|
1) LzmaDec_Allocate / LzmaDec_Free
|
||||||
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
||||||
|
@ -128,11 +137,11 @@ LzmaDec_Allocate* can return:
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaDec_AllocateProbs(CLzmaDec* p, const Byte* props, unsigned propsSize, ISzAlloc* alloc);
|
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||||
void LzmaDec_FreeProbs(CLzmaDec* p, ISzAlloc* alloc);
|
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
|
||||||
|
|
||||||
SRes LzmaDec_Allocate(CLzmaDec* state, const Byte* prop, unsigned propsSize, ISzAlloc* alloc);
|
SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||||
void LzmaDec_Free(CLzmaDec* state, ISzAlloc* alloc);
|
void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
|
||||||
|
|
||||||
/* ---------- Dictionary Interface ---------- */
|
/* ---------- Dictionary Interface ---------- */
|
||||||
|
|
||||||
|
@ -141,7 +150,7 @@ void LzmaDec_Free(CLzmaDec* state, ISzAlloc* alloc);
|
||||||
You must work with CLzmaDec variables directly in this interface.
|
You must work with CLzmaDec variables directly in this interface.
|
||||||
|
|
||||||
STEPS:
|
STEPS:
|
||||||
LzmaDec_Constr()
|
LzmaDec_Construct()
|
||||||
LzmaDec_Allocate()
|
LzmaDec_Allocate()
|
||||||
for (each new stream)
|
for (each new stream)
|
||||||
{
|
{
|
||||||
|
@ -173,10 +182,12 @@ Returns:
|
||||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||||
SZ_ERROR_DATA - Data error
|
SZ_ERROR_DATA - Data error
|
||||||
|
SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaDec_DecodeToDic(CLzmaDec* p, SizeT dicLimit,
|
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
||||||
const Byte* src, SizeT* srcLen, ELzmaFinishMode finishMode, ELzmaStatus* status);
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
/* ---------- Buffer Interface ---------- */
|
/* ---------- Buffer Interface ---------- */
|
||||||
|
|
||||||
|
@ -191,8 +202,9 @@ finishMode:
|
||||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaDec_DecodeToBuf(CLzmaDec* p, Byte* dest, SizeT* destLen,
|
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
||||||
const Byte* src, SizeT* srcLen, ELzmaFinishMode finishMode, ELzmaStatus* status);
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
/* ---------- One Call Interface ---------- */
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
@ -213,14 +225,13 @@ Returns:
|
||||||
SZ_ERROR_MEM - Memory allocation error
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||||
|
SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaDecode(Byte* dest, SizeT* destLen, const Byte* src, SizeT* srcLen,
|
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
const Byte* propData, unsigned propSize, ELzmaFinishMode finishMode,
|
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||||
ELzmaStatus* status, ISzAlloc* alloc);
|
ELzmaStatus *status, ISzAllocPtr alloc);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
EXTERN_C_END
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,17 +1,25 @@
|
||||||
/* Ppmd.h -- PPMD codec common code
|
/* Ppmd.h -- PPMD codec common code
|
||||||
2011-01-27 : Igor Pavlov : Public domain
|
2023-03-05 : Igor Pavlov : Public domain
|
||||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||||
|
|
||||||
#ifndef __PPMD_H
|
#ifndef ZIP7_INC_PPMD_H
|
||||||
#define __PPMD_H
|
#define ZIP7_INC_PPMD_H
|
||||||
|
|
||||||
#include "CpuArch.h"
|
#include "CpuArch.h"
|
||||||
#include "Types.h"
|
|
||||||
|
|
||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
#ifdef MY_CPU_32BIT
|
#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
|
||||||
#define PPMD_32BIT
|
/*
|
||||||
|
PPMD code always uses 32-bit internal fields in PPMD structures to store internal references in main block.
|
||||||
|
if (PPMD_32BIT is defined), the PPMD code stores internal pointers to 32-bit reference fields.
|
||||||
|
if (PPMD_32BIT is NOT defined), the PPMD code stores internal UInt32 offsets to reference fields.
|
||||||
|
if (pointer size is 64-bit), then (PPMD_32BIT) mode is not allowed,
|
||||||
|
if (pointer size is 32-bit), then (PPMD_32BIT) mode is optional,
|
||||||
|
and it's allowed to disable PPMD_32BIT mode even if pointer is 32-bit.
|
||||||
|
PPMD code works slightly faster in (PPMD_32BIT) mode.
|
||||||
|
*/
|
||||||
|
#define PPMD_32BIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PPMD_INT_BITS 7
|
#define PPMD_INT_BITS 7
|
||||||
|
@ -21,7 +29,7 @@ EXTERN_C_BEGIN
|
||||||
#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
|
#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_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_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
|
||||||
#define PPMD_UPDATE_PROB_1(prob) ((prob)-PPMD_GET_MEAN(prob))
|
#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
|
||||||
|
|
||||||
#define PPMD_N1 4
|
#define PPMD_N1 4
|
||||||
#define PPMD_N2 4
|
#define PPMD_N2 4
|
||||||
|
@ -29,64 +37,132 @@ EXTERN_C_BEGIN
|
||||||
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * 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)
|
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
MY_CPU_pragma_pack_push_1
|
||||||
/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */
|
/* 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 */
|
/* SEE-contexts for PPM-contexts with masked symbols */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt16 Summ; /* Freq */
|
UInt16 Summ; /* Freq */
|
||||||
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
|
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
|
||||||
Byte Count; /* Count to next change of Shift */
|
Byte Count; /* Count to next change of Shift */
|
||||||
} CPpmd_See;
|
} CPpmd_See;
|
||||||
|
|
||||||
#define Ppmd_See_Update(p) \
|
#define Ppmd_See_UPDATE(p) \
|
||||||
if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) { \
|
{ if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
|
||||||
(p)->Summ <<= 1; \
|
{ (p)->Summ = (UInt16)((p)->Summ << 1); \
|
||||||
(p)->Count = (Byte)(3 << (p)->Shift++); \
|
(p)->Count = (Byte)(3 << (p)->Shift++); }}
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Byte Symbol;
|
Byte Symbol;
|
||||||
Byte Freq;
|
Byte Freq;
|
||||||
UInt16 SuccessorLow;
|
UInt16 Successor_0;
|
||||||
UInt16 SuccessorHigh;
|
UInt16 Successor_1;
|
||||||
} CPpmd_State;
|
} CPpmd_State;
|
||||||
|
|
||||||
#pragma pack(pop)
|
typedef struct CPpmd_State2_
|
||||||
|
{
|
||||||
|
Byte Symbol;
|
||||||
|
Byte Freq;
|
||||||
|
} CPpmd_State2;
|
||||||
|
|
||||||
|
typedef struct CPpmd_State4_
|
||||||
|
{
|
||||||
|
UInt16 Successor_0;
|
||||||
|
UInt16 Successor_1;
|
||||||
|
} CPpmd_State4;
|
||||||
|
|
||||||
|
MY_CPU_pragma_pop
|
||||||
|
|
||||||
|
/*
|
||||||
|
PPMD code can write full CPpmd_State structure data to CPpmd*_Context
|
||||||
|
at (byte offset = 2) instead of some fields of original CPpmd*_Context structure.
|
||||||
|
|
||||||
|
If we use pointers to different types, but that point to shared
|
||||||
|
memory space, we can have aliasing problem (strict aliasing).
|
||||||
|
|
||||||
|
XLC compiler in -O2 mode can change the order of memory write instructions
|
||||||
|
in relation to read instructions, if we have use pointers to different types.
|
||||||
|
|
||||||
|
To solve that aliasing problem we use combined CPpmd*_Context structure
|
||||||
|
with unions that contain the fields from both structures:
|
||||||
|
the original CPpmd*_Context and CPpmd_State.
|
||||||
|
So we can access the fields from both structures via one pointer,
|
||||||
|
and the compiler doesn't change the order of write instructions
|
||||||
|
in relation to read instructions.
|
||||||
|
|
||||||
|
If we don't use memory write instructions to shared memory in
|
||||||
|
some local code, and we use only reading instructions (read only),
|
||||||
|
then probably it's safe to use pointers to different types for reading.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef
|
|
||||||
#ifdef PPMD_32BIT
|
#ifdef PPMD_32BIT
|
||||||
CPpmd_State*
|
|
||||||
#else
|
|
||||||
UInt32
|
|
||||||
#endif
|
|
||||||
CPpmd_State_Ref;
|
|
||||||
|
|
||||||
typedef
|
#define Ppmd_Ref_Type(type) type *
|
||||||
#ifdef PPMD_32BIT
|
#define Ppmd_GetRef(p, ptr) (ptr)
|
||||||
void*
|
#define Ppmd_GetPtr(p, ptr) (ptr)
|
||||||
#else
|
#define Ppmd_GetPtr_Type(p, ptr, note_type) (ptr)
|
||||||
UInt32
|
|
||||||
#endif
|
|
||||||
CPpmd_Void_Ref;
|
|
||||||
|
|
||||||
typedef
|
|
||||||
#ifdef PPMD_32BIT
|
|
||||||
Byte*
|
|
||||||
#else
|
#else
|
||||||
UInt32
|
|
||||||
#endif
|
|
||||||
CPpmd_Byte_Ref;
|
|
||||||
|
|
||||||
#define PPMD_SetAllBitsIn256Bytes(p) \
|
#define Ppmd_Ref_Type(type) UInt32
|
||||||
{ \
|
#define Ppmd_GetRef(p, ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
|
||||||
unsigned i; \
|
#define Ppmd_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
|
||||||
for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
|
#define Ppmd_GetPtr_Type(p, offs, type) ((type *)Ppmd_GetPtr(p, offs))
|
||||||
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; \
|
|
||||||
} \
|
#endif // PPMD_32BIT
|
||||||
}
|
|
||||||
|
|
||||||
|
typedef Ppmd_Ref_Type(CPpmd_State) CPpmd_State_Ref;
|
||||||
|
typedef Ppmd_Ref_Type(void) CPpmd_Void_Ref;
|
||||||
|
typedef Ppmd_Ref_Type(Byte) CPpmd_Byte_Ref;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
#ifdef MY_CPU_LE_UNALIGN
|
||||||
|
// the unaligned 32-bit access latency can be too large, if the data is not in L1 cache.
|
||||||
|
#define Ppmd_GET_SUCCESSOR(p) ((CPpmd_Void_Ref)*(const UInt32 *)(const void *)&(p)->Successor_0)
|
||||||
|
#define Ppmd_SET_SUCCESSOR(p, v) *(UInt32 *)(void *)(void *)&(p)->Successor_0 = (UInt32)(v)
|
||||||
|
|
||||||
|
#else
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
We can write 16-bit halves to 32-bit (Successor) field in any selected order.
|
||||||
|
But the native order is more consistent way.
|
||||||
|
So we use the native order, if LE/BE order can be detected here at compile time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef MY_CPU_BE
|
||||||
|
|
||||||
|
#define Ppmd_GET_SUCCESSOR(p) \
|
||||||
|
( (CPpmd_Void_Ref) (((UInt32)(p)->Successor_0 << 16) | (p)->Successor_1) )
|
||||||
|
|
||||||
|
#define Ppmd_SET_SUCCESSOR(p, v) { \
|
||||||
|
(p)->Successor_0 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); \
|
||||||
|
(p)->Successor_1 = (UInt16)((UInt32)(v) /* & 0xFFFF */); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define Ppmd_GET_SUCCESSOR(p) \
|
||||||
|
( (CPpmd_Void_Ref) ((p)->Successor_0 | ((UInt32)(p)->Successor_1 << 16)) )
|
||||||
|
|
||||||
|
#define Ppmd_SET_SUCCESSOR(p, v) { \
|
||||||
|
(p)->Successor_0 = (UInt16)((UInt32)(v) /* & 0xFFFF */); \
|
||||||
|
(p)->Successor_1 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
|
||||||
|
#define PPMD_SetAllBitsIn256Bytes(p) \
|
||||||
|
{ size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \
|
||||||
|
p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }}
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +1,11 @@
|
||||||
/* Ppmd7.h -- PPMdH compression codec
|
/* Ppmd7.h -- Ppmd7 (PPMdH) compression codec
|
||||||
2010-03-12 : Igor Pavlov : Public domain
|
2023-04-02 : Igor Pavlov : Public domain
|
||||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : 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
|
#ifndef ZIP7_INC_PPMD7_H
|
||||||
#define __PPMD7_H
|
#define ZIP7_INC_PPMD7_H
|
||||||
|
|
||||||
#include "Ppmd.h"
|
#include "Ppmd.h"
|
||||||
|
|
||||||
|
@ -21,111 +19,162 @@ EXTERN_C_BEGIN
|
||||||
|
|
||||||
struct CPpmd7_Context_;
|
struct CPpmd7_Context_;
|
||||||
|
|
||||||
typedef
|
typedef Ppmd_Ref_Type(struct CPpmd7_Context_) CPpmd7_Context_Ref;
|
||||||
#ifdef PPMD_32BIT
|
|
||||||
struct CPpmd7_Context_*
|
|
||||||
#else
|
|
||||||
UInt32
|
|
||||||
#endif
|
|
||||||
CPpmd7_Context_Ref;
|
|
||||||
|
|
||||||
typedef struct CPpmd7_Context_ {
|
// MY_CPU_pragma_pack_push_1
|
||||||
UInt16 NumStats;
|
|
||||||
|
typedef struct CPpmd7_Context_
|
||||||
|
{
|
||||||
|
UInt16 NumStats;
|
||||||
|
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
UInt16 SummFreq;
|
UInt16 SummFreq;
|
||||||
|
CPpmd_State2 State2;
|
||||||
|
} Union2;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
CPpmd_State_Ref Stats;
|
CPpmd_State_Ref Stats;
|
||||||
CPpmd7_Context_Ref Suffix;
|
CPpmd_State4 State4;
|
||||||
|
} Union4;
|
||||||
|
|
||||||
|
CPpmd7_Context_Ref Suffix;
|
||||||
} CPpmd7_Context;
|
} CPpmd7_Context;
|
||||||
|
|
||||||
#define Ppmd7Context_OneState(p) ((CPpmd_State*)&(p)->SummFreq)
|
// MY_CPU_pragma_pop
|
||||||
|
|
||||||
|
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->Union2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CPpmd7_Context *MinContext, *MaxContext;
|
UInt32 Range;
|
||||||
CPpmd_State* FoundState;
|
UInt32 Code;
|
||||||
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
|
UInt32 Low;
|
||||||
Int32 RunLength, InitRL; /* must be 32-bit at least */
|
IByteInPtr Stream;
|
||||||
|
} CPpmd7_RangeDec;
|
||||||
|
|
||||||
UInt32 Size;
|
|
||||||
UInt32 GlueCount;
|
|
||||||
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
|
|
||||||
UInt32 AlignOffset;
|
|
||||||
|
|
||||||
Byte Indx2Units[PPMD_NUM_INDEXES];
|
typedef struct
|
||||||
Byte Units2Indx[128];
|
{
|
||||||
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
|
UInt32 Range;
|
||||||
Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
|
Byte Cache;
|
||||||
CPpmd_See DummySee, See[25][16];
|
// Byte _dummy_[3];
|
||||||
UInt16 BinSumm[128][64];
|
UInt64 Low;
|
||||||
|
UInt64 CacheSize;
|
||||||
|
IByteOutPtr Stream;
|
||||||
|
} CPpmd7z_RangeEnc;
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
UInt32 AlignOffset;
|
||||||
|
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
CPpmd7_RangeDec dec;
|
||||||
|
CPpmd7z_RangeEnc enc;
|
||||||
|
} rc;
|
||||||
|
|
||||||
|
Byte Indx2Units[PPMD_NUM_INDEXES + 2]; // +2 for alignment
|
||||||
|
Byte Units2Indx[128];
|
||||||
|
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
|
||||||
|
|
||||||
|
Byte NS2BSIndx[256], NS2Indx[256];
|
||||||
|
Byte ExpEscape[16];
|
||||||
|
CPpmd_See DummySee, See[25][16];
|
||||||
|
UInt16 BinSumm[128][64];
|
||||||
|
// int LastSymbol;
|
||||||
} CPpmd7;
|
} CPpmd7;
|
||||||
|
|
||||||
void Ppmd7_Construct(CPpmd7* p);
|
|
||||||
Bool Ppmd7_Alloc(CPpmd7* p, UInt32 size, ISzAlloc* alloc);
|
void Ppmd7_Construct(CPpmd7 *p);
|
||||||
void Ppmd7_Free(CPpmd7* p, ISzAlloc* alloc);
|
BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc);
|
||||||
void Ppmd7_Init(CPpmd7* p, unsigned maxOrder);
|
void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc);
|
||||||
|
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
|
||||||
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
|
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
|
||||||
|
|
||||||
|
|
||||||
/* ---------- Internal Functions ---------- */
|
/* ---------- Internal Functions ---------- */
|
||||||
|
|
||||||
extern const Byte PPMD7_kExpEscape[16];
|
#define Ppmd7_GetPtr(p, ptr) Ppmd_GetPtr(p, ptr)
|
||||||
|
#define Ppmd7_GetContext(p, ptr) Ppmd_GetPtr_Type(p, ptr, CPpmd7_Context)
|
||||||
|
#define Ppmd7_GetStats(p, ctx) Ppmd_GetPtr_Type(p, (ctx)->Union4.Stats, CPpmd_State)
|
||||||
|
|
||||||
#ifdef PPMD_32BIT
|
void Ppmd7_Update1(CPpmd7 *p);
|
||||||
#define Ppmd7_GetPtr(p, ptr) (ptr)
|
void Ppmd7_Update1_0(CPpmd7 *p);
|
||||||
#define Ppmd7_GetContext(p, ptr) (ptr)
|
void Ppmd7_Update2(CPpmd7 *p);
|
||||||
#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);
|
#define PPMD7_HiBitsFlag_3(sym) ((((unsigned)sym + 0xC0) >> (8 - 3)) & (1 << 3))
|
||||||
void Ppmd7_Update1_0(CPpmd7* p);
|
#define PPMD7_HiBitsFlag_4(sym) ((((unsigned)sym + 0xC0) >> (8 - 4)) & (1 << 4))
|
||||||
void Ppmd7_Update2(CPpmd7* p);
|
// #define PPMD7_HiBitsFlag_3(sym) ((sym) < 0x40 ? 0 : (1 << 3))
|
||||||
void Ppmd7_UpdateBin(CPpmd7* p);
|
// #define PPMD7_HiBitsFlag_4(sym) ((sym) < 0x40 ? 0 : (1 << 4))
|
||||||
|
|
||||||
#define Ppmd7_GetBinSumm(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)]
|
&p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1] \
|
||||||
|
[ p->PrevSuccess + ((p->RunLength >> 26) & 0x20) \
|
||||||
|
+ p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] \
|
||||||
|
+ PPMD7_HiBitsFlag_4(Ppmd7Context_OneState(p->MinContext)->Symbol) \
|
||||||
|
+ (p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol)) ]
|
||||||
|
|
||||||
CPpmd_See* Ppmd7_MakeEscFreq(CPpmd7* p, unsigned numMasked, UInt32* scale);
|
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
We support two versions of Ppmd7 (PPMdH) methods that use same CPpmd7 structure:
|
||||||
|
1) Ppmd7a_*: original PPMdH
|
||||||
|
2) Ppmd7z_*: modified PPMdH with 7z Range Coder
|
||||||
|
Ppmd7_*: the structures and functions that are common for both versions of PPMd7 (PPMdH)
|
||||||
|
*/
|
||||||
|
|
||||||
/* ---------- Decode ---------- */
|
/* ---------- Decode ---------- */
|
||||||
|
|
||||||
typedef struct
|
#define PPMD7_SYM_END (-1)
|
||||||
{
|
#define PPMD7_SYM_ERROR (-2)
|
||||||
UInt32 (*GetThreshold)(void* p, UInt32 total);
|
|
||||||
void (*Decode)(void* p, UInt32 start, UInt32 size);
|
|
||||||
UInt32 (*DecodeBit)(void* p, UInt32 size0);
|
|
||||||
} IPpmd7_RangeDec;
|
|
||||||
|
|
||||||
typedef struct
|
/*
|
||||||
{
|
You must set (CPpmd7::rc.dec.Stream) before Ppmd7*_RangeDec_Init()
|
||||||
IPpmd7_RangeDec p;
|
|
||||||
UInt32 Range;
|
|
||||||
UInt32 Code;
|
|
||||||
IByteIn* Stream;
|
|
||||||
} CPpmd7z_RangeDec;
|
|
||||||
|
|
||||||
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec* p);
|
Ppmd7*_DecodeSymbol()
|
||||||
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec* p);
|
out:
|
||||||
|
>= 0 : decoded byte
|
||||||
|
-1 : PPMD7_SYM_END : End of payload marker
|
||||||
|
-2 : PPMD7_SYM_ERROR : Data error
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Ppmd7a_* : original PPMdH */
|
||||||
|
BoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p);
|
||||||
|
#define Ppmd7a_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
||||||
|
int Ppmd7a_DecodeSymbol(CPpmd7 *p);
|
||||||
|
|
||||||
|
/* Ppmd7z_* : modified PPMdH with 7z Range Coder */
|
||||||
|
BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p);
|
||||||
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
||||||
|
int Ppmd7z_DecodeSymbol(CPpmd7 *p);
|
||||||
|
// Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim);
|
||||||
|
|
||||||
int Ppmd7_DecodeSymbol(CPpmd7* p, IPpmd7_RangeDec* rc);
|
|
||||||
|
|
||||||
/* ---------- Encode ---------- */
|
/* ---------- Encode ---------- */
|
||||||
|
|
||||||
typedef struct
|
void Ppmd7z_Init_RangeEnc(CPpmd7 *p);
|
||||||
{
|
void Ppmd7z_Flush_RangeEnc(CPpmd7 *p);
|
||||||
UInt64 Low;
|
// void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol);
|
||||||
UInt32 Range;
|
void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim);
|
||||||
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
|
EXTERN_C_END
|
||||||
|
|
||||||
|
|
|
@ -1,172 +1,312 @@
|
||||||
/* Ppmd7Dec.c -- PPMdH Decoder
|
/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder
|
||||||
2010-03-12 : Igor Pavlov : Public domain
|
2023-09-07 : Igor Pavlov : Public domain
|
||||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
This code is based on:
|
||||||
|
PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||||
|
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
#include "Ppmd7.h"
|
#include "Ppmd7.h"
|
||||||
|
|
||||||
#define kTopValue (1 << 24)
|
#define kTopValue ((UInt32)1 << 24)
|
||||||
|
|
||||||
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec* p)
|
|
||||||
|
#define READ_BYTE(p) IByteIn_Read((p)->Stream)
|
||||||
|
|
||||||
|
BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p)
|
||||||
{
|
{
|
||||||
unsigned _i;
|
unsigned i;
|
||||||
p->Code = 0;
|
p->Code = 0;
|
||||||
p->Range = 0xFFFFFFFF;
|
p->Range = 0xFFFFFFFF;
|
||||||
if (p->Stream->Read((void*)p->Stream) != 0)
|
if (READ_BYTE(p) != 0)
|
||||||
return False;
|
return False;
|
||||||
for (_i = 0; _i < 4; _i++)
|
for (i = 0; i < 4; i++)
|
||||||
p->Code = (p->Code << 8) | p->Stream->Read((void*)p->Stream);
|
p->Code = (p->Code << 8) | READ_BYTE(p);
|
||||||
return (p->Code < 0xFFFFFFFF);
|
return (p->Code < 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UInt32 Range_GetThreshold(void* pp, UInt32 total)
|
#define RC_NORM_BASE(p) if ((p)->Range < kTopValue) \
|
||||||
|
{ (p)->Code = ((p)->Code << 8) | READ_BYTE(p); (p)->Range <<= 8;
|
||||||
|
|
||||||
|
#define RC_NORM_1(p) RC_NORM_BASE(p) }
|
||||||
|
#define RC_NORM(p) RC_NORM_BASE(p) RC_NORM_BASE(p) }}
|
||||||
|
|
||||||
|
// we must use only one type of Normalization from two: LOCAL or REMOTE
|
||||||
|
#define RC_NORM_LOCAL(p) // RC_NORM(p)
|
||||||
|
#define RC_NORM_REMOTE(p) RC_NORM(p)
|
||||||
|
|
||||||
|
#define R (&p->rc.dec)
|
||||||
|
|
||||||
|
Z7_FORCE_INLINE
|
||||||
|
// Z7_NO_INLINE
|
||||||
|
static void Ppmd7z_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size)
|
||||||
{
|
{
|
||||||
CPpmd7z_RangeDec* p = (CPpmd7z_RangeDec*)pp;
|
|
||||||
return (p->Code) / (p->Range /= total);
|
|
||||||
|
R->Code -= start * R->Range;
|
||||||
|
R->Range *= size;
|
||||||
|
RC_NORM_LOCAL(R)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Range_Normalize(CPpmd7z_RangeDec* p)
|
#define RC_Decode(start, size) Ppmd7z_RD_Decode(p, start, size);
|
||||||
|
#define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R)
|
||||||
|
#define RC_GetThreshold(total) (R->Code / (R->Range /= (total)))
|
||||||
|
|
||||||
|
|
||||||
|
#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
|
||||||
|
// typedef CPpmd7_Context * CTX_PTR;
|
||||||
|
#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
|
||||||
|
void Ppmd7_UpdateModel(CPpmd7 *p);
|
||||||
|
|
||||||
|
#define MASK(sym) ((Byte *)charMask)[sym]
|
||||||
|
// Z7_FORCE_INLINE
|
||||||
|
// static
|
||||||
|
int Ppmd7z_DecodeSymbol(CPpmd7 *p)
|
||||||
{
|
{
|
||||||
if (p->Range < kTopValue) {
|
size_t charMask[256 / sizeof(size_t)];
|
||||||
p->Code = (p->Code << 8) | p->Stream->Read((void*)p->Stream);
|
|
||||||
p->Range <<= 8;
|
if (p->MinContext->NumStats != 1)
|
||||||
if (p->Range < kTopValue) {
|
{
|
||||||
p->Code = (p->Code << 8) | p->Stream->Read((void*)p->Stream);
|
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
p->Range <<= 8;
|
unsigned i;
|
||||||
}
|
UInt32 count, hiCnt;
|
||||||
|
const UInt32 summFreq = p->MinContext->Union2.SummFreq;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
count = RC_GetThreshold(summFreq);
|
||||||
|
hiCnt = count;
|
||||||
|
|
||||||
|
if ((Int32)(count -= s->Freq) < 0)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
RC_DecodeFinal(0, s->Freq)
|
||||||
|
p->FoundState = s;
|
||||||
|
sym = s->Symbol;
|
||||||
|
Ppmd7_Update1_0(p);
|
||||||
|
return sym;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void Range_Decode(void* pp, UInt32 start, UInt32 size)
|
p->PrevSuccess = 0;
|
||||||
{
|
i = (unsigned)p->MinContext->NumStats - 1;
|
||||||
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)
|
do
|
||||||
{
|
{
|
||||||
CPpmd7z_RangeDec* p = (CPpmd7z_RangeDec*)pp;
|
if ((Int32)(count -= (++s)->Freq) < 0)
|
||||||
UInt32 newBound = (p->Range >> 14) * size0;
|
{
|
||||||
UInt32 symbol;
|
Byte sym;
|
||||||
if (p->Code < newBound) {
|
RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)
|
||||||
symbol = 0;
|
p->FoundState = s;
|
||||||
p->Range = newBound;
|
sym = s->Symbol;
|
||||||
} else {
|
Ppmd7_Update1(p);
|
||||||
symbol = 1;
|
return sym;
|
||||||
p->Code -= newBound;
|
}
|
||||||
p->Range -= newBound;
|
|
||||||
}
|
}
|
||||||
Range_Normalize(p);
|
while (--i);
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec* p)
|
if (hiCnt >= summFreq)
|
||||||
{
|
return PPMD7_SYM_ERROR;
|
||||||
p->p.GetThreshold = Range_GetThreshold;
|
|
||||||
p->p.Decode = Range_Decode;
|
|
||||||
p->p.DecodeBit = Range_DecodeBit;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MASK(sym) ((signed char*)charMask)[sym]
|
hiCnt -= count;
|
||||||
|
RC_Decode(hiCnt, summFreq - hiCnt)
|
||||||
|
|
||||||
int Ppmd7_DecodeSymbol(CPpmd7* p, IPpmd7_RangeDec* rc)
|
p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol);
|
||||||
{
|
PPMD_SetAllBitsIn256Bytes(charMask)
|
||||||
size_t charMask[256 / sizeof(size_t)];
|
// i = p->MinContext->NumStats - 1;
|
||||||
if (p->MinContext->NumStats != 1) {
|
// do { MASK((--s)->Symbol) = 0; } while (--i);
|
||||||
CPpmd_State* s = Ppmd7_GetStats(p, p->MinContext);
|
{
|
||||||
unsigned _i;
|
CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext);
|
||||||
UInt32 count, hiCnt;
|
MASK(s->Symbol) = 0;
|
||||||
if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) {
|
do
|
||||||
Byte symbol;
|
{
|
||||||
rc->Decode(rc, 0, s->Freq);
|
const unsigned sym0 = s2[0].Symbol;
|
||||||
p->FoundState = s;
|
const unsigned sym1 = s2[1].Symbol;
|
||||||
symbol = s->Symbol;
|
s2 += 2;
|
||||||
Ppmd7_Update1_0(p);
|
MASK(sym0) = 0;
|
||||||
return symbol;
|
MASK(sym1) = 0;
|
||||||
}
|
}
|
||||||
p->PrevSuccess = 0;
|
while (s2 < s);
|
||||||
_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;
|
else
|
||||||
UInt32 freqSum, count, hiCnt;
|
{
|
||||||
CPpmd_See* see;
|
CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
|
||||||
unsigned _i, num, numMasked = p->MinContext->NumStats;
|
UInt16 *prob = Ppmd7_GetBinSumm(p);
|
||||||
do {
|
UInt32 pr = *prob;
|
||||||
p->OrderFall++;
|
UInt32 size0 = (R->Range >> 14) * pr;
|
||||||
if (!p->MinContext->Suffix)
|
pr = PPMD_UPDATE_PROB_1(pr);
|
||||||
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);
|
if (R->Code < size0)
|
||||||
freqSum += hiCnt;
|
{
|
||||||
count = rc->GetThreshold(rc, freqSum);
|
Byte sym;
|
||||||
|
*prob = (UInt16)(pr + (1 << PPMD_INT_BITS));
|
||||||
|
|
||||||
if (count < hiCnt) {
|
// RangeDec_DecodeBit0(size0);
|
||||||
Byte symbol;
|
R->Range = size0;
|
||||||
CPpmd_State** pps = ps;
|
RC_NORM_1(R)
|
||||||
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++)
|
/* we can use single byte normalization here because of
|
||||||
;
|
(min(BinSumm[][]) = 95) > (1 << (14 - 8)) */
|
||||||
s = *pps;
|
|
||||||
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
|
// sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
|
||||||
Ppmd_See_Update(see);
|
// Ppmd7_UpdateBin(p);
|
||||||
p->FoundState = s;
|
{
|
||||||
symbol = s->Symbol;
|
unsigned freq = s->Freq;
|
||||||
Ppmd7_Update2(p);
|
CPpmd7_Context *c = CTX(SUCCESSOR(s));
|
||||||
return symbol;
|
sym = s->Symbol;
|
||||||
}
|
p->FoundState = s;
|
||||||
if (count >= freqSum)
|
p->PrevSuccess = 1;
|
||||||
return -2;
|
p->RunLength++;
|
||||||
rc->Decode(rc, hiCnt, freqSum - hiCnt);
|
s->Freq = (Byte)(freq + (freq < 128));
|
||||||
see->Summ = (UInt16)(see->Summ + freqSum);
|
// NextContext(p);
|
||||||
do {
|
if (p->OrderFall == 0 && (const Byte *)c > p->Text)
|
||||||
MASK(ps[--_i]->Symbol) = 0;
|
p->MaxContext = p->MinContext = c;
|
||||||
} while (_i != 0);
|
else
|
||||||
|
Ppmd7_UpdateModel(p);
|
||||||
|
}
|
||||||
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*prob = (UInt16)pr;
|
||||||
|
p->InitEsc = p->ExpEscape[pr >> 10];
|
||||||
|
|
||||||
|
// RangeDec_DecodeBit1(size0);
|
||||||
|
|
||||||
|
R->Code -= size0;
|
||||||
|
R->Range -= size0;
|
||||||
|
RC_NORM_LOCAL(R)
|
||||||
|
|
||||||
|
PPMD_SetAllBitsIn256Bytes(charMask)
|
||||||
|
MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
CPpmd_State *s, *s2;
|
||||||
|
UInt32 freqSum, count, hiCnt;
|
||||||
|
|
||||||
|
CPpmd_See *see;
|
||||||
|
CPpmd7_Context *mc;
|
||||||
|
unsigned numMasked;
|
||||||
|
RC_NORM_REMOTE(R)
|
||||||
|
mc = p->MinContext;
|
||||||
|
numMasked = mc->NumStats;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p->OrderFall++;
|
||||||
|
if (!mc->Suffix)
|
||||||
|
return PPMD7_SYM_END;
|
||||||
|
mc = Ppmd7_GetContext(p, mc->Suffix);
|
||||||
|
}
|
||||||
|
while (mc->NumStats == numMasked);
|
||||||
|
|
||||||
|
s = Ppmd7_GetStats(p, mc);
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned num = mc->NumStats;
|
||||||
|
unsigned num2 = num / 2;
|
||||||
|
|
||||||
|
num &= 1;
|
||||||
|
hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);
|
||||||
|
s += num;
|
||||||
|
p->MinContext = mc;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const unsigned sym0 = s[0].Symbol;
|
||||||
|
const unsigned sym1 = s[1].Symbol;
|
||||||
|
s += 2;
|
||||||
|
hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));
|
||||||
|
hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));
|
||||||
|
}
|
||||||
|
while (--num2);
|
||||||
|
}
|
||||||
|
|
||||||
|
see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
|
||||||
|
freqSum += hiCnt;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
count = RC_GetThreshold(freqSum);
|
||||||
|
|
||||||
|
if (count < hiCnt)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
|
||||||
|
s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
hiCnt = count;
|
||||||
|
// count -= s->Freq & (UInt32)(MASK(s->Symbol));
|
||||||
|
// if ((Int32)count >= 0)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
|
||||||
|
// count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s--;
|
||||||
|
RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)
|
||||||
|
|
||||||
|
// new (see->Summ) value can overflow over 16-bits in some rare cases
|
||||||
|
Ppmd_See_UPDATE(see)
|
||||||
|
p->FoundState = s;
|
||||||
|
sym = s->Symbol;
|
||||||
|
Ppmd7_Update2(p);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count >= freqSum)
|
||||||
|
return PPMD7_SYM_ERROR;
|
||||||
|
|
||||||
|
RC_Decode(hiCnt, freqSum - hiCnt)
|
||||||
|
|
||||||
|
// We increase (see->Summ) for sum of Freqs of all non_Masked symbols.
|
||||||
|
// new (see->Summ) value can overflow over 16-bits in some rare cases
|
||||||
|
see->Summ = (UInt16)(see->Summ + freqSum);
|
||||||
|
|
||||||
|
s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
s2 = s + p->MinContext->NumStats;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
MASK(s->Symbol) = 0;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
while (s != s2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim)
|
||||||
|
{
|
||||||
|
int sym = 0;
|
||||||
|
if (buf != lim)
|
||||||
|
do
|
||||||
|
{
|
||||||
|
sym = Ppmd7z_DecodeSymbol(p);
|
||||||
|
if (sym < 0)
|
||||||
|
break;
|
||||||
|
*buf = (Byte)sym;
|
||||||
|
}
|
||||||
|
while (++buf < lim);
|
||||||
|
p->LastSymbol = sym;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef kTopValue
|
||||||
|
#undef READ_BYTE
|
||||||
|
#undef RC_NORM_BASE
|
||||||
|
#undef RC_NORM_1
|
||||||
|
#undef RC_NORM
|
||||||
|
#undef RC_NORM_LOCAL
|
||||||
|
#undef RC_NORM_REMOTE
|
||||||
|
#undef R
|
||||||
|
#undef RC_Decode
|
||||||
|
#undef RC_DecodeFinal
|
||||||
|
#undef RC_GetThreshold
|
||||||
|
#undef CTX
|
||||||
|
#undef SUCCESSOR
|
||||||
|
#undef MASK
|
||||||
|
|
|
@ -0,0 +1,295 @@
|
||||||
|
/* Ppmd7aDec.c -- PPMd7a (PPMdH) Decoder
|
||||||
|
2023-09-07 : Igor Pavlov : Public domain
|
||||||
|
This code is based on:
|
||||||
|
PPMd var.H (2001): Dmitry Shkarin : Public domain
|
||||||
|
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Ppmd7.h"
|
||||||
|
|
||||||
|
#define kTop ((UInt32)1 << 24)
|
||||||
|
#define kBot ((UInt32)1 << 15)
|
||||||
|
|
||||||
|
#define READ_BYTE(p) IByteIn_Read((p)->Stream)
|
||||||
|
|
||||||
|
BoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
p->Code = 0;
|
||||||
|
p->Range = 0xFFFFFFFF;
|
||||||
|
p->Low = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
p->Code = (p->Code << 8) | READ_BYTE(p);
|
||||||
|
return (p->Code < 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RC_NORM(p) \
|
||||||
|
while ((p->Low ^ (p->Low + p->Range)) < kTop \
|
||||||
|
|| (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) { \
|
||||||
|
p->Code = (p->Code << 8) | READ_BYTE(p); \
|
||||||
|
p->Range <<= 8; p->Low <<= 8; }
|
||||||
|
|
||||||
|
// we must use only one type of Normalization from two: LOCAL or REMOTE
|
||||||
|
#define RC_NORM_LOCAL(p) // RC_NORM(p)
|
||||||
|
#define RC_NORM_REMOTE(p) RC_NORM(p)
|
||||||
|
|
||||||
|
#define R (&p->rc.dec)
|
||||||
|
|
||||||
|
Z7_FORCE_INLINE
|
||||||
|
// Z7_NO_INLINE
|
||||||
|
static void Ppmd7a_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size)
|
||||||
|
{
|
||||||
|
start *= R->Range;
|
||||||
|
R->Low += start;
|
||||||
|
R->Code -= start;
|
||||||
|
R->Range *= size;
|
||||||
|
RC_NORM_LOCAL(R)
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RC_Decode(start, size) Ppmd7a_RD_Decode(p, start, size);
|
||||||
|
#define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R)
|
||||||
|
#define RC_GetThreshold(total) (R->Code / (R->Range /= (total)))
|
||||||
|
|
||||||
|
|
||||||
|
#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
|
||||||
|
typedef CPpmd7_Context * CTX_PTR;
|
||||||
|
#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
|
||||||
|
void Ppmd7_UpdateModel(CPpmd7 *p);
|
||||||
|
|
||||||
|
#define MASK(sym) ((Byte *)charMask)[sym]
|
||||||
|
|
||||||
|
|
||||||
|
int Ppmd7a_DecodeSymbol(CPpmd7 *p)
|
||||||
|
{
|
||||||
|
size_t charMask[256 / sizeof(size_t)];
|
||||||
|
|
||||||
|
if (p->MinContext->NumStats != 1)
|
||||||
|
{
|
||||||
|
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
unsigned i;
|
||||||
|
UInt32 count, hiCnt;
|
||||||
|
const UInt32 summFreq = p->MinContext->Union2.SummFreq;
|
||||||
|
|
||||||
|
if (summFreq > R->Range)
|
||||||
|
return PPMD7_SYM_ERROR;
|
||||||
|
|
||||||
|
count = RC_GetThreshold(summFreq);
|
||||||
|
hiCnt = count;
|
||||||
|
|
||||||
|
if ((Int32)(count -= s->Freq) < 0)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
RC_DecodeFinal(0, s->Freq)
|
||||||
|
p->FoundState = s;
|
||||||
|
sym = s->Symbol;
|
||||||
|
Ppmd7_Update1_0(p);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
i = (unsigned)p->MinContext->NumStats - 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((Int32)(count -= (++s)->Freq) < 0)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)
|
||||||
|
p->FoundState = s;
|
||||||
|
sym = s->Symbol;
|
||||||
|
Ppmd7_Update1(p);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (--i);
|
||||||
|
|
||||||
|
if (hiCnt >= summFreq)
|
||||||
|
return PPMD7_SYM_ERROR;
|
||||||
|
|
||||||
|
hiCnt -= count;
|
||||||
|
RC_Decode(hiCnt, summFreq - hiCnt)
|
||||||
|
|
||||||
|
p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol);
|
||||||
|
PPMD_SetAllBitsIn256Bytes(charMask)
|
||||||
|
// i = p->MinContext->NumStats - 1;
|
||||||
|
// do { MASK((--s)->Symbol) = 0; } while (--i);
|
||||||
|
{
|
||||||
|
CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
MASK(s->Symbol) = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const unsigned sym0 = s2[0].Symbol;
|
||||||
|
const unsigned sym1 = s2[1].Symbol;
|
||||||
|
s2 += 2;
|
||||||
|
MASK(sym0) = 0;
|
||||||
|
MASK(sym1) = 0;
|
||||||
|
}
|
||||||
|
while (s2 < s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
|
||||||
|
UInt16 *prob = Ppmd7_GetBinSumm(p);
|
||||||
|
UInt32 pr = *prob;
|
||||||
|
UInt32 size0 = (R->Range >> 14) * pr;
|
||||||
|
pr = PPMD_UPDATE_PROB_1(pr);
|
||||||
|
|
||||||
|
if (R->Code < size0)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
*prob = (UInt16)(pr + (1 << PPMD_INT_BITS));
|
||||||
|
|
||||||
|
// RangeDec_DecodeBit0(size0);
|
||||||
|
R->Range = size0;
|
||||||
|
RC_NORM(R)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
|
||||||
|
// Ppmd7_UpdateBin(p);
|
||||||
|
{
|
||||||
|
unsigned freq = s->Freq;
|
||||||
|
CTX_PTR c = CTX(SUCCESSOR(s));
|
||||||
|
sym = s->Symbol;
|
||||||
|
p->FoundState = s;
|
||||||
|
p->PrevSuccess = 1;
|
||||||
|
p->RunLength++;
|
||||||
|
s->Freq = (Byte)(freq + (freq < 128));
|
||||||
|
// NextContext(p);
|
||||||
|
if (p->OrderFall == 0 && (const Byte *)c > p->Text)
|
||||||
|
p->MaxContext = p->MinContext = c;
|
||||||
|
else
|
||||||
|
Ppmd7_UpdateModel(p);
|
||||||
|
}
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
*prob = (UInt16)pr;
|
||||||
|
p->InitEsc = p->ExpEscape[pr >> 10];
|
||||||
|
|
||||||
|
// RangeDec_DecodeBit1(size0);
|
||||||
|
R->Low += size0;
|
||||||
|
R->Code -= size0;
|
||||||
|
R->Range = (R->Range & ~((UInt32)PPMD_BIN_SCALE - 1)) - size0;
|
||||||
|
RC_NORM_LOCAL(R)
|
||||||
|
|
||||||
|
PPMD_SetAllBitsIn256Bytes(charMask)
|
||||||
|
MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
CPpmd_State *s, *s2;
|
||||||
|
UInt32 freqSum, count, hiCnt;
|
||||||
|
|
||||||
|
CPpmd_See *see;
|
||||||
|
CPpmd7_Context *mc;
|
||||||
|
unsigned numMasked;
|
||||||
|
RC_NORM_REMOTE(R)
|
||||||
|
mc = p->MinContext;
|
||||||
|
numMasked = mc->NumStats;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p->OrderFall++;
|
||||||
|
if (!mc->Suffix)
|
||||||
|
return PPMD7_SYM_END;
|
||||||
|
mc = Ppmd7_GetContext(p, mc->Suffix);
|
||||||
|
}
|
||||||
|
while (mc->NumStats == numMasked);
|
||||||
|
|
||||||
|
s = Ppmd7_GetStats(p, mc);
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned num = mc->NumStats;
|
||||||
|
unsigned num2 = num / 2;
|
||||||
|
|
||||||
|
num &= 1;
|
||||||
|
hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);
|
||||||
|
s += num;
|
||||||
|
p->MinContext = mc;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const unsigned sym0 = s[0].Symbol;
|
||||||
|
const unsigned sym1 = s[1].Symbol;
|
||||||
|
s += 2;
|
||||||
|
hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));
|
||||||
|
hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));
|
||||||
|
}
|
||||||
|
while (--num2);
|
||||||
|
}
|
||||||
|
|
||||||
|
see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
|
||||||
|
freqSum += hiCnt;
|
||||||
|
|
||||||
|
if (freqSum > R->Range)
|
||||||
|
return PPMD7_SYM_ERROR;
|
||||||
|
|
||||||
|
count = RC_GetThreshold(freqSum);
|
||||||
|
|
||||||
|
if (count < hiCnt)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
|
||||||
|
s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
hiCnt = count;
|
||||||
|
// count -= s->Freq & (UInt32)(MASK(s->Symbol));
|
||||||
|
// if ((Int32)count >= 0)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
|
||||||
|
// count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s--;
|
||||||
|
RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)
|
||||||
|
|
||||||
|
// new (see->Summ) value can overflow over 16-bits in some rare cases
|
||||||
|
Ppmd_See_UPDATE(see)
|
||||||
|
p->FoundState = s;
|
||||||
|
sym = s->Symbol;
|
||||||
|
Ppmd7_Update2(p);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count >= freqSum)
|
||||||
|
return PPMD7_SYM_ERROR;
|
||||||
|
|
||||||
|
RC_Decode(hiCnt, freqSum - hiCnt)
|
||||||
|
|
||||||
|
// We increase (see->Summ) for sum of Freqs of all non_Masked symbols.
|
||||||
|
// new (see->Summ) value can overflow over 16-bits in some rare cases
|
||||||
|
see->Summ = (UInt16)(see->Summ + freqSum);
|
||||||
|
|
||||||
|
s = Ppmd7_GetStats(p, p->MinContext);
|
||||||
|
s2 = s + p->MinContext->NumStats;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
MASK(s->Symbol) = 0;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
while (s != s2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef kTop
|
||||||
|
#undef kBot
|
||||||
|
#undef READ_BYTE
|
||||||
|
#undef RC_NORM_BASE
|
||||||
|
#undef RC_NORM_1
|
||||||
|
#undef RC_NORM
|
||||||
|
#undef RC_NORM_LOCAL
|
||||||
|
#undef RC_NORM_REMOTE
|
||||||
|
#undef R
|
||||||
|
#undef RC_Decode
|
||||||
|
#undef RC_DecodeFinal
|
||||||
|
#undef RC_GetThreshold
|
||||||
|
#undef CTX
|
||||||
|
#undef SUCCESSOR
|
||||||
|
#undef MASK
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,181 @@
|
||||||
|
/* Ppmd8.h -- Ppmd8 (PPMdI) compression codec
|
||||||
|
2023-04-02 : Igor Pavlov : Public domain
|
||||||
|
This code is based on:
|
||||||
|
PPMd var.I (2002): Dmitry Shkarin : Public domain
|
||||||
|
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
|
||||||
|
|
||||||
|
#ifndef ZIP7_INC_PPMD8_H
|
||||||
|
#define ZIP7_INC_PPMD8_H
|
||||||
|
|
||||||
|
#include "Ppmd.h"
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
#define PPMD8_MIN_ORDER 2
|
||||||
|
#define PPMD8_MAX_ORDER 16
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct CPpmd8_Context_;
|
||||||
|
|
||||||
|
typedef Ppmd_Ref_Type(struct CPpmd8_Context_) CPpmd8_Context_Ref;
|
||||||
|
|
||||||
|
// MY_CPU_pragma_pack_push_1
|
||||||
|
|
||||||
|
typedef struct CPpmd8_Context_
|
||||||
|
{
|
||||||
|
Byte NumStats;
|
||||||
|
Byte Flags;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
UInt16 SummFreq;
|
||||||
|
CPpmd_State2 State2;
|
||||||
|
} Union2;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
CPpmd_State_Ref Stats;
|
||||||
|
CPpmd_State4 State4;
|
||||||
|
} Union4;
|
||||||
|
|
||||||
|
CPpmd8_Context_Ref Suffix;
|
||||||
|
} CPpmd8_Context;
|
||||||
|
|
||||||
|
// MY_CPU_pragma_pop
|
||||||
|
|
||||||
|
#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->Union2)
|
||||||
|
|
||||||
|
/* PPMdI code rev.2 contains the fix over PPMdI code rev.1.
|
||||||
|
But the code PPMdI.2 is not compatible with PPMdI.1 for some files compressed
|
||||||
|
in FREEZE mode. So we disable FREEZE mode support. */
|
||||||
|
|
||||||
|
// #define PPMD8_FREEZE_SUPPORT
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PPMD8_RESTORE_METHOD_RESTART,
|
||||||
|
PPMD8_RESTORE_METHOD_CUT_OFF
|
||||||
|
#ifdef PPMD8_FREEZE_SUPPORT
|
||||||
|
, PPMD8_RESTORE_METHOD_FREEZE
|
||||||
|
#endif
|
||||||
|
, PPMD8_RESTORE_METHOD_UNSUPPPORTED
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CPpmd8_Context *MinContext, *MaxContext;
|
||||||
|
CPpmd_State *FoundState;
|
||||||
|
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, RestoreMethod;
|
||||||
|
Int32 RunLength, InitRL; /* must be 32-bit at least */
|
||||||
|
|
||||||
|
UInt32 Size;
|
||||||
|
UInt32 GlueCount;
|
||||||
|
UInt32 AlignOffset;
|
||||||
|
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
|
||||||
|
|
||||||
|
UInt32 Range;
|
||||||
|
UInt32 Code;
|
||||||
|
UInt32 Low;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
IByteInPtr In;
|
||||||
|
IByteOutPtr Out;
|
||||||
|
} Stream;
|
||||||
|
|
||||||
|
Byte Indx2Units[PPMD_NUM_INDEXES + 2]; // +2 for alignment
|
||||||
|
Byte Units2Indx[128];
|
||||||
|
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
|
||||||
|
UInt32 Stamps[PPMD_NUM_INDEXES];
|
||||||
|
Byte NS2BSIndx[256], NS2Indx[260];
|
||||||
|
Byte ExpEscape[16];
|
||||||
|
CPpmd_See DummySee, See[24][32];
|
||||||
|
UInt16 BinSumm[25][64];
|
||||||
|
|
||||||
|
} CPpmd8;
|
||||||
|
|
||||||
|
|
||||||
|
void Ppmd8_Construct(CPpmd8 *p);
|
||||||
|
BoolInt Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAllocPtr alloc);
|
||||||
|
void Ppmd8_Free(CPpmd8 *p, ISzAllocPtr alloc);
|
||||||
|
void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod);
|
||||||
|
#define Ppmd8_WasAllocated(p) ((p)->Base != NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Internal Functions ---------- */
|
||||||
|
|
||||||
|
#define Ppmd8_GetPtr(p, ptr) Ppmd_GetPtr(p, ptr)
|
||||||
|
#define Ppmd8_GetContext(p, ptr) Ppmd_GetPtr_Type(p, ptr, CPpmd8_Context)
|
||||||
|
#define Ppmd8_GetStats(p, ctx) Ppmd_GetPtr_Type(p, (ctx)->Union4.Stats, CPpmd_State)
|
||||||
|
|
||||||
|
void Ppmd8_Update1(CPpmd8 *p);
|
||||||
|
void Ppmd8_Update1_0(CPpmd8 *p);
|
||||||
|
void Ppmd8_Update2(CPpmd8 *p);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define Ppmd8_GetBinSumm(p) \
|
||||||
|
&p->BinSumm[p->NS2Indx[(size_t)Ppmd8Context_OneState(p->MinContext)->Freq - 1]] \
|
||||||
|
[ p->PrevSuccess + ((p->RunLength >> 26) & 0x20) \
|
||||||
|
+ p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \
|
||||||
|
+ p->MinContext->Flags ]
|
||||||
|
|
||||||
|
|
||||||
|
CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale);
|
||||||
|
|
||||||
|
|
||||||
|
/* 20.01: the original PPMdI encoder and decoder probably could work incorrectly in some rare cases,
|
||||||
|
where the original PPMdI code can give "Divide by Zero" operation.
|
||||||
|
We use the following fix to allow correct working of encoder and decoder in any cases.
|
||||||
|
We correct (Escape_Freq) and (_sum_), if (_sum_) is larger than p->Range) */
|
||||||
|
#define PPMD8_CORRECT_SUM_RANGE(p, _sum_) if (_sum_ > p->Range /* /1 */) _sum_ = p->Range;
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Decode ---------- */
|
||||||
|
|
||||||
|
#define PPMD8_SYM_END (-1)
|
||||||
|
#define PPMD8_SYM_ERROR (-2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
You must set (CPpmd8::Stream.In) before Ppmd8_RangeDec_Init()
|
||||||
|
|
||||||
|
Ppmd8_DecodeSymbol()
|
||||||
|
out:
|
||||||
|
>= 0 : decoded byte
|
||||||
|
-1 : PPMD8_SYM_END : End of payload marker
|
||||||
|
-2 : PPMD8_SYM_ERROR : Data error
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
BoolInt Ppmd8_Init_RangeDec(CPpmd8 *p);
|
||||||
|
#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
||||||
|
int Ppmd8_DecodeSymbol(CPpmd8 *p);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Encode ---------- */
|
||||||
|
|
||||||
|
#define Ppmd8_Init_RangeEnc(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; }
|
||||||
|
void Ppmd8_Flush_RangeEnc(CPpmd8 *p);
|
||||||
|
void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol);
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_C_END
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,295 @@
|
||||||
|
/* Ppmd8Dec.c -- Ppmd8 (PPMdI) Decoder
|
||||||
|
2023-09-07 : Igor Pavlov : Public domain
|
||||||
|
This code is based on:
|
||||||
|
PPMd var.I (2002): Dmitry Shkarin : Public domain
|
||||||
|
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
|
||||||
|
|
||||||
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
#include "Ppmd8.h"
|
||||||
|
|
||||||
|
#define kTop ((UInt32)1 << 24)
|
||||||
|
#define kBot ((UInt32)1 << 15)
|
||||||
|
|
||||||
|
#define READ_BYTE(p) IByteIn_Read((p)->Stream.In)
|
||||||
|
|
||||||
|
BoolInt Ppmd8_Init_RangeDec(CPpmd8 *p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
p->Code = 0;
|
||||||
|
p->Range = 0xFFFFFFFF;
|
||||||
|
p->Low = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
p->Code = (p->Code << 8) | READ_BYTE(p);
|
||||||
|
return (p->Code < 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RC_NORM(p) \
|
||||||
|
while ((p->Low ^ (p->Low + p->Range)) < kTop \
|
||||||
|
|| (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) { \
|
||||||
|
p->Code = (p->Code << 8) | READ_BYTE(p); \
|
||||||
|
p->Range <<= 8; p->Low <<= 8; }
|
||||||
|
|
||||||
|
// we must use only one type of Normalization from two: LOCAL or REMOTE
|
||||||
|
#define RC_NORM_LOCAL(p) // RC_NORM(p)
|
||||||
|
#define RC_NORM_REMOTE(p) RC_NORM(p)
|
||||||
|
|
||||||
|
#define R p
|
||||||
|
|
||||||
|
Z7_FORCE_INLINE
|
||||||
|
// Z7_NO_INLINE
|
||||||
|
static void Ppmd8_RD_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
|
||||||
|
{
|
||||||
|
start *= R->Range;
|
||||||
|
R->Low += start;
|
||||||
|
R->Code -= start;
|
||||||
|
R->Range *= size;
|
||||||
|
RC_NORM_LOCAL(R)
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RC_Decode(start, size) Ppmd8_RD_Decode(p, start, size);
|
||||||
|
#define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R)
|
||||||
|
#define RC_GetThreshold(total) (R->Code / (R->Range /= (total)))
|
||||||
|
|
||||||
|
|
||||||
|
#define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref))
|
||||||
|
// typedef CPpmd8_Context * CTX_PTR;
|
||||||
|
#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
|
||||||
|
void Ppmd8_UpdateModel(CPpmd8 *p);
|
||||||
|
|
||||||
|
#define MASK(sym) ((Byte *)charMask)[sym]
|
||||||
|
|
||||||
|
|
||||||
|
int Ppmd8_DecodeSymbol(CPpmd8 *p)
|
||||||
|
{
|
||||||
|
size_t charMask[256 / sizeof(size_t)];
|
||||||
|
|
||||||
|
if (p->MinContext->NumStats != 0)
|
||||||
|
{
|
||||||
|
CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
|
||||||
|
unsigned i;
|
||||||
|
UInt32 count, hiCnt;
|
||||||
|
UInt32 summFreq = p->MinContext->Union2.SummFreq;
|
||||||
|
|
||||||
|
PPMD8_CORRECT_SUM_RANGE(p, summFreq)
|
||||||
|
|
||||||
|
|
||||||
|
count = RC_GetThreshold(summFreq);
|
||||||
|
hiCnt = count;
|
||||||
|
|
||||||
|
if ((Int32)(count -= s->Freq) < 0)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
RC_DecodeFinal(0, s->Freq)
|
||||||
|
p->FoundState = s;
|
||||||
|
sym = s->Symbol;
|
||||||
|
Ppmd8_Update1_0(p);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
i = p->MinContext->NumStats;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((Int32)(count -= (++s)->Freq) < 0)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)
|
||||||
|
p->FoundState = s;
|
||||||
|
sym = s->Symbol;
|
||||||
|
Ppmd8_Update1(p);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (--i);
|
||||||
|
|
||||||
|
if (hiCnt >= summFreq)
|
||||||
|
return PPMD8_SYM_ERROR;
|
||||||
|
|
||||||
|
hiCnt -= count;
|
||||||
|
RC_Decode(hiCnt, summFreq - hiCnt)
|
||||||
|
|
||||||
|
|
||||||
|
PPMD_SetAllBitsIn256Bytes(charMask)
|
||||||
|
// i = p->MinContext->NumStats - 1;
|
||||||
|
// do { MASK((--s)->Symbol) = 0; } while (--i);
|
||||||
|
{
|
||||||
|
CPpmd_State *s2 = Ppmd8_GetStats(p, p->MinContext);
|
||||||
|
MASK(s->Symbol) = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const unsigned sym0 = s2[0].Symbol;
|
||||||
|
const unsigned sym1 = s2[1].Symbol;
|
||||||
|
s2 += 2;
|
||||||
|
MASK(sym0) = 0;
|
||||||
|
MASK(sym1) = 0;
|
||||||
|
}
|
||||||
|
while (s2 < s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPpmd_State *s = Ppmd8Context_OneState(p->MinContext);
|
||||||
|
UInt16 *prob = Ppmd8_GetBinSumm(p);
|
||||||
|
UInt32 pr = *prob;
|
||||||
|
UInt32 size0 = (R->Range >> 14) * pr;
|
||||||
|
pr = PPMD_UPDATE_PROB_1(pr);
|
||||||
|
|
||||||
|
if (R->Code < size0)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
*prob = (UInt16)(pr + (1 << PPMD_INT_BITS));
|
||||||
|
|
||||||
|
// RangeDec_DecodeBit0(size0);
|
||||||
|
R->Range = size0;
|
||||||
|
RC_NORM(R)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// sym = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol;
|
||||||
|
// Ppmd8_UpdateBin(p);
|
||||||
|
{
|
||||||
|
unsigned freq = s->Freq;
|
||||||
|
CPpmd8_Context *c = CTX(SUCCESSOR(s));
|
||||||
|
sym = s->Symbol;
|
||||||
|
p->FoundState = s;
|
||||||
|
p->PrevSuccess = 1;
|
||||||
|
p->RunLength++;
|
||||||
|
s->Freq = (Byte)(freq + (freq < 196));
|
||||||
|
// NextContext(p);
|
||||||
|
if (p->OrderFall == 0 && (const Byte *)c >= p->UnitsStart)
|
||||||
|
p->MaxContext = p->MinContext = c;
|
||||||
|
else
|
||||||
|
Ppmd8_UpdateModel(p);
|
||||||
|
}
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
*prob = (UInt16)pr;
|
||||||
|
p->InitEsc = p->ExpEscape[pr >> 10];
|
||||||
|
|
||||||
|
// RangeDec_DecodeBit1(rc2, size0);
|
||||||
|
R->Low += size0;
|
||||||
|
R->Code -= size0;
|
||||||
|
R->Range = (R->Range & ~((UInt32)PPMD_BIN_SCALE - 1)) - size0;
|
||||||
|
RC_NORM_LOCAL(R)
|
||||||
|
|
||||||
|
PPMD_SetAllBitsIn256Bytes(charMask)
|
||||||
|
MASK(Ppmd8Context_OneState(p->MinContext)->Symbol) = 0;
|
||||||
|
p->PrevSuccess = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
CPpmd_State *s, *s2;
|
||||||
|
UInt32 freqSum, count, hiCnt;
|
||||||
|
UInt32 freqSum2;
|
||||||
|
CPpmd_See *see;
|
||||||
|
CPpmd8_Context *mc;
|
||||||
|
unsigned numMasked;
|
||||||
|
RC_NORM_REMOTE(R)
|
||||||
|
mc = p->MinContext;
|
||||||
|
numMasked = mc->NumStats;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p->OrderFall++;
|
||||||
|
if (!mc->Suffix)
|
||||||
|
return PPMD8_SYM_END;
|
||||||
|
mc = Ppmd8_GetContext(p, mc->Suffix);
|
||||||
|
}
|
||||||
|
while (mc->NumStats == numMasked);
|
||||||
|
|
||||||
|
s = Ppmd8_GetStats(p, mc);
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned num = (unsigned)mc->NumStats + 1;
|
||||||
|
unsigned num2 = num / 2;
|
||||||
|
|
||||||
|
num &= 1;
|
||||||
|
hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);
|
||||||
|
s += num;
|
||||||
|
p->MinContext = mc;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const unsigned sym0 = s[0].Symbol;
|
||||||
|
const unsigned sym1 = s[1].Symbol;
|
||||||
|
s += 2;
|
||||||
|
hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));
|
||||||
|
hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));
|
||||||
|
}
|
||||||
|
while (--num2);
|
||||||
|
}
|
||||||
|
|
||||||
|
see = Ppmd8_MakeEscFreq(p, numMasked, &freqSum);
|
||||||
|
freqSum += hiCnt;
|
||||||
|
freqSum2 = freqSum;
|
||||||
|
PPMD8_CORRECT_SUM_RANGE(R, freqSum2)
|
||||||
|
|
||||||
|
|
||||||
|
count = RC_GetThreshold(freqSum2);
|
||||||
|
|
||||||
|
if (count < hiCnt)
|
||||||
|
{
|
||||||
|
Byte sym;
|
||||||
|
// Ppmd_See_UPDATE(see) // new (see->Summ) value can overflow over 16-bits in some rare cases
|
||||||
|
s = Ppmd8_GetStats(p, p->MinContext);
|
||||||
|
hiCnt = count;
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
|
||||||
|
// count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s--;
|
||||||
|
RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)
|
||||||
|
|
||||||
|
// new (see->Summ) value can overflow over 16-bits in some rare cases
|
||||||
|
Ppmd_See_UPDATE(see)
|
||||||
|
p->FoundState = s;
|
||||||
|
sym = s->Symbol;
|
||||||
|
Ppmd8_Update2(p);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count >= freqSum2)
|
||||||
|
return PPMD8_SYM_ERROR;
|
||||||
|
|
||||||
|
RC_Decode(hiCnt, freqSum2 - hiCnt)
|
||||||
|
|
||||||
|
// We increase (see->Summ) for sum of Freqs of all non_Masked symbols.
|
||||||
|
// new (see->Summ) value can overflow over 16-bits in some rare cases
|
||||||
|
see->Summ = (UInt16)(see->Summ + freqSum);
|
||||||
|
|
||||||
|
s = Ppmd8_GetStats(p, p->MinContext);
|
||||||
|
s2 = s + p->MinContext->NumStats + 1;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
MASK(s->Symbol) = 0;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
while (s != s2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef kTop
|
||||||
|
#undef kBot
|
||||||
|
#undef READ_BYTE
|
||||||
|
#undef RC_NORM_BASE
|
||||||
|
#undef RC_NORM_1
|
||||||
|
#undef RC_NORM
|
||||||
|
#undef RC_NORM_LOCAL
|
||||||
|
#undef RC_NORM_REMOTE
|
||||||
|
#undef R
|
||||||
|
#undef RC_Decode
|
||||||
|
#undef RC_DecodeFinal
|
||||||
|
#undef RC_GetThreshold
|
||||||
|
#undef CTX
|
||||||
|
#undef SUCCESSOR
|
||||||
|
#undef MASK
|
|
@ -0,0 +1,127 @@
|
||||||
|
/* Precomp.h -- precompilation file
|
||||||
|
2024-01-25 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef ZIP7_INC_PRECOMP_H
|
||||||
|
#define ZIP7_INC_PRECOMP_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
this file must be included before another *.h files and before <windows.h>.
|
||||||
|
this file is included from the following files:
|
||||||
|
C\*.c
|
||||||
|
C\Util\*\Precomp.h <- C\Util\*\*.c
|
||||||
|
CPP\Common\Common.h <- *\StdAfx.h <- *\*.cpp
|
||||||
|
|
||||||
|
this file can set the following macros:
|
||||||
|
Z7_LARGE_PAGES 1
|
||||||
|
Z7_LONG_PATH 1
|
||||||
|
Z7_WIN32_WINNT_MIN 0x0500 (or higher) : we require at least win2000+ for 7-Zip
|
||||||
|
_WIN32_WINNT 0x0500 (or higher)
|
||||||
|
WINVER _WIN32_WINNT
|
||||||
|
UNICODE 1
|
||||||
|
_UNICODE 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Compiler.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// #pragma warning(disable : 4206) // nonstandard extension used : translation unit is empty
|
||||||
|
#if _MSC_VER >= 1912
|
||||||
|
// #pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern "C"' function under - EHc.Undefined behavior may occur if this function throws an exception.
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
// for debug:
|
||||||
|
#define UNICODE 1
|
||||||
|
#define _UNICODE 1
|
||||||
|
#define _WIN32_WINNT 0x0500 // win2000
|
||||||
|
#ifndef WINVER
|
||||||
|
#define WINVER _WIN32_WINNT
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/*
|
||||||
|
this "Precomp.h" file must be included before <windows.h>,
|
||||||
|
if we want to define _WIN32_WINNT before <windows.h>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Z7_LARGE_PAGES
|
||||||
|
#ifndef Z7_NO_LARGE_PAGES
|
||||||
|
#define Z7_LARGE_PAGES 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Z7_LONG_PATH
|
||||||
|
#ifndef Z7_NO_LONG_PATH
|
||||||
|
#define Z7_LONG_PATH 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Z7_DEVICE_FILE
|
||||||
|
#ifndef Z7_NO_DEVICE_FILE
|
||||||
|
// #define Z7_DEVICE_FILE 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// we don't change macros if included after <windows.h>
|
||||||
|
#ifndef _WINDOWS_
|
||||||
|
|
||||||
|
#ifndef Z7_WIN32_WINNT_MIN
|
||||||
|
#if defined(_M_ARM64) || defined(__aarch64__)
|
||||||
|
// #define Z7_WIN32_WINNT_MIN 0x0a00 // win10
|
||||||
|
#define Z7_WIN32_WINNT_MIN 0x0600 // vista
|
||||||
|
#elif defined(_M_ARM) && defined(_M_ARMT) && defined(_M_ARM_NT)
|
||||||
|
// #define Z7_WIN32_WINNT_MIN 0x0602 // win8
|
||||||
|
#define Z7_WIN32_WINNT_MIN 0x0600 // vista
|
||||||
|
#elif defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IA64)
|
||||||
|
#define Z7_WIN32_WINNT_MIN 0x0503 // win2003
|
||||||
|
// #elif defined(_M_IX86) || defined(__i386__)
|
||||||
|
// #define Z7_WIN32_WINNT_MIN 0x0500 // win2000
|
||||||
|
#else // x86 and another(old) systems
|
||||||
|
#define Z7_WIN32_WINNT_MIN 0x0500 // win2000
|
||||||
|
// #define Z7_WIN32_WINNT_MIN 0x0502 // win2003 // for debug
|
||||||
|
#endif
|
||||||
|
#endif // Z7_WIN32_WINNT_MIN
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef Z7_DO_NOT_DEFINE_WIN32_WINNT
|
||||||
|
#ifdef _WIN32_WINNT
|
||||||
|
// #error Stop_Compiling_Bad_WIN32_WINNT
|
||||||
|
#else
|
||||||
|
#ifndef Z7_NO_DEFINE_WIN32_WINNT
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#define _WIN32_WINNT Z7_WIN32_WINNT_MIN
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#endif
|
||||||
|
#endif // _WIN32_WINNT
|
||||||
|
|
||||||
|
#ifndef WINVER
|
||||||
|
#define WINVER _WIN32_WINNT
|
||||||
|
#endif
|
||||||
|
#endif // Z7_DO_NOT_DEFINE_WIN32_WINNT
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _MBCS
|
||||||
|
#ifndef Z7_NO_UNICODE
|
||||||
|
// UNICODE and _UNICODE are used by <windows.h> and by 7-zip code.
|
||||||
|
|
||||||
|
#ifndef UNICODE
|
||||||
|
#define UNICODE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _UNICODE
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#define _UNICODE 1
|
||||||
|
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // Z7_NO_UNICODE
|
||||||
|
#endif // _MBCS
|
||||||
|
#endif // _WINDOWS_
|
||||||
|
|
||||||
|
// #include "7zWindows.h"
|
||||||
|
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* RotateDefs.h -- Rotate functions
|
||||||
|
2023-06-18 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef ZIP7_INC_ROTATE_DEFS_H
|
||||||
|
#define ZIP7_INC_ROTATE_DEFS_H
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* don't use _rotl with old MINGW. It can insert slow call to function. */
|
||||||
|
|
||||||
|
/* #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))
|
||||||
|
|
||||||
|
#if (_MSC_VER >= 1300)
|
||||||
|
#define Z7_ROTL64(x, n) _rotl64((x), (n))
|
||||||
|
#define Z7_ROTR64(x, n) _rotr64((x), (n))
|
||||||
|
#else
|
||||||
|
#define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
|
||||||
|
#define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* new compilers can translate these macros to fast commands. */
|
||||||
|
|
||||||
|
#if defined(__clang__) && (__clang_major__ >= 4) \
|
||||||
|
|| defined(__GNUC__) && (__GNUC__ >= 5)
|
||||||
|
/* GCC 4.9.0 and clang 3.5 can recognize more correct version: */
|
||||||
|
#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (-(n) & 31)))
|
||||||
|
#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (-(n) & 31)))
|
||||||
|
#define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (-(n) & 63)))
|
||||||
|
#define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (-(n) & 63)))
|
||||||
|
#else
|
||||||
|
/* for old GCC / clang: */
|
||||||
|
#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||||
|
#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
|
||||||
|
#define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
|
||||||
|
#define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,256 +0,0 @@
|
||||||
/* Types.h -- Basic types
|
|
||||||
2010-10-09 : Igor Pavlov : Public domain */
|
|
||||||
|
|
||||||
#ifndef __7Z_TYPES_H
|
|
||||||
#define __7Z_TYPES_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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;
|
|
||||||
#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_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
|
|
|
@ -15,7 +15,7 @@ target_sources(vbam-fex
|
||||||
7z_C/7zCrc.h
|
7z_C/7zCrc.h
|
||||||
7z_C/7zCrcOpt.c
|
7z_C/7zCrcOpt.c
|
||||||
7z_C/7zDec.c
|
7z_C/7zDec.c
|
||||||
7z_C/7zIn.c
|
7z_C/7zArcIn.c
|
||||||
7z_C/7zStream.c
|
7z_C/7zStream.c
|
||||||
7z_C/Bcj2.c
|
7z_C/Bcj2.c
|
||||||
7z_C/Bcj2.h
|
7z_C/Bcj2.h
|
||||||
|
@ -24,6 +24,8 @@ target_sources(vbam-fex
|
||||||
7z_C/Bra86.c
|
7z_C/Bra86.c
|
||||||
7z_C/CpuArch.c
|
7z_C/CpuArch.c
|
||||||
7z_C/CpuArch.h
|
7z_C/CpuArch.h
|
||||||
|
7z_C/Delta.c
|
||||||
|
7z_C/Delta.h
|
||||||
7z_C/Lzma2Dec.c
|
7z_C/Lzma2Dec.c
|
||||||
7z_C/Lzma2Dec.h
|
7z_C/Lzma2Dec.h
|
||||||
7z_C/LzmaDec.c
|
7z_C/LzmaDec.c
|
||||||
|
@ -32,7 +34,11 @@ target_sources(vbam-fex
|
||||||
7z_C/Ppmd7.c
|
7z_C/Ppmd7.c
|
||||||
7z_C/Ppmd7.h
|
7z_C/Ppmd7.h
|
||||||
7z_C/Ppmd7Dec.c
|
7z_C/Ppmd7Dec.c
|
||||||
7z_C/Types.h
|
7z_C/Ppmd7aDec.c
|
||||||
|
7z_C/Ppmd8.c
|
||||||
|
7z_C/Ppmd8.h
|
||||||
|
7z_C/Ppmd8Dec.c
|
||||||
|
7z_C/7zTypes.h
|
||||||
fex/Binary_Extractor.cpp
|
fex/Binary_Extractor.cpp
|
||||||
fex/Binary_Extractor.h
|
fex/Binary_Extractor.h
|
||||||
fex/blargg_common.cpp
|
fex/blargg_common.cpp
|
||||||
|
|
|
@ -29,7 +29,7 @@ static ISzAlloc zip7_alloc_temp = { SzAllocTemp, SzFreeTemp };
|
||||||
struct Zip7_Extractor_Impl :
|
struct Zip7_Extractor_Impl :
|
||||||
ISeekInStream
|
ISeekInStream
|
||||||
{
|
{
|
||||||
CLookToRead look;
|
CLookToRead2 look;
|
||||||
CSzArEx db;
|
CSzArEx db;
|
||||||
|
|
||||||
// SzExtract state
|
// SzExtract state
|
||||||
|
@ -46,11 +46,11 @@ extern "C"
|
||||||
// 7-zip callbacks pass an ISeekInStream* for data, so we must cast it
|
// 7-zip callbacks pass an ISeekInStream* for data, so we must cast it
|
||||||
// back to ISeekInStream* FIRST, then cast to our Impl structure
|
// back to ISeekInStream* FIRST, then cast to our Impl structure
|
||||||
|
|
||||||
static SRes zip7_read_( void* vstream, void* out, size_t* size )
|
static SRes zip7_read_( ISeekInStreamPtr vstream, void* out, size_t* size )
|
||||||
{
|
{
|
||||||
assert( out && size );
|
assert( out && size );
|
||||||
ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream);
|
ISeekInStreamPtr stream = (ISeekInStreamPtr)vstream;
|
||||||
Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream);
|
Zip7_Extractor_Impl* impl = (Zip7_Extractor_Impl*)stream;
|
||||||
|
|
||||||
long lsize = (long)*size;
|
long lsize = (long)*size;
|
||||||
blargg_err_t err = impl->in->read_avail( out, &lsize );
|
blargg_err_t err = impl->in->read_avail( out, &lsize );
|
||||||
|
@ -65,10 +65,10 @@ extern "C"
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes zip7_seek_( void* vstream, Int64* pos, ESzSeek mode )
|
static SRes zip7_seek_( ISeekInStreamPtr vstream, Int64* pos, ESzSeek mode )
|
||||||
{
|
{
|
||||||
ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream);
|
ISeekInStreamPtr stream = (ISeekInStreamPtr)vstream;
|
||||||
Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream);
|
Zip7_Extractor_Impl* impl = (Zip7_Extractor_Impl*)stream;
|
||||||
|
|
||||||
// assert( mode != SZ_SEEK_CUR ); // never used
|
// assert( mode != SZ_SEEK_CUR ); // never used
|
||||||
|
|
||||||
|
@ -171,16 +171,16 @@ blargg_err_t Zip7_Extractor::open_v()
|
||||||
impl->buf = NULL;
|
impl->buf = NULL;
|
||||||
impl->buf_size = 0;
|
impl->buf_size = 0;
|
||||||
|
|
||||||
LookToRead_CreateVTable( &impl->look, false );
|
LookToRead2_CreateVTable( &impl->look, false );
|
||||||
impl->ISeekInStream::Read = zip7_read_;
|
impl->ISeekInStream::Read = zip7_read_;
|
||||||
impl->ISeekInStream::Seek = zip7_seek_;
|
impl->ISeekInStream::Seek = zip7_seek_;
|
||||||
impl->look.realStream = impl;
|
impl->look.realStream = impl;
|
||||||
LookToRead_Init( &impl->look );
|
LookToRead2_INIT( &impl->look );
|
||||||
|
|
||||||
SzArEx_Init( &impl->db );
|
SzArEx_Init( &impl->db );
|
||||||
|
|
||||||
impl->in_err = NULL;
|
impl->in_err = NULL;
|
||||||
RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.s,
|
RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.vt,
|
||||||
&zip7_alloc, &zip7_alloc_temp ) ) );
|
&zip7_alloc, &zip7_alloc_temp ) ) );
|
||||||
|
|
||||||
return seek_arc_v( 0 );
|
return seek_arc_v( 0 );
|
||||||
|
@ -271,18 +271,17 @@ bool Zip7_Extractor::utf16ToUtf8( unsigned char* dest, size_t* destLen, const sh
|
||||||
|
|
||||||
blargg_err_t Zip7_Extractor::next_v()
|
blargg_err_t Zip7_Extractor::next_v()
|
||||||
{
|
{
|
||||||
while ( ++index < (int) impl->db.db.NumFiles )
|
while ( ++index < (int) impl->db.NumFiles )
|
||||||
{
|
{
|
||||||
CSzFileItem const& item = impl->db.db.Files [index];
|
if ( !SzArEx_IsDir(&impl->db, index) )
|
||||||
if ( !item.IsDir )
|
|
||||||
{
|
{
|
||||||
if ( item.MTimeDefined )
|
if ( SzBitWithVals_Check(&impl->db.MTime, index) )
|
||||||
{
|
{
|
||||||
const UInt64 epoch = ((UInt64)0x019db1de << 32) + 0xd53e8000;
|
const UInt64 epoch = ((UInt64)0x019db1de << 32) + 0xd53e8000;
|
||||||
/* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
|
/* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
|
||||||
UInt64 time = ((UInt64)item.MTime.High << 32) + item.MTime.Low - epoch;
|
UInt64 time = ((((UInt64)impl->db.MTime.Vals[index].High) << 32) | impl->db.MTime.Vals[index].Low) - epoch;
|
||||||
time /= 1000000;
|
time /= 1000000;
|
||||||
|
|
||||||
time_t _time = time;
|
time_t _time = time;
|
||||||
|
@ -310,7 +309,7 @@ blargg_err_t Zip7_Extractor::next_v()
|
||||||
name8.resize( utf8_length + 1 );
|
name8.resize( utf8_length + 1 );
|
||||||
memcpy( name8.begin(), temp, utf8_length + 1 );
|
memcpy( name8.begin(), temp, utf8_length + 1 );
|
||||||
set_name( name8.begin(), name16.begin() );
|
set_name( name8.begin(), name16.begin() );
|
||||||
set_info( (int)item.Size, 0, (item.CrcDefined ? item.Crc : 0) );
|
set_info( (int)SzArEx_GetFileSize(&impl->db, index), 0, (SzBitWithVals_Check(&impl->db.CRCs, index) ? impl->db.CRCs.Vals[index] : 0) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +329,7 @@ fex_pos_t Zip7_Extractor::tell_arc_v() const
|
||||||
|
|
||||||
blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos )
|
blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos )
|
||||||
{
|
{
|
||||||
assert( 0 <= pos && pos <= (int) impl->db.db.NumFiles );
|
assert( 0 <= pos && pos <= (int) impl->db.NumFiles );
|
||||||
|
|
||||||
index = pos - 1;
|
index = pos - 1;
|
||||||
return next_v();
|
return next_v();
|
||||||
|
@ -341,7 +340,7 @@ blargg_err_t Zip7_Extractor::data_v( void const** out )
|
||||||
impl->in_err = NULL;
|
impl->in_err = NULL;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
RETURN_ERR( zip7_err( SzArEx_Extract( &impl->db, &impl->look.s, index,
|
RETURN_ERR( zip7_err( SzArEx_Extract( &impl->db, &impl->look.vt, index,
|
||||||
&impl->block_index, &impl->buf, &impl->buf_size,
|
&impl->block_index, &impl->buf, &impl->buf_size,
|
||||||
&offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) );
|
&offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) );
|
||||||
assert( count == (size_t) size() );
|
assert( count == (size_t) size() );
|
||||||
|
|
Loading…
Reference in New Issue