Add iTunes Debugger and third-party libraries

- Introduced a new iTunes Debugger application with main functionality to interact with iTunesAPIs.
- Added various third-party libraries including 7zip, bit7z, jsoncpp, libcurl, libeay32, ssleay32, and zlib for enhanced functionality.
- Created project files for the iTunes Debugger in Visual Studio, including .vcxproj, .vcxproj.filters, and .sln files.
- Included a log file for debugging purposes.
- Ensured compatibility with both Debug and Release configurations for Win32 and x64 platforms.
This commit is contained in:
danial
2025-11-15 23:06:05 +08:00
commit 9f481c5e8c
339 changed files with 82952 additions and 0 deletions

View File

@@ -0,0 +1,204 @@
/* 7z.h -- 7z interface
2023-04-02 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_7Z_H
#define ZIP7_INC_7Z_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define k7zStartHeaderSize 0x20
#define k7zSignatureSize 6
extern const Byte k7zSignature[k7zSignatureSize];
typedef struct
{
const Byte *Data;
size_t Size;
} CSzData;
/* CSzCoderInfo & CSzFolder support only default methods */
typedef struct
{
size_t PropsOffset;
UInt32 MethodID;
Byte NumStreams;
Byte PropsSize;
} CSzCoderInfo;
typedef struct
{
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
{
UInt32 NumCoders;
UInt32 NumBonds;
UInt32 NumPackStreams;
UInt32 UnpackStream;
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
} CSzFolder;
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
typedef struct
{
UInt32 Low;
UInt32 High;
} CNtfsFileTime;
typedef struct
{
Byte *Defs; /* MSB 0 bit numbering */
UInt32 *Vals;
} CSzBitUi32s;
typedef struct
{
Byte *Defs; /* MSB 0 bit numbering */
// UInt64 *Vals;
CNtfsFileTime *Vals;
} CSzBitUi64s;
#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
typedef struct
{
UInt32 NumPackStreams;
UInt32 NumFolders;
UInt64 *PackPositions; // NumPackStreams + 1
CSzBitUi32s FolderCRCs; // 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;
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
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);
/*
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.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
SRes SzArEx_Extract(
const CSzArEx *db,
ILookInStreamPtr inStream,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAllocPtr allocMain,
ISzAllocPtr allocTemp);
/*
SzArEx_Open Errors:
SZ_ERROR_NO_ARCHIVE
SZ_ERROR_ARCHIVE
SZ_ERROR_UNSUPPORTED
SZ_ERROR_MEM
SZ_ERROR_CRC
SZ_ERROR_INPUT_EOF
SZ_ERROR_FAIL
*/
SRes SzArEx_Open(CSzArEx *p, ILookInStreamPtr inStream,
ISzAllocPtr allocMain, ISzAllocPtr allocTemp);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,19 @@
/* 7zAlloc.h -- Allocation functions
2023-03-04 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_7Z_ALLOC_H
#define ZIP7_INC_7Z_ALLOC_H
#include "7zTypes.h"
EXTERN_C_BEGIN
void *SzAlloc(ISzAllocPtr p, size_t size);
void SzFree(ISzAllocPtr p, void *address);
void *SzAllocTemp(ISzAllocPtr p, size_t size);
void SzFreeTemp(ISzAllocPtr p, void *address);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,35 @@
/* 7zBuf.h -- Byte Buffer
2023-03-04 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_7Z_BUF_H
#define ZIP7_INC_7Z_BUF_H
#include "7zTypes.h"
EXTERN_C_BEGIN
typedef struct
{
Byte *data;
size_t size;
} CBuf;
void Buf_Init(CBuf *p);
int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc);
void Buf_Free(CBuf *p, ISzAllocPtr alloc);
typedef struct
{
Byte *data;
size_t size;
size_t pos;
} CDynBuf;
void DynBuf_Construct(CDynBuf *p);
void DynBuf_SeekToBeg(CDynBuf *p);
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc);
void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,28 @@
/* 7zCrc.h -- CRC32 calculation
2024-01-22 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_7Z_CRC_H
#define ZIP7_INC_7Z_CRC_H
#include "7zTypes.h"
EXTERN_C_BEGIN
extern UInt32 g_CrcTable[];
/* Call CrcGenerateTable one time before other CRC functions */
void Z7_FASTCALL CrcGenerateTable(void);
#define CRC_INIT_VAL 0xFFFFFFFF
#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, 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
#endif

View File

@@ -0,0 +1,92 @@
/* 7zFile.h -- File IO
2023-03-05 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_FILE_H
#define ZIP7_INC_FILE_H
#ifdef _WIN32
#define USE_WINDOWS_FILE
// #include <windows.h>
#endif
#ifdef USE_WINDOWS_FILE
#include "7zWindows.h"
#else
// note: USE_FOPEN mode is limited to 32-bit file size
// #define USE_FOPEN
// #include <stdio.h>
#endif
#include "7zTypes.h"
EXTERN_C_BEGIN
/* ---------- File ---------- */
typedef struct
{
#ifdef USE_WINDOWS_FILE
HANDLE handle;
#elif defined(USE_FOPEN)
FILE *file;
#else
int fd;
#endif
} CSzFile;
void File_Construct(CSzFile *p);
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
WRes InFile_Open(CSzFile *p, const char *name);
WRes OutFile_Open(CSzFile *p, const char *name);
#endif
#ifdef USE_WINDOWS_FILE
WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
#endif
WRes File_Close(CSzFile *p);
/* reads max(*size, remain file's size) bytes */
WRes File_Read(CSzFile *p, void *data, size_t *size);
/* writes *size bytes */
WRes File_Write(CSzFile *p, const void *data, size_t *size);
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);
WRes File_GetLength(CSzFile *p, UInt64 *length);
/* ---------- FileInStream ---------- */
typedef struct
{
ISeqInStream vt;
CSzFile file;
WRes wres;
} CFileSeqInStream;
void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
typedef struct
{
ISeekInStream vt;
CSzFile file;
WRes wres;
} CFileInStream;
void FileInStream_CreateVTable(CFileInStream *p);
typedef struct
{
ISeqOutStream vt;
CSzFile file;
WRes wres;
} CFileOutStream;
void FileOutStream_CreateVTable(CFileOutStream *p);
EXTERN_C_END
#endif

View File

@@ -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
*/

View File

@@ -0,0 +1,27 @@
#define MY_VER_MAJOR 24
#define MY_VER_MINOR 9
#define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "24.09"
#define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME
#define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")"
#else
#define MY_VERSION_CPU MY_VERSION
#endif
#define MY_DATE "2024-11-29"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2024 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR
#else
#define MY_COPYRIGHT MY_COPYRIGHT_PD
#endif
#define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE

View File

@@ -0,0 +1,101 @@
/* 7zWindows.h -- StdAfx
2023-04-02 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_7Z_WINDOWS_H
#define ZIP7_INC_7Z_WINDOWS_H
#ifdef _WIN32
#if defined(__clang__)
# pragma clang diagnostic push
#endif
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4668) // '_WIN32_WINNT' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
#if _MSC_VER == 1900
// for old kit10 versions
// #pragma warning(disable : 4255) // winuser.h(13979): warning C4255: 'GetThreadDpiAwarenessContext':
#endif
// win10 Windows Kit:
#endif // _MSC_VER
#if defined(_MSC_VER) && _MSC_VER <= 1200 && !defined(_WIN64)
// for msvc6 without sdk2003
#define RPC_NO_WINDOWS_H
#endif
#if defined(__MINGW32__) || defined(__MINGW64__)
// #if defined(__GNUC__) && !defined(__clang__)
#include <windows.h>
#else
#include <Windows.h>
#endif
// #include <basetsd.h>
// #include <wtypes.h>
// but if precompiled with clang-cl then we need
// #include <windows.h>
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1200 && !defined(_WIN64)
#ifndef _W64
typedef long LONG_PTR, *PLONG_PTR;
typedef unsigned long ULONG_PTR, *PULONG_PTR;
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
#define Z7_OLD_WIN_SDK
#endif // _W64
#endif // _MSC_VER == 1200
#ifdef Z7_OLD_WIN_SDK
#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
#ifndef FILE_SPECIAL_ACCESS
#define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS)
#endif
// ShlObj.h:
// #define BIF_NEWDIALOGSTYLE 0x0040
#pragma warning(disable : 4201)
// #pragma warning(disable : 4115)
#undef VARIANT_TRUE
#define VARIANT_TRUE ((VARIANT_BOOL)-1)
#endif
#endif // Z7_OLD_WIN_SDK
#ifdef UNDER_CE
#undef VARIANT_TRUE
#define VARIANT_TRUE ((VARIANT_BOOL)-1)
#endif
#if defined(_MSC_VER)
#if _MSC_VER >= 1400 && _MSC_VER <= 1600
// BaseTsd.h(148) : 'HandleToULong' : unreferenced inline function has been removed
// string.h
// #pragma warning(disable : 4514)
#endif
#endif
/* #include "7zTypes.h" */
#endif

View File

@@ -0,0 +1,60 @@
/* Aes.h -- AES encryption / decryption
2023-04-02 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_AES_H
#define ZIP7_INC_AES_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define AES_BLOCK_SIZE 16
/* Call AesGenTables one time before other AES functions */
void AesGenTables(void);
/* UInt32 pointers must be 16-byte aligned */
/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */
#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4)
/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */
/* keySize = 16 or 24 or 32 (bytes) */
typedef void (Z7_FASTCALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize);
void Z7_FASTCALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize);
void Z7_FASTCALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize);
/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */
void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */
/* data - 16-byte aligned pointer to data */
/* numBlocks - the number of 16-byte blocks in data array */
typedef void (Z7_FASTCALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks);
extern AES_CODE_FUNC g_AesCbc_Decode;
#ifndef Z7_SFX
extern AES_CODE_FUNC g_AesCbc_Encode;
extern AES_CODE_FUNC g_AesCtr_Code;
#define k_Aes_SupportedFunctions_HW (1 << 2)
#define k_Aes_SupportedFunctions_HW_256 (1 << 3)
extern UInt32 g_Aes_SupportedFunctions_Flags;
#endif
#define Z7_DECLARE_AES_CODE_FUNC(funcName) \
void Z7_FASTCALL funcName(UInt32 *ivAes, Byte *data, size_t numBlocks);
Z7_DECLARE_AES_CODE_FUNC (AesCbc_Encode)
Z7_DECLARE_AES_CODE_FUNC (AesCbc_Decode)
Z7_DECLARE_AES_CODE_FUNC (AesCtr_Code)
Z7_DECLARE_AES_CODE_FUNC (AesCbc_Encode_HW)
Z7_DECLARE_AES_CODE_FUNC (AesCbc_Decode_HW)
Z7_DECLARE_AES_CODE_FUNC (AesCtr_Code_HW)
Z7_DECLARE_AES_CODE_FUNC (AesCbc_Decode_HW_256)
Z7_DECLARE_AES_CODE_FUNC (AesCtr_Code_HW_256)
EXTERN_C_END
#endif

View File

@@ -0,0 +1,76 @@
/* Alloc.h -- Memory allocation functions
2024-01-22 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_ALLOC_H
#define ZIP7_INC_ALLOC_H
#include "7zTypes.h"
EXTERN_C_BEGIN
/*
MyFree(NULL) : is allowed, as free(NULL)
MyAlloc(0) : returns NULL : but malloc(0) is allowed to return NULL or non_NULL
MyRealloc(NULL, 0) : returns NULL : but realloc(NULL, 0) is allowed to return NULL or non_NULL
MyRealloc() is similar to realloc() for the following cases:
MyRealloc(non_NULL, 0) : returns NULL and always calls MyFree(ptr)
MyRealloc(NULL, non_ZERO) : returns NULL, if allocation failed
MyRealloc(non_NULL, non_ZERO) : returns NULL, if reallocation failed
*/
void *MyAlloc(size_t size);
void MyFree(void *address);
void *MyRealloc(void *address, size_t size);
void *z7_AlignedAlloc(size_t size);
void z7_AlignedFree(void *p);
#ifdef _WIN32
#ifdef Z7_LARGE_PAGES
void SetLargePageSize(void);
#endif
void *MidAlloc(size_t size);
void MidFree(void *address);
void *BigAlloc(size_t size);
void BigFree(void *address);
/* #define Z7_BIG_ALLOC_IS_ZERO_FILLED */
#else
#define MidAlloc(size) z7_AlignedAlloc(size)
#define MidFree(address) z7_AlignedFree(address)
#define BigAlloc(size) z7_AlignedAlloc(size)
#define BigFree(address) z7_AlignedFree(address)
#endif
extern const ISzAlloc g_Alloc;
#ifdef _WIN32
extern const ISzAlloc g_BigAlloc;
extern const ISzAlloc g_MidAlloc;
#else
#define g_BigAlloc g_AlignedAlloc
#define g_MidAlloc g_AlignedAlloc
#endif
extern const ISzAlloc g_AlignedAlloc;
typedef struct
{
ISzAlloc vt;
ISzAllocPtr baseAlloc;
unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */
size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */
} CAlignOffsetAlloc;
void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,332 @@
/* Bcj2.h -- BCJ2 converter for x86 code (Branch CALL/JUMP variant2)
2023-03-02 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_BCJ2_H
#define ZIP7_INC_BCJ2_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#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)
/*
CBcj2Dec / CBcj2Enc
bufs sizes:
BUF_SIZE(n) = lims[n] - bufs[n]
bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be multiply of 4:
(BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
(BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
*/
// typedef UInt32 CBcj2Prob;
typedef UInt16 CBcj2Prob;
/*
BCJ2 encoder / decoder internal requirements:
- 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

View File

@@ -0,0 +1,105 @@
/* Blake2.h -- BLAKE2sp Hash
2024-01-17 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_BLAKE2_H
#define ZIP7_INC_BLAKE2_H
#include "7zTypes.h"
#if 0
#include "Compiler.h"
#include "CpuArch.h"
#if defined(MY_CPU_X86_OR_AMD64)
#if defined(__SSE2__) \
|| defined(_MSC_VER) && _MSC_VER > 1200 \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \
|| defined(__clang__) \
|| defined(__INTEL_COMPILER)
#include <emmintrin.h> // SSE2
#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)
#include <immintrin.h>
#if defined(__clang__)
#include <avxintrin.h>
#include <avx2intrin.h>
#endif
#endif // avx2
#endif // MY_CPU_X86_OR_AMD64
#endif // 0
EXTERN_C_BEGIN
#define Z7_BLAKE2S_BLOCK_SIZE 64
#define Z7_BLAKE2S_DIGEST_SIZE 32
#define Z7_BLAKE2SP_PARALLEL_DEGREE 8
#define Z7_BLAKE2SP_NUM_STRUCT_WORDS 16
#if 1 || defined(Z7_BLAKE2SP_USE_FUNCTIONS)
typedef void (Z7_FASTCALL *Z7_BLAKE2SP_FUNC_COMPRESS)(UInt32 *states, const Byte *data, const Byte *end);
typedef void (Z7_FASTCALL *Z7_BLAKE2SP_FUNC_INIT)(UInt32 *states);
#endif
// it's required that CBlake2sp is aligned for 32-bytes,
// because the code can use unaligned access with sse and avx256.
// but 64-bytes alignment can be better.
MY_ALIGN(64)
typedef struct
{
union
{
#if 0
#if defined(MY_CPU_X86_OR_AMD64)
#if defined(__SSE2__) \
|| defined(_MSC_VER) && _MSC_VER > 1200 \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \
|| defined(__clang__) \
|| defined(__INTEL_COMPILER)
__m128i _pad_align_128bit[4];
#endif // sse2
#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)
__m256i _pad_align_256bit[2];
#endif // avx2
#endif // x86
#endif // 0
void * _pad_align_ptr[8];
UInt32 _pad_align_32bit[16];
struct
{
unsigned cycPos;
unsigned _pad_unused;
#if 1 || defined(Z7_BLAKE2SP_USE_FUNCTIONS)
Z7_BLAKE2SP_FUNC_COMPRESS func_Compress_Fast;
Z7_BLAKE2SP_FUNC_COMPRESS func_Compress_Single;
Z7_BLAKE2SP_FUNC_INIT func_Init;
Z7_BLAKE2SP_FUNC_INIT func_Final;
#endif
} header;
} u;
// MY_ALIGN(64)
UInt32 states[Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2SP_NUM_STRUCT_WORDS];
// MY_ALIGN(64)
UInt32 buf32[Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2SP_NUM_STRUCT_WORDS * 2];
} CBlake2sp;
BoolInt Blake2sp_SetFunction(CBlake2sp *p, unsigned algo);
void Blake2sp_Init(CBlake2sp *p);
void Blake2sp_InitState(CBlake2sp *p);
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size);
void Blake2sp_Final(CBlake2sp *p, Byte *digest);
void z7_Black2sp_Prepare(void);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,105 @@
/* Bra.h -- Branch converters for executables
2024-01-20 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_BRA_H
#define ZIP7_INC_BRA_H
#include "7zTypes.h"
EXTERN_C_BEGIN
/* #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 data that contain CPU instructions.
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.
There are 2 types of converters:
Byte * Conv_RISC (Byte *data, SizeT size, UInt32 pc);
Byte * ConvSt_X86(Byte *data, SizeT size, UInt32 pc, UInt32 *state);
Each Converter supports 2 versions: one for encoding
and one for decoding (_Enc/_Dec postfixes in function name).
In params:
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)
Return:
The pointer to position in (data) buffer after last byte that was processed.
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
X86 little 1 4
ARMT little 2 2
RISCV little 2 6
ARM little 4 0
ARM64 little 4 0
PPC big 4 0
SPARC big 4 0
IA64 little 16 0
(data) must be aligned for (Alignment).
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 code for conversion in loop:
UInt32 pc = 0;
size = 0;
for (;;)
{
size += Load_more_input_data(data + size);
SizeT processed = Conv(data, size, pc) - data;
if (processed == 0 && no_more_input_data_after_size)
break; // we stop convert loop
data += processed;
size -= processed;
pc += processed;
}
*/
EXTERN_C_END
#endif

View File

@@ -0,0 +1,26 @@
/* BwtSort.h -- BWT block sorting
2023-03-03 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_BWT_SORT_H
#define ZIP7_INC_BWT_SORT_H
#include "7zTypes.h"
EXTERN_C_BEGIN
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */
/* #define BLOCK_SORT_EXTERNAL_FLAGS */
#ifdef BLOCK_SORT_EXTERNAL_FLAGS
#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) ((((blockSize) + 31) >> 5))
#else
#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) 0
#endif
#define BLOCK_SORT_BUF_SIZE(blockSize) ((blockSize) * 2 + BLOCK_SORT_EXTERNAL_SIZE(blockSize) + (1 << 16))
UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);
EXTERN_C_END
#endif

View File

@@ -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

View File

@@ -0,0 +1,678 @@
/* CpuArch.h -- CPU specific code
Igor Pavlov : Public domain */
#ifndef ZIP7_INC_CPU_ARCH_H
#define ZIP7_INC_CPU_ARCH_H
#include "7zTypes.h"
EXTERN_C_BEGIN
/*
MY_CPU_LE means that CPU is 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_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_ARM64EC)
#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
#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
#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
#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)
#define MY_CPU_X86_OR_AMD64
#endif
#if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64)
#define MY_CPU_ARM_OR_ARM64
#endif
#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
#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
#if defined(__BIG_ENDIAN__) \
|| 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
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
#error Stop_Compiling_Bad_Endian
#endif
#if !defined(MY_CPU_LE) && !defined(MY_CPU_BE)
#error Stop_Compiling_CPU_ENDIAN_must_be_detected_at_compile_time
#endif
#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT)
#error Stop_Compiling_Bad_32_64_BIT
#endif
#ifdef __SIZEOF_POINTER__
#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
#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) ( \
((const Byte *)(p))[0] | \
((UInt32)((const Byte *)(p))[1] << 8) | \
((UInt32)((const Byte *)(p))[2] << 16) | \
((UInt32)((const Byte *)(p))[3] << 24))
#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
_ppp_[0] = (Byte)_vvv_; \
_ppp_[1] = (Byte)(_vvv_ >> 8); }
#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
_ppp_[0] = (Byte)_vvv_; \
_ppp_[1] = (Byte)(_vvv_ >> 8); \
_ppp_[2] = (Byte)(_vvv_ >> 16); \
_ppp_[3] = (Byte)(_vvv_ >> 24); }
#endif
#ifndef GetUi64
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
#endif
#ifndef SetUi64
#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
#define GetBe32(p) ( \
((UInt32)((const Byte *)(p))[0] << 24) | \
((UInt32)((const Byte *)(p))[1] << 16) | \
((UInt32)((const Byte *)(p))[2] << 8) | \
((const Byte *)(p))[3] )
#define 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
#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
void Z7_FASTCALL z7_x86_cpuid(UInt32 a[4], UInt32 function);
UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void);
#if defined(MY_CPU_AMD64)
#define Z7_IF_X86_CPUID_SUPPORTED
#else
#define Z7_IF_X86_CPUID_SUPPORTED if (z7_x86_cpuid_GetMaxFunc())
#endif
BoolInt CPU_IsSupported_AES(void);
BoolInt CPU_IsSupported_AVX(void);
BoolInt CPU_IsSupported_AVX2(void);
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);
#elif defined(MY_CPU_ARM_OR_ARM64)
BoolInt CPU_IsSupported_CRC32(void);
BoolInt CPU_IsSupported_NEON(void);
#if defined(_WIN32)
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
#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
#endif

View File

@@ -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

View File

@@ -0,0 +1,20 @@
/* DllSecur.h -- DLL loading for security
2023-03-03 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_DLL_SECUR_H
#define ZIP7_INC_DLL_SECUR_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#ifdef _WIN32
void My_SetDefaultDllDirectories(void);
void LoadSecurityDlls(void);
#endif
EXTERN_C_END
#endif

View File

@@ -0,0 +1,23 @@
/* HuffEnc.h -- Huffman encoding
2023-03-05 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_HUFF_ENC_H
#define ZIP7_INC_HUFF_ENC_H
#include "7zTypes.h"
EXTERN_C_BEGIN
/*
Conditions:
num <= 1024 = 2 ^ NUM_BITS
Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS)
maxLen <= 16 = kMaxLen
Num_Items(p) >= HUFFMAN_TEMP_SIZE(num)
*/
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,160 @@
/* LzFind.h -- Match finder for LZ algorithms
2024-01-22 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZ_FIND_H
#define ZIP7_INC_LZ_FIND_H
#include "7zTypes.h"
EXTERN_C_BEGIN
typedef UInt32 CLzRef;
typedef struct
{
const Byte *buffer;
UInt32 pos;
UInt32 posLimit;
UInt32 streamPos; /* wrap over Zero is allowed (streamPos < pos). Use (UInt32)(streamPos - pos) */
UInt32 lenLimit;
UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
Byte streamEndWasReached;
Byte btMode;
Byte bigHash;
Byte directInput;
UInt32 matchMaxLen;
CLzRef *hash;
CLzRef *son;
UInt32 hashMask;
UInt32 cutValue;
Byte *bufBase;
ISeqInStreamPtr stream;
UInt32 blockSize;
UInt32 keepSizeBefore;
UInt32 keepSizeAfter;
UInt32 numHashBytes;
size_t directInputRem;
UInt32 historySize;
UInt32 fixedHashSize;
Byte numHashBytes_Min;
Byte numHashOutBits;
Byte _pad2_[2];
SRes result;
UInt32 crc[256];
size_t numRefs;
UInt64 expectedDataSize;
} CMatchFinder;
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((const Byte *)(p)->buffer)
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((UInt32)((p)->streamPos - (p)->pos))
/*
#define Inline_MatchFinder_IsFinishedOK(p) \
((p)->streamEndWasReached \
&& (p)->streamPos == (p)->pos \
&& (!(p)->directInput || (p)->directInputRem == 0))
*/
int MatchFinder_NeedMove(CMatchFinder *p);
/* Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); */
void MatchFinder_MoveBlock(CMatchFinder *p);
void MatchFinder_ReadIfRequired(CMatchFinder *p);
void MatchFinder_Construct(CMatchFinder *p);
/* (directInput = 0) is default value.
It's required to provide correct (directInput) value
before calling MatchFinder_Create().
You can set (directInput) by any of the following calls:
- MatchFinder_SET_DIRECT_INPUT_BUF()
- MatchFinder_SET_STREAM()
- MatchFinder_SET_STREAM_MODE()
*/
#define MatchFinder_SET_DIRECT_INPUT_BUF(p, _src_, _srcLen_) { \
(p)->stream = NULL; \
(p)->directInput = 1; \
(p)->buffer = (_src_); \
(p)->directInputRem = (_srcLen_); }
/*
#define MatchFinder_SET_STREAM_MODE(p) { \
(p)->directInput = 0; }
*/
#define MatchFinder_SET_STREAM(p, _stream_) { \
(p)->stream = _stream_; \
(p)->directInput = 0; }
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAllocPtr alloc);
void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
/*
#define MatchFinder_INIT_POS(p, val) \
(p)->pos = (val); \
(p)->streamPos = (val);
*/
// void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
#define MatchFinder_REDUCE_OFFSETS(p, subValue) \
(p)->pos -= (subValue); \
(p)->streamPos -= (subValue);
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *distances, UInt32 maxLen);
/*
Conditions:
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
*/
typedef void (*Mf_Init_Func)(void *object);
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
typedef UInt32 * (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
typedef void (*Mf_Skip_Func)(void *object, UInt32);
typedef struct
{
Mf_Init_Func Init;
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
Mf_GetMatches_Func GetMatches;
Mf_Skip_Func Skip;
} IMatchFinder2;
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable);
void MatchFinder_Init_LowHash(CMatchFinder *p);
void MatchFinder_Init_HighHash(CMatchFinder *p);
void MatchFinder_Init_4(CMatchFinder *p);
// void MatchFinder_Init(CMatchFinder *p);
void MatchFinder_Init(void *p);
UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void LzFindPrepare(void);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,112 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
2024-01-22 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZ_FIND_MT_H
#define ZIP7_INC_LZ_FIND_MT_H
#include "LzFind.h"
#include "Threads.h"
EXTERN_C_BEGIN
typedef struct
{
UInt32 numProcessedBlocks;
CThread thread;
UInt64 affinity;
BoolInt wasCreated;
BoolInt needStart;
BoolInt csWasInitialized;
BoolInt csWasEntered;
BoolInt exit;
BoolInt stopWriting;
CAutoResetEvent canStart;
CAutoResetEvent wasStopped;
CSemaphore freeSemaphore;
CSemaphore filledSemaphore;
CCriticalSection cs;
// UInt32 numBlocks_Sent;
} CMtSync;
struct CMatchFinderMt_;
typedef UInt32 * (*Mf_Mix_Matches)(struct CMatchFinderMt_ *p, UInt32 matchMinPos, UInt32 *distances);
/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
#define kMtCacheLineDummy 128
typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
typedef struct CMatchFinderMt_
{
/* LZ */
const Byte *pointerToCurPos;
UInt32 *btBuf;
const UInt32 *btBufPos;
const UInt32 *btBufPosLimit;
UInt32 lzPos;
UInt32 btNumAvailBytes;
UInt32 *hash;
UInt32 fixedHashSize;
// UInt32 hash4Mask;
UInt32 historySize;
const UInt32 *crc;
Mf_Mix_Matches MixMatchesFunc;
UInt32 failure_LZ_BT; // failure in BT transfered to LZ
// UInt32 failure_LZ_LZ; // failure in LZ tables
UInt32 failureBuf[1];
// UInt32 crc[256];
/* LZ + BT */
CMtSync btSync;
Byte btDummy[kMtCacheLineDummy];
/* BT */
UInt32 *hashBuf;
UInt32 hashBufPos;
UInt32 hashBufPosLimit;
UInt32 hashNumAvail;
UInt32 failure_BT;
CLzRef *son;
UInt32 matchMaxLen;
UInt32 numHashBytes;
UInt32 pos;
const Byte *buffer;
UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
UInt32 cutValue;
/* BT + Hash */
CMtSync hashSync;
/* Byte hashDummy[kMtCacheLineDummy]; */
/* Hash */
Mf_GetHeads GetHeadsFunc;
CMatchFinder *MatchFinder;
// CMatchFinder MatchFinder;
} CMatchFinderMt;
// only for Mt part
void MatchFinderMt_Construct(CMatchFinderMt *p);
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc);
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc);
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable);
/* call MatchFinderMt_InitMt() before IMatchFinder::Init() */
SRes MatchFinderMt_InitMt(CMatchFinderMt *p);
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,34 @@
/* LzHash.h -- HASH constants for LZ algorithms
2023-03-05 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZ_HASH_H
#define ZIP7_INC_LZ_HASH_H
/*
(kHash2Size >= (1 << 8)) : Required
(kHash3Size >= (1 << 16)) : Required
*/
#define kHash2Size (1 << 10)
#define kHash3Size (1 << 16)
// #define kHash4Size (1 << 20)
#define kFix3HashSize (kHash2Size)
#define kFix4HashSize (kHash2Size + kHash3Size)
// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
/*
We use up to 3 crc values for hash:
crc0
crc1 << Shift_1
crc2 << Shift_2
(Shift_1 = 5) and (Shift_2 = 10) is good tradeoff.
Small values for Shift are not good for collision rate.
Big value for Shift_2 increases the minimum size
of hash table, that will be slow for small files.
*/
#define kLzHash_CrcShift_1 5
#define kLzHash_CrcShift_2 10
#endif

View File

@@ -0,0 +1,121 @@
/* Lzma2Dec.h -- LZMA2 Decoder
2023-03-03 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZMA2_DEC_H
#define ZIP7_INC_LZMA2_DEC_H
#include "LzmaDec.h"
EXTERN_C_BEGIN
/* ---------- State Interface ---------- */
typedef struct
{
unsigned state;
Byte control;
Byte needInitLevel;
Byte isExtraMode;
Byte _pad_;
UInt32 packSize;
UInt32 unpackSize;
CLzmaDec decoder;
} CLzma2Dec;
#define Lzma2Dec_CONSTRUCT(p) LzmaDec_CONSTRUCT(&(p)->decoder)
#define Lzma2Dec_Construct(p) Lzma2Dec_CONSTRUCT(p)
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc)
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc)
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
void Lzma2Dec_Init(CLzma2Dec *p);
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT
SZ_ERROR_DATA - Data error
*/
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- LZMA2 block and chunk parsing ---------- */
/*
Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.
It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:
- LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.
- LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.
CLzma2Dec::unpackSize contains unpack size of that chunk
*/
typedef enum
{
/*
LZMA_STATUS_NOT_SPECIFIED // data error
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED //
LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused
*/
LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,
LZMA2_PARSE_STATUS_NEW_CHUNK
} ELzma2ParseStatus;
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
SizeT outSize, // output size
const Byte *src, SizeT *srcLen,
int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position.
);
/*
LZMA2 parser doesn't decode LZMA chunks, so we must read
full input LZMA chunk to decode some part of LZMA chunk.
Lzma2Dec_GetUnpackExtra() returns the value that shows
max possible number of output bytes that can be output by decoder
at current input positon.
*/
#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0)
/* ---------- One Call Interface ---------- */
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,81 @@
/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread
2023-04-13 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZMA2_DEC_MT_H
#define ZIP7_INC_LZMA2_DEC_MT_H
#include "7zTypes.h"
EXTERN_C_BEGIN
typedef struct
{
size_t inBufSize_ST;
size_t outStep_ST;
#ifndef Z7_ST
unsigned numThreads;
size_t inBufSize_MT;
size_t outBlockMax;
size_t inBlockMax;
#endif
} CLzma2DecMtProps;
/* init to single-thread mode */
void Lzma2DecMtProps_Init(CLzma2DecMtProps *p);
/* ---------- CLzma2DecMtHandle Interface ---------- */
/* Lzma2DecMt_ * functions can return the following exit codes:
SRes:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - ISeqOutStream write callback error
// SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
*/
typedef struct CLzma2DecMt CLzma2DecMt;
typedef CLzma2DecMt * CLzma2DecMtHandle;
// Z7_DECLARE_HANDLE(CLzma2DecMtHandle)
CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);
void Lzma2DecMt_Destroy(CLzma2DecMtHandle p);
SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p,
Byte prop,
const CLzma2DecMtProps *props,
ISeqOutStreamPtr outStream,
const UInt64 *outDataSize, // NULL means undefined
int finishMode, // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished
// Byte *outBuf, size_t *outBufSize,
ISeqInStreamPtr inStream,
// const Byte *inData, size_t inDataSize,
// out variables:
UInt64 *inProcessed,
int *isMT, /* out: (*isMT == 0), if single thread decoding was used */
// UInt64 *outProcessed,
ICompressProgressPtr progress);
/* ---------- Read from CLzma2DecMtHandle Interface ---------- */
SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
Byte prop,
const CLzma2DecMtProps *props,
const UInt64 *outDataSize, int finishMode,
ISeqInStreamPtr inStream);
SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
Byte *data, size_t *outSize,
UInt64 *inStreamProcessed);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,57 @@
/* Lzma2Enc.h -- LZMA2 Encoder
2023-04-13 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZMA2_ENC_H
#define ZIP7_INC_LZMA2_ENC_H
#include "LzmaEnc.h"
EXTERN_C_BEGIN
#define LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO 0
#define LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID ((UInt64)(Int64)-1)
typedef struct
{
CLzmaEncProps lzmaProps;
UInt64 blockSize;
int numBlockThreads_Reduced;
int numBlockThreads_Max;
int numTotalThreads;
} CLzma2EncProps;
void Lzma2EncProps_Init(CLzma2EncProps *p);
void Lzma2EncProps_Normalize(CLzma2EncProps *p);
/* ---------- CLzmaEnc2Handle Interface ---------- */
/* Lzma2Enc_* functions can return the following exit codes:
SRes:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - ISeqOutStream write callback error
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
*/
typedef struct CLzma2Enc CLzma2Enc;
typedef CLzma2Enc * CLzma2EncHandle;
// Z7_DECLARE_HANDLE(CLzma2EncHandle)
CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);
void Lzma2Enc_Destroy(CLzma2EncHandle p);
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize);
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
SRes Lzma2Enc_Encode2(CLzma2EncHandle p,
ISeqOutStreamPtr outStream,
Byte *outBuf, size_t *outBufSize,
ISeqInStreamPtr inStream,
const Byte *inData, size_t inDataSize,
ICompressProgressPtr progress);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,111 @@
/* Lzma86.h -- LZMA + x86 (BCJ) Filter
2023-03-03 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZMA86_H
#define ZIP7_INC_LZMA86_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define LZMA86_SIZE_OFFSET (1 + 5)
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
/*
It's an example for LZMA + x86 Filter use.
You can use .lzma86 extension, if you write that stream to file.
.lzma86 header adds one additional byte to standard .lzma header.
.lzma86 header (14 bytes):
Offset Size Description
0 1 = 0 - no filter, pure LZMA
= 1 - x86 filter + LZMA
1 1 lc, lp and pb in encoded form
2 4 dictSize (little endian)
6 8 uncompressed size (little endian)
Lzma86_Encode
-------------
level - compression level: 0 <= level <= 9, the default value for "level" is 5.
dictSize - The dictionary size in bytes. The maximum value is
128 MB = (1 << 27) bytes for 32-bit version
1 GB = (1 << 30) bytes for 64-bit version
The default value is 16 MB = (1 << 24) bytes, for level = 5.
It's recommended to use the dictionary that is larger than 4 KB and
that can be calculated as (1 << N) or (3 << N) sizes.
For better compression ratio dictSize must be >= inSize.
filterMode:
SZ_FILTER_NO - no Filter
SZ_FILTER_YES - x86 Filter
SZ_FILTER_AUTO - it tries both alternatives to select best.
Encoder will use 2 or 3 passes:
2 passes when FILTER_NO provides better compression.
3 passes when FILTER_YES provides better compression.
Lzma86Encode allocates Data with MyAlloc functions.
RAM Requirements for compressing:
RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize
filterMode FilterBlockSize
SZ_FILTER_NO 0
SZ_FILTER_YES inSize
SZ_FILTER_AUTO inSize
Return code:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
enum ESzFilterMode
{
SZ_FILTER_NO,
SZ_FILTER_YES,
SZ_FILTER_AUTO
};
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode);
/*
Lzma86_GetUnpackSize:
In:
src - input data
srcLen - input data size
Out:
unpackSize - size of uncompressed stream
Return code:
SZ_OK - OK
SZ_ERROR_INPUT_EOF - Error in headers
*/
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);
/*
Lzma86_Decode:
In:
dest - output data
destLen - output data size
src - input data
srcLen - input data size
Out:
destLen - processed output size
srcLen - processed input size
Return code:
SZ_OK - OK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - unsupported file
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer
*/
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
EXTERN_C_END
#endif

View File

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

View File

@@ -0,0 +1,83 @@
/* LzmaEnc.h -- LZMA Encoder
2023-04-13 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZMA_ENC_H
#define ZIP7_INC_LZMA_ENC_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define LZMA_PROPS_SIZE 5
typedef struct
{
int level; /* 0 <= level <= 9 */
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
(1 << 12) <= dictSize <= (3 << 29) for 64-bit version
default = (1 << 24) */
int lc; /* 0 <= lc <= 8, default = 3 */
int lp; /* 0 <= lp <= 4, default = 0 */
int pb; /* 0 <= pb <= 4, default = 2 */
int algo; /* 0 - fast, 1 - normal, default = 1 */
int fb; /* 5 <= fb <= 273, default = 32 */
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
int numHashBytes; /* 2, 3 or 4, default = 4 */
unsigned numHashOutBits; /* default = ? */
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
int numThreads; /* 1 or 2, default = 2 */
// int _pad;
UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.
Encoder uses this value to reduce dictionary size */
UInt64 affinity;
} CLzmaEncProps;
void LzmaEncProps_Init(CLzmaEncProps *p);
void LzmaEncProps_Normalize(CLzmaEncProps *p);
UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
/* ---------- CLzmaEncHandle Interface ---------- */
/* LzmaEnc* functions can return the following exit codes:
SRes:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - ISeqOutStream write callback error
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
*/
typedef struct CLzmaEnc CLzmaEnc;
typedef CLzmaEnc * CLzmaEncHandle;
// Z7_DECLARE_HANDLE(CLzmaEncHandle)
CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc);
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize);
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p);
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream,
ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
/* ---------- One Call Interface ---------- */
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,138 @@
/* LzmaLib.h -- LZMA library interface
2023-04-02 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZMA_LIB_H
#define ZIP7_INC_LZMA_LIB_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define Z7_STDAPI int Z7_STDCALL
#define LZMA_PROPS_SIZE 5
/*
RAM requirements for LZMA:
for compression: (dictSize * 11.5 + 6 MB) + state_size
for decompression: dictSize + state_size
state_size = (4 + (1.5 << (lc + lp))) KB
by default (lc=3, lp=0), state_size = 16 KB.
LZMA properties (5 bytes) format
Offset Size Description
0 1 lc, lp and pb in encoded form.
1 4 dictSize (little endian).
*/
/*
LzmaCompress
------------
outPropsSize -
In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
LZMA Encoder will use defult values for any parameter, if it is
-1 for any from: level, loc, lp, pb, fb, numThreads
0 for dictSize
level - compression level: 0 <= level <= 9;
level dictSize algo fb
0: 64 KB 0 32
1: 256 KB 0 32
2: 1 MB 0 32
3: 4 MB 0 32
4: 16 MB 0 32
5: 16 MB 1 32
6: 32 MB 1 32
7: 32 MB 1 64
8: 64 MB 1 64
9: 64 MB 1 64
The default value for "level" is 5.
algo = 0 means fast method
algo = 1 means normal method
dictSize - The dictionary size in bytes. The maximum value is
128 MB = (1 << 27) bytes for 32-bit version
1 GB = (1 << 30) bytes for 64-bit version
The default value is 16 MB = (1 << 24) bytes.
It's recommended to use the dictionary that is larger than 4 KB and
that can be calculated as (1 << N) or (3 << N) sizes.
lc - The number of literal context bits (high bits of previous literal).
It can be in the range from 0 to 8. The default value is 3.
Sometimes lc=4 gives the gain for big files.
lp - The number of literal pos bits (low bits of current position for literals).
It can be in the range from 0 to 4. The default value is 0.
The lp switch is intended for periodical data when the period is equal to 2^lp.
For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's
better to set lc=0, if you change lp switch.
pb - The number of pos bits (low bits of current position).
It can be in the range from 0 to 4. The default value is 2.
The pb switch is intended for periodical data when the period is equal 2^pb.
fb - Word size (the number of fast bytes).
It can be in the range from 5 to 273. The default value is 32.
Usually, a big number gives a little bit better compression ratio and
slower compression process.
numThreads - The number of thereads. 1 or 2. The default value is 2.
Fast mode (algo = 0) can use only 1 thread.
In:
dest - output data buffer
destLen - output data buffer size
src - input data
srcLen - input data size
Out:
destLen - processed output size
Returns:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
Z7_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */
int level, /* 0 <= level <= 9, default = 5 */
unsigned dictSize, /* default = (1 << 24) */
int lc, /* 0 <= lc <= 8, default = 3 */
int lp, /* 0 <= lp <= 4, default = 0 */
int pb, /* 0 <= pb <= 4, default = 2 */
int fb, /* 5 <= fb <= 273, default = 32 */
int numThreads /* 1 or 2, default = 2 */
);
/*
LzmaUncompress
--------------
In:
dest - output data buffer
destLen - output data buffer size
src - input data
srcLen - input data size
Out:
destLen - processed output size
srcLen - processed input size
Returns:
SZ_OK - OK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation arror
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src)
*/
Z7_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
const unsigned char *props, size_t propsSize);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,34 @@
/* Md5.h -- MD5 Hash
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_MD5_H
#define ZIP7_INC_MD5_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define MD5_NUM_BLOCK_WORDS 16
#define MD5_NUM_DIGEST_WORDS 4
#define MD5_BLOCK_SIZE (MD5_NUM_BLOCK_WORDS * 4)
#define MD5_DIGEST_SIZE (MD5_NUM_DIGEST_WORDS * 4)
typedef struct
{
UInt64 count;
UInt64 _pad_1;
// we want 16-bytes alignment here
UInt32 state[MD5_NUM_DIGEST_WORDS];
UInt64 _pad_2[4];
// we want 64-bytes alignment here
Byte buffer[MD5_BLOCK_SIZE];
} CMd5;
void Md5_Init(CMd5 *p);
void Md5_Update(CMd5 *p, const Byte *data, size_t size);
void Md5_Final(CMd5 *p, Byte *digest);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,141 @@
/* MtCoder.h -- Multi-thread Coder
2023-04-13 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_MT_CODER_H
#define ZIP7_INC_MT_CODER_H
#include "MtDec.h"
EXTERN_C_BEGIN
/*
if ( defined MTCODER_USE_WRITE_THREAD) : main thread writes all data blocks to output stream
if (not defined MTCODER_USE_WRITE_THREAD) : any coder thread can write data blocks to output stream
*/
/* #define MTCODER_USE_WRITE_THREAD */
#ifndef Z7_ST
#define MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1)
#define MTCODER_THREADS_MAX 64
#define MTCODER_BLOCKS_MAX (MTCODER_GET_NUM_BLOCKS_FROM_THREADS(MTCODER_THREADS_MAX) + 3)
#else
#define MTCODER_THREADS_MAX 1
#define MTCODER_BLOCKS_MAX 1
#endif
#ifndef Z7_ST
typedef struct
{
ICompressProgress vt;
CMtProgress *mtProgress;
UInt64 inSize;
UInt64 outSize;
} CMtProgressThunk;
void MtProgressThunk_CreateVTable(CMtProgressThunk *p);
#define MtProgressThunk_INIT(p) { (p)->inSize = 0; (p)->outSize = 0; }
struct CMtCoder_;
typedef struct
{
struct CMtCoder_ *mtCoder;
unsigned index;
int stop;
Byte *inBuf;
CAutoResetEvent startEvent;
CThread thread;
} CMtCoderThread;
typedef struct
{
SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex,
const Byte *src, size_t srcSize, int finished);
SRes (*Write)(void *p, unsigned outBufIndex);
} IMtCoderCallback2;
typedef struct
{
SRes res;
unsigned bufIndex;
BoolInt finished;
} CMtCoderBlock;
typedef struct CMtCoder_
{
/* input variables */
size_t blockSize; /* size of input block */
unsigned numThreadsMax;
UInt64 expectedDataSize;
ISeqInStreamPtr inStream;
const Byte *inData;
size_t inDataSize;
ICompressProgressPtr progress;
ISzAllocPtr allocBig;
IMtCoderCallback2 *mtCallback;
void *mtCallbackObject;
/* internal variables */
size_t allocatedBufsSize;
CAutoResetEvent readEvent;
CSemaphore blocksSemaphore;
BoolInt stopReading;
SRes readRes;
#ifdef MTCODER_USE_WRITE_THREAD
CAutoResetEvent writeEvents[MTCODER_BLOCKS_MAX];
#else
CAutoResetEvent finishedEvent;
SRes writeRes;
unsigned writeIndex;
Byte ReadyBlocks[MTCODER_BLOCKS_MAX];
LONG numFinishedThreads;
#endif
unsigned numStartedThreadsLimit;
unsigned numStartedThreads;
unsigned numBlocksMax;
unsigned blockIndex;
UInt64 readProcessed;
CCriticalSection cs;
unsigned freeBlockHead;
unsigned freeBlockList[MTCODER_BLOCKS_MAX];
CMtProgress mtProgress;
CMtCoderBlock blocks[MTCODER_BLOCKS_MAX];
CMtCoderThread threads[MTCODER_THREADS_MAX];
} CMtCoder;
void MtCoder_Construct(CMtCoder *p);
void MtCoder_Destruct(CMtCoder *p);
SRes MtCoder_Code(CMtCoder *p);
#endif
EXTERN_C_END
#endif

View File

@@ -0,0 +1,202 @@
/* MtDec.h -- Multi-thread Decoder
2023-04-02 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_MT_DEC_H
#define ZIP7_INC_MT_DEC_H
#include "7zTypes.h"
#ifndef Z7_ST
#include "Threads.h"
#endif
EXTERN_C_BEGIN
#ifndef Z7_ST
#ifndef Z7_ST
#define MTDEC_THREADS_MAX 32
#else
#define MTDEC_THREADS_MAX 1
#endif
typedef struct
{
ICompressProgressPtr progress;
SRes res;
UInt64 totalInSize;
UInt64 totalOutSize;
CCriticalSection cs;
} CMtProgress;
void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress);
SRes MtProgress_Progress_ST(CMtProgress *p);
SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize);
SRes MtProgress_GetError(CMtProgress *p);
void MtProgress_SetError(CMtProgress *p, SRes res);
struct CMtDec;
typedef struct
{
struct CMtDec_ *mtDec;
unsigned index;
void *inBuf;
size_t inDataSize_Start; // size of input data in start block
UInt64 inDataSize; // total size of input data in all blocks
CThread thread;
CAutoResetEvent canRead;
CAutoResetEvent canWrite;
void *allocaPtr;
} CMtDecThread;
void MtDecThread_FreeInBufs(CMtDecThread *t);
typedef enum
{
MTDEC_PARSE_CONTINUE, // continue this block with more input data
MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread
MTDEC_PARSE_NEW, // new block
MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue)
} EMtDecParseState;
typedef struct
{
// in
int startCall;
const Byte *src;
size_t srcSize;
// in : (srcSize == 0) is allowed
// out : it's allowed to return less that actually was used ?
int srcFinished;
// out
EMtDecParseState state;
BoolInt canCreateNewThread;
UInt64 outPos; // check it (size_t)
} CMtDecCallbackInfo;
typedef struct
{
void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci);
// PreCode() and Code():
// (SRes_return_result != SZ_OK) means stop decoding, no need another blocks
SRes (*PreCode)(void *p, unsigned coderIndex);
SRes (*Code)(void *p, unsigned coderIndex,
const Byte *src, size_t srcSize, int srcFinished,
UInt64 *inCodePos, UInt64 *outCodePos, int *stop);
// stop - means stop another Code calls
/* Write() must be called, if Parse() was called
set (needWrite) if
{
&& (was not interrupted by progress)
&& (was not interrupted in previous block)
}
out:
if (*needContinue), decoder still need to continue decoding with new iteration,
even after MTDEC_PARSE_END
if (*canRecode), we didn't flush current block data, so we still can decode current block later.
*/
SRes (*Write)(void *p, unsigned coderIndex,
BoolInt needWriteToStream,
const Byte *src, size_t srcSize, BoolInt isCross,
// int srcFinished,
BoolInt *needContinue,
BoolInt *canRecode);
} IMtDecCallback2;
typedef struct CMtDec_
{
/* input variables */
size_t inBufSize; /* size of input block */
unsigned numThreadsMax;
// size_t inBlockMax;
unsigned numThreadsMax_2;
ISeqInStreamPtr inStream;
// const Byte *inData;
// size_t inDataSize;
ICompressProgressPtr progress;
ISzAllocPtr alloc;
IMtDecCallback2 *mtCallback;
void *mtCallbackObject;
/* internal variables */
size_t allocatedBufsSize;
BoolInt exitThread;
WRes exitThreadWRes;
UInt64 blockIndex;
BoolInt isAllocError;
BoolInt overflow;
SRes threadingErrorSRes;
BoolInt needContinue;
// CAutoResetEvent finishedEvent;
SRes readRes;
SRes codeRes;
BoolInt wasInterrupted;
unsigned numStartedThreads_Limit;
unsigned numStartedThreads;
Byte *crossBlock;
size_t crossStart;
size_t crossEnd;
UInt64 readProcessed;
BoolInt readWasFinished;
UInt64 inProcessed;
unsigned filledThreadStart;
unsigned numFilledThreads;
#ifndef Z7_ST
BoolInt needInterrupt;
UInt64 interruptIndex;
CMtProgress mtProgress;
CMtDecThread threads[MTDEC_THREADS_MAX];
#endif
} CMtDec;
void MtDec_Construct(CMtDec *p);
void MtDec_Destruct(CMtDec *p);
/*
MtDec_Code() returns:
SZ_OK - in most cases
MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function
*/
SRes MtDec_Code(CMtDec *p);
Byte *MtDec_GetCrossBuff(CMtDec *p);
int MtDec_PrepareRead(CMtDec *p);
const Byte *MtDec_Read(CMtDec *p, size_t *inLim);
#endif
EXTERN_C_END
#endif

View File

@@ -0,0 +1,169 @@
/* Ppmd.h -- PPMD codec common code
2023-03-05 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#ifndef ZIP7_INC_PPMD_H
#define ZIP7_INC_PPMD_H
#include "CpuArch.h"
EXTERN_C_BEGIN
#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
/*
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
#define PPMD_INT_BITS 7
#define PPMD_PERIOD_BITS 7
#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
#define PPMD_N1 4
#define PPMD_N2 4
#define PPMD_N3 4
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
MY_CPU_pragma_pack_push_1
/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */
/* SEE-contexts for PPM-contexts with masked symbols */
typedef struct
{
UInt16 Summ; /* Freq */
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
Byte Count; /* Count to next change of Shift */
} CPpmd_See;
#define Ppmd_See_UPDATE(p) \
{ if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
{ (p)->Summ = (UInt16)((p)->Summ << 1); \
(p)->Count = (Byte)(3 << (p)->Shift++); }}
typedef struct
{
Byte Symbol;
Byte Freq;
UInt16 Successor_0;
UInt16 Successor_1;
} CPpmd_State;
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.
*/
#ifdef PPMD_32BIT
#define Ppmd_Ref_Type(type) type *
#define Ppmd_GetRef(p, ptr) (ptr)
#define Ppmd_GetPtr(p, ptr) (ptr)
#define Ppmd_GetPtr_Type(p, ptr, note_type) (ptr)
#else
#define Ppmd_Ref_Type(type) UInt32
#define Ppmd_GetRef(p, ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
#define Ppmd_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
#define Ppmd_GetPtr_Type(p, offs, type) ((type *)Ppmd_GetPtr(p, offs))
#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
#endif

View File

@@ -0,0 +1,181 @@
/* Ppmd7.h -- Ppmd7 (PPMdH) compression codec
2023-04-02 : Igor Pavlov : Public domain
This code is based on:
PPMd var.H (2001): Dmitry Shkarin : Public domain */
#ifndef ZIP7_INC_PPMD7_H
#define ZIP7_INC_PPMD7_H
#include "Ppmd.h"
EXTERN_C_BEGIN
#define PPMD7_MIN_ORDER 2
#define PPMD7_MAX_ORDER 64
#define PPMD7_MIN_MEM_SIZE (1 << 11)
#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
struct CPpmd7_Context_;
typedef Ppmd_Ref_Type(struct CPpmd7_Context_) CPpmd7_Context_Ref;
// MY_CPU_pragma_pack_push_1
typedef struct CPpmd7_Context_
{
UInt16 NumStats;
union
{
UInt16 SummFreq;
CPpmd_State2 State2;
} Union2;
union
{
CPpmd_State_Ref Stats;
CPpmd_State4 State4;
} Union4;
CPpmd7_Context_Ref Suffix;
} CPpmd7_Context;
// MY_CPU_pragma_pop
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->Union2)
typedef struct
{
UInt32 Range;
UInt32 Code;
UInt32 Low;
IByteInPtr Stream;
} CPpmd7_RangeDec;
typedef struct
{
UInt32 Range;
Byte Cache;
// Byte _dummy_[3];
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;
void Ppmd7_Construct(CPpmd7 *p);
BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc);
void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc);
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
/* ---------- Internal Functions ---------- */
#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)
void Ppmd7_Update1(CPpmd7 *p);
void Ppmd7_Update1_0(CPpmd7 *p);
void Ppmd7_Update2(CPpmd7 *p);
#define PPMD7_HiBitsFlag_3(sym) ((((unsigned)sym + 0xC0) >> (8 - 3)) & (1 << 3))
#define PPMD7_HiBitsFlag_4(sym) ((((unsigned)sym + 0xC0) >> (8 - 4)) & (1 << 4))
// #define PPMD7_HiBitsFlag_3(sym) ((sym) < 0x40 ? 0 : (1 << 3))
// #define PPMD7_HiBitsFlag_4(sym) ((sym) < 0x40 ? 0 : (1 << 4))
#define Ppmd7_GetBinSumm(p) \
&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);
/*
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 ---------- */
#define PPMD7_SYM_END (-1)
#define PPMD7_SYM_ERROR (-2)
/*
You must set (CPpmd7::rc.dec.Stream) before Ppmd7*_RangeDec_Init()
Ppmd7*_DecodeSymbol()
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)
int Ppmd7z_DecodeSymbol(CPpmd7 *p);
// Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim);
/* ---------- Encode ---------- */
void Ppmd7z_Init_RangeEnc(CPpmd7 *p);
void Ppmd7z_Flush_RangeEnc(CPpmd7 *p);
// void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol);
void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim);
EXTERN_C_END
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,86 @@
/* Sha1.h -- SHA-1 Hash
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_SHA1_H
#define ZIP7_INC_SHA1_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define SHA1_NUM_BLOCK_WORDS 16
#define SHA1_NUM_DIGEST_WORDS 5
#define SHA1_BLOCK_SIZE (SHA1_NUM_BLOCK_WORDS * 4)
#define SHA1_DIGEST_SIZE (SHA1_NUM_DIGEST_WORDS * 4)
typedef void (Z7_FASTCALL *SHA1_FUNC_UPDATE_BLOCKS)(UInt32 state[5], const Byte *data, size_t numBlocks);
/*
if (the system supports different SHA1 code implementations)
{
(CSha1::func_UpdateBlocks) will be used
(CSha1::func_UpdateBlocks) can be set by
Sha1_Init() - to default (fastest)
Sha1_SetFunction() - to any algo
}
else
{
(CSha1::func_UpdateBlocks) is ignored.
}
*/
typedef struct
{
union
{
struct
{
SHA1_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
UInt64 count;
} vars;
UInt64 _pad_64bit[4];
void *_pad_align_ptr[2];
} v;
UInt32 state[SHA1_NUM_DIGEST_WORDS];
UInt32 _pad_3[3];
Byte buffer[SHA1_BLOCK_SIZE];
} CSha1;
#define SHA1_ALGO_DEFAULT 0
#define SHA1_ALGO_SW 1
#define SHA1_ALGO_HW 2
/*
Sha1_SetFunction()
return:
0 - (algo) value is not supported, and func_UpdateBlocks was not changed
1 - func_UpdateBlocks was set according (algo) value.
*/
BoolInt Sha1_SetFunction(CSha1 *p, unsigned algo);
void Sha1_InitState(CSha1 *p);
void Sha1_Init(CSha1 *p);
void Sha1_Update(CSha1 *p, const Byte *data, size_t size);
void Sha1_Final(CSha1 *p, Byte *digest);
void Sha1_PrepareBlock(const CSha1 *p, Byte *block, unsigned size);
void Sha1_GetBlockDigest(const CSha1 *p, const Byte *data, Byte *destDigest);
// void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t numBlocks);
/*
call Sha1Prepare() once at program start.
It prepares all supported implementations, and detects the fastest implementation.
*/
void Sha1Prepare(void);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,86 @@
/* Sha256.h -- SHA-256 Hash
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_SHA256_H
#define ZIP7_INC_SHA256_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define SHA256_NUM_BLOCK_WORDS 16
#define SHA256_NUM_DIGEST_WORDS 8
#define SHA256_BLOCK_SIZE (SHA256_NUM_BLOCK_WORDS * 4)
#define SHA256_DIGEST_SIZE (SHA256_NUM_DIGEST_WORDS * 4)
typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byte *data, size_t numBlocks);
/*
if (the system supports different SHA256 code implementations)
{
(CSha256::func_UpdateBlocks) will be used
(CSha256::func_UpdateBlocks) can be set by
Sha256_Init() - to default (fastest)
Sha256_SetFunction() - to any algo
}
else
{
(CSha256::func_UpdateBlocks) is ignored.
}
*/
typedef struct
{
union
{
struct
{
SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
UInt64 count;
} vars;
UInt64 _pad_64bit[4];
void *_pad_align_ptr[2];
} v;
UInt32 state[SHA256_NUM_DIGEST_WORDS];
Byte buffer[SHA256_BLOCK_SIZE];
} CSha256;
#define SHA256_ALGO_DEFAULT 0
#define SHA256_ALGO_SW 1
#define SHA256_ALGO_HW 2
/*
Sha256_SetFunction()
return:
0 - (algo) value is not supported, and func_UpdateBlocks was not changed
1 - func_UpdateBlocks was set according (algo) value.
*/
BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo);
void Sha256_InitState(CSha256 *p);
void Sha256_Init(CSha256 *p);
void Sha256_Update(CSha256 *p, const Byte *data, size_t size);
void Sha256_Final(CSha256 *p, Byte *digest);
// void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks);
/*
call Sha256Prepare() once at program start.
It prepares all supported implementations, and detects the fastest implementation.
*/
void Sha256Prepare(void);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,36 @@
/* Sha3.h -- SHA-3 Hash
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_MD5_H
#define ZIP7_INC_MD5_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define SHA3_NUM_STATE_WORDS 25
#define SHA3_BLOCK_SIZE_FROM_DIGEST_SIZE(digestSize) \
(SHA3_NUM_STATE_WORDS * 8 - (digestSize) * 2)
typedef struct
{
UInt32 count; // < blockSize
UInt32 blockSize; // <= SHA3_NUM_STATE_WORDS * 8
UInt64 _pad1[3];
// we want 32-bytes alignment here
UInt64 state[SHA3_NUM_STATE_WORDS];
UInt64 _pad2[3];
// we want 64-bytes alignment here
Byte buffer[SHA3_NUM_STATE_WORDS * 8]; // last bytes will be unused with predefined blockSize values
} CSha3;
#define Sha3_SET_blockSize(p, blockSize) { (p)->blockSize = (blockSize); }
void Sha3_Init(CSha3 *p);
void Sha3_Update(CSha3 *p, const Byte *data, size_t size);
void Sha3_Final(CSha3 *p, Byte *digest, unsigned digestSize, unsigned shake);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,86 @@
/* Sha512.h -- SHA-512 Hash
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_SHA512_H
#define ZIP7_INC_SHA512_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define SHA512_NUM_BLOCK_WORDS 16
#define SHA512_NUM_DIGEST_WORDS 8
#define SHA512_BLOCK_SIZE (SHA512_NUM_BLOCK_WORDS * 8)
#define SHA512_DIGEST_SIZE (SHA512_NUM_DIGEST_WORDS * 8)
#define SHA512_224_DIGEST_SIZE (224 / 8)
#define SHA512_256_DIGEST_SIZE (256 / 8)
#define SHA512_384_DIGEST_SIZE (384 / 8)
typedef void (Z7_FASTCALL *SHA512_FUNC_UPDATE_BLOCKS)(UInt64 state[8], const Byte *data, size_t numBlocks);
/*
if (the system supports different SHA512 code implementations)
{
(CSha512::func_UpdateBlocks) will be used
(CSha512::func_UpdateBlocks) can be set by
Sha512_Init() - to default (fastest)
Sha512_SetFunction() - to any algo
}
else
{
(CSha512::func_UpdateBlocks) is ignored.
}
*/
typedef struct
{
union
{
struct
{
SHA512_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
UInt64 count;
} vars;
UInt64 _pad_64bit[8];
void *_pad_align_ptr[2];
} v;
UInt64 state[SHA512_NUM_DIGEST_WORDS];
Byte buffer[SHA512_BLOCK_SIZE];
} CSha512;
#define SHA512_ALGO_DEFAULT 0
#define SHA512_ALGO_SW 1
#define SHA512_ALGO_HW 2
/*
Sha512_SetFunction()
return:
0 - (algo) value is not supported, and func_UpdateBlocks was not changed
1 - func_UpdateBlocks was set according (algo) value.
*/
BoolInt Sha512_SetFunction(CSha512 *p, unsigned algo);
// we support only these (digestSize) values: 224/8, 256/8, 384/8, 512/8
void Sha512_InitState(CSha512 *p, unsigned digestSize);
void Sha512_Init(CSha512 *p, unsigned digestSize);
void Sha512_Update(CSha512 *p, const Byte *data, size_t size);
void Sha512_Final(CSha512 *p, Byte *digest, unsigned digestSize);
// void Z7_FASTCALL Sha512_UpdateBlocks(UInt64 state[8], const Byte *data, size_t numBlocks);
/*
call Sha512Prepare() once at program start.
It prepares all supported implementations, and detects the fastest implementation.
*/
void Sha512Prepare(void);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,18 @@
/* Sort.h -- Sort functions
2023-03-05 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_SORT_H
#define ZIP7_INC_SORT_H
#include "7zTypes.h"
EXTERN_C_BEGIN
void HeapSort(UInt32 *p, size_t size);
void HeapSort64(UInt64 *p, size_t size);
/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */
EXTERN_C_END
#endif

View File

@@ -0,0 +1,17 @@
/* SwapBytes.h -- Byte Swap conversion filter
2023-04-02 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_SWAP_BYTES_H
#define ZIP7_INC_SWAP_BYTES_H
#include "7zTypes.h"
EXTERN_C_BEGIN
void z7_SwapBytes2(UInt16 *data, size_t numItems);
void z7_SwapBytes4(UInt32 *data, size_t numItems);
void z7_SwapBytesPrepare(void);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,250 @@
/* Threads.h -- multithreading library
2024-03-28 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_THREADS_H
#define ZIP7_INC_THREADS_H
#ifdef _WIN32
#include "7zWindows.h"
#else
#include "Compiler.h"
// #define Z7_AFFINITY_DISABLE
#if defined(__linux__)
#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
#ifndef Z7_AFFINITY_DISABLE
#define Z7_AFFINITY_SUPPORTED
// #pragma message(" ==== Z7_AFFINITY_SUPPORTED")
#if !defined(_GNU_SOURCE)
// #pragma message(" ==== _GNU_SOURCE set")
// we need _GNU_SOURCE for cpu_set_t, if we compile for MUSL
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define _GNU_SOURCE
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif
#endif
#endif
#include <pthread.h>
#endif
#include "7zTypes.h"
EXTERN_C_BEGIN
#ifdef _WIN32
WRes HandlePtr_Close(HANDLE *h);
WRes Handle_WaitObject(HANDLE h);
typedef HANDLE CThread;
#define Thread_CONSTRUCT(p) { *(p) = NULL; }
#define Thread_WasCreated(p) (*(p) != NULL)
#define Thread_Close(p) HandlePtr_Close(p)
// #define Thread_Wait(p) Handle_WaitObject(*(p))
#ifdef UNDER_CE
// if (USE_THREADS_CreateThread is defined), we use _beginthreadex()
// if (USE_THREADS_CreateThread is not definned), we use CreateThread()
#define USE_THREADS_CreateThread
#endif
typedef
#ifdef USE_THREADS_CreateThread
DWORD
#else
unsigned
#endif
THREAD_FUNC_RET_TYPE;
#define THREAD_FUNC_RET_ZERO 0
typedef DWORD_PTR CAffinityMask;
typedef DWORD_PTR CCpuSet;
#define CpuSet_Zero(p) *(p) = (0)
#define CpuSet_Set(p, cpu) *(p) |= ((DWORD_PTR)1 << (cpu))
#else // _WIN32
typedef struct
{
pthread_t _tid;
int _created;
} CThread;
#define Thread_CONSTRUCT(p) { (p)->_tid = 0; (p)->_created = 0; }
#define Thread_WasCreated(p) ((p)->_created != 0)
WRes Thread_Close(CThread *p);
// #define Thread_Wait Thread_Wait_Close
typedef void * THREAD_FUNC_RET_TYPE;
#define THREAD_FUNC_RET_ZERO NULL
typedef UInt64 CAffinityMask;
#ifdef Z7_AFFINITY_SUPPORTED
typedef cpu_set_t CCpuSet;
#define CpuSet_Zero(p) CPU_ZERO(p)
#define CpuSet_Set(p, cpu) CPU_SET(cpu, p)
#define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p)
#else
typedef UInt64 CCpuSet;
#define CpuSet_Zero(p) *(p) = (0)
#define CpuSet_Set(p, cpu) *(p) |= ((UInt64)1 << (cpu))
#define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0)
#endif
#endif // _WIN32
#define THREAD_FUNC_CALL_TYPE Z7_STDCALL
#if defined(_WIN32) && defined(__GNUC__)
/* GCC compiler for x86 32-bit uses the rule:
the stack is 16-byte aligned before CALL instruction for function calling.
But only root function main() contains instructions that
set 16-byte alignment for stack pointer. And another functions
just keep alignment, if it was set in some parent function.
The problem:
if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(),
the root function of thread doesn't set 16-byte alignment.
And stack frames in all child functions also will be unaligned in that case.
Here we set (force_align_arg_pointer) attribute for root function of new thread.
Do we need (force_align_arg_pointer) also for another systems? */
#define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer))
// #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions
#else
#define THREAD_FUNC_ATTRIB_ALIGN_ARG
#endif
#define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity);
WRes Thread_Wait_Close(CThread *p);
#ifdef _WIN32
#define Thread_Create_With_CpuSet(p, func, param, cs) \
Thread_Create_With_Affinity(p, func, param, *cs)
#else
WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet);
#endif
#ifdef _WIN32
typedef HANDLE CEvent;
typedef CEvent CAutoResetEvent;
typedef CEvent CManualResetEvent;
#define Event_Construct(p) *(p) = NULL
#define Event_IsCreated(p) (*(p) != NULL)
#define Event_Close(p) HandlePtr_Close(p)
#define Event_Wait(p) Handle_WaitObject(*(p))
WRes Event_Set(CEvent *p);
WRes Event_Reset(CEvent *p);
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
typedef HANDLE CSemaphore;
#define Semaphore_Construct(p) *(p) = NULL
#define Semaphore_IsCreated(p) (*(p) != NULL)
#define Semaphore_Close(p) HandlePtr_Close(p)
#define Semaphore_Wait(p) Handle_WaitObject(*(p))
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
WRes Semaphore_Release1(CSemaphore *p);
typedef CRITICAL_SECTION CCriticalSection;
WRes CriticalSection_Init(CCriticalSection *p);
#define CriticalSection_Delete(p) DeleteCriticalSection(p)
#define CriticalSection_Enter(p) EnterCriticalSection(p)
#define CriticalSection_Leave(p) LeaveCriticalSection(p)
#else // _WIN32
typedef struct
{
int _created;
int _manual_reset;
int _state;
pthread_mutex_t _mutex;
pthread_cond_t _cond;
} CEvent;
typedef CEvent CAutoResetEvent;
typedef CEvent CManualResetEvent;
#define Event_Construct(p) (p)->_created = 0
#define Event_IsCreated(p) ((p)->_created)
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
WRes Event_Set(CEvent *p);
WRes Event_Reset(CEvent *p);
WRes Event_Wait(CEvent *p);
WRes Event_Close(CEvent *p);
typedef struct
{
int _created;
UInt32 _count;
UInt32 _maxCount;
pthread_mutex_t _mutex;
pthread_cond_t _cond;
} CSemaphore;
#define Semaphore_Construct(p) (p)->_created = 0
#define Semaphore_IsCreated(p) ((p)->_created)
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1)
WRes Semaphore_Wait(CSemaphore *p);
WRes Semaphore_Close(CSemaphore *p);
typedef struct
{
pthread_mutex_t _mutex;
} CCriticalSection;
WRes CriticalSection_Init(CCriticalSection *p);
void CriticalSection_Delete(CCriticalSection *cs);
void CriticalSection_Enter(CCriticalSection *cs);
void CriticalSection_Leave(CCriticalSection *cs);
LONG InterlockedIncrement(LONG volatile *addend);
LONG InterlockedDecrement(LONG volatile *addend);
#endif // _WIN32
WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,50 @@
/* Xxh64.h -- XXH64 hash calculation interfaces
2023-08-18 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_XXH64_H
#define ZIP7_INC_XXH64_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define Z7_XXH64_BLOCK_SIZE (4 * 8)
typedef struct
{
UInt64 v[4];
} CXxh64State;
void Xxh64State_Init(CXxh64State *p);
// end != data && end == data + Z7_XXH64_BLOCK_SIZE * numBlocks
void Z7_FASTCALL Xxh64State_UpdateBlocks(CXxh64State *p, const void *data, const void *end);
/*
Xxh64State_Digest():
data:
the function processes only
(totalCount & (Z7_XXH64_BLOCK_SIZE - 1)) bytes in (data): (smaller than 32 bytes).
totalCount: total size of hashed stream:
it includes total size of data processed by previous Xxh64State_UpdateBlocks() calls,
and it also includes current processed size in (data).
*/
UInt64 Xxh64State_Digest(const CXxh64State *p, const void *data, UInt64 totalCount);
typedef struct
{
CXxh64State state;
UInt64 count;
UInt64 buf64[4];
} CXxh64;
void Xxh64_Init(CXxh64 *p);
void Xxh64_Update(CXxh64 *p, const void *data, size_t size);
#define Xxh64_Digest(p) \
Xxh64State_Digest(&(p)->state, (p)->buf64, (p)->count)
EXTERN_C_END
#endif

View File

@@ -0,0 +1,536 @@
/* Xz.h - Xz interface
2024-01-26 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_XZ_H
#define ZIP7_INC_XZ_H
#include "Sha256.h"
#include "Delta.h"
EXTERN_C_BEGIN
#define XZ_ID_Subblock 1
#define XZ_ID_Delta 3
#define XZ_ID_X86 4
#define XZ_ID_PPC 5
#define XZ_ID_IA64 6
#define XZ_ID_ARM 7
#define XZ_ID_ARMT 8
#define XZ_ID_SPARC 9
#define XZ_ID_ARM64 0xa
#define XZ_ID_RISCV 0xb
#define XZ_ID_LZMA2 0x21
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v);
/* ---------- xz block ---------- */
#define XZ_BLOCK_HEADER_SIZE_MAX 1024
#define XZ_NUM_FILTERS_MAX 4
#define XZ_BF_NUM_FILTERS_MASK 3
#define XZ_BF_PACK_SIZE (1 << 6)
#define XZ_BF_UNPACK_SIZE (1 << 7)
#define XZ_FILTER_PROPS_SIZE_MAX 20
typedef struct
{
UInt64 id;
UInt32 propsSize;
Byte props[XZ_FILTER_PROPS_SIZE_MAX];
} CXzFilter;
typedef struct
{
UInt64 packSize;
UInt64 unpackSize;
Byte flags;
CXzFilter filters[XZ_NUM_FILTERS_MAX];
} CXzBlock;
#define XzBlock_GetNumFilters(p) (((unsigned)(p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)
#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0)
#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)
#define XzBlock_HasUnsupportedFlags(p) (((p)->flags & ~(XZ_BF_NUM_FILTERS_MASK | XZ_BF_PACK_SIZE | XZ_BF_UNPACK_SIZE)) != 0)
SRes XzBlock_Parse(CXzBlock *p, const Byte *header);
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes);
/* ---------- xz stream ---------- */
#define XZ_SIG_SIZE 6
#define XZ_FOOTER_SIG_SIZE 2
extern const Byte XZ_SIG[XZ_SIG_SIZE];
/*
extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
*/
#define XZ_FOOTER_SIG_0 'Y'
#define XZ_FOOTER_SIG_1 'Z'
#define XZ_STREAM_FLAGS_SIZE 2
#define XZ_STREAM_CRC_SIZE 4
#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)
#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)
#define XZ_CHECK_MASK 0xF
#define XZ_CHECK_NO 0
#define XZ_CHECK_CRC32 1
#define XZ_CHECK_CRC64 4
#define XZ_CHECK_SHA256 10
typedef struct
{
unsigned mode;
UInt32 crc;
UInt64 crc64;
CSha256 sha;
} CXzCheck;
void XzCheck_Init(CXzCheck *p, unsigned mode);
void XzCheck_Update(CXzCheck *p, const void *data, size_t size);
int XzCheck_Final(CXzCheck *p, Byte *digest);
typedef UInt16 CXzStreamFlags;
#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)
#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)
#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)
unsigned XzFlags_GetCheckSize(CXzStreamFlags f);
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf);
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream);
typedef struct
{
UInt64 unpackSize;
UInt64 totalSize;
} CXzBlockSizes;
typedef struct
{
CXzStreamFlags flags;
// Byte _pad[6];
size_t numBlocks;
CXzBlockSizes *blocks;
UInt64 startOffset;
} CXzStream;
void Xz_Construct(CXzStream *p);
void Xz_Free(CXzStream *p, ISzAllocPtr alloc);
#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)
UInt64 Xz_GetUnpackSize(const CXzStream *p);
UInt64 Xz_GetPackSize(const CXzStream *p);
typedef struct
{
size_t num;
size_t numAllocated;
CXzStream *streams;
} CXzs;
void Xzs_Construct(CXzs *p);
void Xzs_Free(CXzs *p, ISzAllocPtr alloc);
SRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr inStream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc);
UInt64 Xzs_GetNumBlocks(const CXzs *p);
UInt64 Xzs_GetUnpackSize(const CXzs *p);
// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
typedef enum
{
CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */
CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
CODER_STATUS_NOT_FINISHED, /* stream was not finished */
CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */
} ECoderStatus;
// ECoderFinishMode values are identical to ELzmaFinishMode
typedef enum
{
CODER_FINISH_ANY, /* finish at any point */
CODER_FINISH_END /* block must be finished at the end */
} ECoderFinishMode;
typedef struct
{
void *p; // state object;
void (*Free)(void *p, ISzAllocPtr alloc);
SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAllocPtr alloc);
void (*Init)(void *p);
SRes (*Code2)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
int srcWasFinished, ECoderFinishMode finishMode,
// int *wasFinished,
ECoderStatus *status);
SizeT (*Filter)(void *p, Byte *data, SizeT size);
} IStateCoder;
typedef struct
{
UInt32 methodId;
UInt32 delta;
UInt32 ip;
UInt32 X86_State;
Byte delta_State[DELTA_STATE_SIZE];
} CXzBcFilterStateBase;
typedef SizeT (*Xz_Func_BcFilterStateBase_Filter)(CXzBcFilterStateBase *p, Byte *data, SizeT size);
SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id,
Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc);
#define MIXCODER_NUM_FILTERS_MAX 4
typedef struct
{
ISzAllocPtr alloc;
Byte *buf;
unsigned numCoders;
Byte *outBuf;
size_t outBufSize;
size_t outWritten; // is equal to lzmaDecoder.dicPos (in outBuf mode)
BoolInt wasFinished;
SRes res;
ECoderStatus status;
// BoolInt SingleBufMode;
int finished[MIXCODER_NUM_FILTERS_MAX - 1];
size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];
size_t size[MIXCODER_NUM_FILTERS_MAX - 1];
UInt64 ids[MIXCODER_NUM_FILTERS_MAX];
SRes results[MIXCODER_NUM_FILTERS_MAX];
IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];
} CMixCoder;
typedef enum
{
XZ_STATE_STREAM_HEADER,
XZ_STATE_STREAM_INDEX,
XZ_STATE_STREAM_INDEX_CRC,
XZ_STATE_STREAM_FOOTER,
XZ_STATE_STREAM_PADDING,
XZ_STATE_BLOCK_HEADER,
XZ_STATE_BLOCK,
XZ_STATE_BLOCK_FOOTER
} EXzState;
typedef struct
{
EXzState state;
unsigned pos;
unsigned alignPos;
unsigned indexPreSize;
CXzStreamFlags streamFlags;
unsigned blockHeaderSize;
UInt64 packSize;
UInt64 unpackSize;
UInt64 numBlocks; // number of finished blocks in current stream
UInt64 indexSize;
UInt64 indexPos;
UInt64 padSize;
UInt64 numStartedStreams;
UInt64 numFinishedStreams;
UInt64 numTotalBlocks;
UInt32 crc;
CMixCoder decoder;
CXzBlock block;
CXzCheck check;
CSha256 sha;
BoolInt parseMode;
BoolInt headerParsedOk;
BoolInt decodeToStreamSignature;
unsigned decodeOnlyOneBlock;
Byte *outBuf;
size_t outBufSize;
size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked
Byte shaDigest[SHA256_DIGEST_SIZE];
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
} CXzUnpacker;
/* alloc : aligned for cache line allocation is better */
void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc);
void XzUnpacker_Init(CXzUnpacker *p);
void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize);
void XzUnpacker_Free(CXzUnpacker *p);
/*
XzUnpacker
The sequence for decoding functions:
{
XzUnpacker_Construct()
[Decoding_Calls]
XzUnpacker_Free()
}
[Decoding_Calls]
There are 3 types of interfaces for [Decoding_Calls] calls:
Interface-1 : Partial output buffers:
{
XzUnpacker_Init()
for()
{
XzUnpacker_Code();
}
XzUnpacker_IsStreamWasFinished()
}
Interface-2 : Direct output buffer:
Use it, if you know exact size of decoded data, and you need
whole xz unpacked data in one output buffer.
xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode.
{
XzUnpacker_Init()
XzUnpacker_SetOutBufMode(); // to set output buffer and size
for()
{
XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code()
}
XzUnpacker_IsStreamWasFinished()
}
Interface-3 : Direct output buffer : One call full decoding
It unpacks whole input buffer to output buffer in one call.
It uses Interface-2 internally.
{
XzUnpacker_CodeFull()
XzUnpacker_IsStreamWasFinished()
}
*/
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
CODER_FINISH_ANY - use smallest number of input bytes
CODER_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
CODER_STATUS_NOT_FINISHED,
CODER_STATUS_NEEDS_MORE_INPUT - the decoder can return it in two cases:
1) it needs more input data to finish current xz stream
2) xz stream was finished successfully. But the decoder supports multiple
concatented xz streams. So it expects more input data for new xz streams.
Call XzUnpacker_IsStreamWasFinished() to check that latest xz stream was finished successfully.
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_DATA - Data error
SZ_ERROR_UNSUPPORTED - Unsupported method or method properties
SZ_ERROR_CRC - CRC error
// SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons:
- xz Stream Signature failure
- CRC32 of xz Stream Header is failed
- The size of Stream padding is not multiple of four bytes.
It's possible to get that error, if xz stream was finished and the stream
contains some another data. In that case you can call XzUnpacker_GetExtraSize()
function to get real size of xz stream.
*/
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int srcFinished,
ECoderFinishMode finishMode, ECoderStatus *status);
SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen,
ECoderFinishMode finishMode, ECoderStatus *status);
/*
If you decode full xz stream(s), then you can call XzUnpacker_IsStreamWasFinished()
after successful XzUnpacker_CodeFull() or after last call of XzUnpacker_Code().
*/
BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p);
/*
XzUnpacker_GetExtraSize() returns then number of unconfirmed bytes,
if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state.
These bytes can be some data after xz archive, or
it can be start of new xz stream.
Call XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of
xz stream in two cases, if XzUnpacker_Code() returns:
res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT
res == SZ_ERROR_NO_ARCHIVE
*/
UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p);
/*
for random block decoding:
XzUnpacker_Init();
set CXzUnpacker::streamFlags
XzUnpacker_PrepareToRandomBlockDecoding()
loop
{
XzUnpacker_Code()
XzUnpacker_IsBlockFinished()
}
*/
void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p);
BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p);
#define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags))
/* ---- Single-Thread and Multi-Thread xz Decoding with Input/Output Streams ---- */
/*
if (CXzDecMtProps::numThreads > 1), the decoder can try to use
Multi-Threading. The decoder analyses xz block header, and if
there are pack size and unpack size values stored in xz block header,
the decoder reads compressed data of block to internal buffers,
and then it can start parallel decoding, if there are another blocks.
The decoder can switch back to Single-Thread decoding after some conditions.
The sequence of calls for xz decoding with in/out Streams:
{
XzDecMt_Create()
XzDecMtProps_Init(XzDecMtProps) to set default values of properties
// then you can change some XzDecMtProps parameters with required values
// here you can set the number of threads and (memUseMax) - the maximum
Memory usage for multithreading decoding.
for()
{
XzDecMt_Decode() // one call per one file
}
XzDecMt_Destroy()
}
*/
typedef struct
{
size_t inBufSize_ST; // size of input buffer for Single-Thread decoding
size_t outStep_ST; // size of output buffer for Single-Thread decoding
BoolInt ignoreErrors; // if set to 1, the decoder can ignore some errors and it skips broken parts of data.
#ifndef Z7_ST
unsigned numThreads; // the number of threads for Multi-Thread decoding. if (umThreads == 1) it will use Single-thread decoding
size_t inBufSize_MT; // size of small input data buffers for Multi-Thread decoding. Big number of such small buffers can be created
size_t memUseMax; // the limit of total memory usage for Multi-Thread decoding.
// it's recommended to set (memUseMax) manually to value that is smaller of total size of RAM in computer.
#endif
} CXzDecMtProps;
void XzDecMtProps_Init(CXzDecMtProps *p);
typedef struct CXzDecMt CXzDecMt;
typedef CXzDecMt * CXzDecMtHandle;
// Z7_DECLARE_HANDLE(CXzDecMtHandle)
/*
alloc : XzDecMt uses CAlignOffsetAlloc internally for addresses allocated by (alloc).
allocMid : for big allocations, aligned allocation is better
*/
CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);
void XzDecMt_Destroy(CXzDecMtHandle p);
typedef struct
{
Byte UnpackSize_Defined;
Byte NumStreams_Defined;
Byte NumBlocks_Defined;
Byte DataAfterEnd; // there are some additional data after good xz streams, and that data is not new xz stream.
Byte DecodingTruncated; // Decoding was Truncated, we need only partial output data
UInt64 InSize; // pack size processed. That value doesn't include the data after
// end of xz stream, if that data was not correct
UInt64 OutSize;
UInt64 NumStreams;
UInt64 NumBlocks;
SRes DecodeRes; // the error code of xz streams data decoding
SRes ReadRes; // error code from ISeqInStream:Read()
SRes ProgressRes; // error code from ICompressProgress:Progress()
SRes CombinedRes; // Combined result error code that shows main rusult
// = S_OK, if there is no error.
// but check also (DataAfterEnd) that can show additional minor errors.
SRes CombinedRes_Type; // = SZ_ERROR_READ, if error from ISeqInStream
// = SZ_ERROR_PROGRESS, if error from ICompressProgress
// = SZ_ERROR_WRITE, if error from ISeqOutStream
// = SZ_ERROR_* codes for decoding
} CXzStatInfo;
void XzStatInfo_Clear(CXzStatInfo *p);
/*
XzDecMt_Decode()
SRes: it's combined decoding result. It also is equal to stat->CombinedRes.
SZ_OK - no error
check also output value in (stat->DataAfterEnd)
that can show additional possible error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_NO_ARCHIVE - is not xz archive
SZ_ERROR_ARCHIVE - Headers error
SZ_ERROR_DATA - Data Error
SZ_ERROR_UNSUPPORTED - Unsupported method or method properties
SZ_ERROR_CRC - CRC Error
SZ_ERROR_INPUT_EOF - it needs more input data
SZ_ERROR_WRITE - ISeqOutStream error
(SZ_ERROR_READ) - ISeqInStream errors
(SZ_ERROR_PROGRESS) - ICompressProgress errors
// SZ_ERROR_THREAD - error in multi-threading functions
MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function
*/
SRes XzDecMt_Decode(CXzDecMtHandle p,
const CXzDecMtProps *props,
const UInt64 *outDataSize, // NULL means undefined
int finishMode, // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished
ISeqOutStreamPtr outStream,
// Byte *outBuf, size_t *outBufSize,
ISeqInStreamPtr inStream,
// const Byte *inData, size_t inDataSize,
CXzStatInfo *stat, // out: decoding results and statistics
int *isMT, // out: 0 means that ST (Single-Thread) version was used
// 1 means that MT (Multi-Thread) version was used
ICompressProgressPtr progress);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,26 @@
/* XzCrc64.h -- CRC64 calculation
2023-12-08 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_XZ_CRC64_H
#define ZIP7_INC_XZ_CRC64_H
#include <stddef.h>
#include "7zTypes.h"
EXTERN_C_BEGIN
// extern UInt64 g_Crc64Table[];
void Z7_FASTCALL Crc64GenerateTable(void);
#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF)
#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL)
// #define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt64 Z7_FASTCALL Crc64Update(UInt64 crc, const void *data, size_t size);
// UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,61 @@
/* XzEnc.h -- Xz Encode
2023-04-13 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_XZ_ENC_H
#define ZIP7_INC_XZ_ENC_H
#include "Lzma2Enc.h"
#include "Xz.h"
EXTERN_C_BEGIN
#define XZ_PROPS_BLOCK_SIZE_AUTO LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO
#define XZ_PROPS_BLOCK_SIZE_SOLID LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
typedef struct
{
UInt32 id;
UInt32 delta;
UInt32 ip;
int ipDefined;
} CXzFilterProps;
void XzFilterProps_Init(CXzFilterProps *p);
typedef struct
{
CLzma2EncProps lzma2Props;
CXzFilterProps filterProps;
unsigned checkId;
UInt64 blockSize;
int numBlockThreads_Reduced;
int numBlockThreads_Max;
int numTotalThreads;
int forceWriteSizesInHeader;
UInt64 reduceSize;
} CXzProps;
void XzProps_Init(CXzProps *p);
typedef struct CXzEnc CXzEnc;
typedef CXzEnc * CXzEncHandle;
// Z7_DECLARE_HANDLE(CXzEncHandle)
CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);
void XzEnc_Destroy(CXzEncHandle p);
SRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props);
void XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize);
SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress);
SRes Xz_Encode(ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream,
const CXzProps *props, ICompressProgressPtr progress);
SRes Xz_EncodeEmpty(ISeqOutStreamPtr outStream);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,173 @@
/* ZstdDec.h -- Zstd Decoder interfaces
2024-01-21 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_ZSTD_DEC_H
#define ZIP7_INC_ZSTD_DEC_H
EXTERN_C_BEGIN
typedef struct CZstdDec CZstdDec;
typedef CZstdDec * CZstdDecHandle;
CZstdDecHandle ZstdDec_Create(ISzAllocPtr alloc_Small, ISzAllocPtr alloc_Big);
void ZstdDec_Destroy(CZstdDecHandle p);
typedef enum
{
ZSTD_STATUS_NOT_SPECIFIED, /* use main error code instead */
ZSTD_STATUS_FINISHED_FRAME, /* data frame or skip frame was finished */
ZSTD_STATUS_NOT_FINISHED, /* just finished non-empty block or unfinished RAW/RLE block */
ZSTD_STATUS_NEEDS_MORE_INPUT, /* the callee needs more input bytes. It has more priority over ZSTD_STATUS_NOT_FINISHED */
ZSTD_STATUS_OUT_REACHED /* is not finihed frame and ((outProcessed > outSize) || (outProcessed == outSize && unfinished RAW/RLE block) */
} enum_ZstdStatus_Dummy;
#define ZstdDecState_DOES_NEED_MORE_INPUT_OR_FINISHED_FRAME(p) \
((p)->status & ZSTD_STATUS_FINISHED_FRAME)
/*
((p)->status == ZSTD_STATUS_NEEDS_MORE_INPUT || \
(p)->status == ZSTD_STATUS_FINISHED_FRAME)
*/
typedef Byte enum_ZstdStatus;
void ZstdDec_Init(CZstdDecHandle p);
typedef struct
{
UInt64 num_Blocks;
Byte descriptor_OR;
Byte descriptor_NOT_OR;
Byte are_ContentSize_Unknown;
Byte windowDescriptor_MAX;
// Byte are_ContentSize_Known;
// Byte are_SingleSegments;
// Byte are_WindowDescriptors;
Byte checksum_Defined;
// Byte are_Checksums;
// Byte are_Non_Checksums;
// Byte are_DictionaryId;
Byte are_DictionaryId_Different;
// Byte reserved[3];
UInt32 checksum; // checksum of last data frame
/// UInt32 dictionaryId_Cur;
UInt32 dictionaryId; // if there are non-zero dictionary IDs, then it's first dictionaryId
UInt64 num_DataFrames;
UInt64 num_SkipFrames;
UInt64 skipFrames_Size;
UInt64 contentSize_Total;
UInt64 contentSize_MAX;
// UInt64 num_Checksums;
// UInt64 num_Non_Checksums; // frames without checksum
// UInt64 num_WindowDescriptors;
// UInt64 num_SingleSegments;
// UInt64 num_Frames_with_ContentSize;
// UInt64 num_Frames_without_ContentSize;
UInt64 windowSize_MAX;
UInt64 windowSize_Allocate_MAX;
// UInt64 num_DictionaryIds;
// UInt64 num_Blocks_forType[4];
// UInt64 num_BlockBytes_forType[4];
// UInt64 num_SingleSegments;
// UInt64 singleSegment_ContentSize_MAX;
} CZstdDecInfo;
#define ZstdDecInfo_CLEAR(p) { memset(p, 0, sizeof(*(p))); }
#define ZstdDecInfo_GET_NUM_FRAMES(p) ((p)->num_DataFrames + (p)->num_SkipFrames)
typedef struct CZstdDecState
{
enum_ZstdStatus status; // out
Byte disableHash;
// Byte mustBeFinished;
Byte outSize_Defined;
// Byte isAfterSizeMode;
// UInt64 inProcessed;
// SRes codeRes;
// Byte needWrite_IsStrong;
const Byte *inBuf;
size_t inPos; // in/out
size_t inLim;
const Byte *win; // out
size_t winPos; // out
size_t wrPos; // in/out
// size_t cycSize; // out : if (!outBuf_fromCaller)
size_t needWrite_Size; // out
Byte *outBuf_fromCaller;
size_t outBufSize_fromCaller;
/* (outBufSize_fromCaller >= full_uncompressed_size_of_all_frames) is required
for success decoding.
If outBufSize_fromCaller < full_uncompressed_size_of_all_frames),
decoding can give error message, because we decode per block basis.
*/
// size_t outStep;
UInt64 outSize; // total in all frames
UInt64 outProcessed; // out decoded in all frames (it can be >= outSize)
CZstdDecInfo info;
} CZstdDecState;
void ZstdDecState_Clear(CZstdDecState *p);
/*
ZstdDec_Decode()
return:
SZ_OK - no error
SZ_ERROR_DATA - Data Error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported method or method properties
SZ_ERROR_CRC - XXH hash Error
// SZ_ERROR_ARCHIVE - Headers error (not used now)
*/
SRes ZstdDec_Decode(CZstdDecHandle dec, CZstdDecState *p);
/*
ZstdDec_ReadUnusedFromInBuf():
returns: the number of bytes that were read from InBuf
(*afterDecoding_tempPos) must be set to zero before first call of ZstdDec_ReadUnusedFromInBuf()
*/
size_t ZstdDec_ReadUnusedFromInBuf(
CZstdDecHandle dec,
size_t afterDecoding_tempPos, // in/out
void *data, size_t size);
typedef struct
{
SRes decode_SRes; // error code of data decoding
Byte is_NonFinishedFrame; // there is unfinished decoding for data frame or skip frame
Byte extraSize;
} CZstdDecResInfo;
/*
#define ZstdDecResInfo_CLEAR(p) \
{ (p)->decode_SRes = 0; \
(p)->is_NonFinishedFrame; \
(p)->extraSize = 0; \
}
// memset(p, 0, sizeof(*p));
*/
/*
additional error codes for CZstdDecResInfo::decode_SRes:
SZ_ERROR_NO_ARCHIVE - is not zstd stream (no frames)
SZ_ERROR_INPUT_EOF - need more data in input stream
*/
void ZstdDec_GetResInfo(const CZstdDec *dec,
const CZstdDecState *p,
SRes res, // it's result from ZstdDec_Decode()
CZstdDecResInfo *info);
EXTERN_C_END
#endif

View File

@@ -0,0 +1,6 @@
// DeflateProps.h
#ifndef ZIP7_INC_DEFLATE_PROPS_H
#define ZIP7_INC_DEFLATE_PROPS_H
#endif

View File

@@ -0,0 +1,134 @@
// HandlerCont.h
#ifndef ZIP7_INC_HANDLER_CONT_H
#define ZIP7_INC_HANDLER_CONT_H
#include "../../Common/MyCom.h"
#include "IArchive.h"
namespace NArchive {
#define Z7_IFACEM_IInArchive_Cont(x) \
x(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) \
x(Close()) \
x(GetNumberOfItems(UInt32 *numItems)) \
x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \
/* x(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) */ \
x(GetArchiveProperty(PROPID propID, PROPVARIANT *value)) \
x(GetNumberOfProperties(UInt32 *numProps)) \
x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
x(GetNumberOfArchiveProperties(UInt32 *numProps)) \
x(GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
// #define Z7_COM7F_PUREO(f) virtual Z7_COM7F_IMF(f) Z7_override =0;
// #define Z7_COM7F_PUREO2(t, f) virtual Z7_COM7F_IMF2(t, f) Z7_override =0;
class CHandlerCont:
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp
{
Z7_COM_UNKNOWN_IMP_2(
IInArchive,
IInArchiveGetStream)
/*
Z7_IFACEM_IInArchive_Cont(Z7_COM7F_PUREO)
// Z7_IFACE_COM7_PURE(IInArchive_Cont)
*/
Z7_COM7F_IMP(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback))
protected:
Z7_IFACE_COM7_IMP(IInArchiveGetStream)
CMyComPtr<IInStream> _stream;
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const = 0;
// destructor must be virtual for this class
virtual ~CHandlerCont() {}
};
#define Z7_IFACEM_IInArchive_Img(x) \
/* x(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) */ \
x(Close()) \
/* x(GetNumberOfItems(UInt32 *numItems)) */ \
x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \
/* x(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) */ \
x(GetArchiveProperty(PROPID propID, PROPVARIANT *value)) \
x(GetNumberOfProperties(UInt32 *numProps)) \
x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
x(GetNumberOfArchiveProperties(UInt32 *numProps)) \
x(GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
class CHandlerImg:
public IInArchive,
public IInArchiveGetStream,
public IInStream,
public CMyUnknownImp
{
Z7_COM_UNKNOWN_IMP_4(
IInArchive,
IInArchiveGetStream,
ISequentialInStream,
IInStream)
Z7_COM7F_IMP(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback))
Z7_COM7F_IMP(GetNumberOfItems(UInt32 *numItems))
Z7_COM7F_IMP(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback))
Z7_IFACE_COM7_IMP(IInStream)
// Z7_IFACEM_IInArchive_Img(Z7_COM7F_PUREO)
protected:
bool _stream_unavailData;
bool _stream_unsupportedMethod;
bool _stream_dataError;
// bool _stream_UsePackSize;
// UInt64 _stream_PackSize;
UInt64 _virtPos;
UInt64 _posInArc;
UInt64 _size;
CMyComPtr<IInStream> Stream;
const char *_imgExt;
void Reset_PosInArc() { _posInArc = (UInt64)0 - 1; }
void Reset_VirtPos() { _virtPos = (UInt64)0; }
void ClearStreamVars()
{
_stream_unavailData = false;
_stream_unsupportedMethod = false;
_stream_dataError = false;
// _stream_UsePackSize = false;
// _stream_PackSize = 0;
}
void Clear_HandlerImg_Vars(); // it doesn't Release (Stream) var.
virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) = 0;
virtual void CloseAtError();
// returns (true), if Get_PackSizeProcessed() is required in Extract()
virtual bool Init_PackSizeProcessed()
{
return false;
}
public:
virtual bool Get_PackSizeProcessed(UInt64 &size)
{
size = 0;
return false;
}
CHandlerImg();
// destructor must be virtual for this class
virtual ~CHandlerImg() {}
};
HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize);
}
#endif

View File

@@ -0,0 +1,87 @@
// HfsHandler.h
#ifndef ZIP7_INC_HFS_HANDLER_H
#define ZIP7_INC_HFS_HANDLER_H
#include "../../Windows/PropVariant.h"
#include "../Compress/LzfseDecoder.h"
#include "../Compress/ZlibDecoder.h"
namespace NArchive {
namespace NHfs {
static const UInt32 k_decmpfs_HeaderSize = 16;
struct CCompressHeader
{
UInt64 UnpackSize;
UInt32 Method;
Byte DataPos;
bool IsCorrect;
bool IsSupported;
bool IsResource;
bool IsMethod_Compressed_Inline() const { return DataPos == k_decmpfs_HeaderSize; }
bool IsMethod_Uncompressed_Inline() const { return DataPos == k_decmpfs_HeaderSize + 1; }
bool IsMethod_Resource() const { return IsResource; }
void Parse(const Byte *p, size_t size);
void Clear()
{
UnpackSize = 0;
Method = 0;
DataPos = 0;
IsCorrect = false;
IsSupported = false;
IsResource = false;
}
CCompressHeader() { Clear(); }
void MethodToProp(NWindows::NCOM::CPropVariant &prop) const;
};
void MethodsMaskToProp(UInt32 methodsMask, NWindows::NCOM::CPropVariant &prop);
class CDecoder
{
CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> _zlibDecoder;
CMyComPtr2_Create<ICompressCoder, NCompress::NLzfse::CDecoder> _lzfseDecoder;
CByteBuffer _tableBuf;
CByteBuffer _buf;
HRESULT ExtractResourceFork_ZLIB(
ISequentialInStream *inStream, ISequentialOutStream *realOutStream,
UInt64 forkSize, UInt64 unpackSize,
UInt64 progressStart, IArchiveExtractCallback *extractCallback);
HRESULT ExtractResourceFork_LZFSE(
ISequentialInStream *inStream, ISequentialOutStream *realOutStream,
UInt64 forkSize, UInt64 unpackSize,
UInt64 progressStart, IArchiveExtractCallback *extractCallback);
HRESULT ExtractResourceFork_ZBM(
ISequentialInStream *inStream, ISequentialOutStream *realOutStream,
UInt64 forkSize, UInt64 unpackSize,
UInt64 progressStart, IArchiveExtractCallback *extractCallback);
public:
HRESULT Extract(
ISequentialInStream *inStreamFork, ISequentialOutStream *realOutStream,
UInt64 forkSize,
const CCompressHeader &compressHeader,
const CByteBuffer *data,
UInt64 progressStart, IArchiveExtractCallback *extractCallback,
int &opRes);
CDecoder(bool IsAdlerOptional);
};
}}
#endif

View File

@@ -0,0 +1,754 @@
// IArchive.h
#ifndef ZIP7_INC_IARCHIVE_H
#define ZIP7_INC_IARCHIVE_H
#include "../IProgress.h"
#include "../IStream.h"
#include "../PropID.h"
Z7_PURE_INTERFACES_BEGIN
#define Z7_IFACE_CONSTR_ARCHIVE_SUB(i, base, n) \
Z7_DECL_IFACE_7ZIP_SUB(i, base, 6, n) \
{ Z7_IFACE_COM7_PURE(i) };
#define Z7_IFACE_CONSTR_ARCHIVE(i, n) \
Z7_IFACE_CONSTR_ARCHIVE_SUB(i, IUnknown, n)
/*
How the function in 7-Zip returns object for output parameter via pointer
1) The caller sets the value of variable before function call:
PROPVARIANT : vt = VT_EMPTY
BSTR : NULL
IUnknown* and derived interfaces : NULL
another scalar types : any non-initialized value is allowed
2) The callee in current 7-Zip code now can free input object for output parameter:
PROPVARIANT : the callee calls VariantClear(propvaiant_ptr) for input
value stored in variable
another types : the callee ignores stored value.
3) The callee writes new value to variable for output parameter and
returns execution to caller.
4) The caller must free or release object returned by the callee:
PROPVARIANT : VariantClear(&propvaiant)
BSTR : SysFreeString(bstr)
IUnknown* and derived interfaces : if (ptr) ptr->Relase()
*/
namespace NFileTimeType
{
enum EEnum
{
kNotDefined = -1,
kWindows = 0,
kUnix,
kDOS,
k1ns
};
}
namespace NArcInfoFlags
{
const UInt32 kKeepName = 1 << 0; // keep name of file in archive name
const UInt32 kAltStreams = 1 << 1; // the handler supports alt streams
const UInt32 kNtSecure = 1 << 2; // the handler supports NT security
const UInt32 kFindSignature = 1 << 3; // the handler can find start of archive
const UInt32 kMultiSignature = 1 << 4; // there are several signatures
const UInt32 kUseGlobalOffset = 1 << 5; // the seek position of stream must be set as global offset
const UInt32 kStartOpen = 1 << 6; // call handler for each start position
const UInt32 kPureStartOpen = 1 << 7; // call handler only for start of file
const UInt32 kBackwardOpen = 1 << 8; // archive can be open backward
const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub)
const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links
const UInt32 kHardLinks = 1 << 11; // the handler supports hard links
const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches
const UInt32 kHashHandler = 1 << 13; // the handler contains the hashes (checksums)
const UInt32 kCTime = 1 << 14;
const UInt32 kCTime_Default = 1 << 15;
const UInt32 kATime = 1 << 16;
const UInt32 kATime_Default = 1 << 17;
const UInt32 kMTime = 1 << 18;
const UInt32 kMTime_Default = 1 << 19;
// const UInt32 kTTime_Reserved = 1 << 20;
// const UInt32 kTTime_Reserved_Default = 1 << 21;
}
namespace NArcInfoTimeFlags
{
const unsigned kTime_Prec_Mask_bit_index = 0;
const unsigned kTime_Prec_Mask_num_bits = 26;
const unsigned kTime_Prec_Default_bit_index = 27;
const unsigned kTime_Prec_Default_num_bits = 5;
}
#define TIME_PREC_TO_ARC_FLAGS_MASK(v) \
((UInt32)1 << (NArcInfoTimeFlags::kTime_Prec_Mask_bit_index + (v)))
#define TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(v) \
((UInt32)(v) << NArcInfoTimeFlags::kTime_Prec_Default_bit_index)
namespace NArchive
{
namespace NHandlerPropID
{
enum
{
kName = 0, // VT_BSTR
kClassID, // binary GUID in VT_BSTR
kExtension, // VT_BSTR
kAddExtension, // VT_BSTR
kUpdate, // VT_BOOL
kKeepName, // VT_BOOL
kSignature, // binary in VT_BSTR
kMultiSignature, // binary in VT_BSTR
kSignatureOffset, // VT_UI4
kAltStreams, // VT_BOOL
kNtSecure, // VT_BOOL
kFlags, // VT_UI4
kTimeFlags // VT_UI4
};
}
namespace NExtract
{
namespace NAskMode
{
enum
{
kExtract = 0,
kTest,
kSkip,
kReadExternal
};
}
namespace NOperationResult
{
enum
{
kOK = 0,
kUnsupportedMethod,
kDataError,
kCRCError,
kUnavailable,
kUnexpectedEnd,
kDataAfterEnd,
kIsNotArc,
kHeadersError,
kWrongPassword
// , kMemError
};
}
}
namespace NEventIndexType
{
enum
{
kNoIndex = 0,
kInArcIndex,
kBlockIndex,
kOutArcIndex
// kArcProp
};
}
namespace NUpdate
{
namespace NOperationResult
{
enum
{
kOK = 0
// kError = 1,
// kError_FileChanged
};
}
}
}
#define Z7_IFACEM_IArchiveOpenCallback(x) \
x(SetTotal(const UInt64 *files, const UInt64 *bytes)) \
x(SetCompleted(const UInt64 *files, const UInt64 *bytes)) \
Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpenCallback, 0x10)
/*
IArchiveExtractCallback::
7-Zip doesn't call IArchiveExtractCallback functions
GetStream()
PrepareOperation()
SetOperationResult()
from different threads simultaneously.
But 7-Zip can call functions for IProgress or ICompressProgressInfo functions
from another threads simultaneously with calls for IArchiveExtractCallback interface.
IArchiveExtractCallback::GetStream()
UInt32 index - index of item in Archive
Int32 askExtractMode (Extract::NAskMode)
if (askMode != NExtract::NAskMode::kExtract)
{
then the callee doesn't write data to stream: (*outStream == NULL)
}
Out:
(*outStream == NULL) - for directories
(*outStream == NULL) - if link (hard link or symbolic link) was created
if (*outStream == NULL && askMode == NExtract::NAskMode::kExtract)
{
then the caller must skip extracting of that file.
}
returns:
S_OK : OK
S_FALSE : data error (for decoders)
if (IProgress::SetTotal() was called)
{
IProgress::SetCompleted(completeValue) uses
packSize - for some stream formats (xz, gz, bz2, lzma, z, ppmd).
unpackSize - for another formats.
}
else
{
IProgress::SetCompleted(completeValue) uses packSize.
}
SetOperationResult()
7-Zip calls SetOperationResult at the end of extracting,
so the callee can close the file, set attributes, timestamps and security information.
Int32 opRes (NExtract::NOperationResult)
*/
// INTERFACE_IProgress(x)
#define Z7_IFACEM_IArchiveExtractCallback(x) \
x(GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)) \
x(PrepareOperation(Int32 askExtractMode)) \
x(SetOperationResult(Int32 opRes)) \
Z7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveExtractCallback, IProgress, 0x20)
/*
v23:
IArchiveExtractCallbackMessage2 can be requested from IArchiveExtractCallback object
by Extract() or UpdateItems() functions to report about extracting errors
ReportExtractResult()
UInt32 indexType (NEventIndexType)
UInt32 index
Int32 opRes (NExtract::NOperationResult)
*/
/*
before v23:
#define Z7_IFACEM_IArchiveExtractCallbackMessage(x) \
x(ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes))
Z7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21)
*/
#define Z7_IFACEM_IArchiveExtractCallbackMessage2(x) \
x(ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes))
Z7_IFACE_CONSTR_ARCHIVE(IArchiveExtractCallbackMessage2, 0x22)
#define Z7_IFACEM_IArchiveOpenVolumeCallback(x) \
x(GetProperty(PROPID propID, PROPVARIANT *value)) \
x(GetStream(const wchar_t *name, IInStream **inStream))
Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpenVolumeCallback, 0x30)
#define Z7_IFACEM_IInArchiveGetStream(x) \
x(GetStream(UInt32 index, ISequentialInStream **stream))
Z7_IFACE_CONSTR_ARCHIVE(IInArchiveGetStream, 0x40)
#define Z7_IFACEM_IArchiveOpenSetSubArchiveName(x) \
x(SetSubArchiveName(const wchar_t *name))
Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpenSetSubArchiveName, 0x50)
/*
IInArchive::Open
stream
if (kUseGlobalOffset), stream current position can be non 0.
if (!kUseGlobalOffset), stream current position is 0.
if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream
if (*maxCheckStartPosition == 0), the handler must check only current position as archive start
IInArchive::Extract:
indices must be sorted
numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means "all files"
testMode != 0 means "test files without writing to outStream"
IInArchive::GetArchiveProperty:
kpidOffset - start offset of archive.
VT_EMPTY : means offset = 0.
VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed
kpidPhySize - size of archive. VT_EMPTY means unknown size.
kpidPhySize is allowed to be larger than file size. In that case it must show
supposed size.
kpidIsDeleted:
kpidIsAltStream:
kpidIsAux:
kpidINode:
must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty.
Notes:
Don't call IInArchive functions for same IInArchive object from different threads simultaneously.
Some IInArchive handlers will work incorrectly in that case.
*/
#if defined(_MSC_VER) && !defined(__clang__)
#define MY_NO_THROW_DECL_ONLY Z7_COM7F_E
#else
#define MY_NO_THROW_DECL_ONLY
#endif
#define Z7_IFACEM_IInArchive(x) \
x(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) \
x(Close()) \
x(GetNumberOfItems(UInt32 *numItems)) \
x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \
x(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) \
x(GetArchiveProperty(PROPID propID, PROPVARIANT *value)) \
x(GetNumberOfProperties(UInt32 *numProps)) \
x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
x(GetNumberOfArchiveProperties(UInt32 *numProps)) \
x(GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
Z7_IFACE_CONSTR_ARCHIVE(IInArchive, 0x60)
namespace NParentType
{
enum
{
kDir = 0,
kAltStream
};
}
namespace NPropDataType
{
const UInt32 kMask_ZeroEnd = 1 << 4;
// const UInt32 kMask_BigEndian = 1 << 5;
const UInt32 kMask_Utf = 1 << 6;
const UInt32 kMask_Utf8 = kMask_Utf | 0;
const UInt32 kMask_Utf16 = kMask_Utf | 1;
// const UInt32 kMask_Utf32 = kMask_Utf | 2;
const UInt32 kNotDefined = 0;
const UInt32 kRaw = 1;
const UInt32 kUtf8z = kMask_Utf8 | kMask_ZeroEnd;
const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd;
}
// UTF string (pointer to wchar_t) with zero end and little-endian.
#define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1))
/*
GetRawProp:
Result:
S_OK - even if property is not set
*/
#define Z7_IFACEM_IArchiveGetRawProps(x) \
x(GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)) \
x(GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) \
x(GetNumRawProps(UInt32 *numProps)) \
x(GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))
Z7_IFACE_CONSTR_ARCHIVE(IArchiveGetRawProps, 0x70)
#define Z7_IFACEM_IArchiveGetRootProps(x) \
x(GetRootProp(PROPID propID, PROPVARIANT *value)) \
x(GetRootRawProp(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) \
Z7_IFACE_CONSTR_ARCHIVE(IArchiveGetRootProps, 0x71)
#define Z7_IFACEM_IArchiveOpenSeq(x) \
x(OpenSeq(ISequentialInStream *stream)) \
Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpenSeq, 0x61)
/*
OpenForSize
Result:
S_FALSE - is not archive
? - DATA error
*/
/*
const UInt32 kOpenFlags_RealPhySize = 1 << 0;
const UInt32 kOpenFlags_NoSeek = 1 << 1;
// const UInt32 kOpenFlags_BeforeExtract = 1 << 2;
*/
/*
Flags:
0 - opens archive with IInStream, if IInStream interface is supported
- if phySize is not available, it doesn't try to make full parse to get phySize
kOpenFlags_NoSeek - ArcOpen2 function doesn't use IInStream interface, even if it's available
kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file
if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified,
the handler can return S_OK, but it doesn't check even Signature.
So next Extract can be called for that sequential stream.
*/
/*
#define Z7_IFACEM_IArchiveOpen2(x) \
x(ArcOpen2(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback))
Z7_IFACE_CONSTR_ARCHIVE(IArchiveOpen2, 0x62)
*/
// ---------- UPDATE ----------
/*
GetUpdateItemInfo outs:
*newData *newProps
0 0 - Copy data and properties from archive
0 1 - Copy data from archive, request new properties
1 0 - that combination is unused now
1 1 - Request new data and new properties. It can be used even for folders
indexInArchive = -1 if there is no item in archive, or if it doesn't matter.
GetStream out:
Result:
S_OK:
(*inStream == NULL) - only for directories
- the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file
(*inStream != NULL) - for any file, even for empty file or anti-file
S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason)
(*inStream == NULL)
The order of calling for hard links:
- GetStream()
- GetProperty(kpidHardLink)
SetOperationResult()
Int32 opRes (NExtract::NOperationResult::kOK)
*/
// INTERFACE_IProgress(x)
#define Z7_IFACEM_IArchiveUpdateCallback(x) \
x(GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)) \
x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \
x(GetStream(UInt32 index, ISequentialInStream **inStream)) \
x(SetOperationResult(Int32 operationResult)) \
Z7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveUpdateCallback, IProgress, 0x80)
// INTERFACE_IArchiveUpdateCallback(x)
#define Z7_IFACEM_IArchiveUpdateCallback2(x) \
x(GetVolumeSize(UInt32 index, UInt64 *size)) \
x(GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)) \
Z7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
namespace NUpdateNotifyOp
{
enum
{
kAdd = 0,
kUpdate,
kAnalyze,
kReplicate,
kRepack,
kSkip,
kDelete,
kHeader,
kHashRead,
kInFileChanged
// , kOpFinished
// , kNumDefined
};
}
/*
IArchiveUpdateCallbackFile::ReportOperation
UInt32 indexType (NEventIndexType)
UInt32 index
UInt32 notifyOp (NUpdateNotifyOp)
*/
#define Z7_IFACEM_IArchiveUpdateCallbackFile(x) \
x(GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp)) \
x(ReportOperation(UInt32 indexType, UInt32 index, UInt32 notifyOp)) \
Z7_IFACE_CONSTR_ARCHIVE(IArchiveUpdateCallbackFile, 0x83)
#define Z7_IFACEM_IArchiveGetDiskProperty(x) \
x(GetDiskProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \
Z7_IFACE_CONSTR_ARCHIVE(IArchiveGetDiskProperty, 0x84)
/*
#define Z7_IFACEM_IArchiveUpdateCallbackArcProp(x) \
x(ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value)) \
x(ReportRawProp(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType)) \
x(ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes)) \
x(DoNeedArcProp(PROPID propID, Int32 *answer)) \
Z7_IFACE_CONSTR_ARCHIVE(IArchiveUpdateCallbackArcProp, 0x85)
*/
/*
UpdateItems()
-------------
outStream: output stream. (the handler) MUST support the case when
Seek position in outStream is not ZERO.
but the caller calls with empty outStream and seek position is ZERO??
archives with stub:
If archive is open and the handler and (Offset > 0), then the handler
knows about stub size.
UpdateItems():
1) the handler MUST copy that stub to outStream
2) the caller MUST NOT copy the stub to outStream, if
"rsfx" property is set with SetProperties
the handler must support the case where
ISequentialOutStream *outStream
*/
#define Z7_IFACEM_IOutArchive(x) \
x(UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback)) \
x(GetFileTimeType(UInt32 *type))
Z7_IFACE_CONSTR_ARCHIVE(IOutArchive, 0xA0)
/*
ISetProperties::SetProperties()
PROPVARIANT values[i].vt:
VT_EMPTY
VT_BOOL
VT_UI4 - if 32-bit number
VT_UI8 - if 64-bit number
VT_BSTR
*/
#define Z7_IFACEM_ISetProperties(x) \
x(SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
Z7_IFACE_CONSTR_ARCHIVE(ISetProperties, 0x03)
#define Z7_IFACEM_IArchiveKeepModeForNextOpen(x) \
x(KeepModeForNextOpen()) \
Z7_IFACE_CONSTR_ARCHIVE(IArchiveKeepModeForNextOpen, 0x04)
/* Exe handler: the handler for executable format (PE, ELF, Mach-O).
SFX archive: executable stub + some tail data.
before 9.31: exe handler didn't parse SFX archives as executable format.
for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */
#define Z7_IFACEM_IArchiveAllowTail(x) \
x(AllowTail(Int32 allowTail)) \
Z7_IFACE_CONSTR_ARCHIVE(IArchiveAllowTail, 0x05)
namespace NRequestMemoryUseFlags
{
const UInt32 k_AllowedSize_WasForced = 1 << 0; // (*allowedSize) was forced by -mmemx or -smemx
const UInt32 k_DefaultLimit_Exceeded = 1 << 1; // default limit of archive format was exceeded
const UInt32 k_MLimit_Exceeded = 1 << 2; // -mmemx value was exceeded
const UInt32 k_SLimit_Exceeded = 1 << 3; // -smemx value was exceeded
const UInt32 k_NoErrorMessage = 1 << 10; // do not show error message, and show only request
const UInt32 k_IsReport = 1 << 11; // only report is required, without user request
const UInt32 k_SkipArc_IsExpected = 1 << 12; // NRequestMemoryAnswerFlags::k_SkipArc flag answer is expected
const UInt32 k_Report_SkipArc = 1 << 13; // report about SkipArc operation
// const UInt32 k_SkipBigFile_IsExpected = 1 << 14; // NRequestMemoryAnswerFlags::k_SkipBigFiles flag answer is expected (unused)
// const UInt32 k_Report_SkipBigFile = 1 << 15; // report about SkipFile operation (unused)
// const UInt32 k_SkipBigFiles_IsExpected = 1 << 16; // NRequestMemoryAnswerFlags::k_SkipBigFiles flag answer is expected (unused)
// const UInt32 k_Report_SkipBigFiles = 1 << 17; // report that all big files will be skipped (unused)
}
namespace NRequestMemoryAnswerFlags
{
const UInt32 k_Allow = 1 << 0; // allow further archive extraction
const UInt32 k_Stop = 1 << 1; // for exit (and return_code == E_ABORT is used)
const UInt32 k_SkipArc = 1 << 2; // skip current archive extraction
// const UInt32 k_SkipBigFile = 1 << 4; // skip extracting of files that exceed limit (unused)
// const UInt32 k_SkipBigFiles = 1 << 5; // skip extracting of files that exceed limit (unused)
const UInt32 k_Limit_Exceeded = 1 << 10; // limit was exceeded
}
/*
*allowedSize is in/out:
in : default allowed memory usage size or forced size, if it was changed by switch -mmemx.
out : value specified by user or unchanged value.
*answerFlags is in/out:
*answerFlags must be set by caller before calling for default action,
indexType : must be set with NEventIndexType::* constant
(indexType == kNoIndex), if request for whole archive.
index : must be set for some (indexType) types (if
fileIndex , if (indexType == NEventIndexType::kInArcIndex)
0, if if (indexType == kNoIndex)
path : NULL can be used for any indexType.
*/
#define Z7_IFACEM_IArchiveRequestMemoryUseCallback(x) \
x(RequestMemoryUse(UInt32 flags, UInt32 indexType, UInt32 index, const wchar_t *path, \
UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))
Z7_IFACE_CONSTR_ARCHIVE(IArchiveRequestMemoryUseCallback, 0x09)
struct CStatProp
{
const char *Name;
UInt32 PropID;
VARTYPE vt;
};
namespace NWindows {
namespace NCOM {
// PropVariant.cpp
BSTR AllocBstrFromAscii(const char *s) throw();
}}
#define IMP_IInArchive_GetProp_Base(fn, f, k) \
Z7_COM7F_IMF(CHandler::fn(UInt32 *numProps)) \
{ *numProps = Z7_ARRAY_SIZE(k); return S_OK; } \
Z7_COM7F_IMF(CHandler::f(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
{ if (index >= Z7_ARRAY_SIZE(k)) return E_INVALIDARG; \
#define IMP_IInArchive_GetProp_NO_NAME(fn, f, k) \
IMP_IInArchive_GetProp_Base(fn, f, k) \
*propID = k[index]; \
*varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; \
*name = NULL; return S_OK; } \
#define IMP_IInArchive_GetProp_WITH_NAME(fn, f, k) \
IMP_IInArchive_GetProp_Base(fn, f, k) \
const CStatProp &prop = k[index]; \
*propID = (PROPID)prop.PropID; \
*varType = prop.vt; \
*name = NWindows::NCOM::AllocBstrFromAscii(prop.Name); return S_OK; } \
#define IMP_IInArchive_Props \
IMP_IInArchive_GetProp_NO_NAME(GetNumberOfProperties, GetPropertyInfo, kProps)
#define IMP_IInArchive_Props_WITH_NAME \
IMP_IInArchive_GetProp_WITH_NAME(GetNumberOfProperties, GetPropertyInfo, kProps)
#define IMP_IInArchive_ArcProps \
IMP_IInArchive_GetProp_NO_NAME(GetNumberOfArchiveProperties, GetArchivePropertyInfo, kArcProps)
#define IMP_IInArchive_ArcProps_WITH_NAME \
IMP_IInArchive_GetProp_WITH_NAME(GetNumberOfArchiveProperties, GetArchivePropertyInfo, kArcProps)
#define IMP_IInArchive_ArcProps_NO_Table \
Z7_COM7F_IMF(CHandler::GetNumberOfArchiveProperties(UInt32 *numProps)) \
{ *numProps = 0; return S_OK; } \
Z7_COM7F_IMF(CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *)) \
{ return E_NOTIMPL; } \
#define IMP_IInArchive_ArcProps_NO \
IMP_IInArchive_ArcProps_NO_Table \
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value)) \
{ value->vt = VT_EMPTY; return S_OK; }
#define Z7_class_CHandler_final \
Z7_class_final(CHandler)
#define Z7_CLASS_IMP_CHandler_IInArchive_0 \
Z7_CLASS_IMP_COM_1(CHandler, IInArchive)
#define Z7_CLASS_IMP_CHandler_IInArchive_1(i1) \
Z7_CLASS_IMP_COM_2(CHandler, IInArchive, i1)
#define Z7_CLASS_IMP_CHandler_IInArchive_2(i1, i2) \
Z7_CLASS_IMP_COM_3(CHandler, IInArchive, i1, i2)
#define Z7_CLASS_IMP_CHandler_IInArchive_3(i1, i2, i3) \
Z7_CLASS_IMP_COM_4(CHandler, IInArchive, i1, i2, i3)
#define Z7_CLASS_IMP_CHandler_IInArchive_4(i1, i2, i3, i4) \
Z7_CLASS_IMP_COM_5(CHandler, IInArchive, i1, i2, i3, i4)
#define Z7_CLASS_IMP_CHandler_IInArchive_5(i1, i2, i3, i4, i5) \
Z7_CLASS_IMP_COM_6(CHandler, IInArchive, i1, i2, i3, i4, i5)
#define k_IsArc_Res_NO 0
#define k_IsArc_Res_YES 1
#define k_IsArc_Res_NEED_MORE 2
// #define k_IsArc_Res_YES_LOW_PROB 3
#define API_FUNC_IsArc EXTERN_C UInt32 WINAPI
#define API_FUNC_static_IsArc extern "C" { static UInt32 WINAPI
extern "C"
{
typedef HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject);
typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size);
typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc);
typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats);
typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value);
typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value);
typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive);
typedef HRESULT (WINAPI *Func_SetLargePageMode)();
// typedef HRESULT (WINAPI *Func_SetClientVersion)(UInt32 version);
typedef IOutArchive * (*Func_CreateOutArchive)();
typedef IInArchive * (*Func_CreateInArchive)();
}
/*
if there is no time in archive, external MTime of archive
will be used instead of _item.Time from archive.
For 7-zip before 22.00 we need to return some supported value.
But (kpidTimeType > kDOS) is not allowed in 7-Zip before 22.00.
So we return highest precision value supported by old 7-Zip.
new 7-Zip 22.00 doesn't use that value in usual cases.
*/
#define DECLARE_AND_SET_CLIENT_VERSION_VAR
#define GET_FileTimeType_NotDefined_for_GetFileTimeType \
NFileTimeType::kWindows
/*
extern UInt32 g_ClientVersion;
#define GET_CLIENT_VERSION(major, minor) \
((UInt32)(((UInt32)(major) << 16) | (UInt32)(minor)))
#define DECLARE_AND_SET_CLIENT_VERSION_VAR \
UInt32 g_ClientVersion = GET_CLIENT_VERSION(MY_VER_MAJOR, MY_VER_MINOR);
#define GET_FileTimeType_NotDefined_for_GetFileTimeType \
((UInt32)(g_ClientVersion >= GET_CLIENT_VERSION(22, 0) ? \
(UInt32)(Int32)NFileTimeType::kNotDefined : \
NFileTimeType::kWindows))
*/
Z7_PURE_INTERFACES_END
#endif

View File

@@ -0,0 +1,11 @@
// StdAfx.h
#ifndef ZIP7_INC_STDAFX_H
#define ZIP7_INC_STDAFX_H
#if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..'
#endif
#include "../../Common/Common.h"
#endif

View File

@@ -0,0 +1,11 @@
// XzHandler.h
#ifndef ZIP7_INC_XZ_HANDLER_H
#define ZIP7_INC_XZ_HANDLER_H
namespace NArchive {
namespace NXz {
}}
#endif

View File

@@ -0,0 +1,477 @@
// ICoder.h
#ifndef ZIP7_INC_ICODER_H
#define ZIP7_INC_ICODER_H
#include "IStream.h"
Z7_PURE_INTERFACES_BEGIN
#define Z7_IFACE_CONSTR_CODER(i, n) \
Z7_DECL_IFACE_7ZIP(i, 4, n) \
{ Z7_IFACE_COM7_PURE(i) };
#define Z7_IFACEM_ICompressProgressInfo(x) \
x(SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))
Z7_IFACE_CONSTR_CODER(ICompressProgressInfo, 0x04)
/*
SetRatioInfo()
(inSize) can be NULL, if unknown
(outSize) can be NULL, if unknown
returns:
S_OK
E_ABORT : Break by user
another error codes
*/
#define Z7_IFACEM_ICompressCoder(x) \
x(Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, \
const UInt64 *inSize, const UInt64 *outSize, \
ICompressProgressInfo *progress))
Z7_IFACE_CONSTR_CODER(ICompressCoder, 0x05)
#define Z7_IFACEM_ICompressCoder2(x) \
x(Code(ISequentialInStream * const *inStreams, const UInt64 *const *inSizes, UInt32 numInStreams, \
ISequentialOutStream *const *outStreams, const UInt64 *const *outSizes, UInt32 numOutStreams, \
ICompressProgressInfo *progress))
Z7_IFACE_CONSTR_CODER(ICompressCoder2, 0x18)
/*
ICompressCoder::Code
ICompressCoder2::Code
returns:
S_OK : OK
S_FALSE : data error (for decoders)
E_OUTOFMEMORY : memory allocation error
E_NOTIMPL : unsupported encoding method (for decoders)
another error code : some error. For example, it can be error code received from inStream or outStream function.
Parameters:
(inStream != NULL)
(outStream != NULL)
if (inSize != NULL)
{
Encoders in 7-Zip ignore (inSize).
Decoder can use (*inSize) to check that stream was decoded correctly.
Some decoders in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode)
}
If it's required to limit the reading from input stream (inStream), it can
be done with ISequentialInStream implementation.
if (outSize != NULL)
{
Encoders in 7-Zip ignore (outSize).
Decoder unpacks no more than (*outSize) bytes.
}
(progress == NULL) is allowed.
Decoding with Code() function
-----------------------------
You can request some interfaces before decoding
- ICompressSetDecoderProperties2
- ICompressSetFinishMode
If you need to decode full stream:
{
1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1);
2) call the Code() function with specified (inSize) and (outSize), if these sizes are known.
}
If you need to decode only part of stream:
{
1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0);
2) Call the Code() function with specified (inSize = NULL) and specified (outSize).
}
Encoding with Code() function
-----------------------------
You can request some interfaces :
- ICompressSetCoderProperties - use it before encoding to set properties
- ICompressWriteCoderProperties - use it before or after encoding to request encoded properties.
ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1)
The rules are similar to ICompressCoder rules
*/
namespace NCoderPropID
{
enum EEnum
{
kDefaultProp = 0,
kDictionarySize, // VT_UI4
kUsedMemorySize, // VT_UI4
kOrder, // VT_UI4
kBlockSize, // VT_UI4 or VT_UI8
kPosStateBits, // VT_UI4
kLitContextBits, // VT_UI4
kLitPosBits, // VT_UI4
kNumFastBytes, // VT_UI4
kMatchFinder, // VT_BSTR
kMatchFinderCycles, // VT_UI4
kNumPasses, // VT_UI4
kAlgorithm, // VT_UI4
kNumThreads, // VT_UI4
kEndMarker, // VT_BOOL
kLevel, // VT_UI4
kReduceSize, // VT_UI8 : it's estimated size of largest data stream that will be compressed
// encoder can use this value to reduce dictionary size and allocate data buffers
kExpectedDataSize, // VT_UI8 : for ICompressSetCoderPropertiesOpt :
// it's estimated size of current data stream
// real data size can differ from that size
// encoder can use this value to optimize encoder initialization
kBlockSize2, // VT_UI4 or VT_UI8
kCheckSize, // VT_UI4 : size of digest in bytes
kFilter, // VT_BSTR
kMemUse, // VT_UI8
kAffinity, // VT_UI8
kBranchOffset, // VT_UI4
kHashBits, // VT_UI4
/*
// kHash3Bits, // VT_UI4
// kHash2Bits, // VT_UI4
// kChainBits, // VT_UI4
kChainSize, // VT_UI4
kNativeLevel, // VT_UI4
kFast, // VT_UI4
kMinMatch, // VT_UI4 The minimum slen is 3 and the maximum is 7.
kOverlapLog, // VT_UI4 The minimum ovlog is 0 and the maximum is 9. (default: 6)
kRowMatchFinder, // VT_BOOL
kLdmEnable, // VT_BOOL
// kLdmWindowSizeLog, // VT_UI4
kLdmWindowSize, // VT_UI4
kLdmHashLog, // VT_UI4 The minimum ldmhlog is 6 and the maximum is 26 (default: 20).
kLdmMinMatchLength, // VT_UI4 The minimum ldmslen is 4 and the maximum is 4096 (default: 64).
kLdmBucketSizeLog, // VT_UI4 The minimum ldmblog is 0 and the maximum is 8 (default: 3).
kLdmHashRateLog, // VT_UI4 The default value is wlog - ldmhlog.
kWriteUnpackSizeFlag, // VT_BOOL
kUsePledged, // VT_BOOL
kUseSizeHintPledgedForSmall, // VT_BOOL
kUseSizeHintForEach, // VT_BOOL
kUseSizeHintGlobal, // VT_BOOL
kParamSelectMode, // VT_UI4
// kSearchLog, // VT_UI4 The minimum slog is 1 and the maximum is 26
// kTargetLen, // VT_UI4 The minimum tlen is 0 and the maximum is 999.
*/
k_NUM_DEFINED
};
}
#define Z7_IFACEM_ICompressSetCoderPropertiesOpt(x) \
x(SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))
Z7_IFACE_CONSTR_CODER(ICompressSetCoderPropertiesOpt, 0x1F)
#define Z7_IFACEM_ICompressSetCoderProperties(x) \
x(SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))
Z7_IFACE_CONSTR_CODER(ICompressSetCoderProperties, 0x20)
/*
#define Z7_IFACEM_ICompressSetDecoderProperties(x) \
x(SetDecoderProperties(ISequentialInStream *inStream))
Z7_IFACE_CONSTR_CODER(ICompressSetDecoderProperties, 0x21)
*/
#define Z7_IFACEM_ICompressSetDecoderProperties2(x) \
x(SetDecoderProperties2(const Byte *data, UInt32 size))
Z7_IFACE_CONSTR_CODER(ICompressSetDecoderProperties2, 0x22)
/* returns:
S_OK
E_NOTIMP : unsupported properties
E_INVALIDARG : incorrect (or unsupported) properties
E_OUTOFMEMORY : memory allocation error
*/
#define Z7_IFACEM_ICompressWriteCoderProperties(x) \
x(WriteCoderProperties(ISequentialOutStream *outStream))
Z7_IFACE_CONSTR_CODER(ICompressWriteCoderProperties, 0x23)
#define Z7_IFACEM_ICompressGetInStreamProcessedSize(x) \
x(GetInStreamProcessedSize(UInt64 *value))
Z7_IFACE_CONSTR_CODER(ICompressGetInStreamProcessedSize, 0x24)
#define Z7_IFACEM_ICompressSetCoderMt(x) \
x(SetNumberOfThreads(UInt32 numThreads))
Z7_IFACE_CONSTR_CODER(ICompressSetCoderMt, 0x25)
#define Z7_IFACEM_ICompressSetFinishMode(x) \
x(SetFinishMode(UInt32 finishMode))
Z7_IFACE_CONSTR_CODER(ICompressSetFinishMode, 0x26)
/* finishMode:
0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined.
1 : full decoding. The stream must be finished at the end of decoding. */
#define Z7_IFACEM_ICompressGetInStreamProcessedSize2(x) \
x(GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value))
Z7_IFACE_CONSTR_CODER(ICompressGetInStreamProcessedSize2, 0x27)
#define Z7_IFACEM_ICompressSetMemLimit(x) \
x(SetMemLimit(UInt64 memUsage))
Z7_IFACE_CONSTR_CODER(ICompressSetMemLimit, 0x28)
/*
ICompressReadUnusedFromInBuf is supported by ICoder object
call ReadUnusedFromInBuf() after ICoder::Code(inStream, ...).
ICoder::Code(inStream, ...) decodes data, and the ICoder object is allowed
to read from inStream to internal buffers more data than minimal data required for decoding.
So we can call ReadUnusedFromInBuf() from same ICoder object to read unused input
data from the internal buffer.
in ReadUnusedFromInBuf(): the Coder is not allowed to use (ISequentialInStream *inStream) object, that was sent to ICoder::Code().
*/
#define Z7_IFACEM_ICompressReadUnusedFromInBuf(x) \
x(ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize))
Z7_IFACE_CONSTR_CODER(ICompressReadUnusedFromInBuf, 0x29)
#define Z7_IFACEM_ICompressGetSubStreamSize(x) \
x(GetSubStreamSize(UInt64 subStream, UInt64 *value))
Z7_IFACE_CONSTR_CODER(ICompressGetSubStreamSize, 0x30)
/* returns:
S_OK : (*value) contains the size or estimated size (can be incorrect size)
S_FALSE : size is undefined
E_NOTIMP : the feature is not implemented
Let's (read_size) is size of data that was already read by ISequentialInStream::Read().
The caller should call GetSubStreamSize() after each Read() and check sizes:
if (start_of_subStream + *value < read_size)
{
// (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream:
start_of_subStream += *value;
subStream++;
}
*/
#define Z7_IFACEM_ICompressSetInStream(x) \
x(SetInStream(ISequentialInStream *inStream)) \
x(ReleaseInStream())
Z7_IFACE_CONSTR_CODER(ICompressSetInStream, 0x31)
#define Z7_IFACEM_ICompressSetOutStream(x) \
x(SetOutStream(ISequentialOutStream *outStream)) \
x(ReleaseOutStream())
Z7_IFACE_CONSTR_CODER(ICompressSetOutStream, 0x32)
/*
#define Z7_IFACEM_ICompressSetInStreamSize(x) \
x(SetInStreamSize(const UInt64 *inSize)) \
Z7_IFACE_CONSTR_CODER(ICompressSetInStreamSize, 0x33)
*/
#define Z7_IFACEM_ICompressSetOutStreamSize(x) \
x(SetOutStreamSize(const UInt64 *outSize))
Z7_IFACE_CONSTR_CODER(ICompressSetOutStreamSize, 0x34)
/* That function initializes decoder structures.
Call this function only for stream version of decoder.
if (outSize == NULL), then output size is unknown
if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */
#define Z7_IFACEM_ICompressSetBufSize(x) \
x(SetInBufSize(UInt32 streamIndex, UInt32 size)) \
x(SetOutBufSize(UInt32 streamIndex, UInt32 size))
Z7_IFACE_CONSTR_CODER(ICompressSetBufSize, 0x35)
#define Z7_IFACEM_ICompressInitEncoder(x) \
x(InitEncoder())
Z7_IFACE_CONSTR_CODER(ICompressInitEncoder, 0x36)
/* That function initializes encoder structures.
Call this function only for stream version of encoder. */
#define Z7_IFACEM_ICompressSetInStream2(x) \
x(SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream)) \
x(ReleaseInStream2(UInt32 streamIndex))
Z7_IFACE_CONSTR_CODER(ICompressSetInStream2, 0x37)
/*
#define Z7_IFACEM_ICompressSetOutStream2(x) \
x(SetOutStream2(UInt32 streamIndex, ISequentialOutStream *outStream))
x(ReleaseOutStream2(UInt32 streamIndex))
Z7_IFACE_CONSTR_CODER(ICompressSetOutStream2, 0x38)
#define Z7_IFACEM_ICompressSetInStreamSize2(x) \
x(SetInStreamSize2(UInt32 streamIndex, const UInt64 *inSize))
Z7_IFACE_CONSTR_CODER(ICompressSetInStreamSize2, 0x39)
*/
/*
#define Z7_IFACEM_ICompressInSubStreams(x) \
x(GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream))
Z7_IFACE_CONSTR_CODER(ICompressInSubStreams, 0x3A)
#define Z7_IFACEM_ICompressOutSubStreams(x) \
x(GetNextOutSubStream(UInt64 *streamIndexRes, ISequentialOutStream **stream))
Z7_IFACE_CONSTR_CODER(ICompressOutSubStreams, 0x3B)
*/
/*
ICompressFilter
Filter(Byte *data, UInt32 size)
(size)
converts as most as possible bytes required for fast processing.
Some filters have (smallest_fast_block).
For example, (smallest_fast_block == 16) for AES CBC/CTR filters.
If data stream is not finished, caller must call Filter() for larger block:
where (size >= smallest_fast_block).
if (size >= smallest_fast_block)
{
The filter can leave some bytes at the end of data without conversion:
if there are data alignment reasons or speed reasons.
The caller can read additional data from stream and call Filter() again.
}
If data stream was finished, caller can call Filter() for (size < smallest_fast_block)
(data) parameter:
Some filters require alignment for any Filter() call:
1) (stream_offset % alignment_size) == (data % alignment_size)
2) (alignment_size == 2^N)
where (stream_offset) - is the number of bytes that were already filtered before.
The callers of Filter() are required to meet these requirements.
(alignment_size) can be different:
16 : for AES filters
4 or 2 : for some branch convert filters
1 : for another filters
(alignment_size >= 16) is enough for all current filters of 7-Zip.
But the caller can use larger (alignment_size).
Recommended alignment for (data) of Filter() call is (alignment_size == 64).
Also it's recommended to use aligned value for (size):
(size % alignment_size == 0),
if it's not last call of Filter() for current stream.
returns: (outSize):
if (outSize == 0) : Filter have not converted anything.
So the caller can stop processing, if data stream was finished.
if (outSize <= size) : Filter have converted outSize bytes
if (outSize > size) : Filter have not converted anything.
and it needs at least outSize bytes to convert one block
(it's for crypto block algorithms).
*/
#define Z7_IFACEM_ICompressFilter(x) \
x(Init()) \
x##2(UInt32, Filter(Byte *data, UInt32 size))
Z7_IFACE_CONSTR_CODER(ICompressFilter, 0x40)
#define Z7_IFACEM_ICompressCodecsInfo(x) \
x(GetNumMethods(UInt32 *numMethods)) \
x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \
x(CreateDecoder(UInt32 index, const GUID *iid, void* *coder)) \
x(CreateEncoder(UInt32 index, const GUID *iid, void* *coder))
Z7_IFACE_CONSTR_CODER(ICompressCodecsInfo, 0x60)
#define Z7_IFACEM_ISetCompressCodecsInfo(x) \
x(SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo))
Z7_IFACE_CONSTR_CODER(ISetCompressCodecsInfo, 0x61)
#define Z7_IFACEM_ICryptoProperties(x) \
x(SetKey(const Byte *data, UInt32 size)) \
x(SetInitVector(const Byte *data, UInt32 size))
Z7_IFACE_CONSTR_CODER(ICryptoProperties, 0x80)
/*
x(ResetSalt())
Z7_IFACE_CONSTR_CODER(ICryptoResetSalt, 0x88)
*/
#define Z7_IFACEM_ICryptoResetInitVector(x) \
x(ResetInitVector())
Z7_IFACE_CONSTR_CODER(ICryptoResetInitVector, 0x8C)
/* Call ResetInitVector() only for encoding.
Call ResetInitVector() before encoding and before WriteCoderProperties().
Crypto encoder can create random IV in that function. */
#define Z7_IFACEM_ICryptoSetPassword(x) \
x(CryptoSetPassword(const Byte *data, UInt32 size))
Z7_IFACE_CONSTR_CODER(ICryptoSetPassword, 0x90)
#define Z7_IFACEM_ICryptoSetCRC(x) \
x(CryptoSetCRC(UInt32 crc))
Z7_IFACE_CONSTR_CODER(ICryptoSetCRC, 0xA0)
namespace NMethodPropID
{
enum EEnum
{
kID,
kName,
kDecoder,
kEncoder,
kPackStreams,
kUnpackStreams,
kDescription,
kDecoderIsAssigned,
kEncoderIsAssigned,
kDigestSize,
kIsFilter
};
}
namespace NModuleInterfaceType
{
/*
virtual destructor in IUnknown:
- no : 7-Zip (Windows)
- no : 7-Zip (Linux) (v23) in default mode
- yes : p7zip
- yes : 7-Zip (Linux) before v23
- yes : 7-Zip (Linux) (v23), if Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN is defined
*/
const UInt32 k_IUnknown_VirtDestructor_No = 0;
const UInt32 k_IUnknown_VirtDestructor_Yes = 1;
const UInt32 k_IUnknown_VirtDestructor_ThisModule =
#if !defined(_WIN32) && defined(Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN)
k_IUnknown_VirtDestructor_Yes;
#else
k_IUnknown_VirtDestructor_No;
#endif
}
namespace NModulePropID
{
enum EEnum
{
kInterfaceType, // VT_UI4
kVersion // VT_UI4
};
}
#define Z7_IFACEM_IHasher(x) \
x##2(void, Init()) \
x##2(void, Update(const void *data, UInt32 size)) \
x##2(void, Final(Byte *digest)) \
x##2(UInt32, GetDigestSize())
Z7_IFACE_CONSTR_CODER(IHasher, 0xC0)
#define Z7_IFACEM_IHashers(x) \
x##2(UInt32, GetNumHashers()) \
x(GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)) \
x(CreateHasher(UInt32 index, IHasher **hasher))
Z7_IFACE_CONSTR_CODER(IHashers, 0xC1)
extern "C"
{
typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods);
typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject);
typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject);
typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers);
typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo);
typedef HRESULT (WINAPI *Func_GetModuleProp)(PROPID propID, PROPVARIANT *value);
}
Z7_PURE_INTERFACES_END
#endif

View File

@@ -0,0 +1,76 @@
// IDecl.h
#ifndef ZIP7_INC_IDECL_H
#define ZIP7_INC_IDECL_H
#include "../Common/Common0.h"
#include "../Common/MyUnknown.h"
#define k_7zip_GUID_Data1 0x23170F69
#define k_7zip_GUID_Data2 0x40C1
#define k_7zip_GUID_Data3_Common 0x278A
#define k_7zip_GUID_Data3_Decoder 0x2790
#define k_7zip_GUID_Data3_Encoder 0x2791
#define k_7zip_GUID_Data3_Hasher 0x2792
#define Z7_DECL_IFACE_7ZIP_SUB(i, _base, groupId, subId) \
Z7_DEFINE_GUID(IID_ ## i, \
k_7zip_GUID_Data1, \
k_7zip_GUID_Data2, \
k_7zip_GUID_Data3_Common, \
0, 0, 0, (groupId), 0, (subId), 0, 0); \
struct Z7_DECLSPEC_NOVTABLE i: public _base
#define Z7_DECL_IFACE_7ZIP(i, groupId, subId) \
Z7_DECL_IFACE_7ZIP_SUB(i, IUnknown, groupId, subId)
#ifdef COM_DECLSPEC_NOTHROW
#define Z7_COMWF_B COM_DECLSPEC_NOTHROW STDMETHODIMP
#define Z7_COMWF_B_(t) COM_DECLSPEC_NOTHROW STDMETHODIMP_(t)
#else
#define Z7_COMWF_B STDMETHODIMP
#define Z7_COMWF_B_(t) STDMETHODIMP_(t)
#endif
#if defined(_MSC_VER) && !defined(COM_DECLSPEC_NOTHROW)
#define Z7_COM7F_B __declspec(nothrow) STDMETHODIMP
#define Z7_COM7F_B_(t) __declspec(nothrow) STDMETHODIMP_(t)
#else
#define Z7_COM7F_B Z7_COMWF_B
#define Z7_COM7F_B_(t) Z7_COMWF_B_(t)
#endif
// #define Z7_COM7F_E Z7_noexcept
#define Z7_COM7F_E throw()
#define Z7_COM7F_EO Z7_COM7F_E Z7_override
#define Z7_COM7F_EOF Z7_COM7F_EO Z7_final
#define Z7_COM7F_IMF(f) Z7_COM7F_B f Z7_COM7F_E
#define Z7_COM7F_IMF2(t, f) Z7_COM7F_B_(t) f Z7_COM7F_E
#define Z7_COM7F_PURE(f) virtual Z7_COM7F_IMF(f) =0;
#define Z7_COM7F_PURE2(t, f) virtual Z7_COM7F_IMF2(t, f) =0;
#define Z7_COM7F_IMP(f) Z7_COM7F_IMF(f) Z7_override Z7_final;
#define Z7_COM7F_IMP2(t, f) Z7_COM7F_IMF2(t, f) Z7_override Z7_final;
#define Z7_COM7F_IMP_NONFINAL(f) Z7_COM7F_IMF(f) Z7_override;
#define Z7_COM7F_IMP_NONFINAL2(t, f) Z7_COM7F_IMF2(t, f) Z7_override;
#define Z7_IFACE_PURE(name) Z7_IFACEN_ ## name(=0;)
#define Z7_IFACE_IMP(name) Z7_IFACEN_ ## name(Z7_override Z7_final;)
#define Z7_IFACE_COM7_PURE(name) Z7_IFACEM_ ## name(Z7_COM7F_PURE)
#define Z7_IFACE_COM7_IMP(name) Z7_IFACEM_ ## name(Z7_COM7F_IMP)
#define Z7_IFACE_COM7_IMP_NONFINAL(name) Z7_IFACEM_ ## name(Z7_COM7F_IMP_NONFINAL)
#define Z7_IFACE_DECL_PURE(name) \
DECLARE_INTERFACE(name) \
{ Z7_IFACE_PURE(name) };
#define Z7_IFACE_DECL_PURE_(name, baseiface) \
DECLARE_INTERFACE_(name, baseiface) \
{ Z7_IFACE_PURE(name) };
#endif

View File

@@ -0,0 +1,54 @@
// IPassword.h
#ifndef ZIP7_INC_IPASSWORD_H
#define ZIP7_INC_IPASSWORD_H
#include "../Common/MyTypes.h"
#include "IDecl.h"
Z7_PURE_INTERFACES_BEGIN
#define Z7_IFACE_CONSTR_PASSWORD(i, n) \
Z7_DECL_IFACE_7ZIP(i, 5, n) \
{ Z7_IFACE_COM7_PURE(i) };
/*
How to use output parameter (BSTR *password):
in: The caller is required to set BSTR value as NULL (no string).
The callee (in 7-Zip code) ignores the input value stored in BSTR variable,
out: The callee rewrites BSTR variable (*password) with new allocated string pointer.
The caller must free BSTR string with function SysFreeString();
*/
#define Z7_IFACEM_ICryptoGetTextPassword(x) \
x(CryptoGetTextPassword(BSTR *password))
Z7_IFACE_CONSTR_PASSWORD(ICryptoGetTextPassword, 0x10)
/*
CryptoGetTextPassword2()
in:
The caller is required to set BSTR value as NULL (no string).
The caller is not required to set (*passwordIsDefined) value.
out:
Return code: != S_OK : error code
Return code: S_OK : success
if (*passwordIsDefined == 1), the variable (*password) contains password string
if (*passwordIsDefined == 0), the password is not defined,
but the callee still could set (*password) to some allocated string, for example, as empty string.
The caller must free BSTR string with function SysFreeString()
*/
#define Z7_IFACEM_ICryptoGetTextPassword2(x) \
x(CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password))
Z7_IFACE_CONSTR_PASSWORD(ICryptoGetTextPassword2, 0x11)
Z7_PURE_INTERFACES_END
#endif

View File

@@ -0,0 +1,20 @@
// IProgress.h
#ifndef ZIP7_INC_IPROGRESS_H
#define ZIP7_INC_IPROGRESS_H
#include "../Common/MyTypes.h"
#include "IDecl.h"
Z7_PURE_INTERFACES_BEGIN
#define Z7_IFACEM_IProgress(x) \
x(SetTotal(UInt64 total)) \
x(SetCompleted(const UInt64 *completeValue)) \
Z7_DECL_IFACE_7ZIP(IProgress, 0, 5)
{ Z7_IFACE_COM7_PURE(IProgress) };
Z7_PURE_INTERFACES_END
#endif

View File

@@ -0,0 +1,210 @@
// IStream.h
#ifndef ZIP7_INC_ISTREAM_H
#define ZIP7_INC_ISTREAM_H
#include "../Common/Common0.h"
#include "../Common/MyTypes.h"
#include "../Common/MyWindows.h"
#include "IDecl.h"
Z7_PURE_INTERFACES_BEGIN
#define Z7_IFACE_CONSTR_STREAM_SUB(i, base, n) \
Z7_DECL_IFACE_7ZIP_SUB(i, base, 3, n) \
{ Z7_IFACE_COM7_PURE(i) };
#define Z7_IFACE_CONSTR_STREAM(i, n) \
Z7_IFACE_CONSTR_STREAM_SUB(i, IUnknown, n)
/*
ISequentialInStream::Read()
The requirement for caller: (processedSize != NULL).
The callee can allow (processedSize == NULL) for compatibility reasons.
if (size == 0), this function returns S_OK and (*processedSize) is set to 0.
if (size != 0)
{
Partial read is allowed: (*processedSize <= avail_size && *processedSize <= size),
where (avail_size) is the size of remaining bytes in stream.
If (avail_size != 0), this function must read at least 1 byte: (*processedSize > 0).
You must call Read() in loop, if you need to read exact amount of data.
}
If seek pointer before Read() call was changed to position past the end of stream:
if (seek_pointer >= stream_size), this function returns S_OK and (*processedSize) is set to 0.
ERROR CASES:
If the function returns error code, then (*processedSize) is size of
data written to (data) buffer (it can be data before error or data with errors).
The recommended way for callee to work with reading errors:
1) write part of data before error to (data) buffer and return S_OK.
2) return error code for further calls of Read().
*/
#define Z7_IFACEM_ISequentialInStream(x) \
x(Read(void *data, UInt32 size, UInt32 *processedSize))
Z7_IFACE_CONSTR_STREAM(ISequentialInStream, 0x01)
/*
ISequentialOutStream::Write()
The requirement for caller: (processedSize != NULL).
The callee can allow (processedSize == NULL) for compatibility reasons.
if (size != 0)
{
Partial write is allowed: (*processedSize <= size),
but this function must write at least 1 byte: (*processedSize > 0).
You must call Write() in loop, if you need to write exact amount of data.
}
ERROR CASES:
If the function returns error code, then (*processedSize) is size of
data written from (data) buffer.
*/
#define Z7_IFACEM_ISequentialOutStream(x) \
x(Write(const void *data, UInt32 size, UInt32 *processedSize))
Z7_IFACE_CONSTR_STREAM(ISequentialOutStream, 0x02)
#ifdef _WIN32
#ifdef __HRESULT_FROM_WIN32
#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)
#else
#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)
#endif
#else
#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK MY_E_ERROR_NEGATIVE_SEEK
#endif
/*
IInStream::Seek() / IOutStream::Seek()
If you seek to position before the beginning of the stream,
Seek() function returns error code:
Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK).
or STG_E_INVALIDFUNCTION
It is allowed to seek past the end of the stream.
if Seek() returns error, then the value of *newPosition is undefined.
*/
#define Z7_IFACEM_IInStream(x) \
x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
Z7_IFACE_CONSTR_STREAM_SUB(IInStream, ISequentialInStream, 0x03)
#define Z7_IFACEM_IOutStream(x) \
x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) \
x(SetSize(UInt64 newSize))
Z7_IFACE_CONSTR_STREAM_SUB(IOutStream, ISequentialOutStream, 0x04)
#define Z7_IFACEM_IStreamGetSize(x) \
x(GetSize(UInt64 *size))
Z7_IFACE_CONSTR_STREAM(IStreamGetSize, 0x06)
#define Z7_IFACEM_IOutStreamFinish(x) \
x(OutStreamFinish())
Z7_IFACE_CONSTR_STREAM(IOutStreamFinish, 0x07)
#define Z7_IFACEM_IStreamGetProps(x) \
x(GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib))
Z7_IFACE_CONSTR_STREAM(IStreamGetProps, 0x08)
struct CStreamFileProps
{
UInt64 Size;
UInt64 VolID;
UInt64 FileID_Low;
UInt64 FileID_High;
UInt32 NumLinks;
UInt32 Attrib;
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
};
#define Z7_IFACEM_IStreamGetProps2(x) \
x(GetProps2(CStreamFileProps *props))
Z7_IFACE_CONSTR_STREAM(IStreamGetProps2, 0x09)
#define Z7_IFACEM_IStreamGetProp(x) \
x(GetProperty(PROPID propID, PROPVARIANT *value)) \
x(ReloadProps())
Z7_IFACE_CONSTR_STREAM(IStreamGetProp, 0x0a)
/*
IStreamSetRestriction::SetRestriction(UInt64 begin, UInt64 end)
It sets region of data in output stream that is restricted.
For restricted region it's expected (or allowed)
that the caller can write to same region with different calls of Write()/SetSize().
Another regions of output stream will be supposed as non-restricted:
- The callee usually doesn't flush the data in restricted region.
- The callee usually can flush data from non-restricted region after writing.
Actual restiction rules depend also from current stream position.
It's recommended to call SetRestriction() just before the Write() call.
So the callee can optimize writing and flushing, if that Write()
operation is not restricted.
Note: Each new call of SetRestriction() sets new restictions,
so previous restrction calls has no effect anymore.
inputs:
(begin > end) is not allowed, and returns E_FAIL;
if (begin == end)
{
No restriction.
The caller will call Write() in sequential order.
After SetRestriction(begin, begin), but before next call of SetRestriction()
{
Additional condition:
it's expected that current stream seek position is equal to stream size.
The callee can make final flushing for any data before current stream seek position.
For each Write(size) call:
The callee can make final flushing for that new written data.
}
The pair of values (begin == 0 && end == 0) is recommended to remove write restriction.
}
if (begin < end)
{
it means that callee must NOT flush any data in region [begin, end).
The caller is allowed to Seek() to that region and rewrite the
data in that restriction region.
if (end == (UInt64)(Int64)-1)
{
there is no upper bound for restricted region.
So non-restricted region will be [0, begin) in that case
}
}
returns:
- if (begin > end) it return ERROR code (E_FAIL)
- S_OK : if no errors.
- Also the call of SetRestriction() can initiate the flushing of already written data.
So it can return the result of that flushing.
Note: IOutStream::SetSize() also can change the data.
So it's not expected the call
IOutStream::SetSize() to region that was written before as unrestricted.
*/
#define Z7_IFACEM_IStreamSetRestriction(x) \
x(SetRestriction(UInt64 begin, UInt64 end)) \
Z7_IFACE_CONSTR_STREAM(IStreamSetRestriction, 0x10)
Z7_PURE_INTERFACES_END
#endif

View File

@@ -0,0 +1,2 @@
#define USE_COPYRIGHT_CR
#include "../../C/7zVersion.h"

View File

@@ -0,0 +1,178 @@
// PropID.h
#ifndef ZIP7_INC_7ZIP_PROP_ID_H
#define ZIP7_INC_7ZIP_PROP_ID_H
#include "../Common/MyTypes.h"
enum
{
kpidNoProperty = 0,
kpidMainSubfile,
kpidHandlerItemIndex,
kpidPath,
kpidName,
kpidExtension,
kpidIsDir,
kpidSize,
kpidPackSize,
kpidAttrib,
kpidCTime,
kpidATime,
kpidMTime,
kpidSolid,
kpidCommented,
kpidEncrypted,
kpidSplitBefore,
kpidSplitAfter,
kpidDictionarySize,
kpidCRC,
kpidType,
kpidIsAnti,
kpidMethod,
kpidHostOS,
kpidFileSystem,
kpidUser,
kpidGroup,
kpidBlock,
kpidComment,
kpidPosition,
kpidPrefix,
kpidNumSubDirs,
kpidNumSubFiles,
kpidUnpackVer,
kpidVolume,
kpidIsVolume,
kpidOffset,
kpidLinks,
kpidNumBlocks,
kpidNumVolumes,
kpidTimeType,
kpidBit64,
kpidBigEndian,
kpidCpu,
kpidPhySize,
kpidHeadersSize,
kpidChecksum,
kpidCharacts,
kpidVa,
kpidId,
kpidShortName,
kpidCreatorApp,
kpidSectorSize,
kpidPosixAttrib,
kpidSymLink,
kpidError,
kpidTotalSize,
kpidFreeSpace,
kpidClusterSize,
kpidVolumeName,
kpidLocalName,
kpidProvider,
kpidNtSecure,
kpidIsAltStream,
kpidIsAux,
kpidIsDeleted,
kpidIsTree,
kpidSha1,
kpidSha256,
kpidErrorType,
kpidNumErrors,
kpidErrorFlags,
kpidWarningFlags,
kpidWarning,
kpidNumStreams,
kpidNumAltStreams,
kpidAltStreamsSize,
kpidVirtualSize,
kpidUnpackSize,
kpidTotalPhySize,
kpidVolumeIndex,
kpidSubType,
kpidShortComment,
kpidCodePage,
kpidIsNotArcType,
kpidPhySizeCantBeDetected,
kpidZerosTailIsAllowed,
kpidTailSize,
kpidEmbeddedStubSize,
kpidNtReparse,
kpidHardLink,
kpidINode,
kpidStreamId,
kpidReadOnly,
kpidOutName,
kpidCopyLink,
kpidArcFileName,
kpidIsHash,
kpidChangeTime,
kpidUserId,
kpidGroupId,
kpidDeviceMajor,
kpidDeviceMinor,
kpidDevMajor,
kpidDevMinor,
kpid_NUM_DEFINED,
kpidUserDefined = 0x10000
};
extern const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE
const UInt32 kpv_ErrorFlags_IsNotArc = 1 << 0;
const UInt32 kpv_ErrorFlags_HeadersError = 1 << 1;
const UInt32 kpv_ErrorFlags_EncryptedHeadersError = 1 << 2;
const UInt32 kpv_ErrorFlags_UnavailableStart = 1 << 3;
const UInt32 kpv_ErrorFlags_UnconfirmedStart = 1 << 4;
const UInt32 kpv_ErrorFlags_UnexpectedEnd = 1 << 5;
const UInt32 kpv_ErrorFlags_DataAfterEnd = 1 << 6;
const UInt32 kpv_ErrorFlags_UnsupportedMethod = 1 << 7;
const UInt32 kpv_ErrorFlags_UnsupportedFeature = 1 << 8;
const UInt32 kpv_ErrorFlags_DataError = 1 << 9;
const UInt32 kpv_ErrorFlags_CrcError = 1 << 10;
// const UInt32 kpv_ErrorFlags_Unsupported = 1 << 11;
/*
linux ctime :
file metadata was last changed.
changing the file modification time
counts as a metadata change, so will also have the side effect of updating the ctime.
PROPVARIANT for timestamps in 7-Zip:
{
vt = VT_FILETIME
wReserved1: set precision level
0 : base value (backward compatibility value)
only filetime is used (7 digits precision).
wReserved2 and wReserved3 can contain random data
1 : Unix (1 sec)
2 : DOS (2 sec)
3 : High Precision (1 ns)
16 - 3 : (reserved) = 1 day
16 - 2 : (reserved) = 1 hour
16 - 1 : (reserved) = 1 minute
16 + 0 : 1 sec (0 digits after point)
16 + (1,2,3,4,5,6,7,8,9) : set subsecond precision level :
(number of decimal digits after point)
16 + 9 : 1 ns (9 digits after point)
wReserved2 = ns % 100 : if (8 or 9 digits pecision)
= 0 : if not (8 or 9 digits pecision)
wReserved3 = 0;
filetime
}
NOTE: TAR-PAX archives created by GNU TAR don't keep
whole information about original level of precision,
and timestamp are stored in reduced form, where tail zero
digits after point are removed.
So 7-Zip can return different precision levels for different items for such TAR archives.
*/
/*
TimePrec returned by IOutArchive::GetFileTimeType()
is used only for updating, when we compare MTime timestamp
from archive with timestamp from directory.
*/
#endif

View File

@@ -0,0 +1,46 @@
// Common/AutoPtr.h
#ifndef ZIP7_INC_COMMON_AUTOPTR_H
#define ZIP7_INC_COMMON_AUTOPTR_H
template<class T> class CMyUniquePtr
// CMyAutoPtr
{
T *_p;
CMyUniquePtr(CMyUniquePtr<T>& p); // : _p(p.release()) {}
CMyUniquePtr<T>& operator=(T *p);
CMyUniquePtr<T>& operator=(CMyUniquePtr<T>& p);
/*
{
reset(p.release());
return (*this);
}
*/
void reset(T* p = NULL)
{
if (p != _p)
delete _p;
_p = p;
}
public:
CMyUniquePtr(T *p = NULL) : _p(p) {}
~CMyUniquePtr() { delete _p; }
T& operator*() const { return *_p; }
T* operator->() const { return _p; }
// operator bool() const { return _p != NULL; }
T* get() const { return _p; }
T* release()
{
T *tmp = _p;
_p = NULL;
return tmp;
}
void Create_if_Empty()
{
if (!_p)
_p = new T;
}
};
#endif

View File

@@ -0,0 +1,6 @@
// Common/C_FileIO.h
#ifndef ZIP7_INC_COMMON_C_FILEIO_H
#define ZIP7_INC_COMMON_C_FILEIO_H
#endif

View File

@@ -0,0 +1,21 @@
// ComTry.h
#ifndef ZIP7_INC_COM_TRY_H
#define ZIP7_INC_COM_TRY_H
#include "MyWindows.h"
// #include "Exception.h"
// #include "NewHandler.h"
#define COM_TRY_BEGIN try {
#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; }
/*
#define COM_TRY_END } \
catch(const CNewException &) { return E_OUTOFMEMORY; } \
catch(...) { return HRESULT_FROM_WIN32(ERROR_NOACCESS); } \
*/
// catch(const CSystemException &e) { return e.ErrorCode; }
// catch(...) { return E_FAIL; }
#endif

View File

@@ -0,0 +1,63 @@
// Common/CommandLineParser.h
#ifndef ZIP7_INC_COMMON_COMMAND_LINE_PARSER_H
#define ZIP7_INC_COMMON_COMMAND_LINE_PARSER_H
#include "MyString.h"
namespace NCommandLineParser {
bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2);
void SplitCommandLine(const UString &s, UStringVector &parts);
namespace NSwitchType
{
enum EEnum
{
kSimple,
kMinus,
kString,
kChar
};
}
struct CSwitchForm
{
const char *Key;
Byte Type;
bool Multi;
Byte MinLen;
// int MaxLen;
const char *PostCharSet;
};
struct CSwitchResult
{
bool ThereIs;
bool WithMinus;
int PostCharIndex;
UStringVector PostStrings;
CSwitchResult(): ThereIs(false) {}
};
class CParser
{
CSwitchResult *_switches;
bool ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches);
public:
UStringVector NonSwitchStrings;
int StopSwitchIndex; // NonSwitchStrings[StopSwitchIndex+] are after "--"
AString ErrorMessage;
UString ErrorLine;
CParser();
~CParser();
bool ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings);
const CSwitchResult& operator[](unsigned index) const { return _switches[index]; }
};
}
#endif

View File

@@ -0,0 +1,28 @@
// Common.h
#if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..'
#endif
#ifndef ZIP7_INC_COMMON_H
#define ZIP7_INC_COMMON_H
#include "../../C/Precomp.h"
#include "Common0.h"
#include "MyWindows.h"
/*
This file is included to all cpp files in 7-Zip.
Each folder contains StdAfx.h file that includes "Common.h".
So 7-Zip includes "Common.h" in both modes:
with precompiled StdAfx.h
and
without precompiled StdAfx.h
include "Common.h" before other h files of 7-zip,
if you need predefined macros.
do not include "Common.h", if you need only interfaces,
and you don't need predefined macros.
*/
#endif

View File

@@ -0,0 +1,330 @@
// Common0.h
#if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..'
#endif
#ifndef ZIP7_INC_COMMON0_H
#define ZIP7_INC_COMMON0_H
#include "../../C/Compiler.h"
/*
This file contains compiler related things for cpp files.
This file is included to all cpp files in 7-Zip via "Common.h".
Also this file is included in "IDecl.h" (that is included in interface files).
So external modules can use 7-Zip interfaces without
predefined macros defined in "Common.h".
*/
#ifdef _MSC_VER
#pragma warning(disable : 4710) // function not inlined
// 'CUncopyable::CUncopyable':
#pragma warning(disable : 4514) // unreferenced inline function has been removed
#if _MSC_VER < 1300
#pragma warning(disable : 4702) // unreachable code
#pragma warning(disable : 4714) // function marked as __forceinline not inlined
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
#endif
#if _MSC_VER < 1400
#pragma warning(disable : 4511) // copy constructor could not be generated // #pragma warning(disable : 4512) // assignment operator could not be generated
#pragma warning(disable : 4512) // assignment operator could not be generated
#endif
#if _MSC_VER > 1400 && _MSC_VER <= 1900
// #pragma warning(disable : 4996)
// strcat: This function or variable may be unsafe
// GetVersion was declared deprecated
#endif
#if _MSC_VER > 1200
// -Wall warnings
#if _MSC_VER <= 1600
#pragma warning(disable : 4917) // 'OLE_HANDLE' : a GUID can only be associated with a class, interface or namespace
#endif
// #pragma warning(disable : 4061) // enumerator '' in switch of enum '' is not explicitly handled by a case label
// #pragma warning(disable : 4266) // no override available for virtual member function from base ''; function is hidden
#pragma warning(disable : 4625) // copy constructor was implicitly defined as deleted
#pragma warning(disable : 4626) // assignment operator was implicitly defined as deleted
#if _MSC_VER >= 1600 && _MSC_VER < 1920
#pragma warning(disable : 4571) // Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught
#endif
#if _MSC_VER >= 1600
#pragma warning(disable : 4365) // 'initializing' : conversion from 'int' to 'unsigned int', signed / unsigned mismatch
#endif
#if _MSC_VER < 1800
// we disable the warning, if we don't use 'final' in class
#pragma warning(disable : 4265) // class has virtual functions, but destructor is not virtual
#endif
#if _MSC_VER >= 1900
#pragma warning(disable : 5026) // move constructor was implicitly defined as deleted
#pragma warning(disable : 5027) // move assignment operator was implicitly defined as deleted
#endif
#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
#if _MSC_VER >= 1925
// #pragma warning(disable : 5204) // 'ISequentialInStream' : class has virtual functions, but its trivial destructor is not virtual; instances of objects derived from this class may not be destructed correctly
#endif
#if _MSC_VER >= 1934
// #pragma warning(disable : 5264) // const variable is not used
#endif
#endif // _MSC_VER > 1200
#endif // _MSC_VER
#if defined(_MSC_VER) // && !defined(__clang__)
#define Z7_DECLSPEC_NOTHROW __declspec(nothrow)
#elif defined(__clang__) || defined(__GNUC__)
#define Z7_DECLSPEC_NOTHROW __attribute__((nothrow))
#else
#define Z7_DECLSPEC_NOTHROW
#endif
/*
#if defined (_MSC_VER) && _MSC_VER >= 1900 \
|| defined(__clang__) && __clang_major__ >= 6 \
|| defined(__GNUC__) && __GNUC__ >= 6
#define Z7_noexcept noexcept
#else
#define Z7_noexcept throw()
#endif
*/
#if defined(__clang__)
#if /* defined(_WIN32) && */ __clang_major__ >= 16
#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic"
#endif
#if __clang_major__ >= 4 && __clang_major__ < 12 && !defined(_WIN32)
/*
if compiled with new GCC libstdc++, GCC libstdc++ can use:
13.2.0/include/c++/
<new> : #define _NEW
<stdlib.h> : #define _GLIBCXX_STDLIB_H 1
*/
#pragma GCC diagnostic ignored "-Wreserved-id-macro"
#endif
// noexcept, final, = delete
#pragma GCC diagnostic ignored "-Wc++98-compat"
#if __clang_major__ >= 4
// throw() dynamic exception specifications are deprecated
#pragma GCC diagnostic ignored "-Wdeprecated-dynamic-exception-spec"
#endif
#if __clang_major__ <= 6 // check it
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
#if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 // 18.1.0RC
#pragma GCC diagnostic ignored "-Wswitch-default"
#endif
// #pragma GCC diagnostic ignored "-Wunused-private-field"
// #pragma GCC diagnostic ignored "-Wnonportable-system-include-path"
// #pragma GCC diagnostic ignored "-Wsuggest-override"
// #pragma GCC diagnostic ignored "-Wsign-conversion"
// #pragma GCC diagnostic ignored "-Winconsistent-missing-override"
// #pragma GCC diagnostic ignored "-Wsuggest-destructor-override"
// #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
// #pragma GCC diagnostic ignored "-Wdeprecated-copy-with-user-provided-dtor"
// #pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor"
// #ifndef _WIN32
// #pragma GCC diagnostic ignored "-Wweak-vtables"
// #endif
/*
#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400) \
|| defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30000)
// enumeration values not explicitly handled in switch
#pragma GCC diagnostic ignored "-Wswitch-enum"
#endif
*/
#endif // __clang__
#ifdef __GNUC__
// #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#endif
/* There is BUG in MSVC 6.0 compiler for operator new[]:
It doesn't check overflow, when it calculates size in bytes for allocated array.
So we can use Z7_ARRAY_NEW macro instead of new[] operator. */
#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64)
#define Z7_ARRAY_NEW(p, T, size) p = new T[((size) > 0xFFFFFFFFu / sizeof(T)) ? 0xFFFFFFFFu / sizeof(T) : (size)];
#else
#define Z7_ARRAY_NEW(p, T, size) p = new T[size];
#endif
#if (defined(__GNUC__) && (__GNUC__ >= 8))
#define Z7_ATTR_NORETURN __attribute__((noreturn))
#elif (defined(__clang__) && (__clang_major__ >= 3))
#if __has_feature(cxx_attributes)
#define Z7_ATTR_NORETURN [[noreturn]]
#else
#define Z7_ATTR_NORETURN __attribute__((noreturn))
#endif
#elif (defined(_MSC_VER) && (_MSC_VER >= 1900))
#define Z7_ATTR_NORETURN [[noreturn]]
#else
#define Z7_ATTR_NORETURN
#endif
// final in "GCC 4.7.0"
// In C++98 and C++03 code the alternative spelling __final can be used instead (this is a GCC extension.)
#if defined (__cplusplus) && __cplusplus >= 201103L \
|| defined(_MSC_VER) && _MSC_VER >= 1800 \
|| defined(__clang__) && __clang_major__ >= 4 \
/* || defined(__GNUC__) && __GNUC__ >= 9 */
#define Z7_final final
#if defined(__clang__) && __cplusplus < 201103L
#pragma GCC diagnostic ignored "-Wc++11-extensions"
#endif
#elif defined (__cplusplus) && __cplusplus >= 199711L \
&& defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__)
#define Z7_final __final
#else
#define Z7_final
#if defined(__clang__) && __clang_major__ >= 4 \
|| defined(__GNUC__) && __GNUC__ >= 4
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#endif
#endif
#define Z7_class_final(c) class c Z7_final
#if defined (__cplusplus) && __cplusplus >= 201103L \
|| (defined(_MSC_VER) && _MSC_VER >= 1800)
#define Z7_CPP_IS_SUPPORTED_default
#define Z7_eq_delete = delete
// #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c) c(const c& k) = default;
#else
#define Z7_eq_delete
// #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c)
#endif
#if defined(__cplusplus) && (__cplusplus >= 201103L) \
|| defined(_MSC_VER) && (_MSC_VER >= 1400) /* && (_MSC_VER != 1600) */ \
|| defined(__clang__) && __clang_major__ >= 4
#if defined(_MSC_VER) && (_MSC_VER == 1600) /* && (_MSC_VER != 1600) */
#pragma warning(disable : 4481) // nonstandard extension used: override specifier 'override'
#define Z7_DESTRUCTOR_override
#else
#define Z7_DESTRUCTOR_override override
#endif
#define Z7_override override
#else
#define Z7_override
#define Z7_DESTRUCTOR_override
#endif
#define Z7_CLASS_NO_COPY(cls) \
private: \
cls(const cls &) Z7_eq_delete; \
cls &operator=(const cls &) Z7_eq_delete;
class CUncopyable
{
protected:
CUncopyable() {} // allow constructor
// ~CUncopyable() {}
Z7_CLASS_NO_COPY(CUncopyable)
};
#define MY_UNCOPYABLE :private CUncopyable
// #define MY_UNCOPYABLE
// typedef void (*Z7_void_Function)(void);
#if defined(__clang__) || defined(__GNUC__)
#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<Z7_void_Function>(e))
#else
#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<void*>(e))
// #define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(e)
#endif
#define Z7_GET_PROC_ADDRESS(func_type, hmodule, func_name) \
Z7_CAST_FUNC(func_type, GetProcAddress(hmodule, func_name))
// || defined(__clang__)
// || defined(__GNUC__)
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define Z7_DECLSPEC_NOVTABLE __declspec(novtable)
#else
#define Z7_DECLSPEC_NOVTABLE
#endif
#ifdef __clang__
#define Z7_PURE_INTERFACES_BEGIN \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
_Pragma("GCC diagnostic ignored \"-Wweak-vtables\"")
#define Z7_PURE_INTERFACES_END \
_Pragma("GCC diagnostic pop")
#else
#define Z7_PURE_INTERFACES_BEGIN
#define Z7_PURE_INTERFACES_END
#endif
// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers
#include "NewHandler.h"
/*
// #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) Z7_ARRAY_SIZE(a)
#endif
*/
#endif // ZIP7_INC_COMMON0_H
// #define Z7_REDEFINE_NULL
#if defined(Z7_REDEFINE_NULL) /* && (!defined(__clang__) || defined(_MSC_VER)) */
// NULL is defined in <stddef.h>
#include <stddef.h>
#undef NULL
#ifdef __cplusplus
#if defined (__cplusplus) && __cplusplus >= 201103L \
|| (defined(_MSC_VER) && _MSC_VER >= 1800)
#define NULL nullptr
#else
#define NULL 0
#endif
#else
#define NULL ((void *)0)
#endif
#else // Z7_REDEFINE_NULL
#if defined(__clang__) && __clang_major__ >= 5
#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
#endif // Z7_REDEFINE_NULL
// for precompiler:
// #include "MyWindows.h"

View File

@@ -0,0 +1,16 @@
// Common/Defs.h
#ifndef ZIP7_INC_COMMON_DEFS_H
#define ZIP7_INC_COMMON_DEFS_H
template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; }
template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; }
template <class T> inline int MyCompare(T a, T b)
{ return a == b ? 0 : (a < b ? -1 : 1); }
inline int BoolToInt(bool v) { return (v ? 1 : 0); }
inline unsigned BoolToUInt(bool v) { return (v ? 1u : 0u); }
inline bool IntToBool(int v) { return (v != 0); }
#endif

View File

@@ -0,0 +1,41 @@
// Common/DynLimBuf.h
#ifndef ZIP7_INC_COMMON_DYN_LIM_BUF_H
#define ZIP7_INC_COMMON_DYN_LIM_BUF_H
#include <string.h>
#include "../../C/Alloc.h"
#include "MyString.h"
class CDynLimBuf
{
Byte *_chars;
size_t _pos;
size_t _size;
size_t _sizeLimit;
bool _error;
CDynLimBuf(const CDynLimBuf &s);
// ---------- forbidden functions ----------
CDynLimBuf &operator+=(wchar_t c);
public:
CDynLimBuf(size_t limit) throw();
~CDynLimBuf() { MyFree(_chars); }
size_t Len() const { return _pos; }
bool IsError() const { return _error; }
void Empty() { _pos = 0; _error = false; }
operator const Byte *() const { return _chars; }
// const char *Ptr() const { return _chars; }
CDynLimBuf &operator+=(char c) throw();
CDynLimBuf &operator+=(const char *s) throw();
};
#endif

View File

@@ -0,0 +1,76 @@
// Common/DynamicBuffer.h
#ifndef ZIP7_INC_COMMON_DYNAMIC_BUFFER_H
#define ZIP7_INC_COMMON_DYNAMIC_BUFFER_H
#include <string.h>
#include "MyTypes.h"
template <class T> class CDynamicBuffer
{
T *_items;
size_t _size;
size_t _pos;
CDynamicBuffer(const CDynamicBuffer &buffer);
void operator=(const CDynamicBuffer &buffer);
void Grow(size_t size)
{
size_t delta = _size >= 64 ? _size : 64;
if (delta < size)
delta = size;
size_t newCap = _size + delta;
if (newCap < delta)
{
newCap = _size + size;
if (newCap < size)
throw 20120116;
}
T *newBuffer = new T[newCap];
if (_pos != 0)
memcpy(newBuffer, _items, _pos * sizeof(T));
delete []_items;
_items = newBuffer;
_size = newCap;
}
public:
CDynamicBuffer(): _items(NULL), _size(0), _pos(0) {}
// operator T *() { return _items; }
operator const T *() const { return _items; }
~CDynamicBuffer() { delete []_items; }
void Free()
{
delete []_items;
_items = NULL;
_size = 0;
_pos = 0;
}
T *GetCurPtrAndGrow(size_t addSize)
{
size_t rem = _size - _pos;
if (rem < addSize)
Grow(addSize - rem);
T *res = _items + _pos;
_pos += addSize;
return res;
}
void AddData(const T *data, size_t size)
{
memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T));
}
size_t GetPos() const { return _pos; }
// void Empty() { _pos = 0; }
};
typedef CDynamicBuffer<Byte> CByteDynamicBuffer;
#endif

View File

@@ -0,0 +1,54 @@
// Common/IntToString.h
#ifndef ZIP7_INC_COMMON_INT_TO_STRING_H
#define ZIP7_INC_COMMON_INT_TO_STRING_H
#include "MyTypes.h"
// return: the pointer to the "terminating" null character after written characters
char * ConvertUInt32ToString(UInt32 value, char *s) throw();
char * ConvertUInt64ToString(UInt64 value, char *s) throw();
wchar_t * ConvertUInt32ToString(UInt32 value, wchar_t *s) throw();
wchar_t * ConvertUInt64ToString(UInt64 value, wchar_t *s) throw();
void ConvertInt64ToString(Int64 value, char *s) throw();
void ConvertInt64ToString(Int64 value, wchar_t *s) throw();
void ConvertUInt64ToOct(UInt64 value, char *s) throw();
extern const char k_Hex_Upper[16];
extern const char k_Hex_Lower[16];
#define GET_HEX_CHAR_UPPER(t) (k_Hex_Upper[t])
#define GET_HEX_CHAR_LOWER(t) (k_Hex_Lower[t])
/*
// #define GET_HEX_CHAR_UPPER(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
static inline unsigned GetHex_Lower(unsigned v)
{
const unsigned v0 = v + '0';
v += 'a' - 10;
if (v < 'a')
v = v0;
return v;
}
static inline char GetHex_Upper(unsigned v)
{
return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));
}
*/
void ConvertUInt32ToHex(UInt32 value, char *s) throw();
void ConvertUInt64ToHex(UInt64 value, char *s) throw();
void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw();
// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw();
// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian.
char *RawLeGuidToString(const Byte *guid, char *s) throw();
char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw();
void ConvertDataToHex_Lower(char *dest, const Byte *src, size_t size) throw();
void ConvertDataToHex_Upper(char *dest, const Byte *src, size_t size) throw();
#endif

View File

@@ -0,0 +1,30 @@
// Common/Lang.h
#ifndef ZIP7_INC_COMMON_LANG_H
#define ZIP7_INC_COMMON_LANG_H
#include "MyString.h"
class CLang
{
wchar_t *_text;
bool OpenFromString(const AString &s);
public:
CRecordVector<UInt32> _ids;
CRecordVector<UInt32> _offsets;
UStringVector Comments;
CLang(): _text(NULL) {}
~CLang() { Clear(); }
bool Open(CFSTR fileName, const char *id);
void Clear() throw();
bool IsEmpty() const { return _ids.IsEmpty(); }
const wchar_t *Get(UInt32 id) const throw();
const wchar_t *Get_by_index(unsigned index) const throw()
{
return _text + (size_t)_offsets[index];
}
};
#endif

View File

@@ -0,0 +1,18 @@
// Common/ListFileUtils.h
#ifndef ZIP7_INC_COMMON_LIST_FILE_UTILS_H
#define ZIP7_INC_COMMON_LIST_FILE_UTILS_H
#include "MyString.h"
#include "MyTypes.h"
#define Z7_WIN_CP_UTF16 1200
#define Z7_WIN_CP_UTF16BE 1201
// bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP);
// = CP_OEMCP
bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage,
DWORD &lastError);
#endif

View File

@@ -0,0 +1,297 @@
// Common/MyBuffer.h
#ifndef ZIP7_INC_COMMON_MY_BUFFER_H
#define ZIP7_INC_COMMON_MY_BUFFER_H
#include <string.h>
#include "Defs.h"
#include "MyTypes.h"
/* 7-Zip now uses CBuffer only as CByteBuffer.
So there is no need to use Z7_ARRAY_NEW macro in CBuffer code. */
template <class T> class CBuffer
{
T *_items;
size_t _size;
public:
void Free()
{
if (_items)
{
delete []_items;
_items = NULL;
}
_size = 0;
}
CBuffer(): _items(NULL), _size(0) {}
CBuffer(size_t size): _items(NULL), _size(0)
{
if (size != 0)
{
_items = new T[size];
_size = size;
}
}
CBuffer(const CBuffer &buffer): _items(NULL), _size(0)
{
const size_t size = buffer._size;
if (size != 0)
{
_items = new T[size];
memcpy(_items, buffer._items, size * sizeof(T));
_size = size;
}
}
~CBuffer() { delete []_items; }
operator T *() { return _items; }
operator const T *() const { return _items; }
const T* ConstData() const { return _items; }
T* NonConstData() const { return _items; }
T* NonConstData() { return _items; }
// const T* Data() const { return _items; }
// T* Data() { return _items; }
size_t Size() const { return _size; }
void Alloc(size_t size)
{
if (size != _size)
{
Free();
if (size != 0)
{
_items = new T[size];
_size = size;
}
}
}
void AllocAtLeast(size_t size)
{
if (size > _size)
{
Free();
_items = new T[size];
_size = size;
}
}
void CopyFrom(const T *data, size_t size)
{
Alloc(size);
if (size != 0)
memcpy(_items, data, size * sizeof(T));
}
void ChangeSize_KeepData(size_t newSize, size_t keepSize)
{
if (newSize == _size)
return;
T *newBuffer = NULL;
if (newSize != 0)
{
newBuffer = new T[newSize];
if (keepSize > _size)
keepSize = _size;
if (keepSize != 0)
memcpy(newBuffer, _items, MyMin(keepSize, newSize) * sizeof(T));
}
delete []_items;
_items = newBuffer;
_size = newSize;
}
void Wipe()
{
if (_size != 0)
memset(_items, 0, _size * sizeof(T));
}
CBuffer& operator=(const CBuffer &buffer)
{
if (&buffer != this)
CopyFrom(buffer, buffer._size);
return *this;
}
};
template <class T>
bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)
{
size_t size1 = b1.Size();
if (size1 != b2.Size())
return false;
if (size1 == 0)
return true;
return memcmp(b1, b2, size1 * sizeof(T)) == 0;
}
template <class T>
bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
{
size_t size1 = b1.Size();
if (size1 != b2.Size())
return true;
if (size1 == 0)
return false;
return memcmp(b1, b2, size1 * sizeof(T)) != 0;
}
// typedef CBuffer<char> CCharBuffer;
// typedef CBuffer<wchar_t> CWCharBuffer;
typedef CBuffer<Byte> CByteBuffer;
class CByteBuffer_Wipe: public CByteBuffer
{
Z7_CLASS_NO_COPY(CByteBuffer_Wipe)
public:
// CByteBuffer_Wipe(): CBuffer<Byte>() {}
CByteBuffer_Wipe(size_t size): CBuffer<Byte>(size) {}
~CByteBuffer_Wipe() { Wipe(); }
};
template <class T> class CObjArray
{
protected:
T *_items;
private:
// we disable copy
CObjArray(const CObjArray &buffer);
void operator=(const CObjArray &buffer);
public:
void Free()
{
delete []_items;
_items = NULL;
}
CObjArray(size_t size): _items(NULL)
{
if (size != 0)
{
Z7_ARRAY_NEW(_items, T, size)
// _items = new T[size];
}
}
CObjArray(): _items(NULL) {}
~CObjArray() { delete []_items; }
operator T *() { return _items; }
operator const T *() const { return _items; }
const T* ConstData() const { return _items; }
T* NonConstData() const { return _items; }
T* NonConstData() { return _items; }
// const T* Data() const { return _items; }
// T* Data() { return _items; }
void Alloc(size_t newSize)
{
delete []_items;
_items = NULL;
Z7_ARRAY_NEW(_items, T, newSize)
// _items = new T[newSize];
}
};
typedef CObjArray<Byte> CByteArr;
typedef CObjArray<bool> CBoolArr;
typedef CObjArray<int> CIntArr;
typedef CObjArray<unsigned> CUIntArr;
template <class T> class CObjArray2
{
T *_items;
unsigned _size;
// we disable copy
CObjArray2(const CObjArray2 &buffer);
void operator=(const CObjArray2 &buffer);
public:
void Free()
{
delete []_items;
_items = NULL;
_size = 0;
}
CObjArray2(): _items(NULL), _size(0) {}
/*
CObjArray2(const CObjArray2 &buffer): _items(NULL), _size(0)
{
size_t newSize = buffer._size;
if (newSize != 0)
{
T *newBuffer = new T[newSize];;
_items = newBuffer;
_size = newSize;
const T *src = buffer;
for (size_t i = 0; i < newSize; i++)
newBuffer[i] = src[i];
}
}
*/
/*
CObjArray2(size_t size): _items(NULL), _size(0)
{
if (size != 0)
{
_items = new T[size];
_size = size;
}
}
*/
~CObjArray2() { delete []_items; }
operator T *() { return _items; }
operator const T *() const { return _items; }
unsigned Size() const { return (unsigned)_size; }
bool IsEmpty() const { return _size == 0; }
// SetSize doesn't keep old items. It allocates new array if size is not equal
void SetSize(unsigned size)
{
if (size == _size)
return;
T *newBuffer = NULL;
if (size != 0)
{
Z7_ARRAY_NEW(newBuffer, T, size)
// newBuffer = new T[size];
}
delete []_items;
_items = newBuffer;
_size = size;
}
/*
CObjArray2& operator=(const CObjArray2 &buffer)
{
Free();
size_t newSize = buffer._size;
if (newSize != 0)
{
T *newBuffer = new T[newSize];;
_items = newBuffer;
_size = newSize;
const T *src = buffer;
for (size_t i = 0; i < newSize; i++)
newBuffer[i] = src[i];
}
return *this;
}
*/
};
#endif

View File

@@ -0,0 +1,185 @@
// Common/MyBuffer2.h
#ifndef ZIP7_INC_COMMON_MY_BUFFER2_H
#define ZIP7_INC_COMMON_MY_BUFFER2_H
#include "../../C/Alloc.h"
#include "MyTypes.h"
class CMidBuffer
{
Byte *_data;
size_t _size;
Z7_CLASS_NO_COPY(CMidBuffer)
public:
CMidBuffer(): _data(NULL), _size(0) {}
~CMidBuffer() { ::MidFree(_data); }
void Free() { ::MidFree(_data); _data = NULL; _size = 0; }
bool IsAllocated() const { return _data != NULL; }
operator Byte *() { return _data; }
operator const Byte *() const { return _data; }
size_t Size() const { return _size; }
void Alloc(size_t size)
{
if (!_data || size != _size)
{
::MidFree(_data);
_size = 0;
_data = NULL;
_data = (Byte *)::MidAlloc(size);
if (_data)
_size = size;
}
}
void AllocAtLeast(size_t size)
{
if (!_data || size > _size)
{
::MidFree(_data);
const size_t kMinSize = (size_t)1 << 16;
if (size < kMinSize)
size = kMinSize;
_size = 0;
_data = NULL;
_data = (Byte *)::MidAlloc(size);
if (_data)
_size = size;
}
}
};
class CAlignedBuffer1
{
Byte *_data;
Z7_CLASS_NO_COPY(CAlignedBuffer1)
public:
~CAlignedBuffer1()
{
z7_AlignedFree(_data);
}
CAlignedBuffer1(size_t size)
{
_data = NULL;
_data = (Byte *)z7_AlignedAlloc(size);
if (!_data)
throw 1;
}
operator Byte *() { return _data; }
operator const Byte *() const { return _data; }
};
class CAlignedBuffer
{
Byte *_data;
size_t _size;
Z7_CLASS_NO_COPY(CAlignedBuffer)
public:
CAlignedBuffer(): _data(NULL), _size(0) {}
~CAlignedBuffer()
{
z7_AlignedFree(_data);
}
/*
CAlignedBuffer(size_t size): _size(0)
{
_data = NULL;
_data = (Byte *)z7_AlignedAlloc(size);
if (!_data)
throw 1;
_size = size;
}
*/
void Free()
{
z7_AlignedFree(_data);
_data = NULL;
_size = 0;
}
bool IsAllocated() const { return _data != NULL; }
operator Byte *() { return _data; }
operator const Byte *() const { return _data; }
size_t Size() const { return _size; }
void Alloc(size_t size)
{
if (!_data || size != _size)
{
z7_AlignedFree(_data);
_size = 0;
_data = NULL;
_data = (Byte *)z7_AlignedAlloc(size);
if (_data)
_size = size;
}
}
void AllocAtLeast(size_t size)
{
if (!_data || size > _size)
{
z7_AlignedFree(_data);
_size = 0;
_data = NULL;
_data = (Byte *)z7_AlignedAlloc(size);
if (_data)
_size = size;
}
}
// (size <= size_max)
void AllocAtLeast_max(size_t size, size_t size_max)
{
if (!_data || size > _size)
{
z7_AlignedFree(_data);
_size = 0;
_data = NULL;
if (size_max < size) size_max = size; // optional check
const size_t delta = size / 2;
size += delta;
if (size < delta || size > size_max)
size = size_max;
_data = (Byte *)z7_AlignedAlloc(size);
if (_data)
_size = size;
}
}
};
/*
CMidAlignedBuffer must return aligned pointer.
- in Windows it uses CMidBuffer(): MidAlloc() : VirtualAlloc()
VirtualAlloc(): Memory allocated is automatically initialized to zero.
MidAlloc(0) returns NULL
- in non-Windows systems it uses g_AlignedAlloc.
g_AlignedAlloc::Alloc(size = 0) can return non NULL.
*/
typedef
#ifdef _WIN32
CMidBuffer
#else
CAlignedBuffer
#endif
CMidAlignedBuffer;
#endif

View File

@@ -0,0 +1,693 @@
// MyCom.h
#ifndef ZIP7_INC_MY_COM_H
#define ZIP7_INC_MY_COM_H
#include "MyWindows.h"
#include "MyTypes.h"
template <class T>
class CMyComPtr
{
T* _p;
public:
CMyComPtr(): _p(NULL) {}
CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); }
CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); }
~CMyComPtr() { if (_p) _p->Release(); }
void Release() { if (_p) { _p->Release(); _p = NULL; } }
operator T*() const { return (T*)_p; }
T* Interface() const { return (T*)_p; }
// T& operator*() const { return *_p; }
T** operator&() { return &_p; }
T* operator->() const { return _p; }
T* operator=(T* p)
{
if (p)
p->AddRef();
if (_p)
_p->Release();
_p = p;
return p;
}
T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
bool operator!() const { return (_p == NULL); }
// bool operator==(T* pT) const { return _p == pT; }
void Attach(T* p2)
{
Release();
_p = p2;
}
T* Detach()
{
T* pt = _p;
_p = NULL;
return pt;
}
#ifdef _WIN32
HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
{
return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
}
#endif
/*
HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
{
CLSID clsid;
HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
ATLASSERT(_p == NULL);
if (SUCCEEDED(hr))
hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
return hr;
}
*/
template <class Q>
HRESULT QueryInterface(REFGUID iid, Q** pp) const throw()
{
// if (*pp) throw 20220216; // for debug
return _p->QueryInterface(iid, (void**)pp);
}
};
template <class iface, class cls>
class CMyComPtr2
{
cls* _p;
CMyComPtr2(const CMyComPtr2<iface, cls>& lp);
CMyComPtr2(cls* p);
CMyComPtr2(iface* p);
iface* operator=(const CMyComPtr2<iface, cls>& lp);
iface* operator=(cls* p);
iface* operator=(iface* p);
public:
CMyComPtr2(): _p(NULL) {}
~CMyComPtr2()
{
if (_p)
{
iface *ip = _p;
ip->Release();
}
}
// void Release() { if (_p) { (iface *)_p->Release(); _p = NULL; } }
cls* operator->() const { return _p; }
cls* ClsPtr() const { return _p; }
operator iface*() const
{
iface *ip = _p;
return ip;
}
iface* Interface() const
{
iface *ip = _p;
return ip;
}
// operator bool() const { return _p != NULL; }
bool IsDefined() const { return _p != NULL; }
void Create_if_Empty()
{
if (!_p)
{
_p = new cls;
iface *ip = _p;
ip->AddRef();
}
}
iface* Detach()
{
iface *ip = _p;
_p = NULL;
return ip;
}
void SetFromCls(cls *src)
{
if (src)
{
iface *ip = src;
ip->AddRef();
}
if (_p)
{
iface *ip = _p;
ip->Release();
}
_p = src;
}
};
template <class iface, class cls>
class CMyComPtr2_Create
{
cls* _p;
CMyComPtr2_Create(const CMyComPtr2_Create<iface, cls>& lp);
CMyComPtr2_Create(cls* p);
CMyComPtr2_Create(iface* p);
iface* operator=(const CMyComPtr2_Create<iface, cls>& lp);
iface* operator=(cls* p);
iface* operator=(iface* p);
public:
CMyComPtr2_Create(): _p(new cls)
{
iface *ip = _p;
ip->AddRef();
}
~CMyComPtr2_Create()
{
iface *ip = _p;
ip->Release();
}
cls* operator->() const { return _p; }
cls* ClsPtr() const { return _p; }
operator iface*() const
{
iface *ip = _p;
return ip;
}
iface* Interface() const
{
iface *ip = _p;
return ip;
}
};
#define Z7_DECL_CMyComPtr_QI_FROM(i, v, unk) \
CMyComPtr<i> v; (unk)->QueryInterface(IID_ ## i, (void **)&v);
//////////////////////////////////////////////////////////
inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)
{
*bstr = ::SysAllocString(src);
return (*bstr) ? S_OK : E_OUTOFMEMORY;
}
class CMyComBSTR
{
BSTR m_str;
Z7_CLASS_NO_COPY(CMyComBSTR)
public:
CMyComBSTR(): m_str(NULL) {}
~CMyComBSTR() { ::SysFreeString(m_str); }
BSTR* operator&() { return &m_str; }
operator LPCOLESTR() const { return m_str; }
// operator bool() const { return m_str != NULL; }
// bool operator!() const { return m_str == NULL; }
void Wipe_and_Free()
{
if (m_str)
{
memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str));
Empty();
}
}
private:
// operator BSTR() const { return m_str; }
CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }
// CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
// CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); }
// CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
/*
CMyComBSTR(REFGUID src)
{
LPOLESTR szGuid;
StringFromCLSID(src, &szGuid);
m_str = ::SysAllocString(szGuid);
CoTaskMemFree(szGuid);
}
*/
/*
CMyComBSTR& operator=(const CMyComBSTR& src)
{
if (m_str != src.m_str)
{
if (m_str)
::SysFreeString(m_str);
m_str = src.MyCopy();
}
return *this;
}
*/
CMyComBSTR& operator=(LPCOLESTR src)
{
::SysFreeString(m_str);
m_str = ::SysAllocString(src);
return *this;
}
unsigned Len() const { return ::SysStringLen(m_str); }
BSTR MyCopy() const
{
// We don't support Byte BSTRs here
return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
/*
UINT byteLen = ::SysStringByteLen(m_str);
BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
if (res && byteLen != 0 && m_str)
memcpy(res, m_str, byteLen);
return res;
*/
}
/*
void Attach(BSTR src) { m_str = src; }
BSTR Detach()
{
BSTR s = m_str;
m_str = NULL;
return s;
}
*/
void Empty()
{
::SysFreeString(m_str);
m_str = NULL;
}
};
class CMyComBSTR_Wipe: public CMyComBSTR
{
Z7_CLASS_NO_COPY(CMyComBSTR_Wipe)
public:
CMyComBSTR_Wipe(): CMyComBSTR() {}
~CMyComBSTR_Wipe() { Wipe_and_Free(); }
};
/*
If CMyUnknownImp doesn't use virtual destructor, the code size is smaller.
But if some class_1 derived from CMyUnknownImp
uses Z7_COM_ADDREF_RELEASE and IUnknown::Release()
and some another class_2 is derived from class_1,
then class_1 must use virtual destructor:
virtual ~class_1();
In that case, class_1::Release() calls correct destructor of class_2.
We can use virtual ~CMyUnknownImp() to disable warning
"class has virtual functions, but destructor is not virtual".
Also we can use virtual ~IUnknown() {} in MyWindows.h
*/
class CMyUnknownImp
{
Z7_CLASS_NO_COPY(CMyUnknownImp)
protected:
ULONG _m_RefCount;
CMyUnknownImp(): _m_RefCount(0) {}
#ifdef _WIN32
#if defined(__GNUC__) || defined(__clang__)
// virtual ~CMyUnknownImp() {} // to disable GCC/CLANG varnings
#endif
#endif
};
#define Z7_COM_QI_BEGIN \
private: STDMETHOD(QueryInterface) (REFGUID iid, void **outObject) throw() Z7_override Z7_final \
{ *outObject = NULL;
#define Z7_COM_QI_ENTRY(i) \
else if (iid == IID_ ## i) \
{ i *ti = this; *outObject = ti; }
// { *outObject = (void *)(i *)this; }
#define Z7_COM_QI_ENTRY_UNKNOWN_0 \
if (iid == IID_IUnknown) \
{ IUnknown *tu = this; *outObject = tu; }
#define Z7_COM_QI_ENTRY_UNKNOWN(i) \
if (iid == IID_IUnknown) \
{ i *ti = this; IUnknown *tu = ti; *outObject = tu; }
// { *outObject = (void *)(IUnknown *)(i *)this; }
#define Z7_COM_QI_BEGIN2(i) \
Z7_COM_QI_BEGIN \
Z7_COM_QI_ENTRY_UNKNOWN(i) \
Z7_COM_QI_ENTRY(i)
#define Z7_COM_ADDREF_RELEASE_MT \
private: \
STDMETHOD_(ULONG, AddRef)() Z7_override Z7_final \
{ return (ULONG)InterlockedIncrement((LONG *)&_m_RefCount); } \
STDMETHOD_(ULONG, Release)() Z7_override Z7_final \
{ const LONG v = InterlockedDecrement((LONG *)&_m_RefCount); \
if (v != 0) return (ULONG)v; \
delete this; return 0; }
#define Z7_COM_QI_END_MT \
else return E_NOINTERFACE; \
InterlockedIncrement((LONG *)&_m_RefCount); /* AddRef(); */ return S_OK; }
// you can define Z7_COM_USE_ATOMIC,
// if you want to call Release() from different threads (for example, for .NET code)
// #define Z7_COM_USE_ATOMIC
#if defined(Z7_COM_USE_ATOMIC) && !defined(Z7_ST)
#ifndef _WIN32
#if 0
#include "../../C/Threads.h"
#else
EXTERN_C_BEGIN
LONG InterlockedIncrement(LONG volatile *addend);
LONG InterlockedDecrement(LONG volatile *addend);
EXTERN_C_END
#endif
#endif // _WIN32
#define Z7_COM_ADDREF_RELEASE Z7_COM_ADDREF_RELEASE_MT
#define Z7_COM_QI_END Z7_COM_QI_END_MT
#else // !Z7_COM_USE_ATOMIC
#define Z7_COM_ADDREF_RELEASE \
private: \
STDMETHOD_(ULONG, AddRef)() throw() Z7_override Z7_final \
{ return ++_m_RefCount; } \
STDMETHOD_(ULONG, Release)() throw() Z7_override Z7_final \
{ if (--_m_RefCount != 0) return _m_RefCount; \
delete this; return 0; }
#define Z7_COM_QI_END \
else return E_NOINTERFACE; \
++_m_RefCount; /* AddRef(); */ return S_OK; }
#endif // !Z7_COM_USE_ATOMIC
#define Z7_COM_UNKNOWN_IMP_SPEC(i) \
Z7_COM_QI_BEGIN \
i \
Z7_COM_QI_END \
Z7_COM_ADDREF_RELEASE
#define Z7_COM_UNKNOWN_IMP_0 \
Z7_COM_QI_BEGIN \
Z7_COM_QI_ENTRY_UNKNOWN_0 \
Z7_COM_QI_END \
Z7_COM_ADDREF_RELEASE
#define Z7_COM_UNKNOWN_IMP_1(i) \
Z7_COM_UNKNOWN_IMP_SPEC( \
Z7_COM_QI_ENTRY_UNKNOWN(i) \
Z7_COM_QI_ENTRY(i) \
)
#define Z7_COM_UNKNOWN_IMP_2(i1, i2) \
Z7_COM_UNKNOWN_IMP_SPEC( \
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
Z7_COM_QI_ENTRY(i1) \
Z7_COM_QI_ENTRY(i2) \
)
#define Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \
Z7_COM_UNKNOWN_IMP_SPEC( \
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
Z7_COM_QI_ENTRY(i1) \
Z7_COM_QI_ENTRY(i2) \
Z7_COM_QI_ENTRY(i3) \
)
#define Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \
Z7_COM_UNKNOWN_IMP_SPEC( \
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
Z7_COM_QI_ENTRY(i1) \
Z7_COM_QI_ENTRY(i2) \
Z7_COM_QI_ENTRY(i3) \
Z7_COM_QI_ENTRY(i4) \
)
#define Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \
Z7_COM_UNKNOWN_IMP_SPEC( \
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
Z7_COM_QI_ENTRY(i1) \
Z7_COM_QI_ENTRY(i2) \
Z7_COM_QI_ENTRY(i3) \
Z7_COM_QI_ENTRY(i4) \
Z7_COM_QI_ENTRY(i5) \
)
#define Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \
Z7_COM_UNKNOWN_IMP_SPEC( \
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
Z7_COM_QI_ENTRY(i1) \
Z7_COM_QI_ENTRY(i2) \
Z7_COM_QI_ENTRY(i3) \
Z7_COM_QI_ENTRY(i4) \
Z7_COM_QI_ENTRY(i5) \
Z7_COM_QI_ENTRY(i6) \
)
#define Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \
Z7_COM_UNKNOWN_IMP_SPEC( \
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
Z7_COM_QI_ENTRY(i1) \
Z7_COM_QI_ENTRY(i2) \
Z7_COM_QI_ENTRY(i3) \
Z7_COM_QI_ENTRY(i4) \
Z7_COM_QI_ENTRY(i5) \
Z7_COM_QI_ENTRY(i6) \
Z7_COM_QI_ENTRY(i7) \
)
#define Z7_COM_UNKNOWN_IMP_8(i1, i2, i3, i4, i5, i6, i7, i8) \
Z7_COM_UNKNOWN_IMP_SPEC( \
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
Z7_COM_QI_ENTRY(i1) \
Z7_COM_QI_ENTRY(i2) \
Z7_COM_QI_ENTRY(i3) \
Z7_COM_QI_ENTRY(i4) \
Z7_COM_QI_ENTRY(i5) \
Z7_COM_QI_ENTRY(i6) \
Z7_COM_QI_ENTRY(i7) \
Z7_COM_QI_ENTRY(i8) \
)
#define Z7_IFACES_IMP_UNK_1(i1) \
Z7_COM_UNKNOWN_IMP_1(i1) \
Z7_IFACE_COM7_IMP(i1) \
#define Z7_IFACES_IMP_UNK_2(i1, i2) \
Z7_COM_UNKNOWN_IMP_2(i1, i2) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
#define Z7_IFACES_IMP_UNK_3(i1, i2, i3) \
Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
Z7_IFACE_COM7_IMP(i3) \
#define Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \
Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
Z7_IFACE_COM7_IMP(i3) \
Z7_IFACE_COM7_IMP(i4) \
#define Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \
Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
Z7_IFACE_COM7_IMP(i3) \
Z7_IFACE_COM7_IMP(i4) \
Z7_IFACE_COM7_IMP(i5) \
#define Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \
Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
Z7_IFACE_COM7_IMP(i3) \
Z7_IFACE_COM7_IMP(i4) \
Z7_IFACE_COM7_IMP(i5) \
Z7_IFACE_COM7_IMP(i6) \
#define Z7_IFACES_IMP_UNK_7(i1, i2, i3, i4, i5, i6, i7) \
Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
Z7_IFACE_COM7_IMP(i3) \
Z7_IFACE_COM7_IMP(i4) \
Z7_IFACE_COM7_IMP(i5) \
Z7_IFACE_COM7_IMP(i6) \
Z7_IFACE_COM7_IMP(i7) \
#define Z7_CLASS_IMP_COM_0(c) \
Z7_class_final(c) : \
public IUnknown, \
public CMyUnknownImp { \
Z7_COM_UNKNOWN_IMP_0 \
private:
#define Z7_CLASS_IMP_COM_1(c, i1) \
Z7_class_final(c) : \
public i1, \
public CMyUnknownImp { \
Z7_IFACES_IMP_UNK_1(i1) \
private:
#define Z7_CLASS_IMP_COM_2(c, i1, i2) \
Z7_class_final(c) : \
public i1, \
public i2, \
public CMyUnknownImp { \
Z7_IFACES_IMP_UNK_2(i1, i2) \
private:
#define Z7_CLASS_IMP_COM_3(c, i1, i2, i3) \
Z7_class_final(c) : \
public i1, \
public i2, \
public i3, \
public CMyUnknownImp { \
Z7_IFACES_IMP_UNK_3(i1, i2, i3) \
private:
#define Z7_CLASS_IMP_COM_4(c, i1, i2, i3, i4) \
Z7_class_final(c) : \
public i1, \
public i2, \
public i3, \
public i4, \
public CMyUnknownImp { \
Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \
private:
#define Z7_CLASS_IMP_COM_5(c, i1, i2, i3, i4, i5) \
Z7_class_final(c) : \
public i1, \
public i2, \
public i3, \
public i4, \
public i5, \
public CMyUnknownImp { \
Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \
private:
#define Z7_CLASS_IMP_COM_6(c, i1, i2, i3, i4, i5, i6) \
Z7_class_final(c) : \
public i1, \
public i2, \
public i3, \
public i4, \
public i5, \
public i6, \
public CMyUnknownImp { \
Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \
private:
#define Z7_CLASS_IMP_COM_7(c, i1, i2, i3, i4, i5, i6, i7) \
Z7_class_final(c) : \
public i1, \
public i2, \
public i3, \
public i4, \
public i5, \
public i6, \
public i7, \
public CMyUnknownImp { \
Z7_IFACES_IMP_UNK_7(i1, i2, i3, i4, i5, i6, i7) \
private:
/*
#define Z7_CLASS_IMP_NOQIB_0(c) \
Z7_class_final(c) : \
public IUnknown, \
public CMyUnknownImp { \
Z7_COM_UNKNOWN_IMP_0 \
private:
*/
#define Z7_CLASS_IMP_NOQIB_1(c, i1) \
Z7_class_final(c) : \
public i1, \
public CMyUnknownImp { \
Z7_COM_UNKNOWN_IMP_0 \
Z7_IFACE_COM7_IMP(i1) \
private:
#define Z7_CLASS_IMP_NOQIB_2(c, i1, i2) \
Z7_class_final(c) : \
public i1, \
public i2, \
public CMyUnknownImp { \
Z7_COM_UNKNOWN_IMP_1(i2) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
private:
#define Z7_CLASS_IMP_NOQIB_3(c, i1, i2, i3) \
Z7_class_final(c) : \
public i1, \
public i2, \
public i3, \
public CMyUnknownImp { \
Z7_COM_UNKNOWN_IMP_2(i2, i3) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
Z7_IFACE_COM7_IMP(i3) \
private:
#define Z7_CLASS_IMP_NOQIB_4(c, i1, i2, i3, i4) \
Z7_class_final(c) : \
public i1, \
public i2, \
public i3, \
public i4, \
public CMyUnknownImp { \
Z7_COM_UNKNOWN_IMP_3(i2, i3, i4) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
Z7_IFACE_COM7_IMP(i3) \
Z7_IFACE_COM7_IMP(i4) \
/*
#define Z7_CLASS_IMP_NOQIB_5(c, i1, i2, i3, i4, i5) \
Z7_class_final(c) : \
public i1, \
public i2, \
public i3, \
public i4, \
public i5, \
public CMyUnknownImp { \
Z7_COM_UNKNOWN_IMP_4(i2, i3, i4, i5) \
Z7_IFACE_COM7_IMP(i1) \
Z7_IFACE_COM7_IMP(i2) \
Z7_IFACE_COM7_IMP(i3) \
Z7_IFACE_COM7_IMP(i4) \
Z7_IFACE_COM7_IMP(i5) \
*/
#define Z7_CLASS_IMP_IInStream(c) \
class c Z7_final : \
public IInStream, \
public CMyUnknownImp { \
Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) \
#define k_My_HRESULT_WritingWasCut 0x20000010
#endif

View File

@@ -0,0 +1,14 @@
// Common/Exception.h
#ifndef ZIP7_INC_COMMON_EXCEPTION_H
#define ZIP7_INC_COMMON_EXCEPTION_H
#include "MyWindows.h"
struct CSystemException
{
HRESULT ErrorCode;
CSystemException(HRESULT errorCode): ErrorCode(errorCode) {}
};
#endif

View File

@@ -0,0 +1,63 @@
// Common/MyGuidDef.h
// #pragma message "Common/MyGuidDef.h"
#ifndef GUID_DEFINED
#define GUID_DEFINED
// #pragma message "GUID_DEFINED"
#include "MyTypes.h"
typedef struct {
UInt32 Data1;
UInt16 Data2;
UInt16 Data3;
Byte Data4[8];
} GUID;
#ifdef __cplusplus
#define REFGUID const GUID &
#else
#define REFGUID const GUID *
#endif
// typedef GUID IID;
typedef GUID CLSID;
#define REFCLSID REFGUID
#define REFIID REFGUID
#ifdef __cplusplus
inline int operator==(REFGUID g1, REFGUID g2)
{
for (unsigned i = 0; i < sizeof(g1); i++)
if (((const Byte *)&g1)[i] != ((const Byte *)&g2)[i])
return 0;
return 1;
}
inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); }
#endif
#endif // GUID_DEFINED
#ifndef EXTERN_C
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C extern
#endif
#endif
#ifdef DEFINE_GUID
#undef DEFINE_GUID
#endif
#ifdef INITGUID
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name; \
EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#else
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name
#endif

View File

@@ -0,0 +1,57 @@
// Common/MyInitGuid.h
#ifndef ZIP7_INC_COMMON_MY_INITGUID_H
#define ZIP7_INC_COMMON_MY_INITGUID_H
/*
This file must be included only to one C++ file in project before
declarations of COM interfaces with DEFINE_GUID macro.
Each GUID must be initialized exactly once in project.
There are two different versions of the DEFINE_GUID macro in guiddef.h (MyGuidDef.h):
- if INITGUID is not defined: DEFINE_GUID declares an external reference to the symbol name.
- if INITGUID is defined: DEFINE_GUID initializes the symbol name to the value of the GUID.
Also we need IID_IUnknown that is initialized in some file for linking:
MSVC: by default the linker uses some lib file that contains IID_IUnknown
MinGW: add -luuid switch for linker
WinCE: we define IID_IUnknown in this file
Other: we define IID_IUnknown in this file
*/
// #include "Common.h"
/* vc6 without sdk needs <objbase.h> before <initguid.h>,
but it doesn't work in new msvc.
So we include full "MyWindows.h" instead of <objbase.h> */
// #include <objbase.h>
#include "MyWindows.h"
#ifdef _WIN32
#ifdef __clang__
// #pragma GCC diagnostic ignored "-Wmissing-variable-declarations"
#endif
#ifdef UNDER_CE
#include <basetyps.h>
#endif
// for vc6 without sdk we must define INITGUID here
#define INITGUID
#include <initguid.h>
#ifdef UNDER_CE
DEFINE_GUID(IID_IUnknown,
0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
#endif
#else // _WIN32
#define INITGUID
#include "MyGuidDef.h"
DEFINE_GUID(IID_IUnknown,
0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
#endif // _WIN32
#endif

View File

@@ -0,0 +1,75 @@
// MyLinux.h
#ifndef ZIP7_INC_COMMON_MY_LINUX_H
#define ZIP7_INC_COMMON_MY_LINUX_H
// #include "../../C/7zTypes.h"
#define MY_LIN_DT_UNKNOWN 0
#define MY_LIN_DT_FIFO 1
#define MY_LIN_DT_CHR 2
#define MY_LIN_DT_DIR 4
#define MY_LIN_DT_BLK 6
#define MY_LIN_DT_REG 8
#define MY_LIN_DT_LNK 10
#define MY_LIN_DT_SOCK 12
#define MY_LIN_DT_WHT 14
#define MY_LIN_S_IFMT 00170000
#define MY_LIN_S_IFSOCK 0140000
#define MY_LIN_S_IFLNK 0120000
#define MY_LIN_S_IFREG 0100000
#define MY_LIN_S_IFBLK 0060000
#define MY_LIN_S_IFDIR 0040000
#define MY_LIN_S_IFCHR 0020000
#define MY_LIN_S_IFIFO 0010000
#define MY_LIN_S_ISLNK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFLNK)
#define MY_LIN_S_ISREG(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFREG)
#define MY_LIN_S_ISDIR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFDIR)
#define MY_LIN_S_ISCHR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFCHR)
#define MY_LIN_S_ISBLK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFBLK)
#define MY_LIN_S_ISFIFO(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFIFO)
#define MY_LIN_S_ISSOCK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFSOCK)
#define MY_LIN_S_ISUID 0004000
#define MY_LIN_S_ISGID 0002000
#define MY_LIN_S_ISVTX 0001000
#define MY_LIN_S_IRWXU 00700
#define MY_LIN_S_IRUSR 00400
#define MY_LIN_S_IWUSR 00200
#define MY_LIN_S_IXUSR 00100
#define MY_LIN_S_IRWXG 00070
#define MY_LIN_S_IRGRP 00040
#define MY_LIN_S_IWGRP 00020
#define MY_LIN_S_IXGRP 00010
#define MY_LIN_S_IRWXO 00007
#define MY_LIN_S_IROTH 00004
#define MY_LIN_S_IWOTH 00002
#define MY_LIN_S_IXOTH 00001
/*
// major/minor encoding for makedev(): MMMMMmmmmmmMMMmm:
inline UInt32 MY_dev_major(UInt64 dev)
{
return ((UInt32)(dev >> 8) & (UInt32)0xfff) | ((UInt32)(dev >> 32) & ~(UInt32)0xfff);
}
inline UInt32 MY_dev_minor(UInt64 dev)
{
return ((UInt32)(dev) & 0xff) | ((UInt32)(dev >> 12) & ~0xff);
}
inline UInt64 MY_dev_makedev(UInt32 __major, UInt32 __minor)
{
return (__minor & 0xff) | ((__major & 0xfff) << 8)
| ((UInt64) (__minor & ~0xff) << 12)
| ((UInt64) (__major & ~0xfff) << 32);
}
*/
#endif

View File

@@ -0,0 +1,28 @@
// MyMap.h
#ifndef ZIP7_INC_COMMON_MY_MAP_H
#define ZIP7_INC_COMMON_MY_MAP_H
#include "MyTypes.h"
#include "MyVector.h"
class CMap32
{
struct CNode
{
UInt32 Key;
UInt32 Keys[2];
UInt32 Values[2];
UInt16 Len;
Byte IsLeaf[2];
};
CRecordVector<CNode> Nodes;
public:
void Clear() { Nodes.Clear(); }
bool Find(UInt32 key, UInt32 &valueRes) const throw();
bool Set(UInt32 key, UInt32 value); // returns true, if there is such key already
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
// Common/MyTypes.h
#ifndef ZIP7_INC_COMMON_MY_TYPES_H
#define ZIP7_INC_COMMON_MY_TYPES_H
#include "Common0.h"
#include "../../C/7zTypes.h"
// typedef int HRes;
// typedef HRESULT HRes;
struct CBoolPair
{
bool Val;
bool Def;
CBoolPair(): Val(false), Def(false) {}
void Init()
{
Val = false;
Def = false;
}
void SetTrueTrue()
{
Val = true;
Def = true;
}
void SetVal_as_Defined(bool val)
{
Val = val;
Def = true;
}
};
#endif

View File

@@ -0,0 +1,8 @@
// MyUnknown.h
#ifndef ZIP7_INC_MY_UNKNOWN_H
#define ZIP7_INC_MY_UNKNOWN_H
#include "MyWindows.h"
#endif

View File

@@ -0,0 +1,724 @@
// Common/MyVector.h
#ifndef ZIP7_INC_COMMON_MY_VECTOR_H
#define ZIP7_INC_COMMON_MY_VECTOR_H
#include <string.h>
#include "Common.h"
const unsigned k_VectorSizeMax = ((unsigned)1 << 31) - 1;
template <class T>
class CRecordVector
{
T *_items;
unsigned _size;
unsigned _capacity;
void MoveItems(unsigned destIndex, unsigned srcIndex)
{
memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T));
}
void ReAllocForNewCapacity(const unsigned newCapacity)
{
T *p;
Z7_ARRAY_NEW(p, T, newCapacity)
// p = new T[newCapacity];
if (_size != 0)
memcpy(p, _items, (size_t)_size * sizeof(T));
delete []_items;
_items = p;
_capacity = newCapacity;
}
public:
void ReserveOnePosition()
{
if (_size != _capacity)
return;
if (_capacity >= k_VectorSizeMax)
throw 2021;
const unsigned rem = k_VectorSizeMax - _capacity;
unsigned add = (_capacity >> 2) + 1;
if (add > rem)
add = rem;
ReAllocForNewCapacity(_capacity + add);
}
CRecordVector(): _items(NULL), _size(0), _capacity(0) {}
CRecordVector(const CRecordVector &v): _items(NULL), _size(0), _capacity(0)
{
const unsigned size = v.Size();
if (size != 0)
{
// Z7_ARRAY_NEW(_items, T, size)
_items = new T[size];
_size = size;
_capacity = size;
memcpy(_items, v._items, (size_t)size * sizeof(T));
}
}
unsigned Size() const { return _size; }
bool IsEmpty() const { return _size == 0; }
void ConstructReserve(unsigned size)
{
if (size != 0)
{
Z7_ARRAY_NEW(_items, T, size)
// _items = new T[size];
_capacity = size;
}
}
void Reserve(unsigned newCapacity)
{
if (newCapacity > _capacity)
{
if (newCapacity > k_VectorSizeMax)
throw 2021;
ReAllocForNewCapacity(newCapacity);
}
}
void ChangeSize_KeepData(unsigned newSize)
{
Reserve(newSize);
_size = newSize;
}
void ClearAndReserve(unsigned newCapacity)
{
Clear();
if (newCapacity > _capacity)
{
if (newCapacity > k_VectorSizeMax)
throw 2021;
delete []_items;
_items = NULL;
_capacity = 0;
Z7_ARRAY_NEW(_items, T, newCapacity)
// _items = new T[newCapacity];
_capacity = newCapacity;
}
}
void ClearAndSetSize(unsigned newSize)
{
ClearAndReserve(newSize);
_size = newSize;
}
void ReserveDown()
{
if (_size == _capacity)
return;
T *p = NULL;
if (_size != 0)
{
// Z7_ARRAY_NEW(p, T, _size)
p = new T[_size];
memcpy(p, _items, (size_t)_size * sizeof(T));
}
delete []_items;
_items = p;
_capacity = _size;
}
~CRecordVector() { delete []_items; }
void ClearAndFree()
{
delete []_items;
_items = NULL;
_size = 0;
_capacity = 0;
}
void Clear() { _size = 0; }
void DeleteBack() { _size--; }
void DeleteFrom(unsigned index)
{
// if (index <= _size)
_size = index;
}
void DeleteFrontal(unsigned num)
{
if (num != 0)
{
MoveItems(0, num);
_size -= num;
}
}
void Delete(unsigned index)
{
MoveItems(index, index + 1);
_size -= 1;
}
/*
void Delete(unsigned index, unsigned num)
{
if (num > 0)
{
MoveItems(index, index + num);
_size -= num;
}
}
*/
CRecordVector& operator=(const CRecordVector &v)
{
if (&v == this)
return *this;
const unsigned size = v.Size();
if (size > _capacity)
{
delete []_items;
_capacity = 0;
_size = 0;
_items = NULL;
_items = new T[size];
_capacity = size;
}
_size = size;
if (size != 0)
memcpy(_items, v._items, (size_t)size * sizeof(T));
return *this;
}
CRecordVector& operator+=(const CRecordVector &v)
{
const unsigned size = v.Size();
if (size != 0)
{
if (_size >= k_VectorSizeMax || size > k_VectorSizeMax - _size)
throw 2021;
const unsigned newSize = _size + size;
Reserve(newSize);
memcpy(_items + _size, v._items, (size_t)size * sizeof(T));
_size = newSize;
}
return *this;
}
unsigned Add(const T item)
{
ReserveOnePosition();
const unsigned size = _size;
_size = size + 1;
_items[size] = item;
return size;
}
/*
unsigned Add2(const T &item)
{
ReserveOnePosition();
const unsigned size = _size;
_size = size + 1;
_items[size] = item;
return size;
}
*/
unsigned AddInReserved(const T item)
{
const unsigned size = _size;
_size = size + 1;
_items[size] = item;
return size;
}
void Insert(unsigned index, const T item)
{
ReserveOnePosition();
MoveItems(index + 1, index);
_items[index] = item;
_size++;
}
void InsertInReserved(unsigned index, const T item)
{
MoveItems(index + 1, index);
_items[index] = item;
_size++;
}
void MoveToFront(unsigned index)
{
if (index != 0)
{
const T temp = _items[index];
memmove(_items + 1, _items, (size_t)index * sizeof(T));
_items[0] = temp;
}
}
const T& operator[](unsigned index) const { return _items[index]; }
T& operator[](unsigned index) { return _items[index]; }
const T& operator[](int index) const { return _items[(unsigned)index]; }
T& operator[](int index) { return _items[(unsigned)index]; }
const T* ConstData() const { return _items; }
T* NonConstData() const { return _items; }
T* NonConstData() { return _items; }
const T* Data() const { return _items; }
T* Data() { return _items; }
const T& FrontItem() const { return _items[0]; }
T& FrontItem() { return _items[0]; }
/*
const T Front() const { return _items[0]; }
T Front() { return _items[0]; }
const T& Front() const { return _items[0]; }
T& Front() { return _items[0]; }
*/
const T& Back() const { return _items[(size_t)_size - 1]; }
T& Back() { return _items[(size_t)_size - 1]; }
/*
void Swap(unsigned i, unsigned j)
{
const T temp = _items[i];
_items[i] = _items[j];
_items[j] = temp;
}
*/
int FindInSorted(const T item, unsigned left, unsigned right) const
{
while (left != right)
{
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
const unsigned mid = (left + right) / 2;
const T midVal = (*this)[mid];
if (item == midVal)
return (int)mid;
if (item < midVal)
right = mid;
else
left = mid + 1;
}
return -1;
}
int FindInSorted2(const T &item, unsigned left, unsigned right) const
{
while (left != right)
{
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
const unsigned mid = (left + right) / 2;
const T& midVal = (*this)[mid];
const int comp = item.Compare(midVal);
if (comp == 0)
return (int)mid;
if (comp < 0)
right = mid;
else
left = mid + 1;
}
return -1;
}
int FindInSorted(const T item) const
{
return FindInSorted(item, 0, _size);
}
int FindInSorted2(const T &item) const
{
return FindInSorted2(item, 0, _size);
}
unsigned AddToUniqueSorted(const T item)
{
unsigned left = 0, right = _size;
while (left != right)
{
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
const unsigned mid = (left + right) / 2;
const T midVal = (*this)[mid];
if (item == midVal)
return mid;
if (item < midVal)
right = mid;
else
left = mid + 1;
}
Insert(right, item);
return right;
}
unsigned AddToUniqueSorted2(const T &item)
{
unsigned left = 0, right = _size;
while (left != right)
{
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
const unsigned mid = (left + right) / 2;
const T& midVal = (*this)[mid];
const int comp = item.Compare(midVal);
if (comp == 0)
return mid;
if (comp < 0)
right = mid;
else
left = mid + 1;
}
Insert(right, item);
return right;
}
static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param)
{
const T temp = p[k];
for (;;)
{
unsigned s = (k << 1);
if (s > size)
break;
if (s < size && compare(p + s + 1, p + s, param) > 0)
s++;
if (compare(&temp, p + s, param) >= 0)
break;
p[k] = p[s];
k = s;
}
p[k] = temp;
}
void Sort(int (*compare)(const T*, const T*, void *), void *param)
{
unsigned size = _size;
if (size <= 1)
return;
T* p = _items - 1;
{
unsigned i = size >> 1;
do
SortRefDown(p, i, size, compare, param);
while (--i);
}
do
{
const T temp = p[size];
p[size--] = p[1];
p[1] = temp;
SortRefDown(p, 1, size, compare, param);
}
while (size > 1);
}
static void SortRefDown2(T* p, unsigned k, unsigned size)
{
const T temp = p[k];
for (;;)
{
unsigned s = (k << 1);
if (s > size)
break;
if (s < size && p[(size_t)s + 1].Compare(p[s]) > 0)
s++;
if (temp.Compare(p[s]) >= 0)
break;
p[k] = p[s];
k = s;
}
p[k] = temp;
}
void Sort2()
{
unsigned size = _size;
if (size <= 1)
return;
T* p = _items - 1;
{
unsigned i = size >> 1;
do
SortRefDown2(p, i, size);
while (--i);
}
do
{
const T temp = p[size];
p[size--] = p[1];
p[1] = temp;
SortRefDown2(p, 1, size);
}
while (size > 1);
}
};
typedef CRecordVector<int> CIntVector;
typedef CRecordVector<unsigned int> CUIntVector;
typedef CRecordVector<bool> CBoolVector;
typedef CRecordVector<unsigned char> CByteVector;
typedef CRecordVector<void *> CPointerVector;
template <class T>
class CObjectVector
{
CPointerVector _v;
public:
unsigned Size() const { return _v.Size(); }
bool IsEmpty() const { return _v.IsEmpty(); }
void ReserveDown() { _v.ReserveDown(); }
// void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); }
void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); }
CObjectVector() {}
CObjectVector(const CObjectVector &v)
{
const unsigned size = v.Size();
_v.ConstructReserve(size);
for (unsigned i = 0; i < size; i++)
AddInReserved(v[i]);
}
CObjectVector& operator=(const CObjectVector &v)
{
if (&v == this)
return *this;
Clear();
const unsigned size = v.Size();
_v.Reserve(size);
for (unsigned i = 0; i < size; i++)
AddInReserved(v[i]);
return *this;
}
CObjectVector& operator+=(const CObjectVector &v)
{
const unsigned addSize = v.Size();
if (addSize != 0)
{
const unsigned size = Size();
if (size >= k_VectorSizeMax || addSize > k_VectorSizeMax - size)
throw 2021;
_v.Reserve(size + addSize);
for (unsigned i = 0; i < addSize; i++)
AddInReserved(v[i]);
}
return *this;
}
const T& operator[](unsigned index) const { return *((T *)_v[index]); }
T& operator[](unsigned index) { return *((T *)_v[index]); }
const T& operator[](int index) const { return *((T *)_v[(unsigned)index]); }
T& operator[](int index) { return *((T *)_v[(unsigned)index]); }
const T& Front() const { return operator[](0); }
T& Front() { return operator[](0); }
const T& Back() const { return *(T *)_v.Back(); }
T& Back() { return *(T *)_v.Back(); }
void MoveToFront(unsigned index) { _v.MoveToFront(index); }
unsigned Add(const T& item)
{
_v.ReserveOnePosition();
return AddInReserved(item);
}
unsigned AddInReserved(const T& item)
{
return _v.AddInReserved(new T(item));
}
void ReserveOnePosition()
{
_v.ReserveOnePosition();
}
unsigned AddInReserved_Ptr_of_new(T *ptr)
{
return _v.AddInReserved(ptr);
}
#define VECTOR_ADD_NEW_OBJECT(v, a) \
(v).ReserveOnePosition(); \
(v).AddInReserved_Ptr_of_new(new a);
T& AddNew()
{
_v.ReserveOnePosition();
T *p = new T;
_v.AddInReserved(p);
return *p;
}
T& AddNewInReserved()
{
T *p = new T;
_v.AddInReserved(p);
return *p;
}
void Insert(unsigned index, const T& item)
{
_v.ReserveOnePosition();
_v.InsertInReserved(index, new T(item));
}
T& InsertNew(unsigned index)
{
_v.ReserveOnePosition();
T *p = new T;
_v.InsertInReserved(index, p);
return *p;
}
~CObjectVector()
{
for (unsigned i = _v.Size(); i != 0;)
delete (T *)_v[--i];
}
void ClearAndFree()
{
Clear();
_v.ClearAndFree();
}
void Clear()
{
for (unsigned i = _v.Size(); i != 0;)
delete (T *)_v[--i];
_v.Clear();
}
void DeleteFrom(unsigned index)
{
const unsigned size = _v.Size();
for (unsigned i = index; i < size; i++)
delete (T *)_v[i];
_v.DeleteFrom(index);
}
void DeleteFrontal(unsigned num)
{
for (unsigned i = 0; i < num; i++)
delete (T *)_v[i];
_v.DeleteFrontal(num);
}
void DeleteBack()
{
delete (T *)_v.Back();
_v.DeleteBack();
}
void Delete(unsigned index)
{
delete (T *)_v[index];
_v.Delete(index);
}
// void Delete(int index) { Delete((unsigned)index); }
/*
void Delete(unsigned index, unsigned num)
{
for (unsigned i = 0; i < num; i++)
delete (T *)_v[index + i];
_v.Delete(index, num);
}
*/
/*
int Find(const T& item) const
{
unsigned size = Size();
for (unsigned i = 0; i < size; i++)
if (item == (*this)[i])
return i;
return -1;
}
*/
int FindInSorted(const T& item) const
{
unsigned left = 0, right = Size();
while (left != right)
{
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
const unsigned mid = (left + right) / 2;
const T& midVal = (*this)[mid];
const int comp = item.Compare(midVal);
if (comp == 0)
return (int)mid;
if (comp < 0)
right = mid;
else
left = mid + 1;
}
return -1;
}
unsigned AddToUniqueSorted(const T& item)
{
unsigned left = 0, right = Size();
while (left != right)
{
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
const unsigned mid = (left + right) / 2;
const T& midVal = (*this)[mid];
const int comp = item.Compare(midVal);
if (comp == 0)
return mid;
if (comp < 0)
right = mid;
else
left = mid + 1;
}
Insert(right, item);
return right;
}
/*
unsigned AddToSorted(const T& item)
{
unsigned left = 0, right = Size();
while (left != right)
{
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
const unsigned mid = (left + right) / 2;
const T& midVal = (*this)[mid];
const int comp = item.Compare(midVal);
if (comp == 0)
{
right = mid + 1;
break;
}
if (comp < 0)
right = mid;
else
left = mid + 1;
}
Insert(right, item);
return right;
}
*/
void Sort(int (*compare)(void *const *, void *const *, void *), void *param)
{ _v.Sort(compare, param); }
static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */)
{ return (*(*((const T *const *)a1))).Compare(*(*((const T *const *)a2))); }
void Sort() { _v.Sort(CompareObjectItems, NULL); }
};
#define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++)
#endif

View File

@@ -0,0 +1,325 @@
// MyWindows.h
#ifdef Z7_DEFINE_GUID
#undef Z7_DEFINE_GUID
#endif
#ifdef INITGUID
#define Z7_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name; \
EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#else
#define Z7_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name
#endif
#ifndef ZIP7_INC_MY_WINDOWS_H
#define ZIP7_INC_MY_WINDOWS_H
#ifdef _WIN32
#include "../../C/7zWindows.h"
#else // _WIN32
#include <stddef.h> // for wchar_t
#include <string.h>
// #include <stdint.h> // for uintptr_t
#include "../../C/7zTypes.h"
#include "MyGuidDef.h"
// WINAPI is __stdcall in Windows-MSVC in windef.h
#define WINAPI
typedef char CHAR;
typedef unsigned char UCHAR;
#undef BYTE
typedef unsigned char BYTE;
typedef short SHORT;
typedef unsigned short USHORT;
#undef WORD
typedef unsigned short WORD;
typedef short VARIANT_BOOL;
#define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff))
#define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16))
// MS uses long for BOOL, but long is 32-bit in MS. So we use int.
// typedef long BOOL;
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
// typedef size_t ULONG_PTR;
// typedef size_t DWORD_PTR;
// typedef uintptr_t UINT_PTR;
// typedef ptrdiff_t UINT_PTR;
typedef Int64 LONGLONG;
typedef UInt64 ULONGLONG;
typedef struct { LONGLONG QuadPart; } LARGE_INTEGER;
typedef struct { ULONGLONG QuadPart; } ULARGE_INTEGER;
typedef const CHAR *LPCSTR;
typedef CHAR TCHAR;
typedef const TCHAR *LPCTSTR;
typedef wchar_t WCHAR;
typedef WCHAR OLECHAR;
typedef const WCHAR *LPCWSTR;
typedef OLECHAR *BSTR;
typedef const OLECHAR *LPCOLESTR;
typedef OLECHAR *LPOLESTR;
typedef struct
{
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
#define FAILED(hr) ((HRESULT)(hr) < 0)
typedef ULONG PROPID;
typedef LONG SCODE;
#define S_OK ((HRESULT)0x00000000L)
#define S_FALSE ((HRESULT)0x00000001L)
#define E_NOTIMPL ((HRESULT)0x80004001L)
#define E_NOINTERFACE ((HRESULT)0x80004002L)
#define E_ABORT ((HRESULT)0x80004004L)
#define E_FAIL ((HRESULT)0x80004005L)
#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)
#define CLASS_E_CLASSNOTAVAILABLE ((HRESULT)0x80040111L)
#ifdef _MSC_VER
#define STDMETHODCALLTYPE __stdcall
#define STDAPICALLTYPE __stdcall
#else
// do we need __export here?
#define STDMETHODCALLTYPE
#define STDAPICALLTYPE
#endif
#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
#ifndef DECLSPEC_NOTHROW
#define DECLSPEC_NOTHROW Z7_DECLSPEC_NOTHROW
#endif
#ifndef DECLSPEC_NOVTABLE
#define DECLSPEC_NOVTABLE Z7_DECLSPEC_NOVTABLE
#endif
#ifndef COM_DECLSPEC_NOTHROW
#ifdef COM_STDMETHOD_CAN_THROW
#define COM_DECLSPEC_NOTHROW
#else
#define COM_DECLSPEC_NOTHROW DECLSPEC_NOTHROW
#endif
#endif
#define DECLARE_INTERFACE(iface) struct DECLSPEC_NOVTABLE iface
#define DECLARE_INTERFACE_(iface, baseiface) struct DECLSPEC_NOVTABLE iface : public baseiface
#define STDMETHOD_(t, f) virtual COM_DECLSPEC_NOTHROW t STDMETHODCALLTYPE f
#define STDMETHOD(f) STDMETHOD_(HRESULT, f)
#define STDMETHODIMP_(t) COM_DECLSPEC_NOTHROW t STDMETHODCALLTYPE
#define STDMETHODIMP STDMETHODIMP_(HRESULT)
#define PURE = 0
// #define MIDL_INTERFACE(x) struct
#ifdef __cplusplus
/*
p7zip and 7-Zip before v23 used virtual destructor in IUnknown,
if _WIN32 is not defined.
It used virtual destructor, because some compilers don't like virtual
interfaces without virtual destructor.
IUnknown in Windows (_WIN32) doesn't use virtual destructor in IUnknown.
We still can define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN here,
if we want to be compatible with old plugin interface of p7zip and 7-Zip before v23.
v23:
In new 7-Zip v23 we try to be more compatible with original IUnknown from _WIN32.
So we do not define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN here,
*/
// #define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN
#ifdef Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN
#if defined(__clang__)
#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override"
#endif
#endif
Z7_PURE_INTERFACES_BEGIN
DEFINE_GUID(IID_IUnknown,
0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
struct IUnknown
{
STDMETHOD(QueryInterface) (REFIID iid, void **outObject) =0;
STDMETHOD_(ULONG, AddRef)() =0;
STDMETHOD_(ULONG, Release)() =0;
#ifdef Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN
virtual ~IUnknown() {}
#endif
};
typedef IUnknown *LPUNKNOWN;
Z7_PURE_INTERFACES_END
#endif // __cplusplus
#define VARIANT_TRUE ((VARIANT_BOOL)-1)
#define VARIANT_FALSE ((VARIANT_BOOL)0)
enum VARENUM
{
VT_EMPTY = 0,
VT_NULL = 1,
VT_I2 = 2,
VT_I4 = 3,
VT_R4 = 4,
VT_R8 = 5,
VT_CY = 6,
VT_DATE = 7,
VT_BSTR = 8,
VT_DISPATCH = 9,
VT_ERROR = 10,
VT_BOOL = 11,
VT_VARIANT = 12,
VT_UNKNOWN = 13,
VT_DECIMAL = 14,
VT_I1 = 16,
VT_UI1 = 17,
VT_UI2 = 18,
VT_UI4 = 19,
VT_I8 = 20,
VT_UI8 = 21,
VT_INT = 22,
VT_UINT = 23,
VT_VOID = 24,
VT_HRESULT = 25,
VT_FILETIME = 64
};
typedef unsigned short VARTYPE;
typedef WORD PROPVAR_PAD1;
typedef WORD PROPVAR_PAD2;
typedef WORD PROPVAR_PAD3;
typedef struct tagPROPVARIANT
{
VARTYPE vt;
PROPVAR_PAD1 wReserved1;
PROPVAR_PAD2 wReserved2;
PROPVAR_PAD3 wReserved3;
union
{
CHAR cVal;
UCHAR bVal;
SHORT iVal;
USHORT uiVal;
LONG lVal;
ULONG ulVal;
INT intVal;
UINT uintVal;
LARGE_INTEGER hVal;
ULARGE_INTEGER uhVal;
VARIANT_BOOL boolVal;
SCODE scode;
FILETIME filetime;
BSTR bstrVal;
};
} PROPVARIANT;
typedef PROPVARIANT tagVARIANT;
typedef tagVARIANT VARIANT;
typedef VARIANT VARIANTARG;
EXTERN_C HRESULT VariantClear(VARIANTARG *prop);
EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src);
typedef struct tagSTATPROPSTG
{
LPOLESTR lpwstrName;
PROPID propid;
VARTYPE vt;
} STATPROPSTG;
EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);
EXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len);
EXTERN_C BSTR SysAllocString(const OLECHAR *sz);
EXTERN_C void SysFreeString(BSTR bstr);
EXTERN_C UINT SysStringByteLen(BSTR bstr);
EXTERN_C UINT SysStringLen(BSTR bstr);
EXTERN_C DWORD GetLastError();
EXTERN_C void SetLastError(DWORD dwCode);
EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);
EXTERN_C DWORD GetCurrentThreadId();
EXTERN_C DWORD GetCurrentProcessId();
#define MAX_PATH 1024
#define CP_ACP 0
#define CP_OEMCP 1
#define CP_UTF8 65001
typedef enum tagSTREAM_SEEK
{
STREAM_SEEK_SET = 0,
STREAM_SEEK_CUR = 1,
STREAM_SEEK_END = 2
} STREAM_SEEK;
typedef struct
{
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME;
BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime);
BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime);
BOOL WINAPI FileTimeToSystemTime(const FILETIME *fileTime, SYSTEMTIME *systemTime);
// VOID WINAPI GetSystemTimeAsFileTime(FILETIME *systemTimeAsFileTime);
DWORD GetTickCount();
/*
#define CREATE_NEW 1
#define CREATE_ALWAYS 2
#define OPEN_EXISTING 3
#define OPEN_ALWAYS 4
#define TRUNCATE_EXISTING 5
*/
#endif // _WIN32
#endif

View File

@@ -0,0 +1,45 @@
// MyXml.h
#ifndef ZIP7_INC_MY_XML_H
#define ZIP7_INC_MY_XML_H
#include "MyString.h"
struct CXmlProp
{
AString Name;
AString Value;
};
class CXmlItem
{
public:
AString Name;
bool IsTag;
CObjectVector<CXmlProp> Props;
CObjectVector<CXmlItem> SubItems;
const char * ParseItem(const char *s, int numAllowedLevels);
bool IsTagged(const char *tag) const throw();
int FindProp(const char *propName) const throw();
AString GetPropVal(const char *propName) const;
AString GetSubString() const;
const AString * GetSubStringPtr() const throw();
int FindSubTag(const char *tag) const throw();
const CXmlItem *FindSubTag_GetPtr(const char *tag) const throw();
AString GetSubStringForTag(const char *tag) const;
void AppendTo(AString &s) const;
};
struct CXml
{
CXmlItem Root;
bool Parse(const char *s);
// void AppendTo(AString &s) const;
};
void z7_xml_DecodeString(AString &s);
#endif

View File

@@ -0,0 +1,121 @@
// Common/NewHandler.h
#ifndef ZIP7_INC_COMMON_NEW_HANDLER_H
#define ZIP7_INC_COMMON_NEW_HANDLER_H
/*
NewHandler.h and NewHandler.cpp allows to solve problem with compilers that
don't throw exception in operator new().
This file must be included before any code that uses operators new() or delete()
and you must compile and link "NewHandler.cpp", if you use some old MSVC compiler.
DOCs:
Since ISO C++98, operator new throws std::bad_alloc when memory allocation fails.
MSVC 6.0 returned a null pointer on an allocation failure.
Beginning in VS2002, operator new conforms to the standard and throws on failure.
By default, the compiler also generates defensive null checks to prevent
these older-style allocators from causing an immediate crash on failure.
The /Zc:throwingNew option tells the compiler to leave out these null checks,
on the assumption that all linked memory allocators conform to the standard.
The operator new() in some MSVC versions doesn't throw exception std::bad_alloc.
MSVC 6.0 (_MSC_VER == 1200) doesn't throw exception.
The code produced by some another MSVC compilers also can be linked
to library that doesn't throw exception.
We suppose that code compiled with VS2015+ (_MSC_VER >= 1900) throws exception std::bad_alloc.
For older _MSC_VER versions we redefine operator new() and operator delete().
Our version of operator new() throws CNewException() exception on failure.
It's still allowed to use redefined version of operator new() from "NewHandler.cpp"
with any compiler. 7-Zip's code can work with std::bad_alloc and CNewException() exceptions.
But if you use some additional code (outside of 7-Zip's code), you must check
that redefined version of operator new() is not problem for your code.
*/
#include <stddef.h>
#ifdef _WIN32
// We can compile my_new and my_delete with _fastcall
/*
void * my_new(size_t size);
void my_delete(void *p) throw();
// void * my_Realloc(void *p, size_t newSize, size_t oldSize);
*/
#endif
#if defined(_MSC_VER) && (_MSC_VER < 1600)
// If you want to use default operator new(), you can disable the following line
#define Z7_REDEFINE_OPERATOR_NEW
#endif
#ifdef Z7_REDEFINE_OPERATOR_NEW
// std::bad_alloc can require additional DLL dependency.
// So we don't define CNewException as std::bad_alloc here.
class CNewException {};
void *
#ifdef _MSC_VER
__cdecl
#endif
operator new(size_t size);
/*
#if 0 && defined(_MSC_VER) && _MSC_VER == 1600
#define Z7_OPERATOR_DELETE_SPEC_THROW0
#else
#define Z7_OPERATOR_DELETE_SPEC_THROW0 throw()
#endif
*/
#if defined(_MSC_VER) && _MSC_VER == 1600
#pragma warning(push)
#pragma warning(disable : 4986) // 'operator delete': exception specification does not match previous declaration
#endif
void
#ifdef _MSC_VER
__cdecl
#endif
operator delete(void *p) throw();
void
#ifdef _MSC_VER
__cdecl
#endif
operator delete(void *p, size_t n) throw();
#if defined(_MSC_VER) && _MSC_VER == 1600
#pragma warning(pop)
#endif
#else
#include <new>
#define CNewException std::bad_alloc
#endif
/*
#ifdef _WIN32
void *
#ifdef _MSC_VER
__cdecl
#endif
operator new[](size_t size);
void
#ifdef _MSC_VER
__cdecl
#endif
operator delete[](void *p) throw();
#endif
*/
#endif

View File

@@ -0,0 +1,14 @@
// Common/Random.h
#ifndef ZIP7_INC_COMMON_RANDOM_H
#define ZIP7_INC_COMMON_RANDOM_H
class CRandom
{
public:
void Init();
void Init(unsigned seed);
int Generate() const;
};
#endif

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef ZIP7_INC_STDAFX_H
#define ZIP7_INC_STDAFX_H
#include "Common.h"
#endif

View File

@@ -0,0 +1,46 @@
// Common/StdInStream.h
#ifndef ZIP7_INC_COMMON_STD_IN_STREAM_H
#define ZIP7_INC_COMMON_STD_IN_STREAM_H
#include <stdio.h>
#include "MyString.h"
#include "MyTypes.h"
class CStdInStream
{
FILE *_stream;
// bool _streamIsOpen;
public:
int CodePage;
CStdInStream(FILE *stream = NULL):
_stream(stream),
// _streamIsOpen(false),
CodePage(-1)
{}
/*
~CStdInStream() { Close(); }
bool Open(LPCTSTR fileName) throw();
bool Close() throw();
*/
// returns:
// false, if ZERO character in stream
// true, if EOF or '\n'
bool ScanAStringUntilNewLine(AString &s);
bool ScanUStringUntilNewLine(UString &s);
// bool ReadToString(AString &resultString);
bool Eof() const throw() { return (feof(_stream) != 0); }
bool Error() const throw() { return (ferror(_stream) != 0); }
int GetChar();
};
extern CStdInStream g_StdIn;
#endif

View File

@@ -0,0 +1,87 @@
// Common/StdOutStream.h
#ifndef ZIP7_INC_COMMON_STD_OUT_STREAM_H
#define ZIP7_INC_COMMON_STD_OUT_STREAM_H
#include <stdio.h>
#include "MyString.h"
#include "MyTypes.h"
class CStdOutStream
{
FILE *_stream;
// bool _streamIsOpen;
public:
bool IsTerminalMode;
CBoolPair ListPathSeparatorSlash;
int CodePage;
CStdOutStream(FILE *stream = NULL):
_stream(stream),
// _streamIsOpen(false),
IsTerminalMode(false),
CodePage(-1)
{
ListPathSeparatorSlash.Val =
#ifdef _WIN32
false;
#else
true;
#endif
}
// ~CStdOutStream() { Close(); }
// void AttachStdStream(FILE *stream) { _stream = stream; _streamIsOpen = false; }
// bool IsDefined() const { return _stream != NULL; }
operator FILE *() { return _stream; }
/*
bool Open(const char *fileName) throw();
bool Close() throw();
*/
bool Flush() throw();
CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream &))
{
(*func)(*this);
return *this;
}
CStdOutStream & operator<<(const char *s) throw()
{
fputs(s, _stream);
return *this;
}
CStdOutStream & operator<<(char c) throw()
{
fputc((unsigned char)c, _stream);
return *this;
}
CStdOutStream & operator<<(Int32 number) throw();
CStdOutStream & operator<<(Int64 number) throw();
CStdOutStream & operator<<(UInt32 number) throw();
CStdOutStream & operator<<(UInt64 number) throw();
CStdOutStream & operator<<(const wchar_t *s);
void PrintUString(const UString &s, AString &temp);
void Convert_UString_to_AString(const UString &src, AString &dest);
void Normalize_UString(UString &s);
void Normalize_UString_Path(UString &s);
void NormalizePrint_UString_Path(const UString &s, UString &tempU, AString &tempA);
void NormalizePrint_UString_Path(const UString &s);
void NormalizePrint_UString(const UString &s);
void NormalizePrint_wstr_Path(const wchar_t *s);
};
CStdOutStream & endl(CStdOutStream & outStream) throw();
extern CStdOutStream g_StdOut;
extern CStdOutStream g_StdErr;
#endif

View File

@@ -0,0 +1,110 @@
// Common/StringConvert.h
#ifndef ZIP7_INC_COMMON_STRING_CONVERT_H
#define ZIP7_INC_COMMON_STRING_CONVERT_H
#include "MyString.h"
#include "MyWindows.h"
UString MultiByteToUnicodeString(const AString &src, UINT codePage = CP_ACP);
UString MultiByteToUnicodeString(const char *src, UINT codePage = CP_ACP);
// optimized versions that work faster for ASCII strings
void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage = CP_ACP);
// void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage);
AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
AString UnicodeStringToMultiByte(const UString &src, UINT codePage = CP_ACP);
inline const wchar_t* GetUnicodeString(const wchar_t *u) { return u; }
inline const UString& GetUnicodeString(const UString &u) { return u; }
inline UString GetUnicodeString(const AString &a) { return MultiByteToUnicodeString(a); }
inline UString GetUnicodeString(const char *a) { return MultiByteToUnicodeString(a); }
inline UString GetUnicodeString(const AString &a, UINT codePage)
{ return MultiByteToUnicodeString(a, codePage); }
inline UString GetUnicodeString(const char *a, UINT codePage)
{ return MultiByteToUnicodeString(a, codePage); }
inline const wchar_t* GetUnicodeString(const wchar_t *u, UINT) { return u; }
inline const UString& GetUnicodeString(const UString &u, UINT) { return u; }
inline const char* GetAnsiString(const char *a) { return a; }
inline const AString& GetAnsiString(const AString &a) { return a; }
inline AString GetAnsiString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }
inline AString GetAnsiString(const UString &u) { return UnicodeStringToMultiByte(u); }
/*
inline const char* GetOemString(const char* oem)
{ return oem; }
inline const AString& GetOemString(const AString &oem)
{ return oem; }
*/
const char* GetOemString(const char* oem);
const AString& GetOemString(const AString &oem);
inline AString GetOemString(const UString &u)
{ return UnicodeStringToMultiByte(u, CP_OEMCP); }
#ifdef _UNICODE
inline const wchar_t* GetSystemString(const wchar_t *u) { return u;}
inline const UString& GetSystemString(const UString &u) { return u;}
inline const wchar_t* GetSystemString(const wchar_t *u, UINT /* codePage */) { return u;}
inline const UString& GetSystemString(const UString &u, UINT /* codePage */) { return u;}
inline UString GetSystemString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }
inline UString GetSystemString(const char *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }
inline UString GetSystemString(const AString &a) { return MultiByteToUnicodeString(a); }
inline UString GetSystemString(const char *a) { return MultiByteToUnicodeString(a); }
#else
inline const char* GetSystemString(const char *a) { return a; }
inline const AString& GetSystemString(const AString &a) { return a; }
inline const char* GetSystemString(const char *a, UINT) { return a; }
inline const AString& GetSystemString(const AString &a, UINT) { return a; }
inline AString GetSystemString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }
inline AString GetSystemString(const UString &u) { return UnicodeStringToMultiByte(u); }
inline AString GetSystemString(const UString &u, UINT codePage) { return UnicodeStringToMultiByte(u, codePage); }
/*
inline AString GetSystemString(const wchar_t *u)
{
UString s;
s = u;
return UnicodeStringToMultiByte(s);
}
*/
#endif
#ifndef UNDER_CE
AString SystemStringToOemString(const CSysString &src);
#endif
#ifdef _WIN32
/* we don't need locale functions in Windows
but we can define ENV_HAVE_LOCALE here for debug purposes */
// #define ENV_HAVE_LOCALE
#else
#define ENV_HAVE_LOCALE
#endif
#ifdef ENV_HAVE_LOCALE
void MY_SetLocale();
const char *GetLocale(void);
#endif
#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)
bool IsNativeUTF8();
#endif
#ifndef _WIN32
extern bool g_ForceToUTF8;
#endif
#endif

View File

@@ -0,0 +1,38 @@
// Common/StringToInt.h
#ifndef ZIP7_INC_COMMON_STRING_TO_INT_H
#define ZIP7_INC_COMMON_STRING_TO_INT_H
#include "MyTypes.h"
UInt32 ConvertStringToUInt32(const char *s, const char **end) throw();
UInt64 ConvertStringToUInt64(const char *s, const char **end) throw();
UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw();
UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw();
// Int32 ConvertStringToInt32(const char *s, const char **end) throw();
Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw();
UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw();
UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw();
UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw();
UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw();
#define Z7_PARSE_HEX_DIGIT(c, err_op) \
{ c -= '0'; \
if (c > 9) { \
c -= 'A' - '0'; \
c &= ~0x20u; \
if (c > 5) { err_op } \
c += 10; \
} \
}
const char *FindNonHexChar(const char *s) throw();
// in: (dest != NULL)
// returns: pointer in dest array after last written byte
Byte *ParseHexString(const char *s, Byte *dest) throw();
#endif

View File

@@ -0,0 +1,19 @@
// Common/TextConfig.h
#ifndef ZIP7_INC_COMMON_TEXT_CONFIG_H
#define ZIP7_INC_COMMON_TEXT_CONFIG_H
#include "MyString.h"
struct CTextConfigPair
{
UString ID;
UString String;
};
bool GetTextConfig(const AString &text, CObjectVector<CTextConfigPair> &pairs);
int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw();
UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id);
#endif

View File

@@ -0,0 +1,384 @@
// Common/UTFConvert.h
#ifndef ZIP7_INC_COMMON_UTF_CONVERT_H
#define ZIP7_INC_COMMON_UTF_CONVERT_H
#include "MyBuffer.h"
#include "MyString.h"
struct CUtf8Check
{
// Byte MaxByte; // in original src stream
bool NonUtf;
bool ZeroChar;
bool SingleSurrogate;
bool Escape;
bool Truncated;
UInt32 MaxHighPoint; // only for points >= 0x80
CUtf8Check() { Clear(); }
void Clear()
{
// MaxByte = 0;
NonUtf = false;
ZeroChar = false;
SingleSurrogate = false;
Escape = false;
Truncated = false;
MaxHighPoint = 0;
}
void Update(const CUtf8Check &c)
{
if (c.NonUtf) NonUtf = true;
if (c.ZeroChar) ZeroChar = true;
if (c.SingleSurrogate) SingleSurrogate = true;
if (c.Escape) Escape = true;
if (c.Truncated) Truncated = true;
if (MaxHighPoint < c.MaxHighPoint) MaxHighPoint = c.MaxHighPoint;
}
void PrintStatus(AString &s) const
{
s.Empty();
// s.Add_OptSpaced("MaxByte=");
// s.Add_UInt32(MaxByte);
if (NonUtf) s.Add_OptSpaced("non-UTF8");
if (ZeroChar) s.Add_OptSpaced("ZeroChar");
if (SingleSurrogate) s.Add_OptSpaced("SingleSurrogate");
if (Escape) s.Add_OptSpaced("Escape");
if (Truncated) s.Add_OptSpaced("Truncated");
if (MaxHighPoint != 0)
{
s.Add_OptSpaced("MaxUnicode=");
s.Add_UInt32(MaxHighPoint);
}
}
bool IsOK(bool allowReduced = false) const
{
if (NonUtf || SingleSurrogate || ZeroChar)
return false;
if (MaxHighPoint >= 0x110000)
return false;
if (Truncated && !allowReduced)
return false;
return true;
}
// it checks full buffer as specified in (size) and it doesn't stop on zero char
void Check_Buf(const char *src, size_t size) throw();
void Check_AString(const AString &s) throw()
{
Check_Buf(s.Ptr(), s.Len());
}
};
/*
if (allowReduced == false) - all UTF-8 character sequences must be finished.
if (allowReduced == true) - it allows truncated last character-Utf8-sequence
*/
bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw();
bool CheckUTF8_AString(const AString &s) throw();
#define Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR (1 << 0)
#define Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE (1 << 1)
#define Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT (1 << 2)
/*
Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR
if (flag is NOT set)
{
it processes SINGLE-SURROGATE-8 as valid Unicode point.
it converts SINGLE-SURROGATE-8 to SINGLE-SURROGATE-16
Note: some sequencies of two SINGLE-SURROGATE-8 points
will generate correct SURROGATE-16-PAIR, and
that SURROGATE-16-PAIR later will be converted to correct
UTF8-SURROGATE-21 point. So we don't restore original
STR-8 sequence in that case.
}
if (flag is set)
{
if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is defined)
it generates ESCAPE for SINGLE-SURROGATE-8,
if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is not defined)
it generates U+fffd for SINGLE-SURROGATE-8,
}
Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE
if (flag is NOT set)
it generates (U+fffd) code for non-UTF-8 (invalid) characters
if (flag is set)
{
It generates (ESCAPE) codes for NON-UTF-8 (invalid) characters.
And later we can restore original UTF-8-RAW characters from (ESCAPE-16-21) codes.
}
Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT
if (flag is NOT set)
{
it process ESCAPE-8 points as another Unicode points.
In Linux: ESCAPE-16 will mean two different ESCAPE-8 seqences,
so we need HIGH-ESCAPE-PLANE-21 to restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW
}
if (flag is set)
{
it generates ESCAPE-16-21 for ESCAPE-8 points
so we can restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW without HIGH-ESCAPE-PLANE-21.
}
Main USE CASES with UTF-8 <-> UTF-16 conversions:
WIN32: UTF-16-RAW -> UTF-8 (Archive) -> UTF-16-RAW
{
set Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE
Do NOT set Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR
Do NOT set Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT
So we restore original SINGLE-SURROGATE-16 from single SINGLE-SURROGATE-8.
}
Linux: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW
{
we want restore original UTF-8-RAW sequence later from that ESCAPE-16.
Set the flags:
Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR
Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE
Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT
}
MacOS: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW
{
we want to restore correct UTF-8 without any BMP processing:
Set the flags:
Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR
Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE
}
*/
// zero char is not allowed in (src) buf
bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags = 0);
bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags = 0);
bool ConvertUTF8ToUnicode(const AString &src, UString &dest);
#define Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR (1 << 8)
#define Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE (1 << 9)
// #define Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE (1 << 10)
/*
Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR
if (flag is NOT set)
{
we extract SINGLE-SURROGATE as normal UTF-8
In Windows : for UTF-16-RAW <-> UTF-8 (archive) <-> UTF-16-RAW in .
In Linux :
use-case-1: UTF-8 -> UTF-16 -> UTF-8 doesn't generate UTF-16 SINGLE-SURROGATE,
if (Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR) is used.
use-case 2: UTF-16-7z (with SINGLE-SURROGATE from Windows) -> UTF-8 (Linux)
will generate SINGLE-SURROGATE-UTF-8 here.
}
if (flag is set)
{
we generate UTF_REPLACEMENT_CHAR (0xfffd) for SINGLE_SURROGATE
it can be used for compatibility mode with WIN32 UTF function
or if we want UTF-8 stream without any errors
}
Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE
if (flag is NOT set) it doesn't extract raw 8-bit symbol from Escape-Plane-16
if (flag is set) it extracts raw 8-bit symbol from Escape-Plane-16
in Linux we need some way to extract NON-UTF8 RAW 8-bits from BMP (UTF-16 7z archive):
if (we use High-Escape-Plane), we can transfer BMP escapes to High-Escape-Plane.
if (we don't use High-Escape-Plane), we must use Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE.
Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE
// that flag affects the code only if (wchar_t is 32-bit)
// that mode with high-escape can be disabled now in UTFConvert.cpp
if (flag is NOT set)
it doesn't extract raw 8-bit symbol from High-Escape-Plane
if (flag is set)
it extracts raw 8-bit symbol from High-Escape-Plane
Main use cases:
WIN32 : UTF-16-RAW -> UTF-8 (archive) -> UTF-16-RAW
{
Do NOT set Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE.
Do NOT set Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR.
So we restore original UTF-16-RAW.
}
Linix : UTF-8 with Escapes -> UTF-16 (7z archive) -> UTF-8 with Escapes
set Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE to extract non-UTF from 7z archive
set Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE for intermediate UTF-16.
Note: high esacape mode can be ignored now in UTFConvert.cpp
macOS:
the system doesn't support incorrect UTF-8 in file names.
set Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR
*/
extern unsigned g_Unicode_To_UTF8_Flags;
void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags = 0);
void ConvertUnicodeToUTF8(const UString &src, AString &dest);
void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest);
/*
#ifndef _WIN32
void Convert_UTF16_To_UTF32(const UString &src, UString &dest);
void Convert_UTF32_To_UTF16(const UString &src, UString &dest);
bool UTF32_IsThere_BigPoint(const UString &src);
bool Unicode_IsThere_BmpEscape(const UString &src);
#endif
bool Unicode_IsThere_Utf16SurrogateError(const UString &src);
*/
#ifdef Z7_WCHART_IS_16BIT
#define Convert_UnicodeEsc16_To_UnicodeEscHigh(s)
#else
void Convert_UnicodeEsc16_To_UnicodeEscHigh(UString &s);
#endif
/*
// #include "../../C/CpuArch.h"
// ---------- Utf16 Little endian functions ----------
// We store 16-bit surrogates even in 32-bit WCHARs in Linux.
// So now we don't use the following code:
#if WCHAR_MAX > 0xffff
// void *p : pointer to src bytes stream
// size_t len : num Utf16 characters : it can include or not include NULL character
inline size_t Utf16LE__Get_Num_WCHARs(const void *p, size_t len)
{
#if WCHAR_MAX > 0xffff
size_t num_wchars = 0;
for (size_t i = 0; i < len; i++)
{
wchar_t c = GetUi16(p);
p = (const void *)((const Byte *)p + 2);
if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
{
wchar_t c2 = GetUi16(p);
if (c2 >= 0xdc00 && c2 < 0xe000)
{
c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
p = (const void *)((const Byte *)p + 2);
i++;
}
}
num_wchars++;
}
return num_wchars;
#else
UNUSED_VAR(p)
return len;
#endif
}
// #include <stdio.h>
inline wchar_t *Utf16LE__To_WCHARs_Sep(const void *p, size_t len, wchar_t *dest)
{
for (size_t i = 0; i < len; i++)
{
wchar_t c = GetUi16(p);
p = (const void *)((const Byte *)p + 2);
#if WCHAR_PATH_SEPARATOR != L'/'
if (c == L'/')
c = WCHAR_PATH_SEPARATOR;
#endif
#if WCHAR_MAX > 0xffff
if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
{
wchar_t c2 = GetUi16(p);
if (c2 >= 0xdc00 && c2 < 0xe000)
{
// printf("\nSurragate : %4x %4x -> ", (int)c, (int)c2);
c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
p = (const void *)((const Byte *)p + 2);
i++;
// printf("%4x\n", (int)c);
}
}
#endif
*dest++ = c;
}
return dest;
}
inline size_t Get_Num_Utf16_chars_from_wchar_string(const wchar_t *p)
{
size_t num = 0;
for (;;)
{
wchar_t c = *p++;
if (c == 0)
return num;
num += ((c >= 0x10000 && c < 0x110000) ? 2 : 1);
}
return num;
}
inline Byte *wchars_to_Utf16LE(const wchar_t *p, Byte *dest)
{
for (;;)
{
wchar_t c = *p++;
if (c == 0)
return dest;
if (c >= 0x10000 && c < 0x110000)
{
SetUi16(dest , (UInt16)(0xd800 + ((c >> 10) & 0x3FF)));
SetUi16(dest + 2, (UInt16)(0xdc00 + ( c & 0x3FF)));
dest += 4;
}
else
{
SetUi16(dest, c);
dest += 2;
}
}
}
#endif
*/
#endif

View File

@@ -0,0 +1,231 @@
// Common/Wildcard.h
#ifndef ZIP7_INC_COMMON_WILDCARD_H
#define ZIP7_INC_COMMON_WILDCARD_H
#include "MyString.h"
int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW;
#ifndef USE_UNICODE_FSTRING
int CompareFileNames(const char *s1, const char *s2);
#endif
bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2);
void SplitPathToParts(const UString &path, UStringVector &pathParts);
void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name);
void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path)
UString ExtractDirPrefixFromPath(const UString &path);
UString ExtractFileNameFromPath(const UString &path);
bool DoesNameContainWildcard(const UString &path);
bool DoesWildcardMatchName(const UString &mask, const UString &name);
namespace NWildcard {
#ifdef _WIN32
// returns true, if name is like "a:", "c:", ...
bool IsDriveColonName(const wchar_t *s);
unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts);
#endif
struct CItem
{
UStringVector PathParts;
bool Recursive;
bool ForFile;
bool ForDir;
bool WildcardMatching;
#ifdef _WIN32
bool IsDriveItem() const
{
return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]);
}
#endif
// CItem(): WildcardMatching(true) {}
bool AreAllAllowed() const;
bool CheckPath(const UStringVector &pathParts, bool isFile) const;
};
const Byte kMark_FileOrDir = 0;
const Byte kMark_StrictFile = 1;
const Byte kMark_StrictFile_IfWildcard = 2;
struct CCensorPathProps
{
bool Recursive;
bool WildcardMatching;
Byte MarkMode;
CCensorPathProps():
Recursive(false),
WildcardMatching(true),
MarkMode(kMark_FileOrDir)
{}
};
class CCensorNode MY_UNCOPYABLE
{
CCensorNode *Parent;
bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;
void AddItemSimple(bool include, CItem &item);
public:
// bool ExcludeDirItems;
CCensorNode():
Parent(NULL)
// , ExcludeDirItems(false)
{}
CCensorNode(const UString &name, CCensorNode *parent):
Parent(parent)
// , ExcludeDirItems(false)
, Name(name)
{}
UString Name; // WIN32 doesn't support wildcards in file names
CObjectVector<CCensorNode> SubNodes;
CObjectVector<CItem> IncludeItems;
CObjectVector<CItem> ExcludeItems;
CCensorNode &Find_SubNode_Or_Add_New(const UString &name)
{
int i = FindSubNode(name);
if (i >= 0)
return SubNodes[(unsigned)i];
// return SubNodes.Add(CCensorNode(name, this));
CCensorNode &node = SubNodes.AddNew();
node.Parent = this;
node.Name = name;
return node;
}
bool AreAllAllowed() const;
int FindSubNode(const UString &path) const;
void AddItem(bool include, CItem &item, int ignoreWildcardIndex = -1);
// void AddItem(bool include, const UString &path, const CCensorPathProps &props);
void Add_Wildcard()
{
CItem item;
item.PathParts.Add(L"*");
item.Recursive = false;
item.ForFile = true;
item.ForDir = true;
item.WildcardMatching = true;
AddItem(
true // include
, item);
}
// NeedCheckSubDirs() returns true, if there are IncludeItems rules that affect items in subdirs
bool NeedCheckSubDirs() const;
bool AreThereIncludeItems() const;
/*
CheckPathVect() doesn't check path in Parent CCensorNode
so use CheckPathVect() for root CCensorNode
OUT:
returns (true) && (include = false) - file in exlude list
returns (true) && (include = true) - file in include list and is not in exlude list
returns (false) - file is not in (include/exlude) list
*/
bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const;
// bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const;
// bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
// CheckPathToRoot_Change() changes pathParts !!!
bool CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const;
bool CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const;
// bool CheckPathToRoot(const UString &path, bool isFile, bool include) const;
void ExtendExclude(const CCensorNode &fromNodes);
};
struct CPair MY_UNCOPYABLE
{
UString Prefix;
CCensorNode Head;
// CPair(const UString &prefix): Prefix(prefix) { };
};
enum ECensorPathMode
{
k_RelatPath, // absolute prefix as Prefix, remain path in Tree
k_FullPath, // drive prefix as Prefix, remain path in Tree
k_AbsPath // full path in Tree
};
struct CCensorPath
{
UString Path;
bool Include;
CCensorPathProps Props;
CCensorPath():
Include(true)
{}
};
class CCensor MY_UNCOPYABLE
{
int FindPairForPrefix(const UString &prefix) const;
public:
CObjectVector<CPair> Pairs;
bool ExcludeDirItems;
bool ExcludeFileItems;
CCensor():
ExcludeDirItems(false),
ExcludeFileItems(false)
{}
CObjectVector<NWildcard::CCensorPath> CensorPaths;
bool AllAreRelative() const
{ return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }
void AddItem(ECensorPathMode pathMode, bool include, const UString &path, const CCensorPathProps &props);
// bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
void ExtendExclude();
void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode);
void AddPreItem(bool include, const UString &path, const CCensorPathProps &props);
void AddPreItem_NoWildcard(const UString &path)
{
CCensorPathProps props;
props.WildcardMatching = false;
AddPreItem(
true, // include
path, props);
}
void AddPreItem_Wildcard()
{
CCensorPathProps props;
// props.WildcardMatching = true;
AddPreItem(
true, // include
UString("*"), props);
}
};
}
#endif

View File

@@ -0,0 +1,25 @@
/*
* bit7z - A C++ static library to interface with the 7-zip shared libraries.
* Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef BIT7Z_HPP
#define BIT7Z_HPP
#include "bitarchiveeditor.hpp"
#include "bitarchivereader.hpp"
#include "bitarchivewriter.hpp"
#include "bitexception.hpp"
#include "bitfilecompressor.hpp"
#include "bitfileextractor.hpp"
#include "bitmemcompressor.hpp"
#include "bitmemextractor.hpp"
#include "bitstreamcompressor.hpp"
#include "bitstreamextractor.hpp"
#endif // BIT7Z_HPP

View File

@@ -0,0 +1,101 @@
/*
* bit7z - A C++ static library to interface with the 7-zip shared libraries.
* Copyright (c) 2014-2023 Riccardo Ostani - All Rights Reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef BIT7ZLIBRARY_HPP
#define BIT7ZLIBRARY_HPP
#include <string>
#include "bitformat.hpp"
#include "bittypes.hpp"
#include "bitwindows.hpp"
//! @cond IGNORE_BLOCK_IN_DOXYGEN
struct IInArchive;
struct IOutArchive;
template< typename T >
class CMyComPtr;
//! @endcond
/**
* @brief The main namespace of the bit7z library.
*/
namespace bit7z {
/**
* @brief The default file path for the 7-zip shared library to be used by bit7z
* in case the user doesn't pass a path to the constructor of the Bit7zLibrary class.
*
* @note On Windows, the default library is 7z.dll, and it is searched following the Win32 API rules
* (https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order).
*
* @note On Linux, the default library is the absolute path to the "7z.so" installed by p7zip.
*
* @note In all other cases, the value will be the relative path to a "7z.so" in the working directory of the program.
*/
#ifdef __DOXYGEN__
constexpr auto kDefaultLibrary = "<platform-dependent value>";
#elif defined( _WIN32 )
constexpr auto kDefaultLibrary = BIT7Z_STRING( "7z.dll" );
#elif defined( __linux__ )
constexpr auto kDefaultLibrary = "/usr/lib/p7zip/7z.so"; // Default installation path of the p7zip shared library.
#else
constexpr auto kDefaultLibrary = "./7z.so";
#endif
/**
* @brief The Bit7zLibrary class allows accessing the basic functionalities provided by the 7z DLLs.
*/
class Bit7zLibrary final {
public:
Bit7zLibrary( const Bit7zLibrary& ) = delete;
Bit7zLibrary( Bit7zLibrary&& ) = delete;
auto operator=( const Bit7zLibrary& ) -> Bit7zLibrary& = delete;
auto operator=( Bit7zLibrary&& ) -> Bit7zLibrary& = delete;
/**
* @brief Constructs a Bit7zLibrary object by loading the specified 7zip shared library.
*
* By default, it searches a 7z.dll in the same path of the application.
*
* @param libraryPath the path to the shared library file to be loaded.
*/
explicit Bit7zLibrary( const tstring& libraryPath = kDefaultLibrary );
/**
* @brief Destructs the Bit7zLibrary object, freeing the loaded shared library.
*/
~Bit7zLibrary();
/**
* @brief Set the 7-zip shared library to use large memory pages.
*/
void setLargePageMode();
private:
HMODULE mLibrary;
FARPROC mCreateObjectFunc;
BIT7Z_NODISCARD
auto initInArchive( const BitInFormat& format ) const -> CMyComPtr< IInArchive >;
BIT7Z_NODISCARD
auto initOutArchive( const BitInOutFormat& format ) const -> CMyComPtr< IOutArchive >;
friend class BitInputArchive;
friend class BitOutputArchive;
};
} // namespace bit7z
#endif // BIT7ZLIBRARY_HPP

Some files were not shown because too many files have changed in this diff Show More