Kaynağa Gözat

Merge branch 'islzma-vs22'

Martijn Laan 1 yıl önce
ebeveyn
işleme
e725799fcb
59 değiştirilmiş dosya ile 11624 ekleme ve 2878 silme
  1. 199 0
      Components/Lzma2/7zStream.c
  2. 597 0
      Components/Lzma2/7zTypes.h
  3. 101 0
      Components/Lzma2/7zWindows.h
  4. 535 57
      Components/Lzma2/Alloc.c
  5. 52 14
      Components/Lzma2/Alloc.h
  6. 236 0
      Components/Lzma2/Compiler.h
  7. 885 0
      Components/Lzma2/CpuArch.c
  8. 647 0
      Components/Lzma2/CpuArch.h
  9. 717 158
      Components/Lzma2/LzFind.c
  10. 88 43
      Components/Lzma2/LzFind.h
  11. 620 237
      Components/Lzma2/LzFindMt.c
  12. 43 36
      Components/Lzma2/LzFindMt.h
  13. 578 0
      Components/Lzma2/LzFindOpt.c
  14. 25 45
      Components/Lzma2/LzHash.h
  15. 265 128
      Components/Lzma2/Lzma2Dec.c
  16. 59 22
      Components/Lzma2/Lzma2Dec.h
  17. 566 245
      Components/Lzma2/Lzma2Enc.c
  18. 27 36
      Components/Lzma2/Lzma2Enc.h
  19. 431 204
      Components/Lzma2/LzmaDec.c
  20. 39 33
      Components/Lzma2/LzmaDec.h
  21. 510 280
      Components/Lzma2/LzmaEnc.c
  22. 38 35
      Components/Lzma2/LzmaEnc.h
  23. 478 234
      Components/Lzma2/MtCoder.c
  24. 105 62
      Components/Lzma2/MtCoder.h
  25. 1124 0
      Components/Lzma2/MtDec.c
  26. 202 0
      Components/Lzma2/MtDec.h
  27. 127 0
      Components/Lzma2/Precomp.h
  28. 517 20
      Components/Lzma2/Threads.c
  29. 206 15
      Components/Lzma2/Threads.h
  30. 0 236
      Components/Lzma2/Types.h
  31. 615 0
      Components/Lzma2/lzma-history.txt
  32. 345 0
      Components/Lzma2/lzma.txt
  33. BIN
      Files/islzma.dll
  34. BIN
      Files/islzma32.exe
  35. BIN
      Files/islzma64.exe
  36. 12 11
      ISHelp/isetup.xml
  37. 2 1
      Projects/Src/ISCmplr/Compile.pas
  38. 16 11
      Projects/Src/ISCmplr/LZMA.pas
  39. 3 10
      Projects/Src/ISCmplr/islzma/islzma.c
  40. 2 1
      Projects/Src/ISCmplr/islzma/islzma.h
  41. 9 4
      Projects/Src/ISCmplr/islzma/islzma.sln
  42. 0 266
      Projects/Src/ISCmplr/islzma/islzma.vcproj
  43. 128 0
      Projects/Src/ISCmplr/islzma/islzma.vcxproj
  44. 93 0
      Projects/Src/ISCmplr/islzma/islzma.vcxproj.filters
  45. 9 0
      Projects/Src/ISCmplr/islzma/islzma.vcxproj.user
  46. 8 11
      Projects/Src/ISCmplr/islzma/islzma_exe.c
  47. 0 413
      Projects/Src/ISCmplr/islzma/islzma_exe.vcproj
  48. 211 0
      Projects/Src/ISCmplr/islzma/islzma_exe.vcxproj
  49. 106 0
      Projects/Src/ISCmplr/islzma/islzma_exe.vcxproj.filters
  50. 15 0
      Projects/Src/ISCmplr/islzma/islzma_exe.vcxproj.user
  51. 17 5
      Projects/Src/Setup/LZMADecomp.pas
  52. 5 0
      Projects/Src/Setup/Lzma2Decode/ISLzma2Dec.c
  53. BIN
      Projects/Src/Setup/Lzma2Decode/ISLzma2Dec.obj
  54. 5 0
      Projects/Src/Setup/Lzma2Decode/ISLzmaDec.c
  55. BIN
      Projects/Src/Setup/Lzma2Decode/ISLzmaDec.obj
  56. 1 1
      Projects/Src/Setup/Lzma2Decode/compile.bat
  57. 1 1
      Projects/Src/SetupLdr/LzmaDecode/compile.bat
  58. 1 1
      README.md
  59. 3 2
      whatsnew.htm

+ 199 - 0
Components/Lzma2/7zStream.c

@@ -0,0 +1,199 @@
+/* 7zStream.c -- 7z Stream functions
+2023-04-02 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+#include <string.h>
+
+#include "7zTypes.h"
+
+
+SRes SeqInStream_ReadMax(ISeqInStreamPtr stream, void *buf, size_t *processedSize)
+{
+  size_t size = *processedSize;
+  *processedSize = 0;
+  while (size != 0)
+  {
+    size_t cur = size;
+    const SRes res = ISeqInStream_Read(stream, buf, &cur);
+    *processedSize += cur;
+    buf = (void *)((Byte *)buf + cur);
+    size -= cur;
+    if (res != SZ_OK)
+      return res;
+    if (cur == 0)
+      return SZ_OK;
+  }
+  return SZ_OK;
+}
+
+/*
+SRes SeqInStream_Read2(ISeqInStreamPtr stream, void *buf, size_t size, SRes errorType)
+{
+  while (size != 0)
+  {
+    size_t processed = size;
+    RINOK(ISeqInStream_Read(stream, buf, &processed))
+    if (processed == 0)
+      return errorType;
+    buf = (void *)((Byte *)buf + processed);
+    size -= processed;
+  }
+  return SZ_OK;
+}
+
+SRes SeqInStream_Read(ISeqInStreamPtr stream, void *buf, size_t size)
+{
+  return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
+}
+*/
+
+
+SRes SeqInStream_ReadByte(ISeqInStreamPtr stream, Byte *buf)
+{
+  size_t processed = 1;
+  RINOK(ISeqInStream_Read(stream, buf, &processed))
+  return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
+}
+
+
+
+SRes LookInStream_SeekTo(ILookInStreamPtr stream, UInt64 offset)
+{
+  Int64 t = (Int64)offset;
+  return ILookInStream_Seek(stream, &t, SZ_SEEK_SET);
+}
+
+SRes LookInStream_LookRead(ILookInStreamPtr stream, void *buf, size_t *size)
+{
+  const void *lookBuf;
+  if (*size == 0)
+    return SZ_OK;
+  RINOK(ILookInStream_Look(stream, &lookBuf, size))
+  memcpy(buf, lookBuf, *size);
+  return ILookInStream_Skip(stream, *size);
+}
+
+SRes LookInStream_Read2(ILookInStreamPtr stream, void *buf, size_t size, SRes errorType)
+{
+  while (size != 0)
+  {
+    size_t processed = size;
+    RINOK(ILookInStream_Read(stream, buf, &processed))
+    if (processed == 0)
+      return errorType;
+    buf = (void *)((Byte *)buf + processed);
+    size -= processed;
+  }
+  return SZ_OK;
+}
+
+SRes LookInStream_Read(ILookInStreamPtr stream, void *buf, size_t size)
+{
+  return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
+}
+
+
+
+#define GET_LookToRead2  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLookToRead2)
+
+static SRes LookToRead2_Look_Lookahead(ILookInStreamPtr pp, const void **buf, size_t *size)
+{
+  SRes res = SZ_OK;
+  GET_LookToRead2
+  size_t size2 = p->size - p->pos;
+  if (size2 == 0 && *size != 0)
+  {
+    p->pos = 0;
+    p->size = 0;
+    size2 = p->bufSize;
+    res = ISeekInStream_Read(p->realStream, p->buf, &size2);
+    p->size = size2;
+  }
+  if (*size > size2)
+    *size = size2;
+  *buf = p->buf + p->pos;
+  return res;
+}
+
+static SRes LookToRead2_Look_Exact(ILookInStreamPtr pp, const void **buf, size_t *size)
+{
+  SRes res = SZ_OK;
+  GET_LookToRead2
+  size_t size2 = p->size - p->pos;
+  if (size2 == 0 && *size != 0)
+  {
+    p->pos = 0;
+    p->size = 0;
+    if (*size > p->bufSize)
+      *size = p->bufSize;
+    res = ISeekInStream_Read(p->realStream, p->buf, size);
+    size2 = p->size = *size;
+  }
+  if (*size > size2)
+    *size = size2;
+  *buf = p->buf + p->pos;
+  return res;
+}
+
+static SRes LookToRead2_Skip(ILookInStreamPtr pp, size_t offset)
+{
+  GET_LookToRead2
+  p->pos += offset;
+  return SZ_OK;
+}
+
+static SRes LookToRead2_Read(ILookInStreamPtr pp, void *buf, size_t *size)
+{
+  GET_LookToRead2
+  size_t rem = p->size - p->pos;
+  if (rem == 0)
+    return ISeekInStream_Read(p->realStream, buf, size);
+  if (rem > *size)
+    rem = *size;
+  memcpy(buf, p->buf + p->pos, rem);
+  p->pos += rem;
+  *size = rem;
+  return SZ_OK;
+}
+
+static SRes LookToRead2_Seek(ILookInStreamPtr pp, Int64 *pos, ESzSeek origin)
+{
+  GET_LookToRead2
+  p->pos = p->size = 0;
+  return ISeekInStream_Seek(p->realStream, pos, origin);
+}
+
+void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead)
+{
+  p->vt.Look = lookahead ?
+      LookToRead2_Look_Lookahead :
+      LookToRead2_Look_Exact;
+  p->vt.Skip = LookToRead2_Skip;
+  p->vt.Read = LookToRead2_Read;
+  p->vt.Seek = LookToRead2_Seek;
+}
+
+
+
+static SRes SecToLook_Read(ISeqInStreamPtr pp, void *buf, size_t *size)
+{
+  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToLook)
+  return LookInStream_LookRead(p->realStream, buf, size);
+}
+
+void SecToLook_CreateVTable(CSecToLook *p)
+{
+  p->vt.Read = SecToLook_Read;
+}
+
+static SRes SecToRead_Read(ISeqInStreamPtr pp, void *buf, size_t *size)
+{
+  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToRead)
+  return ILookInStream_Read(p->realStream, buf, size);
+}
+
+void SecToRead_CreateVTable(CSecToRead *p)
+{
+  p->vt.Read = SecToRead_Read;
+}

+ 597 - 0
Components/Lzma2/7zTypes.h

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

+ 101 - 0
Components/Lzma2/7zWindows.h

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

+ 535 - 57
Components/Lzma2/Alloc.c

@@ -1,33 +1,183 @@
 /* Alloc.c -- Memory allocation functions
 /* Alloc.c -- Memory allocation functions
-2008-09-24
-Igor Pavlov
-Public domain */
+2024-02-18 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
 
 
 #ifdef _WIN32
 #ifdef _WIN32
-#include <windows.h>
+#include "7zWindows.h"
 #endif
 #endif
 #include <stdlib.h>
 #include <stdlib.h>
 
 
 #include "Alloc.h"
 #include "Alloc.h"
 
 
-/* #define _SZ_ALLOC_DEBUG */
+#if defined(Z7_LARGE_PAGES) && defined(_WIN32) && \
+    (!defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502)  // < Win2003 (xp-64)
+  #define Z7_USE_DYN_GetLargePageMinimum
+#endif
+
+// for debug:
+#if 0
+#if defined(__CHERI__) && defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)
+// #pragma message("=== Z7_ALLOC_NO_OFFSET_ALLOCATOR === ")
+#define Z7_ALLOC_NO_OFFSET_ALLOCATOR
+#endif
+#endif
+
+// #define SZ_ALLOC_DEBUG
+/* #define SZ_ALLOC_DEBUG */
 
 
-/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
-#ifdef _SZ_ALLOC_DEBUG
+/* use SZ_ALLOC_DEBUG to debug alloc/free operations */
+#ifdef SZ_ALLOC_DEBUG
+
+#include <string.h>
 #include <stdio.h>
 #include <stdio.h>
-int g_allocCount = 0;
-int g_allocCountMid = 0;
-int g_allocCountBig = 0;
+static int g_allocCount = 0;
+#ifdef _WIN32
+static int g_allocCountMid = 0;
+static int g_allocCountBig = 0;
+#endif
+
+
+#define CONVERT_INT_TO_STR(charType, tempSize) \
+  char temp[tempSize]; unsigned i = 0; \
+  while (val >= 10) { temp[i++] = (char)('0' + (unsigned)(val % 10)); val /= 10; } \
+  *s++ = (charType)('0' + (unsigned)val); \
+  while (i != 0) { i--; *s++ = temp[i]; } \
+  *s = 0;
+
+static void ConvertUInt64ToString(UInt64 val, char *s)
+{
+  CONVERT_INT_TO_STR(char, 24)
+}
+
+#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
+
+static void ConvertUInt64ToHex(UInt64 val, char *s)
+{
+  UInt64 v = val;
+  unsigned i;
+  for (i = 1;; i++)
+  {
+    v >>= 4;
+    if (v == 0)
+      break;
+  }
+  s[i] = 0;
+  do
+  {
+    unsigned t = (unsigned)(val & 0xF);
+    val >>= 4;
+    s[--i] = GET_HEX_CHAR(t);
+  }
+  while (i);
+}
+
+#define DEBUG_OUT_STREAM stderr
+
+static void Print(const char *s)
+{
+  fputs(s, DEBUG_OUT_STREAM);
+}
+
+static void PrintAligned(const char *s, size_t align)
+{
+  size_t len = strlen(s);
+  for(;;)
+  {
+    fputc(' ', DEBUG_OUT_STREAM);
+    if (len >= align)
+      break;
+    ++len;
+  }
+  Print(s);
+}
+
+static void PrintLn(void)
+{
+  Print("\n");
+}
+
+static void PrintHex(UInt64 v, size_t align)
+{
+  char s[32];
+  ConvertUInt64ToHex(v, s);
+  PrintAligned(s, align);
+}
+
+static void PrintDec(int v, size_t align)
+{
+  char s[32];
+  ConvertUInt64ToString((unsigned)v, s);
+  PrintAligned(s, align);
+}
+
+static void PrintAddr(void *p)
+{
+  PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12);
+}
+
+
+#define PRINT_REALLOC(name, cnt, size, ptr) { \
+    Print(name " "); \
+    if (!ptr) PrintDec(cnt++, 10); \
+    PrintHex(size, 10); \
+    PrintAddr(ptr); \
+    PrintLn(); }
+
+#define PRINT_ALLOC(name, cnt, size, ptr) { \
+    Print(name " "); \
+    PrintDec(cnt++, 10); \
+    PrintHex(size, 10); \
+    PrintAddr(ptr); \
+    PrintLn(); }
+ 
+#define PRINT_FREE(name, cnt, ptr) if (ptr) { \
+    Print(name " "); \
+    PrintDec(--cnt, 10); \
+    PrintAddr(ptr); \
+    PrintLn(); }
+ 
+#else
+
+#ifdef _WIN32
+#define PRINT_ALLOC(name, cnt, size, ptr)
+#endif
+#define PRINT_FREE(name, cnt, ptr)
+#define Print(s)
+#define PrintLn()
+#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
+#define PrintHex(v, align)
 #endif
 #endif
+#define PrintAddr(p)
+
+#endif
+
+
+/*
+by specification:
+  malloc(non_NULL, 0)   : returns NULL or a unique pointer value that can later be successfully passed to free()
+  realloc(NULL, size)   : the call is equivalent to malloc(size)
+  realloc(non_NULL, 0)  : the call is equivalent to free(ptr)
+
+in main compilers:
+  malloc(0)             : returns non_NULL
+  realloc(NULL,     0)  : returns non_NULL
+  realloc(non_NULL, 0)  : returns NULL
+*/
+
 
 
 void *MyAlloc(size_t size)
 void *MyAlloc(size_t size)
 {
 {
   if (size == 0)
   if (size == 0)
-    return 0;
-  #ifdef _SZ_ALLOC_DEBUG
+    return NULL;
+  // PRINT_ALLOC("Alloc    ", g_allocCount, size, NULL)
+  #ifdef SZ_ALLOC_DEBUG
   {
   {
     void *p = malloc(size);
     void *p = malloc(size);
-    fprintf(stderr, "\nAlloc %10d bytes, count = %10d,  addr = %8X", size, g_allocCount++, (unsigned)p);
+    if (p)
+    {
+      PRINT_ALLOC("Alloc    ", g_allocCount, size, p)
+    }
     return p;
     return p;
   }
   }
   #else
   #else
@@ -37,91 +187,419 @@ void *MyAlloc(size_t size)
 
 
 void MyFree(void *address)
 void MyFree(void *address)
 {
 {
-  #ifdef _SZ_ALLOC_DEBUG
-  if (address != 0)
-    fprintf(stderr, "\nFree; count = %10d,  addr = %8X", --g_allocCount, (unsigned)address);
-  #endif
+  PRINT_FREE("Free    ", g_allocCount, address)
+  
   free(address);
   free(address);
 }
 }
 
 
+void *MyRealloc(void *address, size_t size)
+{
+  if (size == 0)
+  {
+    MyFree(address);
+    return NULL;
+  }
+  // PRINT_REALLOC("Realloc  ", g_allocCount, size, address)
+  #ifdef SZ_ALLOC_DEBUG
+  {
+    void *p = realloc(address, size);
+    if (p)
+    {
+      PRINT_REALLOC("Realloc    ", g_allocCount, size, address)
+    }
+    return p;
+  }
+  #else
+  return realloc(address, size);
+  #endif
+}
+
+
 #ifdef _WIN32
 #ifdef _WIN32
 
 
 void *MidAlloc(size_t size)
 void *MidAlloc(size_t size)
 {
 {
   if (size == 0)
   if (size == 0)
-    return 0;
-  #ifdef _SZ_ALLOC_DEBUG
-  fprintf(stderr, "\nAlloc_Mid %10d bytes;  count = %10d", size, g_allocCountMid++);
+    return NULL;
+  #ifdef SZ_ALLOC_DEBUG
+  {
+    void *p = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
+    if (p)
+    {
+      PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, p)
+    }
+    return p;
+  }
+  #else
+  return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
   #endif
   #endif
-  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
 }
 }
 
 
 void MidFree(void *address)
 void MidFree(void *address)
 {
 {
-  #ifdef _SZ_ALLOC_DEBUG
-  if (address != 0)
-    fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
-  #endif
-  if (address == 0)
+  PRINT_FREE("Free-Mid", g_allocCountMid, address)
+
+  if (!address)
     return;
     return;
   VirtualFree(address, 0, MEM_RELEASE);
   VirtualFree(address, 0, MEM_RELEASE);
 }
 }
 
 
-#ifndef MEM_LARGE_PAGES
-#undef _7ZIP_LARGE_PAGES
+#ifdef Z7_LARGE_PAGES
+
+#ifdef MEM_LARGE_PAGES
+  #define MY_MEM_LARGE_PAGES  MEM_LARGE_PAGES
+#else
+  #define MY_MEM_LARGE_PAGES  0x20000000
 #endif
 #endif
 
 
-#ifdef _7ZIP_LARGE_PAGES
+extern
+SIZE_T g_LargePageSize;
 SIZE_T g_LargePageSize = 0;
 SIZE_T g_LargePageSize = 0;
-typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
-#endif
+typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID);
 
 
-void SetLargePageSize()
+void SetLargePageSize(void)
 {
 {
-  #ifdef _7ZIP_LARGE_PAGES
-  SIZE_T size = 0;
-  GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
-        GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
-  if (largePageMinimum == 0)
+  SIZE_T size;
+#ifdef Z7_USE_DYN_GetLargePageMinimum
+Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
+
+  const
+   Func_GetLargePageMinimum fn =
+  (Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
+       "GetLargePageMinimum");
+  if (!fn)
     return;
     return;
-  size = largePageMinimum();
+  size = fn();
+#else
+  size = GetLargePageMinimum();
+#endif
   if (size == 0 || (size & (size - 1)) != 0)
   if (size == 0 || (size & (size - 1)) != 0)
     return;
     return;
   g_LargePageSize = size;
   g_LargePageSize = size;
-  #endif
 }
 }
 
 
+#endif // Z7_LARGE_PAGES
 
 
 void *BigAlloc(size_t size)
 void *BigAlloc(size_t size)
 {
 {
   if (size == 0)
   if (size == 0)
-    return 0;
-  #ifdef _SZ_ALLOC_DEBUG
-  fprintf(stderr, "\nAlloc_Big %10d bytes;  count = %10d", size, g_allocCountBig++);
-  #endif
-  
-  #ifdef _7ZIP_LARGE_PAGES
-  if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
+    return NULL;
+
+  PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL)
+
+  #ifdef Z7_LARGE_PAGES
   {
   {
-    void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
-        MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
-    if (res != 0)
-      return res;
+    SIZE_T ps = g_LargePageSize;
+    if (ps != 0 && ps <= (1 << 30) && size > (ps / 2))
+    {
+      size_t size2;
+      ps--;
+      size2 = (size + ps) & ~ps;
+      if (size2 >= size)
+      {
+        void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY_MEM_LARGE_PAGES, PAGE_READWRITE);
+        if (p)
+        {
+          PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p)
+          return p;
+        }
+      }
+    }
   }
   }
   #endif
   #endif
-  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
+
+  return MidAlloc(size);
 }
 }
 
 
 void BigFree(void *address)
 void BigFree(void *address)
 {
 {
-  #ifdef _SZ_ALLOC_DEBUG
-  if (address != 0)
-    fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
+  PRINT_FREE("Free-Big", g_allocCountBig, address)
+  MidFree(address);
+}
+
+#endif // _WIN32
+
+
+static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p)  return MyAlloc(size); }
+static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p)  MyFree(address); }
+const ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+#ifdef _WIN32
+static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p)  return MidAlloc(size); }
+static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p)  MidFree(address); }
+static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p)  return BigAlloc(size); }
+static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p)  BigFree(address); }
+const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
+const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
+#endif
+
+#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
+
+#define ADJUST_ALLOC_SIZE 0
+/*
+#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1)
+*/
+/*
+  Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if
+     MyAlloc() can return address that is NOT multiple of sizeof(void *).
+*/
+
+/*
+  uintptr_t : <stdint.h> C99 (optional)
+            : unsupported in VS6
+*/
+typedef
+  #ifdef _WIN32
+    UINT_PTR
+  #elif 1
+    uintptr_t
+  #else
+    ptrdiff_t
   #endif
   #endif
+    MY_uintptr_t;
+
+#if 0 \
+    || (defined(__CHERI__) \
+    || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ > 8))
+// for 128-bit pointers (cheri):
+#define MY_ALIGN_PTR_DOWN(p, align)  \
+    ((void *)((char *)(p) - ((size_t)(MY_uintptr_t)(p) & ((align) - 1))))
+#else
+#define MY_ALIGN_PTR_DOWN(p, align) \
+    ((void *)((((MY_uintptr_t)(p)) & ~((MY_uintptr_t)(align) - 1))))
+#endif
+
+#endif
+
+#if !defined(_WIN32) \
+    && (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \
+        || defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L))
+  #define USE_posix_memalign
+#endif
+
+#ifndef USE_posix_memalign
+#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align)
+#endif
+
+/*
+  This posix_memalign() is for test purposes only.
+  We also need special Free() function instead of free(),
+  if this posix_memalign() is used.
+*/
+
+/*
+static int posix_memalign(void **ptr, size_t align, size_t size)
+{
+  size_t newSize = size + align;
+  void *p;
+  void *pAligned;
+  *ptr = NULL;
+  if (newSize < size)
+    return 12; // ENOMEM
+  p = MyAlloc(newSize);
+  if (!p)
+    return 12; // ENOMEM
+  pAligned = MY_ALIGN_PTR_UP_PLUS(p, align);
+  ((void **)pAligned)[-1] = p;
+  *ptr = pAligned;
+  return 0;
+}
+*/
+
+/*
+  ALLOC_ALIGN_SIZE >= sizeof(void *)
+  ALLOC_ALIGN_SIZE >= cache_line_size
+*/
+
+#define ALLOC_ALIGN_SIZE ((size_t)1 << 7)
+
+void *z7_AlignedAlloc(size_t size)
+{
+#ifndef USE_posix_memalign
   
   
-  if (address == 0)
-    return;
-  VirtualFree(address, 0, MEM_RELEASE);
+  void *p;
+  void *pAligned;
+  size_t newSize;
+
+  /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
+     block to prevent cache line sharing with another allocated blocks */
+
+  newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE;
+  if (newSize < size)
+    return NULL;
+
+  p = MyAlloc(newSize);
+  
+  if (!p)
+    return NULL;
+  pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE);
+
+  Print(" size="); PrintHex(size, 8);
+  Print(" a_size="); PrintHex(newSize, 8);
+  Print(" ptr="); PrintAddr(p);
+  Print(" a_ptr="); PrintAddr(pAligned);
+  PrintLn();
+
+  ((void **)pAligned)[-1] = p;
+
+  return pAligned;
+
+#else
+
+  void *p;
+  if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size))
+    return NULL;
+
+  Print(" posix_memalign="); PrintAddr(p);
+  PrintLn();
+
+  return p;
+
+#endif
+}
+
+
+void z7_AlignedFree(void *address)
+{
+#ifndef USE_posix_memalign
+  if (address)
+    MyFree(((void **)address)[-1]);
+#else
+  free(address);
+#endif
+}
+
+
+static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
+{
+  UNUSED_VAR(pp)
+  return z7_AlignedAlloc(size);
+}
+
+
+static void SzAlignedFree(ISzAllocPtr pp, void *address)
+{
+  UNUSED_VAR(pp)
+#ifndef USE_posix_memalign
+  if (address)
+    MyFree(((void **)address)[-1]);
+#else
+  free(address);
+#endif
+}
+
+
+const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };
+
+
+
+/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */
+#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
+#if 1
+  #define MY_ALIGN_PTR_DOWN_1(p)  MY_ALIGN_PTR_DOWN(p, sizeof(void *))
+  #define REAL_BLOCK_PTR_VAR(p)  ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1]
+#else
+  // we can use this simplified code,
+  // if (CAlignOffsetAlloc::offset == (k * sizeof(void *))
+  #define REAL_BLOCK_PTR_VAR(p)  (((void **)(p))[-1])
+#endif
+#endif
+
+
+#if 0
+#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
+#include <stdio.h>
+static void PrintPtr(const char *s, const void *p)
+{
+  const Byte *p2 = (const Byte *)&p;
+  unsigned i;
+  printf("%s %p ", s, p);
+  for (i = sizeof(p); i != 0;)
+  {
+    i--;
+    printf("%02x", p2[i]);
+  }
+  printf("\n");
+}
+#endif
+#endif
+
+
+static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
+{
+#if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR)
+  UNUSED_VAR(pp)
+  return z7_AlignedAlloc(size);
+#else
+  const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt);
+  void *adr;
+  void *pAligned;
+  size_t newSize;
+  size_t extra;
+  size_t alignSize = (size_t)1 << p->numAlignBits;
+
+  if (alignSize < sizeof(void *))
+    alignSize = sizeof(void *);
+  
+  if (p->offset >= alignSize)
+    return NULL;
+
+  /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
+     block to prevent cache line sharing with another allocated blocks */
+  extra = p->offset & (sizeof(void *) - 1);
+  newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE;
+  if (newSize < size)
+    return NULL;
+
+  adr = ISzAlloc_Alloc(p->baseAlloc, newSize);
+  
+  if (!adr)
+    return NULL;
+
+  pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr +
+      alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset;
+
+#if 0
+  printf("\nalignSize = %6x, offset=%6x, size=%8x \n", (unsigned)alignSize, (unsigned)p->offset, (unsigned)size);
+  PrintPtr("base", adr);
+  PrintPtr("alig", pAligned);
+#endif
+
+  PrintLn();
+  Print("- Aligned: ");
+  Print(" size="); PrintHex(size, 8);
+  Print(" a_size="); PrintHex(newSize, 8);
+  Print(" ptr="); PrintAddr(adr);
+  Print(" a_ptr="); PrintAddr(pAligned);
+  PrintLn();
+
+  REAL_BLOCK_PTR_VAR(pAligned) = adr;
+
+  return pAligned;
+#endif
 }
 }
 
 
+
+static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)
+{
+#if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR)
+  UNUSED_VAR(pp)
+  z7_AlignedFree(address);
+#else
+  if (address)
+  {
+    const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt);
+    PrintLn();
+    Print("- Aligned Free: ");
+    PrintLn();
+    ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address));
+  }
 #endif
 #endif
+}
+
+
+void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p)
+{
+  p->vt.Alloc = AlignOffsetAlloc_Alloc;
+  p->vt.Free = AlignOffsetAlloc_Free;
+}

+ 52 - 14
Components/Lzma2/Alloc.h

@@ -1,38 +1,76 @@
 /* Alloc.h -- Memory allocation functions
 /* Alloc.h -- Memory allocation functions
-2009-02-07 : Igor Pavlov : Public domain */
+2024-01-22 : Igor Pavlov : Public domain */
 
 
-#ifndef __COMMON_ALLOC_H
-#define __COMMON_ALLOC_H
+#ifndef ZIP7_INC_ALLOC_H
+#define ZIP7_INC_ALLOC_H
 
 
-#include <stddef.h>
+#include "7zTypes.h"
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+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 *MyAlloc(size_t size);
 void MyFree(void *address);
 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 _WIN32
 
 
-void SetLargePageSize();
+#ifdef Z7_LARGE_PAGES
+void SetLargePageSize(void);
+#endif
 
 
 void *MidAlloc(size_t size);
 void *MidAlloc(size_t size);
 void MidFree(void *address);
 void MidFree(void *address);
 void *BigAlloc(size_t size);
 void *BigAlloc(size_t size);
 void BigFree(void *address);
 void BigFree(void *address);
 
 
+/* #define Z7_BIG_ALLOC_IS_ZERO_FILLED */
+
 #else
 #else
 
 
-#define MidAlloc(size) MyAlloc(size)
-#define MidFree(address) MyFree(address)
-#define BigAlloc(size) MyAlloc(size)
-#define BigFree(address) MyFree(address)
+#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
 #endif
 
 
-#ifdef __cplusplus
-}
+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
 #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
 #endif

+ 236 - 0
Components/Lzma2/Compiler.h

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

+ 885 - 0
Components/Lzma2/CpuArch.c

@@ -0,0 +1,885 @@
+/* CpuArch.c -- CPU specific code
+2024-05-18 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+// #include <stdio.h>
+
+#include "CpuArch.h"
+
+#ifdef MY_CPU_X86_OR_AMD64
+
+#undef NEED_CHECK_FOR_CPUID
+#if !defined(MY_CPU_AMD64)
+#define NEED_CHECK_FOR_CPUID
+#endif
+
+/*
+  cpuid instruction supports (subFunction) parameter in ECX,
+  that is used only with some specific (function) parameter values.
+  But we always use only (subFunction==0).
+*/
+/*
+  __cpuid(): MSVC and GCC/CLANG use same function/macro name
+             but parameters are different.
+   We use MSVC __cpuid() parameters style for our z7_x86_cpuid() function.
+*/
+
+#if defined(__GNUC__) /* && (__GNUC__ >= 10) */ \
+    || defined(__clang__) /* && (__clang_major__ >= 10) */
+
+/* there was some CLANG/GCC compilers that have issues with
+   rbx(ebx) handling in asm blocks in -fPIC mode (__PIC__ is defined).
+   compiler's <cpuid.h> contains the macro __cpuid() that is similar to our code.
+   The history of __cpuid() changes in CLANG/GCC:
+   GCC:
+     2007: it preserved ebx for (__PIC__ && __i386__)
+     2013: it preserved rbx and ebx for __PIC__
+     2014: it doesn't preserves rbx and ebx anymore
+     we suppose that (__GNUC__ >= 5) fixed that __PIC__ ebx/rbx problem.
+   CLANG:
+     2014+: it preserves rbx, but only for 64-bit code. No __PIC__ check.
+   Why CLANG cares about 64-bit mode only, and doesn't care about ebx (in 32-bit)?
+   Do we need __PIC__ test for CLANG or we must care about rbx even if
+   __PIC__ is not defined?
+*/
+
+#define ASM_LN "\n"
+   
+#if defined(MY_CPU_AMD64) && defined(__PIC__) \
+    && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
+
+#define x86_cpuid_MACRO(p, func) { \
+  __asm__ __volatile__ ( \
+    ASM_LN   "mov     %%rbx, %q1"  \
+    ASM_LN   "cpuid"               \
+    ASM_LN   "xchg    %%rbx, %q1"  \
+    : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
+
+  /* "=&r" selects free register. It can select even rbx, if that register is free.
+     "=&D" for (RDI) also works, but the code can be larger with "=&D"
+     "2"(0) means (subFunction = 0),
+     2 is (zero-based) index in the output constraint list "=c" (ECX). */
+
+#elif defined(MY_CPU_X86) && defined(__PIC__) \
+    && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
+
+#define x86_cpuid_MACRO(p, func) { \
+  __asm__ __volatile__ ( \
+    ASM_LN   "mov     %%ebx, %k1"  \
+    ASM_LN   "cpuid"               \
+    ASM_LN   "xchg    %%ebx, %k1"  \
+    : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
+
+#else
+
+#define x86_cpuid_MACRO(p, func) { \
+  __asm__ __volatile__ ( \
+    ASM_LN   "cpuid"               \
+    : "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
+
+#endif
+
+
+void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
+{
+  x86_cpuid_MACRO(p, func)
+}
+
+
+Z7_NO_INLINE
+UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
+{
+ #if defined(NEED_CHECK_FOR_CPUID)
+  #define EFALGS_CPUID_BIT 21
+  UInt32 a;
+  __asm__ __volatile__ (
+    ASM_LN   "pushf"
+    ASM_LN   "pushf"
+    ASM_LN   "pop     %0"
+    // ASM_LN   "movl    %0, %1"
+    // ASM_LN   "xorl    $0x200000, %0"
+    ASM_LN   "btc     %1, %0"
+    ASM_LN   "push    %0"
+    ASM_LN   "popf"
+    ASM_LN   "pushf"
+    ASM_LN   "pop     %0"
+    ASM_LN   "xorl    (%%esp), %0"
+
+    ASM_LN   "popf"
+    ASM_LN
+    : "=&r" (a) // "=a"
+    : "i" (EFALGS_CPUID_BIT)
+    );
+  if ((a & (1 << EFALGS_CPUID_BIT)) == 0)
+    return 0;
+ #endif
+  {
+    UInt32 p[4];
+    x86_cpuid_MACRO(p, 0)
+    return p[0];
+  }
+}
+
+#undef ASM_LN
+
+#elif !defined(_MSC_VER)
+
+/*
+// for gcc/clang and other: we can try to use __cpuid macro:
+#include <cpuid.h>
+void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
+{
+  __cpuid(func, p[0], p[1], p[2], p[3]);
+}
+UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
+{
+  return (UInt32)__get_cpuid_max(0, NULL);
+}
+*/
+// for unsupported cpuid:
+void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
+{
+  UNUSED_VAR(func)
+  p[0] = p[1] = p[2] = p[3] = 0;
+}
+UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
+{
+  return 0;
+}
+
+#else // _MSC_VER
+
+#if !defined(MY_CPU_AMD64)
+
+UInt32 __declspec(naked) Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
+{
+  #if defined(NEED_CHECK_FOR_CPUID)
+  #define EFALGS_CPUID_BIT 21
+  __asm   pushfd
+  __asm   pushfd
+  /*
+  __asm   pop     eax
+  // __asm   mov     edx, eax
+  __asm   btc     eax, EFALGS_CPUID_BIT
+  __asm   push    eax
+  */
+  __asm   btc     dword ptr [esp], EFALGS_CPUID_BIT
+  __asm   popfd
+  __asm   pushfd
+  __asm   pop     eax
+  // __asm   xor     eax, edx
+  __asm   xor     eax, [esp]
+  // __asm   push    edx
+  __asm   popfd
+  __asm   and     eax, (1 shl EFALGS_CPUID_BIT)
+  __asm   jz end_func
+  #endif
+  __asm   push    ebx
+  __asm   xor     eax, eax    // func
+  __asm   xor     ecx, ecx    // subFunction (optional) for (func == 0)
+  __asm   cpuid
+  __asm   pop     ebx
+  #if defined(NEED_CHECK_FOR_CPUID)
+  end_func:
+  #endif
+  __asm   ret 0
+}
+
+void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
+{
+  UNUSED_VAR(p)
+  UNUSED_VAR(func)
+  __asm   push    ebx
+  __asm   push    edi
+  __asm   mov     edi, ecx    // p
+  __asm   mov     eax, edx    // func
+  __asm   xor     ecx, ecx    // subfunction (optional) for (func == 0)
+  __asm   cpuid
+  __asm   mov     [edi     ], eax
+  __asm   mov     [edi +  4], ebx
+  __asm   mov     [edi +  8], ecx
+  __asm   mov     [edi + 12], edx
+  __asm   pop     edi
+  __asm   pop     ebx
+  __asm   ret     0
+}
+
+#else // MY_CPU_AMD64
+
+    #if _MSC_VER >= 1600
+      #include <intrin.h>
+      #define MY_cpuidex  __cpuidex
+    #else
+/*
+ __cpuid (func == (0 or 7)) requires subfunction number in ECX.
+  MSDN: The __cpuid intrinsic clears the ECX register before calling the cpuid instruction.
+   __cpuid() in new MSVC clears ECX.
+   __cpuid() in old MSVC (14.00) x64 doesn't clear ECX
+ We still can use __cpuid for low (func) values that don't require ECX,
+ but __cpuid() in old MSVC will be incorrect for some func values: (func == 7).
+ So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction,
+ where ECX value is first parameter for FASTCALL / NO_INLINE func,
+ So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and
+ old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value.
+ 
+DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!!
+*/
+static
+Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int32 *CPUInfo)
+{
+  UNUSED_VAR(subFunction)
+  __cpuid(CPUInfo, func);
+}
+      #define MY_cpuidex(info, func, func2)  MY_cpuidex_HACK(func2, func, info)
+      #pragma message("======== MY_cpuidex_HACK WAS USED ========")
+    #endif // _MSC_VER >= 1600
+
+#if !defined(MY_CPU_AMD64)
+/* inlining for __cpuid() in MSVC x86 (32-bit) produces big ineffective code,
+   so we disable inlining here */
+Z7_NO_INLINE
+#endif
+void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
+{
+  MY_cpuidex((Int32 *)p, (Int32)func, 0);
+}
+
+Z7_NO_INLINE
+UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
+{
+  Int32 a[4];
+  MY_cpuidex(a, 0, 0);
+  return a[0];
+}
+
+#endif // MY_CPU_AMD64
+#endif // _MSC_VER
+
+#if defined(NEED_CHECK_FOR_CPUID)
+#define CHECK_CPUID_IS_SUPPORTED { if (z7_x86_cpuid_GetMaxFunc() == 0) return 0; }
+#else
+#define CHECK_CPUID_IS_SUPPORTED
+#endif
+#undef NEED_CHECK_FOR_CPUID
+
+
+static
+BoolInt x86cpuid_Func_1(UInt32 *p)
+{
+  CHECK_CPUID_IS_SUPPORTED
+  z7_x86_cpuid(p, 1);
+  return True;
+}
+
+/*
+static const UInt32 kVendors[][1] =
+{
+  { 0x756E6547 }, // , 0x49656E69, 0x6C65746E },
+  { 0x68747541 }, // , 0x69746E65, 0x444D4163 },
+  { 0x746E6543 }  // , 0x48727561, 0x736C7561 }
+};
+*/
+
+/*
+typedef struct
+{
+  UInt32 maxFunc;
+  UInt32 vendor[3];
+  UInt32 ver;
+  UInt32 b;
+  UInt32 c;
+  UInt32 d;
+} Cx86cpuid;
+
+enum
+{
+  CPU_FIRM_INTEL,
+  CPU_FIRM_AMD,
+  CPU_FIRM_VIA
+};
+int x86cpuid_GetFirm(const Cx86cpuid *p);
+#define x86cpuid_ver_GetFamily(ver) (((ver >> 16) & 0xff0) | ((ver >> 8) & 0xf))
+#define x86cpuid_ver_GetModel(ver)  (((ver >> 12) &  0xf0) | ((ver >> 4) & 0xf))
+#define x86cpuid_ver_GetStepping(ver) (ver & 0xf)
+
+int x86cpuid_GetFirm(const Cx86cpuid *p)
+{
+  unsigned i;
+  for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[0]); i++)
+  {
+    const UInt32 *v = kVendors[i];
+    if (v[0] == p->vendor[0]
+        // && v[1] == p->vendor[1]
+        // && v[2] == p->vendor[2]
+        )
+      return (int)i;
+  }
+  return -1;
+}
+
+BoolInt CPU_Is_InOrder()
+{
+  Cx86cpuid p;
+  UInt32 family, model;
+  if (!x86cpuid_CheckAndRead(&p))
+    return True;
+
+  family = x86cpuid_ver_GetFamily(p.ver);
+  model = x86cpuid_ver_GetModel(p.ver);
+
+  switch (x86cpuid_GetFirm(&p))
+  {
+    case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
+        // In-Order Atom CPU
+           model == 0x1C  // 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330
+        || model == 0x26  // 45 nm, Z6xx
+        || model == 0x27  // 32 nm, Z2460
+        || model == 0x35  // 32 nm, Z2760
+        || model == 0x36  // 32 nm, N2xxx, D2xxx
+        )));
+    case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
+    case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
+  }
+  return False; // v23 : unknown processors are not In-Order
+}
+*/
+
+#ifdef _WIN32
+#include "7zWindows.h"
+#endif
+
+#if !defined(MY_CPU_AMD64) && defined(_WIN32)
+
+/* for legacy SSE ia32: there is no user-space cpu instruction to check
+   that OS supports SSE register storing/restoring on context switches.
+   So we need some OS-specific function to check that it's safe to use SSE registers.
+*/
+
+Z7_FORCE_INLINE
+static BoolInt CPU_Sys_Is_SSE_Supported(void)
+{
+#ifdef _MSC_VER
+  #pragma warning(push)
+  #pragma warning(disable : 4996) // `GetVersion': was declared deprecated
+#endif
+  /* low byte is major version of Windows
+     We suppose that any Windows version since
+     Windows2000 (major == 5) supports SSE registers */
+  return (Byte)GetVersion() >= 5;
+#if defined(_MSC_VER)
+  #pragma warning(pop)
+#endif
+}
+#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
+#else
+#define CHECK_SYS_SSE_SUPPORT
+#endif
+
+
+#if !defined(MY_CPU_AMD64)
+
+BoolInt CPU_IsSupported_CMOV(void)
+{
+  UInt32 a[4];
+  if (!x86cpuid_Func_1(&a[0]))
+    return 0;
+  return (BoolInt)(a[3] >> 15) & 1;
+}
+
+BoolInt CPU_IsSupported_SSE(void)
+{
+  UInt32 a[4];
+  CHECK_SYS_SSE_SUPPORT
+  if (!x86cpuid_Func_1(&a[0]))
+    return 0;
+  return (BoolInt)(a[3] >> 25) & 1;
+}
+
+BoolInt CPU_IsSupported_SSE2(void)
+{
+  UInt32 a[4];
+  CHECK_SYS_SSE_SUPPORT
+  if (!x86cpuid_Func_1(&a[0]))
+    return 0;
+  return (BoolInt)(a[3] >> 26) & 1;
+}
+
+#endif
+
+
+static UInt32 x86cpuid_Func_1_ECX(void)
+{
+  UInt32 a[4];
+  CHECK_SYS_SSE_SUPPORT
+  if (!x86cpuid_Func_1(&a[0]))
+    return 0;
+  return a[2];
+}
+
+BoolInt CPU_IsSupported_AES(void)
+{
+  return (BoolInt)(x86cpuid_Func_1_ECX() >> 25) & 1;
+}
+
+BoolInt CPU_IsSupported_SSSE3(void)
+{
+  return (BoolInt)(x86cpuid_Func_1_ECX() >> 9) & 1;
+}
+
+BoolInt CPU_IsSupported_SSE41(void)
+{
+  return (BoolInt)(x86cpuid_Func_1_ECX() >> 19) & 1;
+}
+
+BoolInt CPU_IsSupported_SHA(void)
+{
+  CHECK_SYS_SSE_SUPPORT
+
+  if (z7_x86_cpuid_GetMaxFunc() < 7)
+    return False;
+  {
+    UInt32 d[4];
+    z7_x86_cpuid(d, 7);
+    return (BoolInt)(d[1] >> 29) & 1;
+  }
+}
+
+/*
+MSVC: _xgetbv() intrinsic is available since VS2010SP1.
+   MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in
+   <immintrin.h> that we can use or check.
+   For any 32-bit x86 we can use asm code in MSVC,
+   but MSVC asm code is huge after compilation.
+   So _xgetbv() is better
+
+ICC: _xgetbv() intrinsic is available (in what version of ICC?)
+   ICC defines (__GNUC___) and it supports gnu assembler
+   also ICC supports MASM style code with -use-msasm switch.
+   but ICC doesn't support __attribute__((__target__))
+
+GCC/CLANG 9:
+  _xgetbv() is macro that works via __builtin_ia32_xgetbv()
+  and we need __attribute__((__target__("xsave")).
+  But with __target__("xsave") the function will be not
+  inlined to function that has no __target__("xsave") attribute.
+  If we want _xgetbv() call inlining, then we should use asm version
+  instead of calling _xgetbv().
+  Note:intrinsic is broke before GCC 8.2:
+    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684
+*/
+
+#if    defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) \
+    || defined(_MSC_VER) && (_MSC_VER >= 1600) && (_MSC_FULL_VER >= 160040219)  \
+    || defined(__GNUC__) && (__GNUC__ >= 9) \
+    || defined(__clang__) && (__clang_major__ >= 9)
+// we define ATTRIB_XGETBV, if we want to use predefined _xgetbv() from compiler
+#if defined(__INTEL_COMPILER)
+#define ATTRIB_XGETBV
+#elif defined(__GNUC__) || defined(__clang__)
+// we don't define ATTRIB_XGETBV here, because asm version is better for inlining.
+// #define ATTRIB_XGETBV __attribute__((__target__("xsave")))
+#else
+#define ATTRIB_XGETBV
+#endif
+#endif
+
+#if defined(ATTRIB_XGETBV)
+#include <immintrin.h>
+#endif
+
+
+// XFEATURE_ENABLED_MASK/XCR0
+#define MY_XCR_XFEATURE_ENABLED_MASK 0
+
+#if defined(ATTRIB_XGETBV)
+ATTRIB_XGETBV
+#endif
+static UInt64 x86_xgetbv_0(UInt32 num)
+{
+#if defined(ATTRIB_XGETBV)
+  {
+    return
+      #if (defined(_MSC_VER))
+        _xgetbv(num);
+      #else
+        __builtin_ia32_xgetbv(
+          #if !defined(__clang__)
+            (int)
+          #endif
+            num);
+      #endif
+  }
+
+#elif defined(__GNUC__) || defined(__clang__) || defined(__SUNPRO_CC)
+
+  UInt32 a, d;
+ #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+  __asm__
+  (
+    "xgetbv"
+    : "=a"(a), "=d"(d) : "c"(num) : "cc"
+  );
+ #else // is old gcc
+  __asm__
+  (
+    ".byte 0x0f, 0x01, 0xd0" "\n\t"
+    : "=a"(a), "=d"(d) : "c"(num) : "cc"
+  );
+ #endif
+  return ((UInt64)d << 32) | a;
+  // return a;
+
+#elif defined(_MSC_VER) && !defined(MY_CPU_AMD64)
+  
+  UInt32 a, d;
+  __asm {
+    push eax
+    push edx
+    push ecx
+    mov ecx, num;
+    // xor ecx, ecx // = MY_XCR_XFEATURE_ENABLED_MASK
+    _emit 0x0f
+    _emit 0x01
+    _emit 0xd0
+    mov a, eax
+    mov d, edx
+    pop ecx
+    pop edx
+    pop eax
+  }
+  return ((UInt64)d << 32) | a;
+  // return a;
+
+#else // it's unknown compiler
+  // #error "Need xgetbv function"
+  UNUSED_VAR(num)
+  // for MSVC-X64 we could call external function from external file.
+  /* Actually we had checked OSXSAVE/AVX in cpuid before.
+     So it's expected that OS supports at least AVX and below. */
+  // if (num != MY_XCR_XFEATURE_ENABLED_MASK) return 0; // if not XCR0
+  return
+      // (1 << 0) |  // x87
+        (1 << 1)   // SSE
+      | (1 << 2);  // AVX
+  
+#endif
+}
+
+#ifdef _WIN32
+/*
+  Windows versions do not know about new ISA extensions that
+  can be introduced. But we still can use new extensions,
+  even if Windows doesn't report about supporting them,
+  But we can use new extensions, only if Windows knows about new ISA extension
+  that changes the number or size of registers: SSE, AVX/XSAVE, AVX512
+  So it's enough to check
+    MY_PF_AVX_INSTRUCTIONS_AVAILABLE
+      instead of
+    MY_PF_AVX2_INSTRUCTIONS_AVAILABLE
+*/
+#define MY_PF_XSAVE_ENABLED                            17
+// #define MY_PF_SSSE3_INSTRUCTIONS_AVAILABLE             36
+// #define MY_PF_SSE4_1_INSTRUCTIONS_AVAILABLE            37
+// #define MY_PF_SSE4_2_INSTRUCTIONS_AVAILABLE            38
+// #define MY_PF_AVX_INSTRUCTIONS_AVAILABLE               39
+// #define MY_PF_AVX2_INSTRUCTIONS_AVAILABLE              40
+// #define MY_PF_AVX512F_INSTRUCTIONS_AVAILABLE           41
+#endif
+
+BoolInt CPU_IsSupported_AVX(void)
+{
+  #ifdef _WIN32
+  if (!IsProcessorFeaturePresent(MY_PF_XSAVE_ENABLED))
+    return False;
+  /* PF_AVX_INSTRUCTIONS_AVAILABLE probably is supported starting from
+     some latest Win10 revisions. But we need AVX in older Windows also.
+     So we don't use the following check: */
+  /*
+  if (!IsProcessorFeaturePresent(MY_PF_AVX_INSTRUCTIONS_AVAILABLE))
+    return False;
+  */
+  #endif
+
+  /*
+    OS must use new special XSAVE/XRSTOR instructions to save
+    AVX registers when it required for context switching.
+    At OS statring:
+      OS sets CR4.OSXSAVE flag to signal the processor that OS supports the XSAVE extensions.
+      Also OS sets bitmask in XCR0 register that defines what
+      registers will be processed by XSAVE instruction:
+        XCR0.SSE[bit 0] - x87 registers and state
+        XCR0.SSE[bit 1] - SSE registers and state
+        XCR0.AVX[bit 2] - AVX registers and state
+    CR4.OSXSAVE is reflected to CPUID.1:ECX.OSXSAVE[bit 27].
+       So we can read that bit in user-space.
+    XCR0 is available for reading in user-space by new XGETBV instruction.
+  */
+  {
+    const UInt32 c = x86cpuid_Func_1_ECX();
+    if (0 == (1
+        & (c >> 28)   // AVX instructions are supported by hardware
+        & (c >> 27))) // OSXSAVE bit: XSAVE and related instructions are enabled by OS.
+      return False;
+  }
+
+  /* also we can check
+     CPUID.1:ECX.XSAVE [bit 26] : that shows that
+        XSAVE, XRESTOR, XSETBV, XGETBV instructions are supported by hardware.
+     But that check is redundant, because if OSXSAVE bit is set, then XSAVE is also set */
+
+  /* If OS have enabled XSAVE extension instructions (OSXSAVE == 1),
+     in most cases we expect that OS also will support storing/restoring
+     for AVX and SSE states at least.
+     But to be ensure for that we call user-space instruction
+     XGETBV(0) to get XCR0 value that contains bitmask that defines
+     what exact states(registers) OS have enabled for storing/restoring.
+  */
+
+  {
+    const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);
+    // printf("\n=== XGetBV=0x%x\n", bm);
+    return 1
+        & (BoolInt)(bm >> 1)  // SSE state is supported (set by OS) for storing/restoring
+        & (BoolInt)(bm >> 2); // AVX state is supported (set by OS) for storing/restoring
+  }
+  // since Win7SP1: we can use GetEnabledXStateFeatures();
+}
+
+
+BoolInt CPU_IsSupported_AVX2(void)
+{
+  if (!CPU_IsSupported_AVX())
+    return False;
+  if (z7_x86_cpuid_GetMaxFunc() < 7)
+    return False;
+  {
+    UInt32 d[4];
+    z7_x86_cpuid(d, 7);
+    // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
+    return 1
+      & (BoolInt)(d[1] >> 5); // avx2
+  }
+}
+
+#if 0
+BoolInt CPU_IsSupported_AVX512F_AVX512VL(void)
+{
+  if (!CPU_IsSupported_AVX())
+    return False;
+  if (z7_x86_cpuid_GetMaxFunc() < 7)
+    return False;
+  {
+    UInt32 d[4];
+    BoolInt v;
+    z7_x86_cpuid(d, 7);
+    // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
+    v = 1
+      & (BoolInt)(d[1] >> 16)  // avx512f
+      & (BoolInt)(d[1] >> 31); // avx512vl
+    if (!v)
+      return False;
+  }
+  {
+    const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);
+    // printf("\n=== XGetBV=0x%x\n", bm);
+    return 1
+        & (BoolInt)(bm >> 5)  // OPMASK
+        & (BoolInt)(bm >> 6)  // ZMM upper 256-bit
+        & (BoolInt)(bm >> 7); // ZMM16 ... ZMM31
+  }
+}
+#endif
+
+BoolInt CPU_IsSupported_VAES_AVX2(void)
+{
+  if (!CPU_IsSupported_AVX())
+    return False;
+  if (z7_x86_cpuid_GetMaxFunc() < 7)
+    return False;
+  {
+    UInt32 d[4];
+    z7_x86_cpuid(d, 7);
+    // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
+    return 1
+      & (BoolInt)(d[1] >> 5) // avx2
+      // & (d[1] >> 31) // avx512vl
+      & (BoolInt)(d[2] >> 9); // vaes // VEX-256/EVEX
+  }
+}
+
+BoolInt CPU_IsSupported_PageGB(void)
+{
+  CHECK_CPUID_IS_SUPPORTED
+  {
+    UInt32 d[4];
+    z7_x86_cpuid(d, 0x80000000);
+    if (d[0] < 0x80000001)
+      return False;
+    z7_x86_cpuid(d, 0x80000001);
+    return (BoolInt)(d[3] >> 26) & 1;
+  }
+}
+
+
+#elif defined(MY_CPU_ARM_OR_ARM64)
+
+#ifdef _WIN32
+
+#include "7zWindows.h"
+
+BoolInt CPU_IsSupported_CRC32(void)  { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
+BoolInt CPU_IsSupported_CRYPTO(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
+BoolInt CPU_IsSupported_NEON(void)   { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
+
+#else
+
+#if defined(__APPLE__)
+
+/*
+#include <stdio.h>
+#include <string.h>
+static void Print_sysctlbyname(const char *name)
+{
+  size_t bufSize = 256;
+  char buf[256];
+  int res = sysctlbyname(name, &buf, &bufSize, NULL, 0);
+  {
+    int i;
+    printf("\nres = %d : %s : '%s' : bufSize = %d, numeric", res, name, buf, (unsigned)bufSize);
+    for (i = 0; i < 20; i++)
+      printf(" %2x", (unsigned)(Byte)buf[i]);
+
+  }
+}
+*/
+/*
+  Print_sysctlbyname("hw.pagesize");
+  Print_sysctlbyname("machdep.cpu.brand_string");
+*/
+
+static BoolInt z7_sysctlbyname_Get_BoolInt(const char *name)
+{
+  UInt32 val = 0;
+  if (z7_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1)
+    return 1;
+  return 0;
+}
+
+BoolInt CPU_IsSupported_CRC32(void)
+{
+  return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_crc32");
+}
+
+BoolInt CPU_IsSupported_NEON(void)
+{
+  return z7_sysctlbyname_Get_BoolInt("hw.optional.neon");
+}
+
+#ifdef MY_CPU_ARM64
+#define APPLE_CRYPTO_SUPPORT_VAL 1
+#else
+#define APPLE_CRYPTO_SUPPORT_VAL 0
+#endif
+
+BoolInt CPU_IsSupported_SHA1(void) { return APPLE_CRYPTO_SUPPORT_VAL; }
+BoolInt CPU_IsSupported_SHA2(void) { return APPLE_CRYPTO_SUPPORT_VAL; }
+BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
+
+
+#else // __APPLE__
+
+#if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
+  #define Z7_GETAUXV_AVAILABLE
+#else
+// #pragma message("=== is not NEW GLIBC === ")
+  #if defined __has_include
+  #if __has_include (<sys/auxv.h>)
+// #pragma message("=== sys/auxv.h is avail=== ")
+    #define Z7_GETAUXV_AVAILABLE
+  #endif
+  #endif
+#endif
+
+#ifdef Z7_GETAUXV_AVAILABLE
+// #pragma message("=== Z7_GETAUXV_AVAILABLE === ")
+#include <sys/auxv.h>
+#define USE_HWCAP
+#endif
+
+#ifdef USE_HWCAP
+
+#if defined(__FreeBSD__)
+static unsigned long MY_getauxval(int aux)
+{
+  unsigned long val;
+  if (elf_aux_info(aux, &val, sizeof(val)))
+    return 0;
+  return val;
+}
+#else
+#define MY_getauxval  getauxval
+  #if defined __has_include
+  #if __has_include (<asm/hwcap.h>)
+#include <asm/hwcap.h>
+  #endif
+  #endif
+#endif
+
+  #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \
+  BoolInt CPU_IsSupported_ ## name1(void) { return (MY_getauxval(AT_HWCAP)  & (HWCAP_  ## name2)); }
+
+#ifdef MY_CPU_ARM64
+  #define MY_HWCAP_CHECK_FUNC(name) \
+  MY_HWCAP_CHECK_FUNC_2(name, name)
+#if 1 || defined(__ARM_NEON)
+  BoolInt CPU_IsSupported_NEON(void) { return True; }
+#else
+  MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD)
+#endif
+// MY_HWCAP_CHECK_FUNC (ASIMD)
+#elif defined(MY_CPU_ARM)
+  #define MY_HWCAP_CHECK_FUNC(name) \
+  BoolInt CPU_IsSupported_ ## name(void) { return (MY_getauxval(AT_HWCAP2) & (HWCAP2_ ## name)); }
+  MY_HWCAP_CHECK_FUNC_2(NEON, NEON)
+#endif
+
+#else // USE_HWCAP
+
+  #define MY_HWCAP_CHECK_FUNC(name) \
+  BoolInt CPU_IsSupported_ ## name(void) { return 0; }
+  MY_HWCAP_CHECK_FUNC(NEON)
+
+#endif // USE_HWCAP
+
+MY_HWCAP_CHECK_FUNC (CRC32)
+MY_HWCAP_CHECK_FUNC (SHA1)
+MY_HWCAP_CHECK_FUNC (SHA2)
+MY_HWCAP_CHECK_FUNC (AES)
+
+#endif // __APPLE__
+#endif // _WIN32
+
+#endif // MY_CPU_ARM_OR_ARM64
+
+
+
+#ifdef __APPLE__
+
+#include <sys/sysctl.h>
+
+int z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize)
+{
+  return sysctlbyname(name, buf, bufSize, NULL, 0);
+}
+
+int z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val)
+{
+  size_t bufSize = sizeof(*val);
+  const int res = z7_sysctlbyname_Get(name, val, &bufSize);
+  if (res == 0 && bufSize != sizeof(*val))
+    return EFAULT;
+  return res;
+}
+
+#endif

+ 647 - 0
Components/Lzma2/CpuArch.h

@@ -0,0 +1,647 @@
+/* CpuArch.h -- CPU specific code
+2024-06-17 : 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)
+
+#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))
+#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 GetBe16
+#define GetBe16(p) ( (UInt16) ( \
+    ((UInt16)((const Byte *)(p))[0] << 8) | \
+             ((const Byte *)(p))[1] ))
+#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
+
+
+#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_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
+
+#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

Dosya farkı çok büyük olduğundan ihmal edildi
+ 717 - 158
Components/Lzma2/LzFind.c


+ 88 - 43
Components/Lzma2/LzFind.h

@@ -1,80 +1,121 @@
 /* LzFind.h -- Match finder for LZ algorithms
 /* LzFind.h -- Match finder for LZ algorithms
-2009-04-22 : Igor Pavlov : Public domain */
+2024-01-22 : Igor Pavlov : Public domain */
 
 
-#ifndef __LZ_FIND_H
-#define __LZ_FIND_H
+#ifndef ZIP7_INC_LZ_FIND_H
+#define ZIP7_INC_LZ_FIND_H
 
 
-#include "Types.h"
+#include "7zTypes.h"
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+EXTERN_C_BEGIN
 
 
 typedef UInt32 CLzRef;
 typedef UInt32 CLzRef;
 
 
-typedef struct _CMatchFinder
+typedef struct
 {
 {
-  Byte *buffer;
+  const Byte *buffer;
   UInt32 pos;
   UInt32 pos;
   UInt32 posLimit;
   UInt32 posLimit;
-  UInt32 streamPos;
+  UInt32 streamPos;  /* wrap over Zero is allowed (streamPos < pos). Use (UInt32)(streamPos - pos) */
   UInt32 lenLimit;
   UInt32 lenLimit;
 
 
   UInt32 cyclicBufferPos;
   UInt32 cyclicBufferPos;
   UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
   UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
 
 
+  Byte streamEndWasReached;
+  Byte btMode;
+  Byte bigHash;
+  Byte directInput;
+
   UInt32 matchMaxLen;
   UInt32 matchMaxLen;
   CLzRef *hash;
   CLzRef *hash;
   CLzRef *son;
   CLzRef *son;
   UInt32 hashMask;
   UInt32 hashMask;
   UInt32 cutValue;
   UInt32 cutValue;
 
 
-  Byte *bufferBase;
-  ISeqInStream *stream;
-  int streamEndWasReached;
-
+  Byte *bufBase;
+  ISeqInStreamPtr stream;
+  
   UInt32 blockSize;
   UInt32 blockSize;
   UInt32 keepSizeBefore;
   UInt32 keepSizeBefore;
   UInt32 keepSizeAfter;
   UInt32 keepSizeAfter;
 
 
   UInt32 numHashBytes;
   UInt32 numHashBytes;
-  int directInput;
   size_t directInputRem;
   size_t directInputRem;
-  int btMode;
-  int bigHash;
   UInt32 historySize;
   UInt32 historySize;
   UInt32 fixedHashSize;
   UInt32 fixedHashSize;
-  UInt32 hashSizeSum;
-  UInt32 numSons;
+  Byte numHashBytes_Min;
+  Byte numHashOutBits;
+  Byte _pad2_[2];
   SRes result;
   SRes result;
   UInt32 crc[256];
   UInt32 crc[256];
+  size_t numRefs;
+
+  UInt64 expectedDataSize;
 } CMatchFinder;
 } CMatchFinder;
 
 
-#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
-#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((const Byte *)(p)->buffer)
 
 
-#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
+#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);
 int MatchFinder_NeedMove(CMatchFinder *p);
-Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
+/* Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); */
 void MatchFinder_MoveBlock(CMatchFinder *p);
 void MatchFinder_MoveBlock(CMatchFinder *p);
 void MatchFinder_ReadIfRequired(CMatchFinder *p);
 void MatchFinder_ReadIfRequired(CMatchFinder *p);
 
 
 void MatchFinder_Construct(CMatchFinder *p);
 void MatchFinder_Construct(CMatchFinder *p);
 
 
-/* Conditions:
-     historySize <= 3 GB
-     keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
+/* (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,
 int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
     UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
     UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
-    ISzAlloc *alloc);
-void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
-void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
+    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,
 UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
-    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
     UInt32 *distances, UInt32 maxLen);
     UInt32 *distances, UInt32 maxLen);
 
 
 /*
 /*
@@ -84,32 +125,36 @@ Conditions:
 */
 */
 
 
 typedef void (*Mf_Init_Func)(void *object);
 typedef void (*Mf_Init_Func)(void *object);
-typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
 typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
 typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
 typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
 typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
-typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
+typedef UInt32 * (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
 typedef void (*Mf_Skip_Func)(void *object, UInt32);
 typedef void (*Mf_Skip_Func)(void *object, UInt32);
 
 
-typedef struct _IMatchFinder
+typedef struct
 {
 {
   Mf_Init_Func Init;
   Mf_Init_Func Init;
-  Mf_GetIndexByte_Func GetIndexByte;
   Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
   Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
   Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
   Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
   Mf_GetMatches_Func GetMatches;
   Mf_GetMatches_Func GetMatches;
   Mf_Skip_Func Skip;
   Mf_Skip_Func Skip;
-} IMatchFinder;
+} 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);
 
 
-void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
 
 
-void MatchFinder_Init(CMatchFinder *p);
-UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
-UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
 void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
 void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
 void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
 void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
 
 
-#ifdef __cplusplus
-}
-#endif
+void LzFindPrepare(void);
+
+EXTERN_C_END
 
 
 #endif
 #endif

Dosya farkı çok büyük olduğundan ihmal edildi
+ 620 - 237
Components/Lzma2/LzFindMt.c


+ 43 - 36
Components/Lzma2/LzFindMt.h

@@ -1,44 +1,40 @@
 /* LzFindMt.h -- multithreaded Match finder for LZ algorithms
 /* LzFindMt.h -- multithreaded Match finder for LZ algorithms
-2009-02-07 : Igor Pavlov : Public domain */
+2024-01-22 : Igor Pavlov : Public domain */
 
 
-#ifndef __LZ_FIND_MT_H
-#define __LZ_FIND_MT_H
+#ifndef ZIP7_INC_LZ_FIND_MT_H
+#define ZIP7_INC_LZ_FIND_MT_H
 
 
 #include "LzFind.h"
 #include "LzFind.h"
 #include "Threads.h"
 #include "Threads.h"
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+EXTERN_C_BEGIN
 
 
-#define kMtHashBlockSize (1 << 13)
-#define kMtHashNumBlocks (1 << 3)
-#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)
+typedef struct
+{
+  UInt32 numProcessedBlocks;
+  CThread thread;
+  UInt64 affinity;
 
 
-#define kMtBtBlockSize (1 << 14)
-#define kMtBtNumBlocks (1 << 6)
-#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)
+  BoolInt wasCreated;
+  BoolInt needStart;
+  BoolInt csWasInitialized;
+  BoolInt csWasEntered;
 
 
-typedef struct _CMtSync
-{
-  Bool wasCreated;
-  Bool needStart;
-  Bool exit;
-  Bool stopWriting;
+  BoolInt exit;
+  BoolInt stopWriting;
 
 
-  CThread thread;
   CAutoResetEvent canStart;
   CAutoResetEvent canStart;
-  CAutoResetEvent wasStarted;
   CAutoResetEvent wasStopped;
   CAutoResetEvent wasStopped;
   CSemaphore freeSemaphore;
   CSemaphore freeSemaphore;
   CSemaphore filledSemaphore;
   CSemaphore filledSemaphore;
-  Bool csWasInitialized;
-  Bool csWasEntered;
   CCriticalSection cs;
   CCriticalSection cs;
-  UInt32 numProcessedBlocks;
+  // UInt32 numBlocks_Sent;
 } CMtSync;
 } CMtSync;
 
 
-typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
+
+struct CMatchFinderMt_;
+
+typedef UInt32 * (*Mf_Mix_Matches)(struct CMatchFinderMt_ *p, UInt32 matchMinPos, UInt32 *distances);
 
 
 /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
 /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
 #define kMtCacheLineDummy 128
 #define kMtCacheLineDummy 128
@@ -46,23 +42,28 @@ typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distance
 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
   UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
   UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
 
 
-typedef struct _CMatchFinderMt
+typedef struct CMatchFinderMt_
 {
 {
   /* LZ */
   /* LZ */
   const Byte *pointerToCurPos;
   const Byte *pointerToCurPos;
   UInt32 *btBuf;
   UInt32 *btBuf;
-  UInt32 btBufPos;
-  UInt32 btBufPosLimit;
+  const UInt32 *btBufPos;
+  const UInt32 *btBufPosLimit;
   UInt32 lzPos;
   UInt32 lzPos;
   UInt32 btNumAvailBytes;
   UInt32 btNumAvailBytes;
 
 
   UInt32 *hash;
   UInt32 *hash;
   UInt32 fixedHashSize;
   UInt32 fixedHashSize;
+  // UInt32 hash4Mask;
   UInt32 historySize;
   UInt32 historySize;
   const UInt32 *crc;
   const UInt32 *crc;
 
 
   Mf_Mix_Matches MixMatchesFunc;
   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 */
   /* LZ + BT */
   CMtSync btSync;
   CMtSync btSync;
   Byte btDummy[kMtCacheLineDummy];
   Byte btDummy[kMtCacheLineDummy];
@@ -72,14 +73,16 @@ typedef struct _CMatchFinderMt
   UInt32 hashBufPos;
   UInt32 hashBufPos;
   UInt32 hashBufPosLimit;
   UInt32 hashBufPosLimit;
   UInt32 hashNumAvail;
   UInt32 hashNumAvail;
+  UInt32 failure_BT;
+
 
 
   CLzRef *son;
   CLzRef *son;
   UInt32 matchMaxLen;
   UInt32 matchMaxLen;
   UInt32 numHashBytes;
   UInt32 numHashBytes;
   UInt32 pos;
   UInt32 pos;
-  Byte *buffer;
+  const Byte *buffer;
   UInt32 cyclicBufferPos;
   UInt32 cyclicBufferPos;
-  UInt32 cyclicBufferSize; /* it must be historySize + 1 */
+  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
   UInt32 cutValue;
   UInt32 cutValue;
 
 
   /* BT + Hash */
   /* BT + Hash */
@@ -89,17 +92,21 @@ typedef struct _CMatchFinderMt
   /* Hash */
   /* Hash */
   Mf_GetHeads GetHeadsFunc;
   Mf_GetHeads GetHeadsFunc;
   CMatchFinder *MatchFinder;
   CMatchFinder *MatchFinder;
+  // CMatchFinder MatchFinder;
 } CMatchFinderMt;
 } CMatchFinderMt;
 
 
+// only for Mt part
 void MatchFinderMt_Construct(CMatchFinderMt *p);
 void MatchFinderMt_Construct(CMatchFinderMt *p);
-void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc);
+
 SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
 SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
-    UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);
-void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
+    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);
 void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
 
 
-#ifdef __cplusplus
-}
-#endif
+EXTERN_C_END
 
 
 #endif
 #endif

+ 578 - 0
Components/Lzma2/LzFindOpt.c

@@ -0,0 +1,578 @@
+/* LzFindOpt.c -- multithreaded Match finder for LZ algorithms
+2023-04-02 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+#include "CpuArch.h"
+#include "LzFind.h"
+
+// #include "LzFindMt.h"
+
+// #define LOG_ITERS
+
+// #define LOG_THREAD
+
+#ifdef LOG_THREAD
+#include <stdio.h>
+#define PRF(x) x
+#else
+// #define PRF(x)
+#endif
+
+#ifdef LOG_ITERS
+#include <stdio.h>
+UInt64 g_NumIters_Tree;
+UInt64 g_NumIters_Loop;
+UInt64 g_NumIters_Bytes;
+#define LOG_ITER(x) x
+#else
+#define LOG_ITER(x)
+#endif
+
+// ---------- BT THREAD ----------
+
+#define USE_SON_PREFETCH
+#define USE_LONG_MATCH_OPT
+
+#define kEmptyHashValue 0
+
+// #define CYC_TO_POS_OFFSET 0
+
+// #define CYC_TO_POS_OFFSET 1 // for debug
+
+/*
+Z7_NO_INLINE
+UInt32 * Z7_FASTCALL GetMatchesSpecN_1(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,
+    UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, UInt32 *posRes)
+{
+  do
+  {
+    UInt32 delta;
+    if (hash == size)
+      break;
+    delta = *hash++;
+
+    if (delta == 0 || delta > (UInt32)pos)
+      return NULL;
+
+    lenLimit++;
+
+    if (delta == (UInt32)pos)
+    {
+      CLzRef *ptr1 = son + ((size_t)pos << 1) - CYC_TO_POS_OFFSET * 2;
+      *d++ = 0;
+      ptr1[0] = kEmptyHashValue;
+      ptr1[1] = kEmptyHashValue;
+    }
+else
+{
+  UInt32 *_distances = ++d;
+
+  CLzRef *ptr0 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2 + 1;
+  CLzRef *ptr1 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;
+
+  const Byte *len0 = cur, *len1 = cur;
+  UInt32 cutValue = _cutValue;
+  const Byte *maxLen = cur + _maxLen;
+
+  for (LOG_ITER(g_NumIters_Tree++);;)
+  {
+    LOG_ITER(g_NumIters_Loop++);
+    {
+      const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
+      CLzRef *pair = son + ((size_t)(((ptrdiff_t)pos - CYC_TO_POS_OFFSET) + diff) << 1);
+      const Byte *len = (len0 < len1 ? len0 : len1);
+
+    #ifdef USE_SON_PREFETCH
+      const UInt32 pair0 = *pair;
+    #endif
+
+      if (len[diff] == len[0])
+      {
+        if (++len != lenLimit && len[diff] == len[0])
+          while (++len != lenLimit)
+          {
+            LOG_ITER(g_NumIters_Bytes++);
+            if (len[diff] != len[0])
+              break;
+          }
+        if (maxLen < len)
+        {
+          maxLen = len;
+          *d++ = (UInt32)(len - cur);
+          *d++ = delta - 1;
+          
+          if (len == lenLimit)
+          {
+            const UInt32 pair1 = pair[1];
+            *ptr1 =
+              #ifdef USE_SON_PREFETCH
+                pair0;
+              #else
+                pair[0];
+              #endif
+            *ptr0 = pair1;
+
+            _distances[-1] = (UInt32)(d - _distances);
+
+            #ifdef USE_LONG_MATCH_OPT
+
+                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
+                  break;
+
+            {
+              for (;;)
+              {
+                hash++;
+                pos++;
+                cur++;
+                lenLimit++;
+                {
+                  CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;
+                  #if 0
+                  *(UInt64 *)(void *)ptr = ((const UInt64 *)(const void *)ptr)[diff];
+                  #else
+                  const UInt32 p0 = ptr[0 + (diff * 2)];
+                  const UInt32 p1 = ptr[1 + (diff * 2)];
+                  ptr[0] = p0;
+                  ptr[1] = p1;
+                  // ptr[0] = ptr[0 + (diff * 2)];
+                  // ptr[1] = ptr[1 + (diff * 2)];
+                  #endif
+                }
+                // PrintSon(son + 2, pos - 1);
+                // printf("\npos = %x delta = %x\n", pos, delta);
+                len++;
+                *d++ = 2;
+                *d++ = (UInt32)(len - cur);
+                *d++ = delta - 1;
+                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
+                  break;
+              }
+            }
+            #endif
+
+            break;
+          }
+        }
+      }
+
+      {
+        const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff);
+        if (len[diff] < len[0])
+        {
+          delta = pair[1];
+          if (delta >= curMatch)
+            return NULL;
+          *ptr1 = curMatch;
+          ptr1 = pair + 1;
+          len1 = len;
+        }
+        else
+        {
+          delta = *pair;
+          if (delta >= curMatch)
+            return NULL;
+          *ptr0 = curMatch;
+          ptr0 = pair;
+          len0 = len;
+        }
+
+        delta = (UInt32)pos - delta;
+ 
+        if (--cutValue == 0 || delta >= pos)
+        {
+          *ptr0 = *ptr1 = kEmptyHashValue;
+          _distances[-1] = (UInt32)(d - _distances);
+          break;
+        }
+      }
+    }
+  } // for (tree iterations)
+}
+    pos++;
+    cur++;
+  }
+  while (d < limit);
+  *posRes = (UInt32)pos;
+  return d;
+}
+*/
+
+/* define cbs if you use 2 functions.
+       GetMatchesSpecN_1() :  (pos <  _cyclicBufferSize)
+       GetMatchesSpecN_2() :  (pos >= _cyclicBufferSize)
+
+  do not define cbs if you use 1 function:
+       GetMatchesSpecN_2()
+*/
+
+// #define cbs _cyclicBufferSize
+
+/*
+  we use size_t for (pos) and (_cyclicBufferPos_ instead of UInt32
+  to eliminate "movsx" BUG in old MSVC x64 compiler.
+*/
+
+UInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,
+    UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,
+    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,
+    UInt32 *posRes);
+
+Z7_NO_INLINE
+UInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,
+    UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,
+    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,
+    UInt32 *posRes)
+{
+  do // while (hash != size)
+  {
+    UInt32 delta;
+    
+  #ifndef cbs
+    UInt32 cbs;
+  #endif
+
+    if (hash == size)
+      break;
+
+    delta = *hash++;
+
+    if (delta == 0)
+      return NULL;
+
+    lenLimit++;
+
+  #ifndef cbs
+    cbs = _cyclicBufferSize;
+    if ((UInt32)pos < cbs)
+    {
+      if (delta > (UInt32)pos)
+        return NULL;
+      cbs = (UInt32)pos;
+    }
+  #endif
+
+    if (delta >= cbs)
+    {
+      CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
+      *d++ = 0;
+      ptr1[0] = kEmptyHashValue;
+      ptr1[1] = kEmptyHashValue;
+    }
+else
+{
+  UInt32 *_distances = ++d;
+
+  CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
+  CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
+
+  UInt32 cutValue = _cutValue;
+  const Byte *len0 = cur, *len1 = cur;
+  const Byte *maxLen = cur + _maxLen;
+
+  // if (cutValue == 0) { *ptr0 = *ptr1 = kEmptyHashValue; } else
+  for (LOG_ITER(g_NumIters_Tree++);;)
+  {
+    LOG_ITER(g_NumIters_Loop++);
+    {
+      // SPEC code
+      CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - (ptrdiff_t)delta
+          + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)
+          ) << 1);
+
+      const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
+      const Byte *len = (len0 < len1 ? len0 : len1);
+
+    #ifdef USE_SON_PREFETCH
+      const UInt32 pair0 = *pair;
+    #endif
+
+      if (len[diff] == len[0])
+      {
+        if (++len != lenLimit && len[diff] == len[0])
+          while (++len != lenLimit)
+          {
+            LOG_ITER(g_NumIters_Bytes++);
+            if (len[diff] != len[0])
+              break;
+          }
+        if (maxLen < len)
+        {
+          maxLen = len;
+          *d++ = (UInt32)(len - cur);
+          *d++ = delta - 1;
+          
+          if (len == lenLimit)
+          {
+            const UInt32 pair1 = pair[1];
+            *ptr1 =
+              #ifdef USE_SON_PREFETCH
+                pair0;
+              #else
+                pair[0];
+              #endif
+            *ptr0 = pair1;
+
+            _distances[-1] = (UInt32)(d - _distances);
+
+            #ifdef USE_LONG_MATCH_OPT
+
+                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
+                  break;
+
+            {
+              for (;;)
+              {
+                *d++ = 2;
+                *d++ = (UInt32)(lenLimit - cur);
+                *d++ = delta - 1;
+                cur++;
+                lenLimit++;
+                // SPEC
+                _cyclicBufferPos++;
+                {
+                  // SPEC code
+                  CLzRef *dest = son + ((size_t)(_cyclicBufferPos) << 1);
+                  const CLzRef *src = dest + ((diff
+                      + (ptrdiff_t)(UInt32)((_cyclicBufferPos < delta) ? cbs : 0)) << 1);
+                  // CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;
+                  #if 0
+                  *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src);
+                  #else
+                  const UInt32 p0 = src[0];
+                  const UInt32 p1 = src[1];
+                  dest[0] = p0;
+                  dest[1] = p1;
+                  #endif
+                }
+                pos++;
+                hash++;
+                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
+                  break;
+              } // for() end for long matches
+            }
+            #endif
+
+            break; // break from TREE iterations
+          }
+        }
+      }
+      {
+        const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff);
+        if (len[diff] < len[0])
+        {
+          delta = pair[1];
+          *ptr1 = curMatch;
+          ptr1 = pair + 1;
+          len1 = len;
+          if (delta >= curMatch)
+            return NULL;
+        }
+        else
+        {
+          delta = *pair;
+          *ptr0 = curMatch;
+          ptr0 = pair;
+          len0 = len;
+          if (delta >= curMatch)
+            return NULL;
+        }
+        delta = (UInt32)pos - delta;
+ 
+        if (--cutValue == 0 || delta >= cbs)
+        {
+          *ptr0 = *ptr1 = kEmptyHashValue;
+          _distances[-1] = (UInt32)(d - _distances);
+          break;
+        }
+      }
+    }
+  } // for (tree iterations)
+}
+    pos++;
+    _cyclicBufferPos++;
+    cur++;
+  }
+  while (d < limit);
+  *posRes = (UInt32)pos;
+  return d;
+}
+
+
+
+/*
+typedef UInt32 uint32plus; // size_t
+
+UInt32 * Z7_FASTCALL GetMatchesSpecN_3(uint32plus lenLimit, size_t pos, const Byte *cur, CLzRef *son,
+    UInt32 _cutValue, UInt32 *d, uint32plus _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,
+    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,
+    UInt32 *posRes)
+{
+  do // while (hash != size)
+  {
+    UInt32 delta;
+
+  #ifndef cbs
+    UInt32 cbs;
+  #endif
+
+    if (hash == size)
+      break;
+
+    delta = *hash++;
+
+    if (delta == 0)
+      return NULL;
+
+  #ifndef cbs
+    cbs = _cyclicBufferSize;
+    if ((UInt32)pos < cbs)
+    {
+      if (delta > (UInt32)pos)
+        return NULL;
+      cbs = (UInt32)pos;
+    }
+  #endif
+    
+    if (delta >= cbs)
+    {
+      CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
+      *d++ = 0;
+      ptr1[0] = kEmptyHashValue;
+      ptr1[1] = kEmptyHashValue;
+    }
+else
+{
+  CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
+  CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
+  UInt32 *_distances = ++d;
+  uint32plus len0 = 0, len1 = 0;
+  UInt32 cutValue = _cutValue;
+  uint32plus maxLen = _maxLen;
+  // lenLimit++; // const Byte *lenLimit = cur + _lenLimit;
+
+  for (LOG_ITER(g_NumIters_Tree++);;)
+  {
+    LOG_ITER(g_NumIters_Loop++);
+    {
+      // const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
+      CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - delta
+          + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)
+          ) << 1);
+      const Byte *pb = cur - delta;
+      uint32plus len = (len0 < len1 ? len0 : len1);
+
+    #ifdef USE_SON_PREFETCH
+      const UInt32 pair0 = *pair;
+    #endif
+
+      if (pb[len] == cur[len])
+      {
+        if (++len != lenLimit && pb[len] == cur[len])
+          while (++len != lenLimit)
+            if (pb[len] != cur[len])
+              break;
+        if (maxLen < len)
+        {
+          maxLen = len;
+          *d++ = (UInt32)len;
+          *d++ = delta - 1;
+          if (len == lenLimit)
+          {
+            {
+              const UInt32 pair1 = pair[1];
+              *ptr0 = pair1;
+              *ptr1 =
+              #ifdef USE_SON_PREFETCH
+                pair0;
+              #else
+                pair[0];
+              #endif
+            }
+
+            _distances[-1] = (UInt32)(d - _distances);
+
+            #ifdef USE_LONG_MATCH_OPT
+
+                if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit)
+                  break;
+
+            {
+              const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;
+              for (;;)
+              {
+                *d++ = 2;
+                *d++ = (UInt32)lenLimit;
+                *d++ = delta - 1;
+                _cyclicBufferPos++;
+                {
+                  CLzRef *dest = son + ((size_t)_cyclicBufferPos << 1);
+                  const CLzRef *src = dest + ((diff +
+                      (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)) << 1);
+                #if 0
+                  *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src);
+                #else
+                  const UInt32 p0 = src[0];
+                  const UInt32 p1 = src[1];
+                  dest[0] = p0;
+                  dest[1] = p1;
+                #endif
+                }
+                hash++;
+                pos++;
+                cur++;
+                pb++;
+                if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit)
+                  break;
+              }
+            }
+            #endif
+
+            break;
+          }
+        }
+      }
+      {
+        const UInt32 curMatch = (UInt32)pos - delta;
+        if (pb[len] < cur[len])
+        {
+          delta = pair[1];
+          *ptr1 = curMatch;
+          ptr1 = pair + 1;
+          len1 = len;
+        }
+        else
+        {
+          delta = *pair;
+          *ptr0 = curMatch;
+          ptr0 = pair;
+          len0 = len;
+        }
+
+        {
+          if (delta >= curMatch)
+            return NULL;
+          delta = (UInt32)pos - delta;
+          if (delta >= cbs
+              // delta >= _cyclicBufferSize || delta >= pos
+              || --cutValue == 0)
+          {
+            *ptr0 = *ptr1 = kEmptyHashValue;
+            _distances[-1] = (UInt32)(d - _distances);
+            break;
+          }
+        }
+      }
+    }
+  } // for (tree iterations)
+}
+    pos++;
+    _cyclicBufferPos++;
+    cur++;
+  }
+  while (d < limit);
+  *posRes = (UInt32)pos;
+  return d;
+}
+*/

+ 25 - 45
Components/Lzma2/LzHash.h

@@ -1,54 +1,34 @@
-/* LzHash.h -- HASH functions for LZ algorithms
-2009-02-07 : Igor Pavlov : Public domain */
+/* LzHash.h -- HASH constants for LZ algorithms
+2023-03-05 : Igor Pavlov : Public domain */
 
 
-#ifndef __LZ_HASH_H
-#define __LZ_HASH_H
+#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 kHash2Size (1 << 10)
 #define kHash3Size (1 << 16)
 #define kHash3Size (1 << 16)
-#define kHash4Size (1 << 20)
+// #define kHash4Size (1 << 20)
 
 
 #define kFix3HashSize (kHash2Size)
 #define kFix3HashSize (kHash2Size)
 #define kFix4HashSize (kHash2Size + kHash3Size)
 #define kFix4HashSize (kHash2Size + kHash3Size)
-#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
-
-#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
-
-#define HASH3_CALC { \
-  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
-  hash2Value = temp & (kHash2Size - 1); \
-  hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
-
-#define HASH4_CALC { \
-  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
-  hash2Value = temp & (kHash2Size - 1); \
-  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
-  hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
-
-#define HASH5_CALC { \
-  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
-  hash2Value = temp & (kHash2Size - 1); \
-  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
-  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
-  hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
-  hash4Value &= (kHash4Size - 1); }
-
-/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
-#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
-
-
-#define MT_HASH2_CALC \
-  hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
-
-#define MT_HASH3_CALC { \
-  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
-  hash2Value = temp & (kHash2Size - 1); \
-  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
-
-#define MT_HASH4_CALC { \
-  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
-  hash2Value = temp & (kHash2Size - 1); \
-  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
-  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
+// #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
 #endif

+ 265 - 128
Components/Lzma2/Lzma2Dec.c

@@ -1,8 +1,10 @@
 /* Lzma2Dec.c -- LZMA2 Decoder
 /* Lzma2Dec.c -- LZMA2 Decoder
-2009-05-03 : Igor Pavlov : Public domain */
+2024-03-01 : Igor Pavlov : Public domain */
 
 
 /* #define SHOW_DEBUG_INFO */
 /* #define SHOW_DEBUG_INFO */
 
 
+#include "Precomp.h"
+
 #ifdef SHOW_DEBUG_INFO
 #ifdef SHOW_DEBUG_INFO
 #include <stdio.h>
 #include <stdio.h>
 #endif
 #endif
@@ -12,28 +14,22 @@
 #include "Lzma2Dec.h"
 #include "Lzma2Dec.h"
 
 
 /*
 /*
-00000000  -  EOS
-00000001 U U  -  Uncompressed Reset Dic
-00000010 U U  -  Uncompressed No Reset
-100uuuuu U U P P  -  LZMA no reset
-101uuuuu U U P P  -  LZMA reset state
-110uuuuu U U P P S  -  LZMA reset state + new prop
-111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic
+00000000  -  End of data
+00000001 U U  -  Uncompressed, reset dic, need reset state and set new prop
+00000010 U U  -  Uncompressed, no reset
+100uuuuu U U P P  -  LZMA, no reset
+101uuuuu U U P P  -  LZMA, reset state
+110uuuuu U U P P S  -  LZMA, reset state + set new prop
+111uuuuu U U P P S  -  LZMA, reset state + set new prop, reset dic
 
 
   u, U - Unpack Size
   u, U - Unpack Size
   P - Pack Size
   P - Pack Size
   S - Props
   S - Props
 */
 */
 
 
-#define LZMA2_CONTROL_LZMA (1 << 7)
-#define LZMA2_CONTROL_COPY_NO_RESET 2
 #define LZMA2_CONTROL_COPY_RESET_DIC 1
 #define LZMA2_CONTROL_COPY_RESET_DIC 1
-#define LZMA2_CONTROL_EOF 0
-
-#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
 
 
-#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
-#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
+#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
 
 
 #define LZMA2_LCLP_MAX 4
 #define LZMA2_LCLP_MAX 4
 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
@@ -72,47 +68,57 @@ static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
   return SZ_OK;
   return SZ_OK;
 }
 }
 
 
-SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
+SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
 {
 {
   Byte props[LZMA_PROPS_SIZE];
   Byte props[LZMA_PROPS_SIZE];
-  RINOK(Lzma2Dec_GetOldProps(prop, props));
+  RINOK(Lzma2Dec_GetOldProps(prop, props))
   return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
   return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
 }
 }
 
 
-SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
+SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
 {
 {
   Byte props[LZMA_PROPS_SIZE];
   Byte props[LZMA_PROPS_SIZE];
-  RINOK(Lzma2Dec_GetOldProps(prop, props));
+  RINOK(Lzma2Dec_GetOldProps(prop, props))
   return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
   return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
 }
 }
 
 
 void Lzma2Dec_Init(CLzma2Dec *p)
 void Lzma2Dec_Init(CLzma2Dec *p)
 {
 {
   p->state = LZMA2_STATE_CONTROL;
   p->state = LZMA2_STATE_CONTROL;
-  p->needInitDic = True;
-  p->needInitState = True;
-  p->needInitProp = True;
+  p->needInitLevel = 0xE0;
+  p->isExtraMode = False;
+  p->unpackSize = 0;
+  
+  // p->decoder.dicPos = 0; // we can use it instead of full init
   LzmaDec_Init(&p->decoder);
   LzmaDec_Init(&p->decoder);
 }
 }
 
 
-static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
+// ELzma2State
+static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
 {
 {
-  switch(p->state)
+  switch (p->state)
   {
   {
     case LZMA2_STATE_CONTROL:
     case LZMA2_STATE_CONTROL:
+      p->isExtraMode = False;
       p->control = b;
       p->control = b;
-      PRF(printf("\n %4X ", p->decoder.dicPos));
-      PRF(printf(" %2X", b));
-      if (p->control == 0)
+      PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
+      PRF(printf(" %02X", (unsigned)b));
+      if (b == 0)
         return LZMA2_STATE_FINISHED;
         return LZMA2_STATE_FINISHED;
       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
       {
       {
-        if ((p->control & 0x7F) > 2)
+        if (b == LZMA2_CONTROL_COPY_RESET_DIC)
+          p->needInitLevel = 0xC0;
+        else if (b > 2 || p->needInitLevel == 0xE0)
           return LZMA2_STATE_ERROR;
           return LZMA2_STATE_ERROR;
-        p->unpackSize = 0;
       }
       }
       else
       else
-        p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
+      {
+        if (b < p->needInitLevel)
+          return LZMA2_STATE_ERROR;
+        p->needInitLevel = 0;
+        p->unpackSize = (UInt32)(b & 0x1F) << 16;
+      }
       return LZMA2_STATE_UNPACK0;
       return LZMA2_STATE_UNPACK0;
     
     
     case LZMA2_STATE_UNPACK0:
     case LZMA2_STATE_UNPACK0:
@@ -122,8 +128,8 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
     case LZMA2_STATE_UNPACK1:
     case LZMA2_STATE_UNPACK1:
       p->unpackSize |= (UInt32)b;
       p->unpackSize |= (UInt32)b;
       p->unpackSize++;
       p->unpackSize++;
-      PRF(printf(" %8d", p->unpackSize));
-      return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
+      PRF(printf(" %7u", (unsigned)p->unpackSize));
+      return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
     
     
     case LZMA2_STATE_PACK0:
     case LZMA2_STATE_PACK0:
       p->packSize = (UInt32)b << 8;
       p->packSize = (UInt32)b << 8;
@@ -132,28 +138,29 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
     case LZMA2_STATE_PACK1:
     case LZMA2_STATE_PACK1:
       p->packSize |= (UInt32)b;
       p->packSize |= (UInt32)b;
       p->packSize++;
       p->packSize++;
-      PRF(printf(" %8d", p->packSize));
-      return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
-        (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
+      // if (p->packSize < 5) return LZMA2_STATE_ERROR;
+      PRF(printf(" %5u", (unsigned)p->packSize));
+      return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
 
 
     case LZMA2_STATE_PROP:
     case LZMA2_STATE_PROP:
     {
     {
-      int lc, lp;
+      unsigned lc, lp;
       if (b >= (9 * 5 * 5))
       if (b >= (9 * 5 * 5))
         return LZMA2_STATE_ERROR;
         return LZMA2_STATE_ERROR;
       lc = b % 9;
       lc = b % 9;
       b /= 9;
       b /= 9;
-      p->decoder.prop.pb = b / 5;
+      p->decoder.prop.pb = (Byte)(b / 5);
       lp = b % 5;
       lp = b % 5;
       if (lc + lp > LZMA2_LCLP_MAX)
       if (lc + lp > LZMA2_LCLP_MAX)
         return LZMA2_STATE_ERROR;
         return LZMA2_STATE_ERROR;
-      p->decoder.prop.lc = lc;
-      p->decoder.prop.lp = lp;
-      p->needInitProp = False;
+      p->decoder.prop.lc = (Byte)lc;
+      p->decoder.prop.lp = (Byte)lp;
       return LZMA2_STATE_DATA;
       return LZMA2_STATE_DATA;
     }
     }
+    
+    default:
+      return LZMA2_STATE_ERROR;
   }
   }
-  return LZMA2_STATE_ERROR;
 }
 }
 
 
 static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
 static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
@@ -165,7 +172,8 @@ static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT s
   p->processedPos += (UInt32)size;
   p->processedPos += (UInt32)size;
 }
 }
 
 
-void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
+void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
+
 
 
 SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
 SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
@@ -174,16 +182,24 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
   *srcLen = 0;
   *srcLen = 0;
   *status = LZMA_STATUS_NOT_SPECIFIED;
   *status = LZMA_STATUS_NOT_SPECIFIED;
 
 
-  while (p->state != LZMA2_STATE_FINISHED)
+  while (p->state != LZMA2_STATE_ERROR)
   {
   {
-    SizeT dicPos = p->decoder.dicPos;
-    if (p->state == LZMA2_STATE_ERROR)
-      return SZ_ERROR_DATA;
+    SizeT dicPos;
+
+    if (p->state == LZMA2_STATE_FINISHED)
+    {
+      *status = LZMA_STATUS_FINISHED_WITH_MARK;
+      return SZ_OK;
+    }
+    
+    dicPos = p->decoder.dicPos;
+    
     if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
     if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
     {
     {
       *status = LZMA_STATUS_NOT_FINISHED;
       *status = LZMA_STATUS_NOT_FINISHED;
       return SZ_OK;
       return SZ_OK;
     }
     }
+
     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
     {
     {
       if (*srcLen == inSize)
       if (*srcLen == inSize)
@@ -193,22 +209,25 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
       }
       }
       (*srcLen)++;
       (*srcLen)++;
       p->state = Lzma2Dec_UpdateState(p, *src++);
       p->state = Lzma2Dec_UpdateState(p, *src++);
+      if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
+        break;
       continue;
       continue;
     }
     }
+    
     {
     {
-      SizeT destSizeCur = dicLimit - dicPos;
-      SizeT srcSizeCur = inSize - *srcLen;
+      SizeT inCur = inSize - *srcLen;
+      SizeT outCur = dicLimit - dicPos;
       ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
       ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
       
       
-      if (p->unpackSize <= destSizeCur)
+      if (outCur >= p->unpackSize)
       {
       {
-        destSizeCur = (SizeT)p->unpackSize;
+        outCur = (SizeT)p->unpackSize;
         curFinishMode = LZMA_FINISH_END;
         curFinishMode = LZMA_FINISH_END;
       }
       }
 
 
       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
       {
       {
-        if (*srcLen == inSize)
+        if (inCur == 0)
         {
         {
           *status = LZMA_STATUS_NEEDS_MORE_INPUT;
           *status = LZMA_STATUS_NEEDS_MORE_INPUT;
           return SZ_OK;
           return SZ_OK;
@@ -216,141 +235,259 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
 
 
         if (p->state == LZMA2_STATE_DATA)
         if (p->state == LZMA2_STATE_DATA)
         {
         {
-          Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
-          if (initDic)
-            p->needInitProp = p->needInitState = True;
-          else if (p->needInitDic)
-            return SZ_ERROR_DATA;
-          p->needInitDic = False;
+          BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
           LzmaDec_InitDicAndState(&p->decoder, initDic, False);
           LzmaDec_InitDicAndState(&p->decoder, initDic, False);
         }
         }
 
 
-        if (srcSizeCur > destSizeCur)
-          srcSizeCur = destSizeCur;
-
-        if (srcSizeCur == 0)
-          return SZ_ERROR_DATA;
+        if (inCur > outCur)
+          inCur = outCur;
+        if (inCur == 0)
+          break;
 
 
-        LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
+        LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
 
 
-        src += srcSizeCur;
-        *srcLen += srcSizeCur;
-        p->unpackSize -= (UInt32)srcSizeCur;
+        src += inCur;
+        *srcLen += inCur;
+        p->unpackSize -= (UInt32)inCur;
         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
       }
       }
       else
       else
       {
       {
-        SizeT outSizeProcessed;
         SRes res;
         SRes res;
 
 
         if (p->state == LZMA2_STATE_DATA)
         if (p->state == LZMA2_STATE_DATA)
         {
         {
-          int mode = LZMA2_GET_LZMA_MODE(p);
-          Bool initDic = (mode == 3);
-          Bool initState = (mode > 0);
-          if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
-            return SZ_ERROR_DATA;
-          
+          BoolInt initDic = (p->control >= 0xE0);
+          BoolInt initState = (p->control >= 0xA0);
           LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
           LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
-          p->needInitDic = False;
-          p->needInitState = False;
           p->state = LZMA2_STATE_DATA_CONT;
           p->state = LZMA2_STATE_DATA_CONT;
         }
         }
-        if (srcSizeCur > p->packSize)
-          srcSizeCur = (SizeT)p->packSize;
-          
-        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
+  
+        if (inCur > p->packSize)
+          inCur = (SizeT)p->packSize;
         
         
-        src += srcSizeCur;
-        *srcLen += srcSizeCur;
-        p->packSize -= (UInt32)srcSizeCur;
+        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
 
 
-        outSizeProcessed = p->decoder.dicPos - dicPos;
-        p->unpackSize -= (UInt32)outSizeProcessed;
+        src += inCur;
+        *srcLen += inCur;
+        p->packSize -= (UInt32)inCur;
+        outCur = p->decoder.dicPos - dicPos;
+        p->unpackSize -= (UInt32)outCur;
 
 
-        RINOK(res);
+        if (res != 0)
+          break;
+        
         if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
         if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
-          return res;
+        {
+          if (p->packSize == 0)
+            break;
+          return SZ_OK;
+        }
 
 
-        if (srcSizeCur == 0 && outSizeProcessed == 0)
+        if (inCur == 0 && outCur == 0)
         {
         {
-          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
-              p->unpackSize != 0 || p->packSize != 0)
-            return SZ_ERROR_DATA;
+          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+              || p->unpackSize != 0
+              || p->packSize != 0)
+            break;
           p->state = LZMA2_STATE_CONTROL;
           p->state = LZMA2_STATE_CONTROL;
         }
         }
-        if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
-          *status = LZMA_STATUS_NOT_FINISHED;
+        
+        *status = LZMA_STATUS_NOT_SPECIFIED;
       }
       }
     }
     }
   }
   }
-  *status = LZMA_STATUS_FINISHED_WITH_MARK;
-  return SZ_OK;
+  
+  *status = LZMA_STATUS_NOT_SPECIFIED;
+  p->state = LZMA2_STATE_ERROR;
+  return SZ_ERROR_DATA;
+}
+
+
+
+
+ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
+    SizeT outSize,
+    const Byte *src, SizeT *srcLen,
+    int checkFinishBlock)
+{
+  SizeT inSize = *srcLen;
+  *srcLen = 0;
+
+  while (p->state != LZMA2_STATE_ERROR)
+  {
+    if (p->state == LZMA2_STATE_FINISHED)
+      return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
+
+    if (outSize == 0 && !checkFinishBlock)
+      return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
+    
+    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
+    {
+      if (*srcLen == inSize)
+        return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
+      (*srcLen)++;
+
+      p->state = Lzma2Dec_UpdateState(p, *src++);
+
+      if (p->state == LZMA2_STATE_UNPACK0)
+      {
+        // if (p->decoder.dicPos != 0)
+        if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
+          return LZMA2_PARSE_STATUS_NEW_BLOCK;
+        // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
+      }
+
+      // The following code can be commented.
+      // It's not big problem, if we read additional input bytes.
+      // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
+
+      if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
+      {
+        // checkFinishBlock is true. So we expect that block must be finished,
+        // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
+        // break;
+        return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
+      }
+
+      if (p->state == LZMA2_STATE_DATA)
+        return LZMA2_PARSE_STATUS_NEW_CHUNK;
+
+      continue;
+    }
+
+    if (outSize == 0)
+      return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
+
+    {
+      SizeT inCur = inSize - *srcLen;
+
+      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
+      {
+        if (inCur == 0)
+          return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
+        if (inCur > p->unpackSize)
+          inCur = p->unpackSize;
+        if (inCur > outSize)
+          inCur = outSize;
+        p->decoder.dicPos += inCur;
+        src += inCur;
+        *srcLen += inCur;
+        outSize -= inCur;
+        p->unpackSize -= (UInt32)inCur;
+        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
+      }
+      else
+      {
+        p->isExtraMode = True;
+
+        if (inCur == 0)
+        {
+          if (p->packSize != 0)
+            return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
+        }
+        else if (p->state == LZMA2_STATE_DATA)
+        {
+          p->state = LZMA2_STATE_DATA_CONT;
+          if (*src != 0)
+          {
+            // first byte of lzma chunk must be Zero
+            *srcLen += 1;
+            p->packSize--;
+            break;
+          }
+        }
+  
+        if (inCur > p->packSize)
+          inCur = (SizeT)p->packSize;
+
+        src += inCur;
+        *srcLen += inCur;
+        p->packSize -= (UInt32)inCur;
+
+        if (p->packSize == 0)
+        {
+          SizeT rem = outSize;
+          if (rem > p->unpackSize)
+            rem = p->unpackSize;
+          p->decoder.dicPos += rem;
+          p->unpackSize -= (UInt32)rem;
+          outSize -= rem;
+          if (p->unpackSize == 0)
+            p->state = LZMA2_STATE_CONTROL;
+        }
+      }
+    }
+  }
+  
+  p->state = LZMA2_STATE_ERROR;
+  return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
 }
 }
 
 
+
+
+
 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
 {
 {
   SizeT outSize = *destLen, inSize = *srcLen;
   SizeT outSize = *destLen, inSize = *srcLen;
   *srcLen = *destLen = 0;
   *srcLen = *destLen = 0;
+  
   for (;;)
   for (;;)
   {
   {
-    SizeT srcSizeCur = inSize, outSizeCur, dicPos;
+    SizeT inCur = inSize, outCur, dicPos;
     ELzmaFinishMode curFinishMode;
     ELzmaFinishMode curFinishMode;
     SRes res;
     SRes res;
+    
     if (p->decoder.dicPos == p->decoder.dicBufSize)
     if (p->decoder.dicPos == p->decoder.dicBufSize)
       p->decoder.dicPos = 0;
       p->decoder.dicPos = 0;
     dicPos = p->decoder.dicPos;
     dicPos = p->decoder.dicPos;
-    if (outSize > p->decoder.dicBufSize - dicPos)
-    {
-      outSizeCur = p->decoder.dicBufSize;
-      curFinishMode = LZMA_FINISH_ANY;
-    }
-    else
+    curFinishMode = LZMA_FINISH_ANY;
+    outCur = p->decoder.dicBufSize - dicPos;
+    
+    if (outCur >= outSize)
     {
     {
-      outSizeCur = dicPos + outSize;
+      outCur = outSize;
       curFinishMode = finishMode;
       curFinishMode = finishMode;
     }
     }
 
 
-    res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
-    src += srcSizeCur;
-    inSize -= srcSizeCur;
-    *srcLen += srcSizeCur;
-    outSizeCur = p->decoder.dicPos - dicPos;
-    memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
-    dest += outSizeCur;
-    outSize -= outSizeCur;
-    *destLen += outSizeCur;
+    res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
+    
+    src += inCur;
+    inSize -= inCur;
+    *srcLen += inCur;
+    outCur = p->decoder.dicPos - dicPos;
+    memcpy(dest, p->decoder.dic + dicPos, outCur);
+    dest += outCur;
+    outSize -= outCur;
+    *destLen += outCur;
     if (res != 0)
     if (res != 0)
       return res;
       return res;
-    if (outSizeCur == 0 || outSize == 0)
+    if (outCur == 0 || outSize == 0)
       return SZ_OK;
       return SZ_OK;
   }
   }
 }
 }
 
 
+
 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
-    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
+    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
 {
 {
-  CLzma2Dec decoder;
+  CLzma2Dec p;
   SRes res;
   SRes res;
   SizeT outSize = *destLen, inSize = *srcLen;
   SizeT outSize = *destLen, inSize = *srcLen;
-  Byte props[LZMA_PROPS_SIZE];
-
-  Lzma2Dec_Construct(&decoder);
-
   *destLen = *srcLen = 0;
   *destLen = *srcLen = 0;
   *status = LZMA_STATUS_NOT_SPECIFIED;
   *status = LZMA_STATUS_NOT_SPECIFIED;
-  decoder.decoder.dic = dest;
-  decoder.decoder.dicBufSize = outSize;
-
-  RINOK(Lzma2Dec_GetOldProps(prop, props));
-  RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
-  
+  Lzma2Dec_CONSTRUCT(&p)
+  RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc))
+  p.decoder.dic = dest;
+  p.decoder.dicBufSize = outSize;
+  Lzma2Dec_Init(&p);
   *srcLen = inSize;
   *srcLen = inSize;
-  res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
-  *destLen = decoder.decoder.dicPos;
+  res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
+  *destLen = p.decoder.dicPos;
   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
     res = SZ_ERROR_INPUT_EOF;
     res = SZ_ERROR_INPUT_EOF;
-
-  LzmaDec_FreeProbs(&decoder.decoder, alloc);
+  Lzma2Dec_FreeProbs(&p, alloc);
   return res;
   return res;
 }
 }
+
+#undef PRF

+ 59 - 22
Components/Lzma2/Lzma2Dec.h

@@ -1,38 +1,36 @@
 /* Lzma2Dec.h -- LZMA2 Decoder
 /* Lzma2Dec.h -- LZMA2 Decoder
-2009-05-03 : Igor Pavlov : Public domain */
+2023-03-03 : Igor Pavlov : Public domain */
 
 
-#ifndef __LZMA2_DEC_H
-#define __LZMA2_DEC_H
+#ifndef ZIP7_INC_LZMA2_DEC_H
+#define ZIP7_INC_LZMA2_DEC_H
 
 
 #include "LzmaDec.h"
 #include "LzmaDec.h"
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+EXTERN_C_BEGIN
 
 
 /* ---------- State Interface ---------- */
 /* ---------- State Interface ---------- */
 
 
 typedef struct
 typedef struct
 {
 {
-  CLzmaDec decoder;
+  unsigned state;
+  Byte control;
+  Byte needInitLevel;
+  Byte isExtraMode;
+  Byte _pad_;
   UInt32 packSize;
   UInt32 packSize;
   UInt32 unpackSize;
   UInt32 unpackSize;
-  int state;
-  Byte control;
-  Bool needInitDic;
-  Bool needInitState;
-  Bool needInitProp;
+  CLzmaDec decoder;
 } CLzma2Dec;
 } CLzma2Dec;
 
 
-#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
-#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
-#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
+#define Lzma2Dec_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, ISzAlloc *alloc);
-SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
+SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
+SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
 void Lzma2Dec_Init(CLzma2Dec *p);
 void Lzma2Dec_Init(CLzma2Dec *p);
 
 
-
 /*
 /*
 finishMode:
 finishMode:
   It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
   It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
@@ -55,6 +53,47 @@ SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
 
 
 
 
+/* ---------- LZMA2 block and chunk parsing ---------- */
+
+/*
+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 ---------- */
 /* ---------- One Call Interface ---------- */
 
 
 /*
 /*
@@ -75,10 +114,8 @@ Returns:
 */
 */
 
 
 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
-    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
+    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);
 
 
-#ifdef __cplusplus
-}
-#endif
+EXTERN_C_END
 
 
 #endif
 #endif

+ 566 - 245
Components/Lzma2/Lzma2Enc.c

@@ -1,17 +1,18 @@
 /* Lzma2Enc.c -- LZMA2 Encoder
 /* Lzma2Enc.c -- LZMA2 Encoder
-2009-11-24 : Igor Pavlov : Public domain */
+2023-04-13 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
 
 
-/* #include <stdio.h> */
 #include <string.h>
 #include <string.h>
 
 
-/* #define _7ZIP_ST */
+/* #define Z7_ST */
 
 
 #include "Lzma2Enc.h"
 #include "Lzma2Enc.h"
 
 
-#ifndef _7ZIP_ST
+#ifndef Z7_ST
 #include "MtCoder.h"
 #include "MtCoder.h"
 #else
 #else
-#define NUM_MT_CODER_THREADS_MAX 1
+#define MTCODER_THREADS_MAX 1
 #endif
 #endif
 
 
 #define LZMA2_CONTROL_LZMA (1 << 7)
 #define LZMA2_CONTROL_LZMA (1 << 7)
@@ -33,50 +34,106 @@
 
 
 #define PRF(x) /* x */
 #define PRF(x) /* x */
 
 
+
+/* ---------- CLimitedSeqInStream ---------- */
+
+typedef struct
+{
+  ISeqInStream vt;
+  ISeqInStreamPtr realStream;
+  UInt64 limit;
+  UInt64 processed;
+  int finished;
+} CLimitedSeqInStream;
+
+static void LimitedSeqInStream_Init(CLimitedSeqInStream *p)
+{
+  p->limit = (UInt64)(Int64)-1;
+  p->processed = 0;
+  p->finished = 0;
+}
+
+static SRes LimitedSeqInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size)
+{
+  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLimitedSeqInStream)
+  size_t size2 = *size;
+  SRes res = SZ_OK;
+  
+  if (p->limit != (UInt64)(Int64)-1)
+  {
+    const UInt64 rem = p->limit - p->processed;
+    if (size2 > rem)
+      size2 = (size_t)rem;
+  }
+  if (size2 != 0)
+  {
+    res = ISeqInStream_Read(p->realStream, data, &size2);
+    p->finished = (size2 == 0 ? 1 : 0);
+    p->processed += size2;
+  }
+  *size = size2;
+  return res;
+}
+
+
 /* ---------- CLzma2EncInt ---------- */
 /* ---------- CLzma2EncInt ---------- */
 
 
 typedef struct
 typedef struct
 {
 {
   CLzmaEncHandle enc;
   CLzmaEncHandle enc;
+  Byte propsAreSet;
+  Byte propsByte;
+  Byte needInitState;
+  Byte needInitProp;
   UInt64 srcPos;
   UInt64 srcPos;
-  Byte props;
-  Bool needInitState;
-  Bool needInitProp;
 } CLzma2EncInt;
 } CLzma2EncInt;
 
 
-static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)
+
+static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props)
+{
+  if (!p->propsAreSet)
+  {
+    SizeT propsSize = LZMA_PROPS_SIZE;
+    Byte propsEncoded[LZMA_PROPS_SIZE];
+    RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps))
+    RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize))
+    p->propsByte = propsEncoded[0];
+    p->propsAreSet = True;
+  }
+  return SZ_OK;
+}
+
+static void Lzma2EncInt_InitBlock(CLzma2EncInt *p)
 {
 {
-  Byte propsEncoded[LZMA_PROPS_SIZE];
-  SizeT propsSize = LZMA_PROPS_SIZE;
-  RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
-  RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
   p->srcPos = 0;
   p->srcPos = 0;
-  p->props = propsEncoded[0];
   p->needInitState = True;
   p->needInitState = True;
   p->needInitProp = True;
   p->needInitProp = True;
-  return SZ_OK;
 }
 }
 
 
-SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
-    ISzAlloc *alloc, ISzAlloc *allocBig);
-SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
-    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);
-SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
+
+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize,
+    ISzAllocPtr alloc, ISzAllocPtr allocBig);
+SRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen,
+    UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit,
     Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
     Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
-const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
-void LzmaEnc_Finish(CLzmaEncHandle pp);
-void LzmaEnc_SaveState(CLzmaEncHandle pp);
-void LzmaEnc_RestoreState(CLzmaEncHandle pp);
+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p);
+void LzmaEnc_Finish(CLzmaEncHandle p);
+void LzmaEnc_SaveState(CLzmaEncHandle p);
+void LzmaEnc_RestoreState(CLzmaEncHandle p);
 
 
+/*
+UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p);
+*/
 
 
 static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
 static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
-    size_t *packSizeRes, ISeqOutStream *outStream)
+    size_t *packSizeRes, ISeqOutStreamPtr outStream)
 {
 {
   size_t packSizeLimit = *packSizeRes;
   size_t packSizeLimit = *packSizeRes;
   size_t packSize = packSizeLimit;
   size_t packSize = packSizeLimit;
   UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
   UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
   unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
   unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
-  Bool useCopyBlock;
+  BoolInt useCopyBlock;
   SRes res;
   SRes res;
 
 
   *packSizeRes = 0;
   *packSizeRes = 0;
@@ -107,9 +164,10 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
   {
   {
     size_t destPos = 0;
     size_t destPos = 0;
     PRF(printf("################# COPY           "));
     PRF(printf("################# COPY           "));
+
     while (unpackSize > 0)
     while (unpackSize > 0)
     {
     {
-      UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
+      const UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
       if (packSizeLimit - destPos < u + 3)
       if (packSizeLimit - destPos < u + 3)
         return SZ_ERROR_OUTPUT_EOF;
         return SZ_ERROR_OUTPUT_EOF;
       outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
       outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
@@ -119,10 +177,11 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
       unpackSize -= u;
       unpackSize -= u;
       destPos += u;
       destPos += u;
       p->srcPos += u;
       p->srcPos += u;
+      
       if (outStream)
       if (outStream)
       {
       {
         *packSizeRes += destPos;
         *packSizeRes += destPos;
-        if (outStream->Write(outStream, outBuf, destPos) != destPos)
+        if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
           return SZ_ERROR_WRITE;
           return SZ_ERROR_WRITE;
         destPos = 0;
         destPos = 0;
       }
       }
@@ -130,25 +189,27 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
         *packSizeRes = destPos;
         *packSizeRes = destPos;
       /* needInitState = True; */
       /* needInitState = True; */
     }
     }
+    
     LzmaEnc_RestoreState(p->enc);
     LzmaEnc_RestoreState(p->enc);
     return SZ_OK;
     return SZ_OK;
   }
   }
+
   {
   {
     size_t destPos = 0;
     size_t destPos = 0;
-    UInt32 u = unpackSize - 1;
-    UInt32 pm = (UInt32)(packSize - 1);
-    unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
+    const UInt32 u = unpackSize - 1;
+    const UInt32 pm = (UInt32)(packSize - 1);
+    const unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
 
 
     PRF(printf("               "));
     PRF(printf("               "));
 
 
-    outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | (u >> 16) & 0x1F);
+    outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
     outBuf[destPos++] = (Byte)(u >> 8);
     outBuf[destPos++] = (Byte)(u >> 8);
     outBuf[destPos++] = (Byte)u;
     outBuf[destPos++] = (Byte)u;
     outBuf[destPos++] = (Byte)(pm >> 8);
     outBuf[destPos++] = (Byte)(pm >> 8);
     outBuf[destPos++] = (Byte)pm;
     outBuf[destPos++] = (Byte)pm;
     
     
     if (p->needInitProp)
     if (p->needInitProp)
-      outBuf[destPos++] = p->props;
+      outBuf[destPos++] = p->propsByte;
     
     
     p->needInitProp = False;
     p->needInitProp = False;
     p->needInitState = False;
     p->needInitState = False;
@@ -156,268 +217,254 @@ static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
     p->srcPos += unpackSize;
     p->srcPos += unpackSize;
 
 
     if (outStream)
     if (outStream)
-      if (outStream->Write(outStream, outBuf, destPos) != destPos)
+      if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)
         return SZ_ERROR_WRITE;
         return SZ_ERROR_WRITE;
+    
     *packSizeRes = destPos;
     *packSizeRes = destPos;
     return SZ_OK;
     return SZ_OK;
   }
   }
 }
 }
 
 
+
 /* ---------- Lzma2 Props ---------- */
 /* ---------- Lzma2 Props ---------- */
 
 
 void Lzma2EncProps_Init(CLzma2EncProps *p)
 void Lzma2EncProps_Init(CLzma2EncProps *p)
 {
 {
   LzmaEncProps_Init(&p->lzmaProps);
   LzmaEncProps_Init(&p->lzmaProps);
+  p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO;
+  p->numBlockThreads_Reduced = -1;
+  p->numBlockThreads_Max = -1;
   p->numTotalThreads = -1;
   p->numTotalThreads = -1;
-  p->numBlockThreads = -1;
-  p->blockSize = 0;
 }
 }
 
 
-
-static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
+void Lzma2EncProps_Normalize(CLzma2EncProps *p)
 {
 {
-  return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
-}
+  UInt64 fileSize;
+  int t1, t1n, t2, t2r, t3;
+  {
+    CLzmaEncProps lzmaProps = p->lzmaProps;
+    LzmaEncProps_Normalize(&lzmaProps);
+    t1n = lzmaProps.numThreads;
+  }
 
 
-/* ---------- Lzma2 ---------- */
+  t1 = p->lzmaProps.numThreads;
+  t2 = p->numBlockThreads_Max;
+  t3 = p->numTotalThreads;
 
 
-extern struct _CLzma2Enc;
+  if (t2 > MTCODER_THREADS_MAX)
+    t2 = MTCODER_THREADS_MAX;
 
 
-typedef struct _CLzma2Enc
-{
-  Byte propEncoded;
-  CLzma2EncProps props;
-  
-  Byte *outBuf;
+  if (t3 <= 0)
+  {
+    if (t2 <= 0)
+      t2 = 1;
+    t3 = t1n * t2;
+  }
+  else if (t2 <= 0)
+  {
+    t2 = t3 / t1n;
+    if (t2 == 0)
+    {
+      t1 = 1;
+      t2 = t3;
+    }
+    if (t2 > MTCODER_THREADS_MAX)
+      t2 = MTCODER_THREADS_MAX;
+  }
+  else if (t1 <= 0)
+  {
+    t1 = t3 / t2;
+    if (t1 == 0)
+      t1 = 1;
+  }
+  else
+    t3 = t1n * t2;
 
 
-  ISzAlloc *alloc;
-  ISzAlloc *allocBig;
+  p->lzmaProps.numThreads = t1;
 
 
-  CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];
+  t2r = t2;
 
 
-  #ifndef _7ZIP_ST
-  CMtCoder mtCoder;
-  #endif
+  fileSize = p->lzmaProps.reduceSize;
 
 
-} CLzma2Enc;
+  if (   p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
+      && p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO
+      && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))
+    p->lzmaProps.reduceSize = p->blockSize;
 
 
+  LzmaEncProps_Normalize(&p->lzmaProps);
 
 
-/* ---------- Lzma2EncThread ---------- */
+  p->lzmaProps.reduceSize = fileSize;
 
 
-static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
-  ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
-{
-  UInt64 packTotal = 0;
-  SRes res = SZ_OK;
+  t1 = p->lzmaProps.numThreads;
 
 
-  if (mainEncoder->outBuf == 0)
+  if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID)
   {
   {
-    mainEncoder->outBuf = IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
-    if (mainEncoder->outBuf == 0)
-      return SZ_ERROR_MEM;
+    t2r = t2 = 1;
+    t3 = t1;
   }
   }
-  RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
-  RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
-      mainEncoder->alloc, mainEncoder->allocBig));
-  for (;;)
+  else if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO && t2 <= 1)
   {
   {
-    size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
-    res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);
-    if (res != SZ_OK)
-      break;
-    packTotal += packSize;
-    res = Progress(progress, p->srcPos, packTotal);
-    if (res != SZ_OK)
-      break;
-    if (packSize == 0)
-      break;
+    /* if there is no block multi-threading, we use SOLID block */
+    p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID;
   }
   }
-  LzmaEnc_Finish(p->enc);
-  if (res == SZ_OK)
+  else
   {
   {
-    Byte b = 0;
-    if (outStream->Write(outStream, &b, 1) != 1)
-      return SZ_ERROR_WRITE;
+    if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO)
+    {
+      const UInt32 kMinSize = (UInt32)1 << 20;
+      const UInt32 kMaxSize = (UInt32)1 << 28;
+      const UInt32 dictSize = p->lzmaProps.dictSize;
+      UInt64 blockSize = (UInt64)dictSize << 2;
+      if (blockSize < kMinSize) blockSize = kMinSize;
+      if (blockSize > kMaxSize) blockSize = kMaxSize;
+      if (blockSize < dictSize) blockSize = dictSize;
+      blockSize += (kMinSize - 1);
+      blockSize &= ~(UInt64)(kMinSize - 1);
+      p->blockSize = blockSize;
+    }
+    
+    if (t2 > 1 && fileSize != (UInt64)(Int64)-1)
+    {
+      UInt64 numBlocks = fileSize / p->blockSize;
+      if (numBlocks * p->blockSize != fileSize)
+        numBlocks++;
+      if (numBlocks < (unsigned)t2)
+      {
+        t2r = (int)numBlocks;
+        if (t2r == 0)
+          t2r = 1;
+        t3 = t1 * t2r;
+      }
+    }
   }
   }
-  return res;
+  
+  p->numBlockThreads_Max = t2;
+  p->numBlockThreads_Reduced = t2r;
+  p->numTotalThreads = t3;
 }
 }
 
 
-#ifndef _7ZIP_ST
 
 
-typedef struct
+static SRes Progress(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize)
 {
 {
-  IMtCoderCallback funcTable;
-  CLzma2Enc *lzma2Enc;
-} CMtCallbackImp;
+  return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
+}
+
 
 
-static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,
-      const Byte *src, size_t srcSize, int finished)
+/* ---------- Lzma2 ---------- */
+
+struct CLzma2Enc
 {
 {
-  CMtCallbackImp *imp = (CMtCallbackImp *)pp;
-  CLzma2Enc *mainEncoder = imp->lzma2Enc;
-  CLzma2EncInt *p = &mainEncoder->coders[index];
+  Byte propEncoded;
+  CLzma2EncProps props;
+  UInt64 expectedDataSize;
+  
+  Byte *tempBufLzma;
 
 
-  SRes res = SZ_OK;
-  {
-    size_t destLim = *destSize;
-    *destSize = 0;
+  ISzAllocPtr alloc;
+  ISzAllocPtr allocBig;
 
 
-    if (srcSize != 0)
-    {
-      RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
-     
-      RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,
-          mainEncoder->alloc, mainEncoder->allocBig));
-     
-      while (p->srcPos < srcSize)
-      {
-        size_t packSize = destLim - *destSize;
-        res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);
-        if (res != SZ_OK)
-          break;
-        *destSize += packSize;
+  CLzma2EncInt coders[MTCODER_THREADS_MAX];
 
 
-        if (packSize == 0)
-        {
-          res = SZ_ERROR_FAIL;
-          break;
-        }
+  #ifndef Z7_ST
+  
+  ISeqOutStreamPtr outStream;
+  Byte *outBuf;
+  size_t outBuf_Rem;   /* remainder in outBuf */
 
 
-        if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)
-        {
-          res = SZ_ERROR_PROGRESS;
-          break;
-        }
-      }
-      LzmaEnc_Finish(p->enc);
-      if (res != SZ_OK)
-        return res;
-    }
-    if (finished)
-    {
-      if (*destSize == destLim)
-        return SZ_ERROR_OUTPUT_EOF;
-      dest[(*destSize)++] = 0;
-    }
-  }
-  return res;
-}
+  size_t outBufSize;   /* size of allocated outBufs[i] */
+  size_t outBufsDataSizes[MTCODER_BLOCKS_MAX];
+  BoolInt mtCoder_WasConstructed;
+  CMtCoder mtCoder;
+  Byte *outBufs[MTCODER_BLOCKS_MAX];
+
+  #endif
+};
 
 
-#endif
 
 
-/* ---------- Lzma2Enc ---------- */
 
 
-CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
+CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)
 {
 {
-  CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
-  if (p == 0)
+  CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));
+  if (!p)
     return NULL;
     return NULL;
   Lzma2EncProps_Init(&p->props);
   Lzma2EncProps_Init(&p->props);
   Lzma2EncProps_Normalize(&p->props);
   Lzma2EncProps_Normalize(&p->props);
-  p->outBuf = 0;
+  p->expectedDataSize = (UInt64)(Int64)-1;
+  p->tempBufLzma = NULL;
   p->alloc = alloc;
   p->alloc = alloc;
   p->allocBig = allocBig;
   p->allocBig = allocBig;
   {
   {
     unsigned i;
     unsigned i;
-    for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
-      p->coders[i].enc = 0;
+    for (i = 0; i < MTCODER_THREADS_MAX; i++)
+      p->coders[i].enc = NULL;
+  }
+  
+  #ifndef Z7_ST
+  p->mtCoder_WasConstructed = False;
+  {
+    unsigned i;
+    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
+      p->outBufs[i] = NULL;
+    p->outBufSize = 0;
   }
   }
-  #ifndef _7ZIP_ST
-  MtCoder_Construct(&p->mtCoder);
   #endif
   #endif
 
 
-  return p;
+  return (CLzma2EncHandle)p;
 }
 }
 
 
-void Lzma2Enc_Destroy(CLzma2EncHandle pp)
+
+#ifndef Z7_ST
+
+static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)
 {
 {
-  CLzma2Enc *p = (CLzma2Enc *)pp;
   unsigned i;
   unsigned i;
-  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
-  {
-    CLzma2EncInt *t = &p->coders[i];
-    if (t->enc)
+  for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
+    if (p->outBufs[i])
     {
     {
-      LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
-      t->enc = 0;
+      ISzAlloc_Free(p->alloc, p->outBufs[i]);
+      p->outBufs[i] = NULL;
     }
     }
-  }
-
-  #ifndef _7ZIP_ST
-  MtCoder_Destruct(&p->mtCoder);
-  #endif
-
-  IAlloc_Free(p->alloc, p->outBuf);
-  IAlloc_Free(p->alloc, pp);
+  p->outBufSize = 0;
 }
 }
 
 
-void Lzma2EncProps_Normalize(CLzma2EncProps *p)
-{
-  int t1, t1n, t2, t3;
-  CLzmaEncProps lzmaProps = p->lzmaProps;
-  
-  LzmaEncProps_Normalize(&lzmaProps);
-
-  t1 = p->lzmaProps.numThreads;
-  t1n = lzmaProps.numThreads;
-  t2 = p->numBlockThreads;
-  t3 = p->numTotalThreads;
+#endif
 
 
-  #ifndef _7ZIP_ST
-  if (t2 > NUM_MT_CODER_THREADS_MAX)
-    t2 = NUM_MT_CODER_THREADS_MAX;
-  #else
-  t2 = 1;
-  #endif
+// #define GET_CLzma2Enc_p  CLzma2Enc *p = (CLzma2Enc *)(void *)p;
 
 
-  if (t3 <= 0)
-  {
-    if (t2 <= 0)
-      t2 = 1;
-    t3 = t1n * t2;
-  }
-  else
+void Lzma2Enc_Destroy(CLzma2EncHandle p)
+{
+  // GET_CLzma2Enc_p
+  unsigned i;
+  for (i = 0; i < MTCODER_THREADS_MAX; i++)
   {
   {
-    if (t2 <= 0)
-    {
-      t2 = t3 / t1n;
-      if (t2 == 0)
-      {
-        t1 = 1;
-        t2 = t3;
-      }
-    }
-    else if (t1 <= 0)
+    CLzma2EncInt *t = &p->coders[i];
+    if (t->enc)
     {
     {
-      t1 = t3 / t2;
-      if (t1 == 0)
-        t1 = 1;
+      LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
+      t->enc = NULL;
     }
     }
-    else
-      t3 = t1n * t2;
   }
   }
 
 
-  p->lzmaProps.numThreads = t1;
-  p->numBlockThreads = t2;
-  p->numTotalThreads = t3;
-  LzmaEncProps_Normalize(&p->lzmaProps);
 
 
-  if (p->blockSize == 0)
+  #ifndef Z7_ST
+  if (p->mtCoder_WasConstructed)
   {
   {
-    UInt64 blockSize = (UInt64)lzmaProps.dictSize << 2;
-    const UInt32 kMinSize = (UInt32)1 << 20;
-    const UInt32 kMaxSize = (UInt32)1 << 28;
-    if (blockSize < kMinSize) blockSize = kMinSize;
-    if (blockSize > kMaxSize) blockSize = kMaxSize;
-    if (blockSize < lzmaProps.dictSize)
-      blockSize = lzmaProps.dictSize;
-    p->blockSize = (size_t)blockSize;
+    MtCoder_Destruct(&p->mtCoder);
+    p->mtCoder_WasConstructed = False;
   }
   }
+  Lzma2Enc_FreeOutBufs(p);
+  #endif
+
+  ISzAlloc_Free(p->alloc, p->tempBufLzma);
+  p->tempBufLzma = NULL;
+
+  ISzAlloc_Free(p->alloc, p);
 }
 }
 
 
-SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
+
+SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props)
 {
 {
-  CLzma2Enc *p = (CLzma2Enc *)pp;
+  // GET_CLzma2Enc_p
   CLzmaEncProps lzmaProps = props->lzmaProps;
   CLzmaEncProps lzmaProps = props->lzmaProps;
   LzmaEncProps_Normalize(&lzmaProps);
   LzmaEncProps_Normalize(&lzmaProps);
   if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
   if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
@@ -427,9 +474,17 @@ SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
   return SZ_OK;
   return SZ_OK;
 }
 }
 
 
-Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
+
+void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize)
 {
 {
-  CLzma2Enc *p = (CLzma2Enc *)pp;
+  // GET_CLzma2Enc_p
+  p->expectedDataSize = expectedDataSiize;
+}
+
+
+Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p)
+{
+  // GET_CLzma2Enc_p
   unsigned i;
   unsigned i;
   UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
   UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
   for (i = 0; i < 40; i++)
   for (i = 0; i < 40; i++)
@@ -438,47 +493,313 @@ Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
   return (Byte)i;
   return (Byte)i;
 }
 }
 
 
-SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
-    ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
+
+static SRes Lzma2Enc_EncodeMt1(
+    CLzma2Enc *me,
+    CLzma2EncInt *p,
+    ISeqOutStreamPtr outStream,
+    Byte *outBuf, size_t *outBufSize,
+    ISeqInStreamPtr inStream,
+    const Byte *inData, size_t inDataSize,
+    int finished,
+    ICompressProgressPtr progress)
 {
 {
-  CLzma2Enc *p = (CLzma2Enc *)pp;
-  int i;
+  UInt64 unpackTotal = 0;
+  UInt64 packTotal = 0;
+  size_t outLim = 0;
+  CLimitedSeqInStream limitedInStream;
 
 
-  for (i = 0; i < p->props.numBlockThreads; i++)
+  if (outBuf)
   {
   {
-    CLzma2EncInt *t = &p->coders[i];
-    if (t->enc == NULL)
+    outLim = *outBufSize;
+    *outBufSize = 0;
+  }
+
+  if (!p->enc)
+  {
+    p->propsAreSet = False;
+    p->enc = LzmaEnc_Create(me->alloc);
+    if (!p->enc)
+      return SZ_ERROR_MEM;
+  }
+
+  limitedInStream.realStream = inStream;
+  if (inStream)
+  {
+    limitedInStream.vt.Read = LimitedSeqInStream_Read;
+  }
+  
+  if (!outBuf)
+  {
+    // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma
+    if (!me->tempBufLzma)
     {
     {
-      t->enc = LzmaEnc_Create(p->alloc);
-      if (t->enc == NULL)
+      me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
+      if (!me->tempBufLzma)
         return SZ_ERROR_MEM;
         return SZ_ERROR_MEM;
     }
     }
   }
   }
 
 
-  #ifndef _7ZIP_ST
-  if (p->props.numBlockThreads <= 1)
-  #endif
-    return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
-
-  #ifndef _7ZIP_ST
+  RINOK(Lzma2EncInt_InitStream(p, &me->props))
 
 
+  for (;;)
   {
   {
-    CMtCallbackImp mtCallback;
+    SRes res = SZ_OK;
+    SizeT inSizeCur = 0;
+
+    Lzma2EncInt_InitBlock(p);
+    
+    LimitedSeqInStream_Init(&limitedInStream);
+    limitedInStream.limit = me->props.blockSize;
+
+    if (inStream)
+    {
+      UInt64 expected = (UInt64)(Int64)-1;
+      // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize
+      if (me->expectedDataSize != (UInt64)(Int64)-1
+          && me->expectedDataSize >= unpackTotal)
+        expected = me->expectedDataSize - unpackTotal;
+      if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
+          && expected > me->props.blockSize)
+        expected = (size_t)me->props.blockSize;
+
+      LzmaEnc_SetDataSize(p->enc, expected);
+
+      RINOK(LzmaEnc_PrepareForLzma2(p->enc,
+          &limitedInStream.vt,
+          LZMA2_KEEP_WINDOW_SIZE,
+          me->alloc,
+          me->allocBig))
+    }
+    else
+    {
+      inSizeCur = (SizeT)(inDataSize - (size_t)unpackTotal);
+      if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID
+          && inSizeCur > me->props.blockSize)
+        inSizeCur = (SizeT)(size_t)me->props.blockSize;
+    
+      // LzmaEnc_SetDataSize(p->enc, inSizeCur);
+      
+      RINOK(LzmaEnc_MemPrepare(p->enc,
+          inData + (size_t)unpackTotal, inSizeCur,
+          LZMA2_KEEP_WINDOW_SIZE,
+          me->alloc,
+          me->allocBig))
+    }
+
+    for (;;)
+    {
+      size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
+      if (outBuf)
+        packSize = outLim - (size_t)packTotal;
+      
+      res = Lzma2EncInt_EncodeSubblock(p,
+          outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,
+          outBuf ? NULL : outStream);
+      
+      if (res != SZ_OK)
+        break;
+
+      packTotal += packSize;
+      if (outBuf)
+        *outBufSize = (size_t)packTotal;
+      
+      res = Progress(progress, unpackTotal + p->srcPos, packTotal);
+      if (res != SZ_OK)
+        break;
+
+      /*
+      if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)
+        break;
+      */
 
 
-    mtCallback.funcTable.Code = MtCallbackImp_Code;
-    mtCallback.lzma2Enc = p;
+      if (packSize == 0)
+        break;
+    }
+    
+    LzmaEnc_Finish(p->enc);
+    
+    unpackTotal += p->srcPos;
+    
+    RINOK(res)
+
+    if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))
+      return SZ_ERROR_FAIL;
     
     
+    if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))
+    {
+      if (finished)
+      {
+        if (outBuf)
+        {
+          const size_t destPos = *outBufSize;
+          if (destPos >= outLim)
+            return SZ_ERROR_OUTPUT_EOF;
+          outBuf[destPos] = LZMA2_CONTROL_EOF; // 0
+          *outBufSize = destPos + 1;
+        }
+        else
+        {
+          const Byte b = LZMA2_CONTROL_EOF; // 0;
+          if (ISeqOutStream_Write(outStream, &b, 1) != 1)
+            return SZ_ERROR_WRITE;
+        }
+      }
+      return SZ_OK;
+    }
+  }
+}
+
+
+
+#ifndef Z7_ST
+
+static SRes Lzma2Enc_MtCallback_Code(void *p, unsigned coderIndex, unsigned outBufIndex,
+    const Byte *src, size_t srcSize, int finished)
+{
+  CLzma2Enc *me = (CLzma2Enc *)p;
+  size_t destSize = me->outBufSize;
+  SRes res;
+  CMtProgressThunk progressThunk;
+
+  Byte *dest = me->outBufs[outBufIndex];
+
+  me->outBufsDataSizes[outBufIndex] = 0;
+
+  if (!dest)
+  {
+    dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
+    if (!dest)
+      return SZ_ERROR_MEM;
+    me->outBufs[outBufIndex] = dest;
+  }
+
+  MtProgressThunk_CreateVTable(&progressThunk);
+  progressThunk.mtProgress = &me->mtCoder.mtProgress;
+  progressThunk.inSize = 0;
+  progressThunk.outSize = 0;
+
+  res = Lzma2Enc_EncodeMt1(me,
+      &me->coders[coderIndex],
+      NULL, dest, &destSize,
+      NULL, src, srcSize,
+      finished,
+      &progressThunk.vt);
+
+  me->outBufsDataSizes[outBufIndex] = destSize;
+
+  return res;
+}
+
+
+static SRes Lzma2Enc_MtCallback_Write(void *p, unsigned outBufIndex)
+{
+  CLzma2Enc *me = (CLzma2Enc *)p;
+  size_t size = me->outBufsDataSizes[outBufIndex];
+  const Byte *data = me->outBufs[outBufIndex];
+  
+  if (me->outStream)
+    return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE;
+  
+  if (size > me->outBuf_Rem)
+    return SZ_ERROR_OUTPUT_EOF;
+  memcpy(me->outBuf, data, size);
+  me->outBuf_Rem -= size;
+  me->outBuf += size;
+  return SZ_OK;
+}
+
+#endif
+
+
+
+SRes Lzma2Enc_Encode2(CLzma2EncHandle p,
+    ISeqOutStreamPtr outStream,
+    Byte *outBuf, size_t *outBufSize,
+    ISeqInStreamPtr inStream,
+    const Byte *inData, size_t inDataSize,
+    ICompressProgressPtr progress)
+{
+  // GET_CLzma2Enc_p
+
+  if (inStream && inData)
+    return SZ_ERROR_PARAM;
+
+  if (outStream && outBuf)
+    return SZ_ERROR_PARAM;
+
+  {
+    unsigned i;
+    for (i = 0; i < MTCODER_THREADS_MAX; i++)
+      p->coders[i].propsAreSet = False;
+  }
+
+  #ifndef Z7_ST
+  
+  if (p->props.numBlockThreads_Reduced > 1)
+  {
+    IMtCoderCallback2 vt;
+
+    if (!p->mtCoder_WasConstructed)
+    {
+      p->mtCoder_WasConstructed = True;
+      MtCoder_Construct(&p->mtCoder);
+    }
+
+    vt.Code = Lzma2Enc_MtCallback_Code;
+    vt.Write = Lzma2Enc_MtCallback_Write;
+
+    p->outStream = outStream;
+    p->outBuf = NULL;
+    p->outBuf_Rem = 0;
+    if (!outStream)
+    {
+      p->outBuf = outBuf;
+      p->outBuf_Rem = *outBufSize;
+      *outBufSize = 0;
+    }
+
+    p->mtCoder.allocBig = p->allocBig;
     p->mtCoder.progress = progress;
     p->mtCoder.progress = progress;
     p->mtCoder.inStream = inStream;
     p->mtCoder.inStream = inStream;
-    p->mtCoder.outStream = outStream;
-    p->mtCoder.alloc = p->alloc;
-    p->mtCoder.mtCallback = &mtCallback.funcTable;
+    p->mtCoder.inData = inData;
+    p->mtCoder.inDataSize = inDataSize;
+    p->mtCoder.mtCallback = &vt;
+    p->mtCoder.mtCallbackObject = p;
+
+    p->mtCoder.blockSize = (size_t)p->props.blockSize;
+    if (p->mtCoder.blockSize != p->props.blockSize)
+      return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */
 
 
-    p->mtCoder.blockSize = p->props.blockSize;
-    p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
-    p->mtCoder.numThreads = p->props.numBlockThreads;
+    {
+      const size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16;
+      if (destBlockSize < p->mtCoder.blockSize)
+        return SZ_ERROR_PARAM;
+      if (p->outBufSize != destBlockSize)
+        Lzma2Enc_FreeOutBufs(p);
+      p->outBufSize = destBlockSize;
+    }
+
+    p->mtCoder.numThreadsMax = (unsigned)p->props.numBlockThreads_Max;
+    p->mtCoder.expectedDataSize = p->expectedDataSize;
     
     
-    return MtCoder_Code(&p->mtCoder);
+    {
+      const SRes res = MtCoder_Code(&p->mtCoder);
+      if (!outStream)
+        *outBufSize = (size_t)(p->outBuf - outBuf);
+      return res;
+    }
   }
   }
+
   #endif
   #endif
+
+
+  return Lzma2Enc_EncodeMt1(p,
+      &p->coders[0],
+      outStream, outBuf, outBufSize,
+      inStream, inData, inDataSize,
+      True, /* finished */
+      progress);
 }
 }
+
+#undef PRF

+ 27 - 36
Components/Lzma2/Lzma2Enc.h

@@ -1,20 +1,22 @@
 /* Lzma2Enc.h -- LZMA2 Encoder
 /* Lzma2Enc.h -- LZMA2 Encoder
-2009-02-07 : Igor Pavlov : Public domain */
+2023-04-13 : Igor Pavlov : Public domain */
 
 
-#ifndef __LZMA2_ENC_H
-#define __LZMA2_ENC_H
+#ifndef ZIP7_INC_LZMA2_ENC_H
+#define ZIP7_INC_LZMA2_ENC_H
 
 
 #include "LzmaEnc.h"
 #include "LzmaEnc.h"
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+EXTERN_C_BEGIN
+
+#define LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO   0
+#define LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID  ((UInt64)(Int64)-1)
 
 
 typedef struct
 typedef struct
 {
 {
   CLzmaEncProps lzmaProps;
   CLzmaEncProps lzmaProps;
-  size_t blockSize;
-  int numBlockThreads;
+  UInt64 blockSize;
+  int numBlockThreads_Reduced;
+  int numBlockThreads_Max;
   int numTotalThreads;
   int numTotalThreads;
 } CLzma2EncProps;
 } CLzma2EncProps;
 
 
@@ -24,43 +26,32 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p);
 /* ---------- CLzmaEnc2Handle Interface ---------- */
 /* ---------- CLzmaEnc2Handle Interface ---------- */
 
 
 /* Lzma2Enc_* functions can return the following exit codes:
 /* Lzma2Enc_* functions can return the following exit codes:
-Returns:
+SRes:
   SZ_OK           - OK
   SZ_OK           - OK
   SZ_ERROR_MEM    - Memory allocation error
   SZ_ERROR_MEM    - Memory allocation error
   SZ_ERROR_PARAM  - Incorrect paramater in props
   SZ_ERROR_PARAM  - Incorrect paramater in props
-  SZ_ERROR_WRITE  - Write callback error
+  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_PROGRESS - some break from progress callback
-  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+  SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
 */
 */
 
 
-typedef void * CLzma2EncHandle;
+typedef struct CLzma2Enc CLzma2Enc;
+typedef CLzma2Enc * CLzma2EncHandle;
+// Z7_DECLARE_HANDLE(CLzma2EncHandle)
 
 
-CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);
+CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);
 void Lzma2Enc_Destroy(CLzma2EncHandle p);
 void Lzma2Enc_Destroy(CLzma2EncHandle p);
 SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
 SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
+void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize);
 Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
 Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
-SRes Lzma2Enc_Encode(CLzma2EncHandle p,
-    ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
-
-/* ---------- One Call Interface ---------- */
-
-/* Lzma2Encode
-Return code:
-  SZ_OK               - OK
-  SZ_ERROR_MEM        - Memory allocation error
-  SZ_ERROR_PARAM      - Incorrect paramater
-  SZ_ERROR_OUTPUT_EOF - output buffer overflow
-  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)
-*/
-
-/*
-SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
-    const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,
-    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
-*/
-
-#ifdef __cplusplus
-}
-#endif
+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
 #endif

Dosya farkı çok büyük olduğundan ihmal edildi
+ 431 - 204
Components/Lzma2/LzmaDec.c


+ 39 - 33
Components/Lzma2/LzmaDec.h

@@ -1,33 +1,36 @@
 /* LzmaDec.h -- LZMA Decoder
 /* LzmaDec.h -- LZMA Decoder
-2009-02-07 : Igor Pavlov : Public domain */
+2023-04-02 : Igor Pavlov : Public domain */
 
 
-#ifndef __LZMA_DEC_H
-#define __LZMA_DEC_H
+#ifndef ZIP7_INC_LZMA_DEC_H
+#define ZIP7_INC_LZMA_DEC_H
 
 
-#include "Types.h"
+#include "7zTypes.h"
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+EXTERN_C_BEGIN
 
 
-/* #define _LZMA_PROB32 */
-/* _LZMA_PROB32 can increase the speed on some CPUs,
+/* #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 */
    but memory usage for CLzmaDec::probs will be doubled in that case */
 
 
-#ifdef _LZMA_PROB32
-#define CLzmaProb UInt32
+typedef
+#ifdef Z7_LZMA_PROB32
+  UInt32
 #else
 #else
-#define CLzmaProb UInt16
+  UInt16
 #endif
 #endif
+  CLzmaProb;
 
 
 
 
 /* ---------- LZMA Properties ---------- */
 /* ---------- LZMA Properties ---------- */
 
 
 #define LZMA_PROPS_SIZE 5
 #define LZMA_PROPS_SIZE 5
 
 
-typedef struct _CLzmaProps
+typedef struct
 {
 {
-  unsigned lc, lp, pb;
+  Byte lc;
+  Byte lp;
+  Byte pb;
+  Byte _pad_;
   UInt32 dicSize;
   UInt32 dicSize;
 } CLzmaProps;
 } CLzmaProps;
 
 
@@ -49,32 +52,35 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
 
 
 typedef struct
 typedef struct
 {
 {
+  /* Don't change this structure. ASM code can use it. */
   CLzmaProps prop;
   CLzmaProps prop;
   CLzmaProb *probs;
   CLzmaProb *probs;
+  CLzmaProb *probs_1664;
   Byte *dic;
   Byte *dic;
-  const Byte *buf;
-  UInt32 range, code;
-  SizeT dicPos;
   SizeT dicBufSize;
   SizeT dicBufSize;
+  SizeT dicPos;
+  const Byte *buf;
+  UInt32 range;
+  UInt32 code;
   UInt32 processedPos;
   UInt32 processedPos;
   UInt32 checkDicSize;
   UInt32 checkDicSize;
-  unsigned state;
   UInt32 reps[4];
   UInt32 reps[4];
-  unsigned remainLen;
-  int needFlush;
-  int needInitState;
+  UInt32 state;
+  UInt32 remainLen;
+
   UInt32 numProbs;
   UInt32 numProbs;
   unsigned tempBufSize;
   unsigned tempBufSize;
   Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
   Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
 } CLzmaDec;
 } CLzmaDec;
 
 
-#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
+#define LzmaDec_CONSTRUCT(p) { (p)->dic = NULL; (p)->probs = NULL; }
+#define LzmaDec_Construct(p) LzmaDec_CONSTRUCT(p)
 
 
 void LzmaDec_Init(CLzmaDec *p);
 void LzmaDec_Init(CLzmaDec *p);
 
 
 /* There are two types of LZMA streams:
 /* There are two types of LZMA streams:
-     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
-     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
+     - Stream with end mark. That end mark adds about 6 bytes to compressed size.
+     - Stream without end mark. You must know exact uncompressed size to decompress such stream. */
 
 
 typedef enum
 typedef enum
 {
 {
@@ -131,11 +137,11 @@ LzmaDec_Allocate* can return:
   SZ_ERROR_UNSUPPORTED - Unsupported properties
   SZ_ERROR_UNSUPPORTED - Unsupported properties
 */
 */
    
    
-SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
-void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
 
 
-SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
-void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
+void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
 
 
 /* ---------- Dictionary Interface ---------- */
 /* ---------- Dictionary Interface ---------- */
 
 
@@ -144,7 +150,7 @@ void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
    You must work with CLzmaDec variables directly in this interface.
    You must work with CLzmaDec variables directly in this interface.
 
 
    STEPS:
    STEPS:
-     LzmaDec_Constr()
+     LzmaDec_Construct()
      LzmaDec_Allocate()
      LzmaDec_Allocate()
      for (each new stream)
      for (each new stream)
      {
      {
@@ -176,6 +182,7 @@ Returns:
       LZMA_STATUS_NEEDS_MORE_INPUT
       LZMA_STATUS_NEEDS_MORE_INPUT
       LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
       LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
   SZ_ERROR_DATA - Data error
   SZ_ERROR_DATA - Data error
+  SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure
 */
 */
 
 
 SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
 SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
@@ -218,14 +225,13 @@ Returns:
   SZ_ERROR_MEM  - Memory allocation error
   SZ_ERROR_MEM  - Memory allocation error
   SZ_ERROR_UNSUPPORTED - Unsupported properties
   SZ_ERROR_UNSUPPORTED - Unsupported properties
   SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
   SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+  SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure
 */
 */
 
 
 SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
 SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
     const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
     const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
-    ELzmaStatus *status, ISzAlloc *alloc);
+    ELzmaStatus *status, ISzAllocPtr alloc);
 
 
-#ifdef __cplusplus
-}
-#endif
+EXTERN_C_END
 
 
 #endif
 #endif

Dosya farkı çok büyük olduğundan ihmal edildi
+ 510 - 280
Components/Lzma2/LzmaEnc.c


+ 38 - 35
Components/Lzma2/LzmaEnc.h

@@ -1,23 +1,21 @@
 /*  LzmaEnc.h -- LZMA Encoder
 /*  LzmaEnc.h -- LZMA Encoder
-2009-02-07 : Igor Pavlov : Public domain */
+2023-04-13 : Igor Pavlov : Public domain */
 
 
-#ifndef __LZMA_ENC_H
-#define __LZMA_ENC_H
+#ifndef ZIP7_INC_LZMA_ENC_H
+#define ZIP7_INC_LZMA_ENC_H
 
 
-#include "Types.h"
+#include "7zTypes.h"
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+EXTERN_C_BEGIN
 
 
 #define LZMA_PROPS_SIZE 5
 #define LZMA_PROPS_SIZE 5
 
 
-typedef struct _CLzmaEncProps
+typedef struct
 {
 {
-  int level;       /*  0 <= level <= 9 */
+  int level;       /* 0 <= level <= 9 */
   UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
   UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
-                      (1 << 12) <= dictSize <= (1 << 30) for 64-bit version
-                       default = (1 << 24) */
+                      (1 << 12) <= dictSize <= (3 << 29) for 64-bit version
+                      default = (1 << 24) */
   int lc;          /* 0 <= lc <= 8, default = 3 */
   int lc;          /* 0 <= lc <= 8, default = 3 */
   int lp;          /* 0 <= lp <= 4, default = 0 */
   int lp;          /* 0 <= lp <= 4, default = 0 */
   int pb;          /* 0 <= pb <= 4, default = 2 */
   int pb;          /* 0 <= pb <= 4, default = 2 */
@@ -25,9 +23,17 @@ typedef struct _CLzmaEncProps
   int fb;          /* 5 <= fb <= 273, default = 32 */
   int fb;          /* 5 <= fb <= 273, default = 32 */
   int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
   int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
   int numHashBytes; /* 2, 3 or 4, default = 4 */
   int numHashBytes; /* 2, 3 or 4, default = 4 */
-  UInt32 mc;        /* 1 <= mc <= (1 << 30), default = 32 */
+  unsigned numHashOutBits;  /* default = ? */
+  UInt32 mc;       /* 1 <= mc <= (1 << 30), default = 32 */
   unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
   unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
   int numThreads;  /* 1 or 2, default = 2 */
   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;
 } CLzmaEncProps;
 
 
 void LzmaEncProps_Init(CLzmaEncProps *p);
 void LzmaEncProps_Init(CLzmaEncProps *p);
@@ -37,44 +43,41 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
 
 
 /* ---------- CLzmaEncHandle Interface ---------- */
 /* ---------- CLzmaEncHandle Interface ---------- */
 
 
-/* LzmaEnc_* functions can return the following exit codes:
-Returns:
+/* LzmaEnc* functions can return the following exit codes:
+SRes:
   SZ_OK           - OK
   SZ_OK           - OK
   SZ_ERROR_MEM    - Memory allocation error
   SZ_ERROR_MEM    - Memory allocation error
   SZ_ERROR_PARAM  - Incorrect paramater in props
   SZ_ERROR_PARAM  - Incorrect paramater in props
-  SZ_ERROR_WRITE  - Write callback error.
+  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_PROGRESS - some break from progress callback
-  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+  SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
 */
 */
 
 
-typedef void * CLzmaEncHandle;
+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);
 
 
-CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
-void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
 SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
 SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
+void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize);
 SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
 SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
-SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
-    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+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,
 SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
-    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+    int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
 
 
-/* ---------- One Call Interface ---------- */
 
 
-/* LzmaEncode
-Return code:
-  SZ_OK               - OK
-  SZ_ERROR_MEM        - Memory allocation error
-  SZ_ERROR_PARAM      - Incorrect paramater
-  SZ_ERROR_OUTPUT_EOF - output buffer overflow
-  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)
-*/
+/* ---------- One Call Interface ---------- */
 
 
 SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
 SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
     const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
     const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
-    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+    ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
 
 
-#ifdef __cplusplus
-}
-#endif
+EXTERN_C_END
 
 
 #endif
 #endif

+ 478 - 234
Components/Lzma2/MtCoder.c

@@ -1,327 +1,571 @@
 /* MtCoder.c -- Multi-thread Coder
 /* MtCoder.c -- Multi-thread Coder
-2010-03-24 : Igor Pavlov : Public domain */
+2023-09-07 : Igor Pavlov : Public domain */
 
 
-#include <stdio.h>
+#include "Precomp.h"
 
 
 #include "MtCoder.h"
 #include "MtCoder.h"
 
 
-void LoopThread_Construct(CLoopThread *p)
-{
-  Thread_Construct(&p->thread);
-  Event_Construct(&p->startEvent);
-  Event_Construct(&p->finishedEvent);
-}
-
-void LoopThread_Close(CLoopThread *p)
-{
-  Thread_Close(&p->thread);
-  Event_Close(&p->startEvent);
-  Event_Close(&p->finishedEvent);
-}
+#ifndef Z7_ST
 
 
-static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
+static SRes MtProgressThunk_Progress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize)
 {
 {
-  CLoopThread *p = (CLoopThread *)pp;
-  for (;;)
+  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CMtProgressThunk)
+  UInt64 inSize2 = 0;
+  UInt64 outSize2 = 0;
+  if (inSize != (UInt64)(Int64)-1)
   {
   {
-    if (Event_Wait(&p->startEvent) != 0)
-      return SZ_ERROR_THREAD;
-    if (p->stop)
-      return 0;
-    p->res = p->func(p->param);
-    if (Event_Set(&p->finishedEvent) != 0)
-      return SZ_ERROR_THREAD;
+    inSize2 = inSize - p->inSize;
+    p->inSize = inSize;
   }
   }
+  if (outSize != (UInt64)(Int64)-1)
+  {
+    outSize2 = outSize - p->outSize;
+    p->outSize = outSize;
+  }
+  return MtProgress_ProgressAdd(p->mtProgress, inSize2, outSize2);
 }
 }
 
 
-WRes LoopThread_Create(CLoopThread *p)
-{
-  p->stop = 0;
-  RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));
-  RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));
-  return Thread_Create(&p->thread, LoopThreadFunc, p);
-}
 
 
-WRes LoopThread_StopAndWait(CLoopThread *p)
+void MtProgressThunk_CreateVTable(CMtProgressThunk *p)
 {
 {
-  p->stop = 1;
-  if (Event_Set(&p->startEvent) != 0)
-    return SZ_ERROR_THREAD;
-  return Thread_Wait(&p->thread);
+  p->vt.Progress = MtProgressThunk_Progress;
 }
 }
 
 
-WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }
-WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }
 
 
-static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
-{
-  return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
-}
 
 
-static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
-{
-  unsigned i;
-  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
-    p->inSizes[i] = p->outSizes[i] = 0;
-  p->totalInSize = p->totalOutSize = 0;
-  p->progress = progress;
-  p->res = SZ_OK;
-}
+#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
 
 
-static void MtProgress_Reinit(CMtProgress *p, unsigned index)
-{
-  p->inSizes[index] = 0;
-  p->outSizes[index] = 0;
-}
 
 
-#define UPDATE_PROGRESS(size, prev, total) \
-  if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }
+static THREAD_FUNC_DECL ThreadFunc(void *pp);
 
 
-SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)
-{
-  SRes res;
-  CriticalSection_Enter(&p->cs);
-  UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)
-  UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)
-  if (p->res == SZ_OK)
-    p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);
-  res = p->res;
-  CriticalSection_Leave(&p->cs);
-  return res;
-}
 
 
-static void MtProgress_SetError(CMtProgress *p, SRes res)
+static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t)
 {
 {
-  CriticalSection_Enter(&p->cs);
-  if (p->res == SZ_OK)
-    p->res = res;
-  CriticalSection_Leave(&p->cs);
+  WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->startEvent);
+  if (wres == 0)
+  {
+    t->stop = False;
+    if (!Thread_WasCreated(&t->thread))
+      wres = Thread_Create(&t->thread, ThreadFunc, t);
+    if (wres == 0)
+      wres = Event_Set(&t->startEvent);
+  }
+  if (wres == 0)
+    return SZ_OK;
+  return MY_SRes_HRESULT_FROM_WRes(wres);
 }
 }
 
 
-static void MtCoder_SetError(CMtCoder* p, SRes res)
+
+static void MtCoderThread_Destruct(CMtCoderThread *t)
 {
 {
-  CriticalSection_Enter(&p->cs);
-  if (p->res == SZ_OK)
-    p->res = res;
-  CriticalSection_Leave(&p->cs);
-}
+  if (Thread_WasCreated(&t->thread))
+  {
+    t->stop = 1;
+    Event_Set(&t->startEvent);
+    Thread_Wait_Close(&t->thread);
+  }
 
 
-/* ---------- MtThread ---------- */
+  Event_Close(&t->startEvent);
 
 
-void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
-{
-  p->mtCoder = mtCoder;
-  p->outBuf = 0;
-  p->inBuf = 0;
-  Event_Construct(&p->canRead);
-  Event_Construct(&p->canWrite);
-  LoopThread_Construct(&p->thread);
+  if (t->inBuf)
+  {
+    ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf);
+    t->inBuf = NULL;
+  }
 }
 }
 
 
-#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }
 
 
-static void CMtThread_CloseEvents(CMtThread *p)
-{
-  Event_Close(&p->canRead);
-  Event_Close(&p->canWrite);
-}
 
 
-static void CMtThread_Destruct(CMtThread *p)
+
+/*
+  ThreadFunc2() returns:
+  SZ_OK           - in all normal cases (even for stream error or memory allocation error)
+  SZ_ERROR_THREAD - in case of failure in system synch function
+*/
+
+static SRes ThreadFunc2(CMtCoderThread *t)
 {
 {
-  CMtThread_CloseEvents(p);
+  CMtCoder *mtc = t->mtCoder;
 
 
-  if (Thread_WasCreated(&p->thread.thread))
+  for (;;)
   {
   {
-    LoopThread_StopAndWait(&p->thread);
-    LoopThread_Close(&p->thread);
-  }
+    unsigned bi;
+    SRes res;
+    SRes res2;
+    BoolInt finished;
+    unsigned bufIndex;
+    size_t size;
+    const Byte *inData;
+    UInt64 readProcessed = 0;
+    
+    RINOK_THREAD(Event_Wait(&mtc->readEvent))
+
+    /* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */
+
+    if (mtc->stopReading)
+    {
+      return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD;
+    }
 
 
-  if (p->mtCoder->alloc)
-    IAlloc_Free(p->mtCoder->alloc, p->outBuf);
-  p->outBuf = 0;
+    res = MtProgress_GetError(&mtc->mtProgress);
+    
+    size = 0;
+    inData = NULL;
+    finished = True;
 
 
-  if (p->mtCoder->alloc)
-    IAlloc_Free(p->mtCoder->alloc, p->inBuf);
-  p->inBuf = 0;
-}
+    if (res == SZ_OK)
+    {
+      size = mtc->blockSize;
+      if (mtc->inStream)
+      {
+        if (!t->inBuf)
+        {
+          t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize);
+          if (!t->inBuf)
+            res = SZ_ERROR_MEM;
+        }
+        if (res == SZ_OK)
+        {
+          res = SeqInStream_ReadMax(mtc->inStream, t->inBuf, &size);
+          readProcessed = mtc->readProcessed + size;
+          mtc->readProcessed = readProcessed;
+        }
+        if (res != SZ_OK)
+        {
+          mtc->readRes = res;
+          /* after reading error - we can stop encoding of previous blocks */
+          MtProgress_SetError(&mtc->mtProgress, res);
+        }
+        else
+          finished = (size != mtc->blockSize);
+      }
+      else
+      {
+        size_t rem;
+        readProcessed = mtc->readProcessed;
+        rem = mtc->inDataSize - (size_t)readProcessed;
+        if (size > rem)
+          size = rem;
+        inData = mtc->inData + (size_t)readProcessed;
+        readProcessed += size;
+        mtc->readProcessed = readProcessed;
+        finished = (mtc->inDataSize == (size_t)readProcessed);
+      }
+    }
 
 
-#define MY_BUF_ALLOC(buf, size, newSize) \
-  if (buf == 0 || size != newSize) \
-  { IAlloc_Free(p->mtCoder->alloc, buf); \
-    size = newSize; buf = IAlloc_Alloc(p->mtCoder->alloc, size); \
-    if (buf == 0) return SZ_ERROR_MEM; }
+    /* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */
 
 
-static SRes CMtThread_Prepare(CMtThread *p)
-{
-  MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)
-  MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)
+    res2 = SZ_OK;
 
 
-  p->stopReading = False;
-  p->stopWriting = False;
-  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));
-  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));
+    if (Semaphore_Wait(&mtc->blocksSemaphore) != 0)
+    {
+      res2 = SZ_ERROR_THREAD;
+      if (res == SZ_OK)
+      {
+        res = res2;
+        // MtProgress_SetError(&mtc->mtProgress, res);
+      }
+    }
 
 
-  return SZ_OK;
-}
+    bi = mtc->blockIndex;
 
 
-static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
-{
-  size_t size = *processedSize;
-  *processedSize = 0;
-  while (size != 0)
-  {
-    size_t curSize = size;
-    SRes res = stream->Read(stream, data, &curSize);
-    *processedSize += curSize;
-    data += curSize;
-    size -= curSize;
-    RINOK(res);
-    if (curSize == 0)
-      return SZ_OK;
-  }
-  return SZ_OK;
-}
+    if (++mtc->blockIndex >= mtc->numBlocksMax)
+      mtc->blockIndex = 0;
 
 
-#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads  - 1 ? 0 : p->index + 1]
+    bufIndex = (unsigned)(int)-1;
 
 
-static SRes MtThread_Process(CMtThread *p, Bool *stop)
-{
-  CMtThread *next;
-  *stop = True;
-  if (Event_Wait(&p->canRead) != 0)
-    return SZ_ERROR_THREAD;
-  
-  next = GET_NEXT_THREAD(p);
-  
-  if (p->stopReading)
-  {
-    next->stopReading = True;
-    return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;
-  }
+    if (res == SZ_OK)
+      res = MtProgress_GetError(&mtc->mtProgress);
 
 
-  {
-    size_t size = p->mtCoder->blockSize;
-    size_t destSize = p->outBufSize;
-
-    RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));
-    next->stopReading = *stop = (size != p->mtCoder->blockSize);
-    if (Event_Set(&next->canRead) != 0)
-      return SZ_ERROR_THREAD;
-
-    RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,
-        p->outBuf, &destSize, p->inBuf, size, *stop));
-
-    MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);
-
-    if (Event_Wait(&p->canWrite) != 0)
-      return SZ_ERROR_THREAD;
-    if (p->stopWriting)
-      return SZ_ERROR_FAIL;
-    if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)
-      return SZ_ERROR_WRITE;
-    return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;
+    if (res != SZ_OK)
+      finished = True;
+
+    if (!finished)
+    {
+      if (mtc->numStartedThreads < mtc->numStartedThreadsLimit
+          && mtc->expectedDataSize != readProcessed)
+      {
+        res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]);
+        if (res == SZ_OK)
+          mtc->numStartedThreads++;
+        else
+        {
+          MtProgress_SetError(&mtc->mtProgress, res);
+          finished = True;
+        }
+      }
+    }
+
+    if (finished)
+      mtc->stopReading = True;
+
+    RINOK_THREAD(Event_Set(&mtc->readEvent))
+
+    if (res2 != SZ_OK)
+      return res2;
+
+    if (res == SZ_OK)
+    {
+      CriticalSection_Enter(&mtc->cs);
+      bufIndex = mtc->freeBlockHead;
+      mtc->freeBlockHead = mtc->freeBlockList[bufIndex];
+      CriticalSection_Leave(&mtc->cs);
+      
+      res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex,
+          mtc->inStream ? t->inBuf : inData, size, finished);
+      
+      // MtProgress_Reinit(&mtc->mtProgress, t->index);
+
+      if (res != SZ_OK)
+        MtProgress_SetError(&mtc->mtProgress, res);
+    }
+
+    {
+      CMtCoderBlock *block = &mtc->blocks[bi];
+      block->res = res;
+      block->bufIndex = bufIndex;
+      block->finished = finished;
+    }
+    
+    #ifdef MTCODER_USE_WRITE_THREAD
+      RINOK_THREAD(Event_Set(&mtc->writeEvents[bi]))
+    #else
+    {
+      unsigned wi;
+      {
+        CriticalSection_Enter(&mtc->cs);
+        wi = mtc->writeIndex;
+        if (wi == bi)
+          mtc->writeIndex = (unsigned)(int)-1;
+        else
+          mtc->ReadyBlocks[bi] = True;
+        CriticalSection_Leave(&mtc->cs);
+      }
+
+      if (wi != bi)
+      {
+        if (res != SZ_OK || finished)
+          return 0;
+        continue;
+      }
+
+      if (mtc->writeRes != SZ_OK)
+        res = mtc->writeRes;
+
+      for (;;)
+      {
+        if (res == SZ_OK && bufIndex != (unsigned)(int)-1)
+        {
+          res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex);
+          if (res != SZ_OK)
+          {
+            mtc->writeRes = res;
+            MtProgress_SetError(&mtc->mtProgress, res);
+          }
+        }
+
+        if (++wi >= mtc->numBlocksMax)
+          wi = 0;
+        {
+          BoolInt isReady;
+
+          CriticalSection_Enter(&mtc->cs);
+          
+          if (bufIndex != (unsigned)(int)-1)
+          {
+            mtc->freeBlockList[bufIndex] = mtc->freeBlockHead;
+            mtc->freeBlockHead = bufIndex;
+          }
+          
+          isReady = mtc->ReadyBlocks[wi];
+          
+          if (isReady)
+            mtc->ReadyBlocks[wi] = False;
+          else
+            mtc->writeIndex = wi;
+          
+          CriticalSection_Leave(&mtc->cs);
+
+          RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore))
+
+          if (!isReady)
+            break;
+        }
+
+        {
+          CMtCoderBlock *block = &mtc->blocks[wi];
+          if (res == SZ_OK && block->res != SZ_OK)
+            res = block->res;
+          bufIndex = block->bufIndex;
+          finished = block->finished;
+        }
+      }
+    }
+    #endif
+      
+    if (finished || res != SZ_OK)
+      return 0;
   }
   }
 }
 }
 
 
-static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
+
+static THREAD_FUNC_DECL ThreadFunc(void *pp)
 {
 {
-  CMtThread *p = (CMtThread *)pp;
+  CMtCoderThread *t = (CMtCoderThread *)pp;
   for (;;)
   for (;;)
   {
   {
-    Bool stop;
-    CMtThread *next = GET_NEXT_THREAD(p);
-    SRes res = MtThread_Process(p, &stop);
-    if (res != SZ_OK)
+    if (Event_Wait(&t->startEvent) != 0)
+      return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD;
+    if (t->stop)
+      return 0;
     {
     {
-      MtCoder_SetError(p->mtCoder, res);
-      MtProgress_SetError(&p->mtCoder->mtProgress, res);
-      next->stopReading = True;
-      next->stopWriting = True;
-      Event_Set(&next->canRead);
-      Event_Set(&next->canWrite);
-      return res;
+      SRes res = ThreadFunc2(t);
+      CMtCoder *mtc = t->mtCoder;
+      if (res != SZ_OK)
+      {
+        MtProgress_SetError(&mtc->mtProgress, res);
+      }
+      
+      #ifndef MTCODER_USE_WRITE_THREAD
+      {
+        unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads);
+        if (numFinished == mtc->numStartedThreads)
+          if (Event_Set(&mtc->finishedEvent) != 0)
+            return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD;
+      }
+      #endif
     }
     }
-    if (stop)
-      return 0;
   }
   }
 }
 }
 
 
-void MtCoder_Construct(CMtCoder* p)
+
+
+void MtCoder_Construct(CMtCoder *p)
 {
 {
   unsigned i;
   unsigned i;
-  p->alloc = 0;
-  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
+  
+  p->blockSize = 0;
+  p->numThreadsMax = 0;
+  p->expectedDataSize = (UInt64)(Int64)-1;
+
+  p->inStream = NULL;
+  p->inData = NULL;
+  p->inDataSize = 0;
+
+  p->progress = NULL;
+  p->allocBig = NULL;
+
+  p->mtCallback = NULL;
+  p->mtCallbackObject = NULL;
+
+  p->allocatedBufsSize = 0;
+
+  Event_Construct(&p->readEvent);
+  Semaphore_Construct(&p->blocksSemaphore);
+
+  for (i = 0; i < MTCODER_THREADS_MAX; i++)
   {
   {
-    CMtThread *t = &p->threads[i];
+    CMtCoderThread *t = &p->threads[i];
+    t->mtCoder = p;
     t->index = i;
     t->index = i;
-    CMtThread_Construct(t, p);
+    t->inBuf = NULL;
+    t->stop = False;
+    Event_Construct(&t->startEvent);
+    Thread_CONSTRUCT(&t->thread)
   }
   }
+
+  #ifdef MTCODER_USE_WRITE_THREAD
+    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
+      Event_Construct(&p->writeEvents[i]);
+  #else
+    Event_Construct(&p->finishedEvent);
+  #endif
+
   CriticalSection_Init(&p->cs);
   CriticalSection_Init(&p->cs);
   CriticalSection_Init(&p->mtProgress.cs);
   CriticalSection_Init(&p->mtProgress.cs);
 }
 }
 
 
-void MtCoder_Destruct(CMtCoder* p)
+
+
+
+static void MtCoder_Free(CMtCoder *p)
 {
 {
   unsigned i;
   unsigned i;
-  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
-    CMtThread_Destruct(&p->threads[i]);
+
+  /*
+  p->stopReading = True;
+  if (Event_IsCreated(&p->readEvent))
+    Event_Set(&p->readEvent);
+  */
+
+  for (i = 0; i < MTCODER_THREADS_MAX; i++)
+    MtCoderThread_Destruct(&p->threads[i]);
+
+  Event_Close(&p->readEvent);
+  Semaphore_Close(&p->blocksSemaphore);
+
+  #ifdef MTCODER_USE_WRITE_THREAD
+    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
+      Event_Close(&p->writeEvents[i]);
+  #else
+    Event_Close(&p->finishedEvent);
+  #endif
+}
+
+
+void MtCoder_Destruct(CMtCoder *p)
+{
+  MtCoder_Free(p);
+
   CriticalSection_Delete(&p->cs);
   CriticalSection_Delete(&p->cs);
   CriticalSection_Delete(&p->mtProgress.cs);
   CriticalSection_Delete(&p->mtProgress.cs);
 }
 }
 
 
+
 SRes MtCoder_Code(CMtCoder *p)
 SRes MtCoder_Code(CMtCoder *p)
 {
 {
-  unsigned i, numThreads = p->numThreads;
+  unsigned numThreads = p->numThreadsMax;
+  unsigned numBlocksMax;
+  unsigned i;
   SRes res = SZ_OK;
   SRes res = SZ_OK;
-  p->res = SZ_OK;
+
+  if (numThreads > MTCODER_THREADS_MAX)
+      numThreads = MTCODER_THREADS_MAX;
+  numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads);
+  
+  if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++;
+  if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++;
+  if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++;
+
+  if (numBlocksMax > MTCODER_BLOCKS_MAX)
+      numBlocksMax = MTCODER_BLOCKS_MAX;
+
+  if (p->blockSize != p->allocatedBufsSize)
+  {
+    for (i = 0; i < MTCODER_THREADS_MAX; i++)
+    {
+      CMtCoderThread *t = &p->threads[i];
+      if (t->inBuf)
+      {
+        ISzAlloc_Free(p->allocBig, t->inBuf);
+        t->inBuf = NULL;
+      }
+    }
+    p->allocatedBufsSize = p->blockSize;
+  }
+
+  p->readRes = SZ_OK;
 
 
   MtProgress_Init(&p->mtProgress, p->progress);
   MtProgress_Init(&p->mtProgress, p->progress);
 
 
-  for (i = 0; i < numThreads; i++)
+  #ifdef MTCODER_USE_WRITE_THREAD
+    for (i = 0; i < numBlocksMax; i++)
+    {
+      RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->writeEvents[i]))
+    }
+  #else
+    RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent))
+  #endif
+
   {
   {
-    RINOK(CMtThread_Prepare(&p->threads[i]));
+    RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->readEvent))
+    RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, (UInt32)numBlocksMax, (UInt32)numBlocksMax))
   }
   }
 
 
-  for (i = 0; i < numThreads; i++)
+  for (i = 0; i < MTCODER_BLOCKS_MAX - 1; i++)
+    p->freeBlockList[i] = i + 1;
+  p->freeBlockList[MTCODER_BLOCKS_MAX - 1] = (unsigned)(int)-1;
+  p->freeBlockHead = 0;
+
+  p->readProcessed = 0;
+  p->blockIndex = 0;
+  p->numBlocksMax = numBlocksMax;
+  p->stopReading = False;
+
+  #ifndef MTCODER_USE_WRITE_THREAD
+    p->writeIndex = 0;
+    p->writeRes = SZ_OK;
+    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)
+      p->ReadyBlocks[i] = False;
+    p->numFinishedThreads = 0;
+  #endif
+
+  p->numStartedThreadsLimit = numThreads;
+  p->numStartedThreads = 0;
+
+  // for (i = 0; i < numThreads; i++)
+  {
+    CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++];
+    RINOK(MtCoderThread_CreateAndStart(nextThread))
+  }
+
+  RINOK_THREAD(Event_Set(&p->readEvent))
+
+  #ifdef MTCODER_USE_WRITE_THREAD
   {
   {
-    CMtThread *t = &p->threads[i];
-    CLoopThread *lt = &t->thread;
+    unsigned bi = 0;
 
 
-    if (!Thread_WasCreated(&lt->thread))
+    for (;; bi++)
     {
     {
-      lt->func = ThreadFunc;
-      lt->param = t;
+      if (bi >= numBlocksMax)
+        bi = 0;
+
+      RINOK_THREAD(Event_Wait(&p->writeEvents[bi]))
 
 
-      if (LoopThread_Create(lt) != SZ_OK)
       {
       {
-        res = SZ_ERROR_THREAD;
-        break;
+        const CMtCoderBlock *block = &p->blocks[bi];
+        unsigned bufIndex = block->bufIndex;
+        BoolInt finished = block->finished;
+        if (res == SZ_OK && block->res != SZ_OK)
+          res = block->res;
+
+        if (bufIndex != (unsigned)(int)-1)
+        {
+          if (res == SZ_OK)
+          {
+            res = p->mtCallback->Write(p->mtCallbackObject, bufIndex);
+            if (res != SZ_OK)
+              MtProgress_SetError(&p->mtProgress, res);
+          }
+          
+          CriticalSection_Enter(&p->cs);
+          {
+            p->freeBlockList[bufIndex] = p->freeBlockHead;
+            p->freeBlockHead = bufIndex;
+          }
+          CriticalSection_Leave(&p->cs);
+        }
+        
+        RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore))
+
+        if (finished)
+          break;
       }
       }
     }
     }
   }
   }
+  #else
+  {
+    WRes wres = Event_Wait(&p->finishedEvent);
+    res = MY_SRes_HRESULT_FROM_WRes(wres);
+  }
+  #endif
 
 
   if (res == SZ_OK)
   if (res == SZ_OK)
-  {
-    unsigned j;
-    for (i = 0; i < numThreads; i++)
-    {
-      CMtThread *t = &p->threads[i];
-      if (LoopThread_StartSubThread(&t->thread) != SZ_OK)
-      {
-        res = SZ_ERROR_THREAD;
-        p->threads[0].stopReading = True;
-        break;
-      }
-    }
+    res = p->readRes;
 
 
-    Event_Set(&p->threads[0].canWrite);
-    Event_Set(&p->threads[0].canRead);
+  if (res == SZ_OK)
+    res = p->mtProgress.res;
 
 
-    for (j = 0; j < i; j++)
-      LoopThread_WaitSubThread(&p->threads[j].thread);
-  }
+  #ifndef MTCODER_USE_WRITE_THREAD
+    if (res == SZ_OK)
+      res = p->writeRes;
+  #endif
 
 
-  for (i = 0; i < numThreads; i++)
-    CMtThread_CloseEvents(&p->threads[i]);
-  return (res == SZ_OK) ? p->res : res;
+  if (res != SZ_OK)
+    MtCoder_Free(p);
+  return res;
 }
 }
+
+#endif
+
+#undef RINOK_THREAD

+ 105 - 62
Components/Lzma2/MtCoder.h

@@ -1,98 +1,141 @@
 /* MtCoder.h -- Multi-thread Coder
 /* MtCoder.h -- Multi-thread Coder
-2009-11-19 : Igor Pavlov : Public domain */
+2023-04-13 : Igor Pavlov : Public domain */
 
 
-#ifndef __MT_CODER_H
-#define __MT_CODER_H
+#ifndef ZIP7_INC_MT_CODER_H
+#define ZIP7_INC_MT_CODER_H
 
 
-#include "Threads.h"
+#include "MtDec.h"
 
 
 EXTERN_C_BEGIN
 EXTERN_C_BEGIN
 
 
-typedef struct
-{
-  CThread thread;
-  CAutoResetEvent startEvent;
-  CAutoResetEvent finishedEvent;
-  int stop;
-  
-  THREAD_FUNC_TYPE func;
-  LPVOID param;
-  THREAD_FUNC_RET_TYPE res;
-} CLoopThread;
-
-void LoopThread_Construct(CLoopThread *p);
-void LoopThread_Close(CLoopThread *p);
-WRes LoopThread_Create(CLoopThread *p);
-WRes LoopThread_StopAndWait(CLoopThread *p);
-WRes LoopThread_StartSubThread(CLoopThread *p);
-WRes LoopThread_WaitSubThread(CLoopThread *p);
-
-#ifndef _7ZIP_ST
-#define NUM_MT_CODER_THREADS_MAX 32
+/*
+  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
 #else
-#define NUM_MT_CODER_THREADS_MAX 1
+  #define MTCODER_THREADS_MAX 1
+  #define MTCODER_BLOCKS_MAX 1
 #endif
 #endif
 
 
+
+#ifndef Z7_ST
+
+
 typedef struct
 typedef struct
 {
 {
-  UInt64 totalInSize;
-  UInt64 totalOutSize;
-  ICompressProgress *progress;
-  SRes res;
-  CCriticalSection cs;
-  UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];
-  UInt64 outSizes[NUM_MT_CODER_THREADS_MAX];
-} CMtProgress;
+  ICompressProgress vt;
+  CMtProgress *mtProgress;
+  UInt64 inSize;
+  UInt64 outSize;
+} CMtProgressThunk;
+
+void MtProgressThunk_CreateVTable(CMtProgressThunk *p);
+    
+#define MtProgressThunk_INIT(p) { (p)->inSize = 0; (p)->outSize = 0; }
+
 
 
-SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);
+struct CMtCoder_;
 
 
-struct _CMtCoder;
 
 
 typedef struct
 typedef struct
 {
 {
-  struct _CMtCoder *mtCoder;
-  Byte *outBuf;
-  size_t outBufSize;
-  Byte *inBuf;
-  size_t inBufSize;
+  struct CMtCoder_ *mtCoder;
   unsigned index;
   unsigned index;
-  CLoopThread thread;
+  int stop;
+  Byte *inBuf;
+
+  CAutoResetEvent startEvent;
+  CThread thread;
+} CMtCoderThread;
 
 
-  Bool stopReading;
-  Bool stopWriting;
-  CAutoResetEvent canRead;
-  CAutoResetEvent canWrite;
-} CMtThread;
 
 
 typedef struct
 typedef struct
 {
 {
-  SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize,
+  SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex,
       const Byte *src, size_t srcSize, int finished);
       const Byte *src, size_t srcSize, int finished);
-} IMtCoderCallback;
+  SRes (*Write)(void *p, unsigned outBufIndex);
+} IMtCoderCallback2;
+
+
+typedef struct
+{
+  SRes res;
+  unsigned bufIndex;
+  BoolInt finished;
+} CMtCoderBlock;
 
 
-typedef struct _CMtCoder
+
+typedef struct CMtCoder_
 {
 {
-  size_t blockSize;
-  size_t destBlockSize;
-  unsigned numThreads;
+  /* input variables */
   
   
-  ISeqInStream *inStream;
-  ISeqOutStream *outStream;
-  ICompressProgress *progress;
-  ISzAlloc *alloc;
+  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;
 
 
-  IMtCoderCallback *mtCallback;
   CCriticalSection cs;
   CCriticalSection cs;
-  SRes res;
+
+  unsigned freeBlockHead;
+  unsigned freeBlockList[MTCODER_BLOCKS_MAX];
 
 
   CMtProgress mtProgress;
   CMtProgress mtProgress;
-  CMtThread threads[NUM_MT_CODER_THREADS_MAX];
+  CMtCoderBlock blocks[MTCODER_BLOCKS_MAX];
+  CMtCoderThread threads[MTCODER_THREADS_MAX];
 } CMtCoder;
 } CMtCoder;
 
 
-void MtCoder_Construct(CMtCoder* p);
-void MtCoder_Destruct(CMtCoder* p);
+
+void MtCoder_Construct(CMtCoder *p);
+void MtCoder_Destruct(CMtCoder *p);
 SRes MtCoder_Code(CMtCoder *p);
 SRes MtCoder_Code(CMtCoder *p);
 
 
+
+#endif
+
+
 EXTERN_C_END
 EXTERN_C_END
 
 
 #endif
 #endif

+ 1124 - 0
Components/Lzma2/MtDec.c

@@ -0,0 +1,1124 @@
+/* MtDec.c -- Multi-thread Decoder
+2024-02-20 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+// #define SHOW_DEBUG_INFO
+
+// #include <stdio.h>
+#include <string.h>
+
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#include "MtDec.h"
+
+#ifndef Z7_ST
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
+
+void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress)
+{
+  p->progress = progress;
+  p->res = SZ_OK;
+  p->totalInSize = 0;
+  p->totalOutSize = 0;
+}
+
+
+SRes MtProgress_Progress_ST(CMtProgress *p)
+{
+  if (p->res == SZ_OK && p->progress)
+    if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK)
+      p->res = SZ_ERROR_PROGRESS;
+  return p->res;
+}
+
+
+SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize)
+{
+  SRes res;
+  CriticalSection_Enter(&p->cs);
+  
+  p->totalInSize += inSize;
+  p->totalOutSize += outSize;
+  if (p->res == SZ_OK && p->progress)
+    if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK)
+      p->res = SZ_ERROR_PROGRESS;
+  res = p->res;
+  
+  CriticalSection_Leave(&p->cs);
+  return res;
+}
+
+
+SRes MtProgress_GetError(CMtProgress *p)
+{
+  SRes res;
+  CriticalSection_Enter(&p->cs);
+  res = p->res;
+  CriticalSection_Leave(&p->cs);
+  return res;
+}
+
+
+void MtProgress_SetError(CMtProgress *p, SRes res)
+{
+  CriticalSection_Enter(&p->cs);
+  if (p->res == SZ_OK)
+    p->res = res;
+  CriticalSection_Leave(&p->cs);
+}
+
+
+#define RINOK_THREAD(x) RINOK_WRes(x)
+
+
+struct CMtDecBufLink_
+{
+  struct CMtDecBufLink_ *next;
+  void *pad[3];
+};
+
+typedef struct CMtDecBufLink_ CMtDecBufLink;
+
+#define MTDEC__LINK_DATA_OFFSET sizeof(CMtDecBufLink)
+#define MTDEC__DATA_PTR_FROM_LINK(link) ((Byte *)(link) + MTDEC__LINK_DATA_OFFSET)
+
+
+
+static THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp);
+
+
+static WRes MtDecThread_CreateEvents(CMtDecThread *t)
+{
+  WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->canWrite);
+  if (wres == 0)
+  {
+    wres = AutoResetEvent_OptCreate_And_Reset(&t->canRead);
+    if (wres == 0)
+      return SZ_OK;
+  }
+  return wres;
+}
+
+
+static SRes MtDecThread_CreateAndStart(CMtDecThread *t)
+{
+  WRes wres = MtDecThread_CreateEvents(t);
+  // wres = 17; // for test
+  if (wres == 0)
+  {
+    if (Thread_WasCreated(&t->thread))
+      return SZ_OK;
+    wres = Thread_Create(&t->thread, MtDec_ThreadFunc, t);
+    if (wres == 0)
+      return SZ_OK;
+  }
+  return MY_SRes_HRESULT_FROM_WRes(wres);
+}
+
+
+void MtDecThread_FreeInBufs(CMtDecThread *t)
+{
+  if (t->inBuf)
+  {
+    void *link = t->inBuf;
+    t->inBuf = NULL;
+    do
+    {
+      void *next = ((CMtDecBufLink *)link)->next;
+      ISzAlloc_Free(t->mtDec->alloc, link);
+      link = next;
+    }
+    while (link);
+  }
+}
+
+
+static void MtDecThread_CloseThread(CMtDecThread *t)
+{
+  if (Thread_WasCreated(&t->thread))
+  {
+    Event_Set(&t->canWrite); /* we can disable it. There are no threads waiting canWrite in normal cases */
+    Event_Set(&t->canRead);
+    Thread_Wait_Close(&t->thread);
+  }
+
+  Event_Close(&t->canRead);
+  Event_Close(&t->canWrite);
+}
+
+static void MtDec_CloseThreads(CMtDec *p)
+{
+  unsigned i;
+  for (i = 0; i < MTDEC_THREADS_MAX; i++)
+    MtDecThread_CloseThread(&p->threads[i]);
+}
+
+static void MtDecThread_Destruct(CMtDecThread *t)
+{
+  MtDecThread_CloseThread(t);
+  MtDecThread_FreeInBufs(t);
+}
+
+
+
+static SRes MtDec_GetError_Spec(CMtDec *p, UInt64 interruptIndex, BoolInt *wasInterrupted)
+{
+  SRes res;
+  CriticalSection_Enter(&p->mtProgress.cs);
+  *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex);
+  res = p->mtProgress.res;
+  CriticalSection_Leave(&p->mtProgress.cs);
+  return res;
+}
+
+static SRes MtDec_Progress_GetError_Spec(CMtDec *p, UInt64 inSize, UInt64 outSize, UInt64 interruptIndex, BoolInt *wasInterrupted)
+{
+  SRes res;
+  CriticalSection_Enter(&p->mtProgress.cs);
+
+  p->mtProgress.totalInSize += inSize;
+  p->mtProgress.totalOutSize += outSize;
+  if (p->mtProgress.res == SZ_OK && p->mtProgress.progress)
+    if (ICompressProgress_Progress(p->mtProgress.progress, p->mtProgress.totalInSize, p->mtProgress.totalOutSize) != SZ_OK)
+      p->mtProgress.res = SZ_ERROR_PROGRESS;
+
+  *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex);
+  res = p->mtProgress.res;
+  
+  CriticalSection_Leave(&p->mtProgress.cs);
+
+  return res;
+}
+
+static void MtDec_Interrupt(CMtDec *p, UInt64 interruptIndex)
+{
+  CriticalSection_Enter(&p->mtProgress.cs);
+  if (!p->needInterrupt || interruptIndex < p->interruptIndex)
+  {
+    p->interruptIndex = interruptIndex;
+    p->needInterrupt = True;
+  }
+  CriticalSection_Leave(&p->mtProgress.cs);
+}
+
+Byte *MtDec_GetCrossBuff(CMtDec *p)
+{
+  Byte *cr = p->crossBlock;
+  if (!cr)
+  {
+    cr = (Byte *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize);
+    if (!cr)
+      return NULL;
+    p->crossBlock = cr;
+  }
+  return MTDEC__DATA_PTR_FROM_LINK(cr);
+}
+
+
+/*
+  MtDec_ThreadFunc2() returns:
+  0      - in all normal cases (even for stream error or memory allocation error)
+  (!= 0) - WRes error return by system threading function
+*/
+
+// #define MTDEC_ProgessStep (1 << 22)
+#define MTDEC_ProgessStep (1 << 0)
+
+static WRes MtDec_ThreadFunc2(CMtDecThread *t)
+{
+  CMtDec *p = t->mtDec;
+
+  PRF_STR_INT("MtDec_ThreadFunc2", t->index)
+
+  // SetThreadAffinityMask(GetCurrentThread(), 1 << t->index);
+
+  for (;;)
+  {
+    SRes res, codeRes;
+    BoolInt wasInterrupted, isAllocError, overflow, finish;
+    SRes threadingErrorSRes;
+    BoolInt needCode, needWrite, needContinue;
+    
+    size_t inDataSize_Start;
+    UInt64 inDataSize;
+    // UInt64 inDataSize_Full;
+    
+    UInt64 blockIndex;
+
+    UInt64 inPrev = 0;
+    UInt64 outPrev = 0;
+    UInt64 inCodePos;
+    UInt64 outCodePos;
+    
+    Byte *afterEndData = NULL;
+    size_t afterEndData_Size = 0;
+    BoolInt afterEndData_IsCross = False;
+
+    BoolInt canCreateNewThread = False;
+    // CMtDecCallbackInfo parse;
+    CMtDecThread *nextThread;
+
+    PRF_STR_INT("=============== Event_Wait(&t->canRead)", t->index)
+
+    RINOK_THREAD(Event_Wait(&t->canRead))
+    if (p->exitThread)
+      return 0;
+
+    PRF_STR_INT("after Event_Wait(&t->canRead)", t->index)
+
+    // if (t->index == 3) return 19; // for test
+
+    blockIndex = p->blockIndex++;
+
+    // PRF(printf("\ncanRead\n"))
+
+    res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted);
+
+    finish = p->readWasFinished;
+    needCode = False;
+    needWrite = False;
+    isAllocError = False;
+    overflow = False;
+
+    inDataSize_Start = 0;
+    inDataSize = 0;
+    // inDataSize_Full = 0;
+
+    if (res == SZ_OK && !wasInterrupted)
+    {
+      // if (p->inStream)
+      {
+        CMtDecBufLink *prev = NULL;
+        CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf;
+        size_t crossSize = p->crossEnd - p->crossStart;
+
+        PRF(printf("\ncrossSize = %d\n", crossSize));
+
+        for (;;)
+        {
+          if (!link)
+          {
+            link = (CMtDecBufLink *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize);
+            if (!link)
+            {
+              finish = True;
+              // p->allocError_for_Read_BlockIndex = blockIndex;
+              isAllocError = True;
+              break;
+            }
+            link->next = NULL;
+            if (prev)
+            {
+              // static unsigned g_num = 0;
+              // printf("\n%6d : %x", ++g_num, (unsigned)(size_t)((Byte *)link - (Byte *)prev));
+              prev->next = link;
+            }
+            else
+              t->inBuf = (void *)link;
+          }
+
+          {
+            Byte *data = MTDEC__DATA_PTR_FROM_LINK(link);
+            Byte *parseData = data;
+            size_t size;
+
+            if (crossSize != 0)
+            {
+              inDataSize = crossSize;
+              // inDataSize_Full = inDataSize;
+              inDataSize_Start = crossSize;
+              size = crossSize;
+              parseData = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart;
+              PRF(printf("\ncross : crossStart = %7d  crossEnd = %7d finish = %1d",
+                  (int)p->crossStart, (int)p->crossEnd, (int)finish));
+            }
+            else
+            {
+              size = p->inBufSize;
+              
+              res = SeqInStream_ReadMax(p->inStream, data, &size);
+              
+              // size = 10; // test
+
+              inDataSize += size;
+              // inDataSize_Full = inDataSize;
+              if (!prev)
+                inDataSize_Start = size;
+
+              p->readProcessed += size;
+              finish = (size != p->inBufSize);
+              if (finish)
+                p->readWasFinished = True;
+              
+              // res = E_INVALIDARG; // test
+
+              if (res != SZ_OK)
+              {
+                // PRF(printf("\nRead error = %d\n", res))
+                // we want to decode all data before error
+                p->readRes = res;
+                // p->readError_BlockIndex = blockIndex;
+                p->readWasFinished = True;
+                finish = True;
+                res = SZ_OK;
+                // break;
+              }
+
+              if (inDataSize - inPrev >= MTDEC_ProgessStep)
+              {
+                res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted);
+                if (res != SZ_OK || wasInterrupted)
+                  break;
+                inPrev = inDataSize;
+              }
+            }
+
+            {
+              CMtDecCallbackInfo parse;
+
+              parse.startCall = (prev == NULL);
+              parse.src = parseData;
+              parse.srcSize = size;
+              parse.srcFinished = finish;
+              parse.canCreateNewThread = True;
+
+              PRF(printf("\nParse size = %d\n", (unsigned)size));
+
+              p->mtCallback->Parse(p->mtCallbackObject, t->index, &parse);
+
+              PRF(printf("   Parse processed = %d, state = %d \n", (unsigned)parse.srcSize, (unsigned)parse.state));
+
+              needWrite = True;
+              canCreateNewThread = parse.canCreateNewThread;
+
+              // printf("\n\n%12I64u %12I64u", (UInt64)p->mtProgress.totalInSize, (UInt64)p->mtProgress.totalOutSize);
+              
+              if (
+                  // parseRes != SZ_OK ||
+                  // inDataSize - (size - parse.srcSize) > p->inBlockMax
+                  // ||
+                  parse.state == MTDEC_PARSE_OVERFLOW
+                  // || wasInterrupted
+                  )
+              {
+                // Overflow or Parse error - switch from MT decoding to ST decoding
+                finish = True;
+                overflow = True;
+
+                {
+                  PRF(printf("\n Overflow"));
+                  // PRF(printf("\nisBlockFinished = %d", (unsigned)parse.blockWasFinished));
+                  PRF(printf("\n inDataSize = %d", (unsigned)inDataSize));
+                }
+                
+                if (crossSize != 0)
+                  memcpy(data, parseData, size);
+                p->crossStart = 0;
+                p->crossEnd = 0;
+                break;
+              }
+
+              if (crossSize != 0)
+              {
+                memcpy(data, parseData, parse.srcSize);
+                p->crossStart += parse.srcSize;
+              }
+
+              if (parse.state != MTDEC_PARSE_CONTINUE || finish)
+              {
+                // we don't need to parse in current thread anymore
+
+                if (parse.state == MTDEC_PARSE_END)
+                  finish = True;
+
+                needCode = True;
+                // p->crossFinished = finish;
+
+                if (parse.srcSize == size)
+                {
+                  // full parsed - no cross transfer
+                  p->crossStart = 0;
+                  p->crossEnd = 0;
+                  break;
+                }
+
+                if (parse.state == MTDEC_PARSE_END)
+                {
+                  afterEndData = parseData + parse.srcSize;
+                  afterEndData_Size = size - parse.srcSize;
+                  if (crossSize != 0)
+                    afterEndData_IsCross = True;
+                  // we reduce data size to required bytes (parsed only)
+                  inDataSize -= afterEndData_Size;
+                  if (!prev)
+                    inDataSize_Start = parse.srcSize;
+                  break;
+                }
+
+                {
+                  // partial parsed - need cross transfer
+                  if (crossSize != 0)
+                    inDataSize = parse.srcSize; // it's only parsed now
+                  else
+                  {
+                    // partial parsed - is not in initial cross block - we need to copy new data to cross block
+                    Byte *cr = MtDec_GetCrossBuff(p);
+                    if (!cr)
+                    {
+                      {
+                        PRF(printf("\ncross alloc error error\n"));
+                        // res = SZ_ERROR_MEM;
+                        finish = True;
+                        // p->allocError_for_Read_BlockIndex = blockIndex;
+                        isAllocError = True;
+                        break;
+                      }
+                    }
+
+                    {
+                      size_t crSize = size - parse.srcSize;
+                      inDataSize -= crSize;
+                      p->crossEnd = crSize;
+                      p->crossStart = 0;
+                      memcpy(cr, parseData + parse.srcSize, crSize);
+                    }
+                  }
+
+                  // inDataSize_Full = inDataSize;
+                  if (!prev)
+                    inDataSize_Start = parse.srcSize; // it's partial size (parsed only)
+
+                  finish = False;
+                  break;
+                }
+              }
+
+              if (parse.srcSize != size)
+              {
+                res = SZ_ERROR_FAIL;
+                PRF(printf("\nfinished error SZ_ERROR_FAIL = %d\n", res));
+                break;
+              }
+            }
+          }
+          
+          prev = link;
+          link = link->next;
+
+          if (crossSize != 0)
+          {
+            crossSize = 0;
+            p->crossStart = 0;
+            p->crossEnd = 0;
+          }
+        }
+      }
+
+      if (res == SZ_OK)
+        res = MtDec_GetError_Spec(p, blockIndex, &wasInterrupted);
+    }
+
+    codeRes = SZ_OK;
+
+    if (res == SZ_OK && needCode && !wasInterrupted)
+    {
+      codeRes = p->mtCallback->PreCode(p->mtCallbackObject, t->index);
+      if (codeRes != SZ_OK)
+      {
+        needCode = False;
+        finish = True;
+        // SZ_ERROR_MEM is expected error here.
+        //   if (codeRes == SZ_ERROR_MEM) - we will try single-thread decoding later.
+        //   if (codeRes != SZ_ERROR_MEM) - we can stop decoding or try single-thread decoding.
+      }
+    }
+    
+    if (res != SZ_OK || wasInterrupted)
+      finish = True;
+    
+    nextThread = NULL;
+    threadingErrorSRes = SZ_OK;
+
+    if (!finish)
+    {
+      if (p->numStartedThreads < p->numStartedThreads_Limit && canCreateNewThread)
+      {
+        SRes res2 = MtDecThread_CreateAndStart(&p->threads[p->numStartedThreads]);
+        if (res2 == SZ_OK)
+        {
+          // if (p->numStartedThreads % 1000 == 0) PRF(printf("\n numStartedThreads=%d\n", p->numStartedThreads));
+          p->numStartedThreads++;
+        }
+        else
+        {
+          PRF(printf("\nERROR: numStartedThreads=%d\n", p->numStartedThreads));
+          if (p->numStartedThreads == 1)
+          {
+            // if only one thread is possible, we leave muti-threading code
+            finish = True;
+            needCode = False;
+            threadingErrorSRes = res2;
+          }
+          else
+            p->numStartedThreads_Limit = p->numStartedThreads;
+        }
+      }
+      
+      if (!finish)
+      {
+        unsigned nextIndex = t->index + 1;
+        nextThread = &p->threads[nextIndex >= p->numStartedThreads ? 0 : nextIndex];
+        RINOK_THREAD(Event_Set(&nextThread->canRead))
+        // We have started executing for new iteration (with next thread)
+        // And that next thread now is responsible for possible exit from decoding (threading_code)
+      }
+    }
+
+    // each call of Event_Set(&nextThread->canRead) must be followed by call of Event_Set(&nextThread->canWrite)
+    // if ( !finish ) we must call Event_Set(&nextThread->canWrite) in any case
+    // if (  finish ) we switch to single-thread mode and there are 2 ways at the end of current iteration (current block):
+    //   - if (needContinue) after Write(&needContinue), we restore decoding with new iteration
+    //   - otherwise we stop decoding and exit from MtDec_ThreadFunc2()
+
+    // Don't change (finish) variable in the further code
+
+
+    // ---------- CODE ----------
+
+    inPrev = 0;
+    outPrev = 0;
+    inCodePos = 0;
+    outCodePos = 0;
+
+    if (res == SZ_OK && needCode && codeRes == SZ_OK)
+    {
+      BoolInt isStartBlock = True;
+      CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf;
+
+      for (;;)
+      {
+        size_t inSize;
+        int stop;
+
+        if (isStartBlock)
+          inSize = inDataSize_Start;
+        else
+        {
+          UInt64 rem = inDataSize - inCodePos;
+          inSize = p->inBufSize;
+          if (inSize > rem)
+            inSize = (size_t)rem;
+        }
+
+        inCodePos += inSize;
+        stop = True;
+
+        codeRes = p->mtCallback->Code(p->mtCallbackObject, t->index,
+            (const Byte *)MTDEC__DATA_PTR_FROM_LINK(link), inSize,
+            (inCodePos == inDataSize), // srcFinished
+            &inCodePos, &outCodePos, &stop);
+        
+        if (codeRes != SZ_OK)
+        {
+          PRF(printf("\nCode Interrupt error = %x\n", codeRes));
+          // we interrupt only later blocks
+          MtDec_Interrupt(p, blockIndex);
+          break;
+        }
+
+        if (stop || inCodePos == inDataSize)
+          break;
+  
+        {
+          const UInt64 inDelta = inCodePos - inPrev;
+          const UInt64 outDelta = outCodePos - outPrev;
+          if (inDelta >= MTDEC_ProgessStep || outDelta >= MTDEC_ProgessStep)
+          {
+            // Sleep(1);
+            res = MtDec_Progress_GetError_Spec(p, inDelta, outDelta, blockIndex, &wasInterrupted);
+            if (res != SZ_OK || wasInterrupted)
+              break;
+            inPrev = inCodePos;
+            outPrev = outCodePos;
+          }
+        }
+
+        link = link->next;
+        isStartBlock = False;
+      }
+    }
+
+
+    // ---------- WRITE ----------
+   
+    RINOK_THREAD(Event_Wait(&t->canWrite))
+
+  {
+    BoolInt isErrorMode = False;
+    BoolInt canRecode = True;
+    BoolInt needWriteToStream = needWrite;
+
+    if (p->exitThread) return 0; // it's never executed in normal cases
+
+    if (p->wasInterrupted)
+      wasInterrupted = True;
+    else
+    {
+      if (codeRes != SZ_OK) // || !needCode // check it !!!
+      {
+        p->wasInterrupted = True;
+        p->codeRes = codeRes;
+        if (codeRes == SZ_ERROR_MEM)
+          isAllocError = True;
+      }
+      
+      if (threadingErrorSRes)
+      {
+        p->wasInterrupted = True;
+        p->threadingErrorSRes = threadingErrorSRes;
+        needWriteToStream = False;
+      }
+      if (isAllocError)
+      {
+        p->wasInterrupted = True;
+        p->isAllocError = True;
+        needWriteToStream = False;
+      }
+      if (overflow)
+      {
+        p->wasInterrupted = True;
+        p->overflow = True;
+        needWriteToStream = False;
+      }
+    }
+
+    if (needCode)
+    {
+      if (wasInterrupted)
+      {
+        inCodePos = 0;
+        outCodePos = 0;
+      }
+      {
+        const UInt64 inDelta = inCodePos - inPrev;
+        const UInt64 outDelta = outCodePos - outPrev;
+        // if (inDelta != 0 || outDelta != 0)
+        res = MtProgress_ProgressAdd(&p->mtProgress, inDelta, outDelta);
+      }
+    }
+
+    needContinue = (!finish);
+
+    // if (res == SZ_OK && needWrite && !wasInterrupted)
+    if (needWrite)
+    {
+      // p->inProcessed += inCodePos;
+
+      PRF(printf("\n--Write afterSize = %d\n", (unsigned)afterEndData_Size));
+
+      res = p->mtCallback->Write(p->mtCallbackObject, t->index,
+          res == SZ_OK && needWriteToStream && !wasInterrupted, // needWrite
+          afterEndData, afterEndData_Size, afterEndData_IsCross,
+          &needContinue,
+          &canRecode);
+
+      // res = SZ_ERROR_FAIL; // for test
+
+      PRF(printf("\nAfter Write needContinue = %d\n", (unsigned)needContinue));
+      PRF(printf("\nprocessed = %d\n", (unsigned)p->inProcessed));
+
+      if (res != SZ_OK)
+      {
+        PRF(printf("\nWrite error = %d\n", res));
+        isErrorMode = True;
+        p->wasInterrupted = True;
+      }
+      if (res != SZ_OK
+          || (!needContinue && !finish))
+      {
+        PRF(printf("\nWrite Interrupt error = %x\n", res));
+        MtDec_Interrupt(p, blockIndex);
+      }
+    }
+
+    if (canRecode)
+    if (!needCode
+        || res != SZ_OK
+        || p->wasInterrupted
+        || codeRes != SZ_OK
+        || wasInterrupted
+        || p->numFilledThreads != 0
+        || isErrorMode)
+    {
+      if (p->numFilledThreads == 0)
+        p->filledThreadStart = t->index;
+      if (inDataSize != 0 || !finish)
+      {
+        t->inDataSize_Start = inDataSize_Start;
+        t->inDataSize = inDataSize;
+        p->numFilledThreads++;
+      }
+      PRF(printf("\np->numFilledThreads = %d\n", p->numFilledThreads));
+      PRF(printf("p->filledThreadStart = %d\n", p->filledThreadStart));
+    }
+
+    if (!finish)
+    {
+      RINOK_THREAD(Event_Set(&nextThread->canWrite))
+    }
+    else
+    {
+      if (needContinue)
+      {
+        // we restore decoding with new iteration
+        RINOK_THREAD(Event_Set(&p->threads[0].canWrite))
+      }
+      else
+      {
+        // we exit from decoding
+        if (t->index == 0)
+          return SZ_OK;
+        p->exitThread = True;
+      }
+      RINOK_THREAD(Event_Set(&p->threads[0].canRead))
+    }
+  }
+  }
+}
+
+#ifdef _WIN32
+#define USE_ALLOCA
+#endif
+
+#ifdef USE_ALLOCA
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+
+
+typedef
+  #ifdef _WIN32
+    UINT_PTR
+  #elif 1
+    uintptr_t
+  #else
+    ptrdiff_t
+  #endif
+    MY_uintptr_t;
+
+static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp)
+{
+  WRes res;
+
+  CMtDecThread *t = (CMtDecThread *)pp;
+  CMtDec *p;
+
+  // fprintf(stdout, "\n%d = %p\n", t->index, &t);
+
+  res = MtDec_ThreadFunc2(t);
+  p = t->mtDec;
+  if (res == 0)
+    return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)p->exitThreadWRes;
+  {
+    // it's unexpected situation for some threading function error
+    if (p->exitThreadWRes == 0)
+      p->exitThreadWRes = res;
+    PRF(printf("\nthread exit error = %d\n", res));
+    p->exitThread = True;
+    Event_Set(&p->threads[0].canRead);
+    Event_Set(&p->threads[0].canWrite);
+    MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res));
+  }
+  return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)res;
+}
+
+static Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp)
+{
+  #ifdef USE_ALLOCA
+  CMtDecThread *t = (CMtDecThread *)pp;
+  // fprintf(stderr, "\n%d = %p - before", t->index, &t);
+  t->allocaPtr = alloca(t->index * 128);
+  #endif
+  return MtDec_ThreadFunc1(pp);
+}
+
+
+int MtDec_PrepareRead(CMtDec *p)
+{
+  if (p->crossBlock && p->crossStart == p->crossEnd)
+  {
+    ISzAlloc_Free(p->alloc, p->crossBlock);
+    p->crossBlock = NULL;
+  }
+    
+  {
+    unsigned i;
+    for (i = 0; i < MTDEC_THREADS_MAX; i++)
+      if (i > p->numStartedThreads
+          || p->numFilledThreads <=
+            (i >= p->filledThreadStart ?
+              i - p->filledThreadStart :
+              i + p->numStartedThreads - p->filledThreadStart))
+        MtDecThread_FreeInBufs(&p->threads[i]);
+  }
+
+  return (p->numFilledThreads != 0) || (p->crossStart != p->crossEnd);
+}
+
+    
+const Byte *MtDec_Read(CMtDec *p, size_t *inLim)
+{
+  while (p->numFilledThreads != 0)
+  {
+    CMtDecThread *t = &p->threads[p->filledThreadStart];
+    
+    if (*inLim != 0)
+    {
+      {
+        void *link = t->inBuf;
+        void *next = ((CMtDecBufLink *)link)->next;
+        ISzAlloc_Free(p->alloc, link);
+        t->inBuf = next;
+      }
+      
+      if (t->inDataSize == 0)
+      {
+        MtDecThread_FreeInBufs(t);
+        if (--p->numFilledThreads == 0)
+          break;
+        if (++p->filledThreadStart == p->numStartedThreads)
+          p->filledThreadStart = 0;
+        t = &p->threads[p->filledThreadStart];
+      }
+    }
+    
+    {
+      size_t lim = t->inDataSize_Start;
+      if (lim != 0)
+        t->inDataSize_Start = 0;
+      else
+      {
+        UInt64 rem = t->inDataSize;
+        lim = p->inBufSize;
+        if (lim > rem)
+          lim = (size_t)rem;
+      }
+      t->inDataSize -= lim;
+      *inLim = lim;
+      return (const Byte *)MTDEC__DATA_PTR_FROM_LINK(t->inBuf);
+    }
+  }
+
+  {
+    size_t crossSize = p->crossEnd - p->crossStart;
+    if (crossSize != 0)
+    {
+      const Byte *data = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart;
+      *inLim = crossSize;
+      p->crossStart = 0;
+      p->crossEnd = 0;
+      return data;
+    }
+    *inLim = 0;
+    if (p->crossBlock)
+    {
+      ISzAlloc_Free(p->alloc, p->crossBlock);
+      p->crossBlock = NULL;
+    }
+    return NULL;
+  }
+}
+
+
+void MtDec_Construct(CMtDec *p)
+{
+  unsigned i;
+  
+  p->inBufSize = (size_t)1 << 18;
+
+  p->numThreadsMax = 0;
+
+  p->inStream = NULL;
+  
+  // p->inData = NULL;
+  // p->inDataSize = 0;
+
+  p->crossBlock = NULL;
+  p->crossStart = 0;
+  p->crossEnd = 0;
+
+  p->numFilledThreads = 0;
+
+  p->progress = NULL;
+  p->alloc = NULL;
+
+  p->mtCallback = NULL;
+  p->mtCallbackObject = NULL;
+
+  p->allocatedBufsSize = 0;
+
+  for (i = 0; i < MTDEC_THREADS_MAX; i++)
+  {
+    CMtDecThread *t = &p->threads[i];
+    t->mtDec = p;
+    t->index = i;
+    t->inBuf = NULL;
+    Event_Construct(&t->canRead);
+    Event_Construct(&t->canWrite);
+    Thread_CONSTRUCT(&t->thread)
+  }
+
+  // Event_Construct(&p->finishedEvent);
+
+  CriticalSection_Init(&p->mtProgress.cs);
+}
+
+
+static void MtDec_Free(CMtDec *p)
+{
+  unsigned i;
+
+  p->exitThread = True;
+
+  for (i = 0; i < MTDEC_THREADS_MAX; i++)
+    MtDecThread_Destruct(&p->threads[i]);
+
+  // Event_Close(&p->finishedEvent);
+
+  if (p->crossBlock)
+  {
+    ISzAlloc_Free(p->alloc, p->crossBlock);
+    p->crossBlock = NULL;
+  }
+}
+
+
+void MtDec_Destruct(CMtDec *p)
+{
+  MtDec_Free(p);
+
+  CriticalSection_Delete(&p->mtProgress.cs);
+}
+
+
+SRes MtDec_Code(CMtDec *p)
+{
+  unsigned i;
+
+  p->inProcessed = 0;
+
+  p->blockIndex = 1; // it must be larger than not_defined index (0)
+  p->isAllocError = False;
+  p->overflow = False;
+  p->threadingErrorSRes = SZ_OK;
+
+  p->needContinue = True;
+
+  p->readWasFinished = False;
+  p->needInterrupt = False;
+  p->interruptIndex = (UInt64)(Int64)-1;
+
+  p->readProcessed = 0;
+  p->readRes = SZ_OK;
+  p->codeRes = SZ_OK;
+  p->wasInterrupted = False;
+
+  p->crossStart = 0;
+  p->crossEnd = 0;
+
+  p->filledThreadStart = 0;
+  p->numFilledThreads = 0;
+
+  {
+    unsigned numThreads = p->numThreadsMax;
+    if (numThreads > MTDEC_THREADS_MAX)
+      numThreads = MTDEC_THREADS_MAX;
+    p->numStartedThreads_Limit = numThreads;
+    p->numStartedThreads = 0;
+  }
+
+  if (p->inBufSize != p->allocatedBufsSize)
+  {
+    for (i = 0; i < MTDEC_THREADS_MAX; i++)
+    {
+      CMtDecThread *t = &p->threads[i];
+      if (t->inBuf)
+        MtDecThread_FreeInBufs(t);
+    }
+    if (p->crossBlock)
+    {
+      ISzAlloc_Free(p->alloc, p->crossBlock);
+      p->crossBlock = NULL;
+    }
+
+    p->allocatedBufsSize = p->inBufSize;
+  }
+
+  MtProgress_Init(&p->mtProgress, p->progress);
+
+  // RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent))
+  p->exitThread = False;
+  p->exitThreadWRes = 0;
+
+  {
+    WRes wres;
+    SRes sres;
+    CMtDecThread *nextThread = &p->threads[p->numStartedThreads++];
+    // wres = MtDecThread_CreateAndStart(nextThread);
+    wres = MtDecThread_CreateEvents(nextThread);
+    if (wres == 0) { wres = Event_Set(&nextThread->canWrite);
+    if (wres == 0) { wres = Event_Set(&nextThread->canRead);
+    if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread);
+    wres = (WRes)(MY_uintptr_t)res;
+    if (wres != 0)
+    {
+      p->needContinue = False;
+      MtDec_CloseThreads(p);
+    }}}}
+
+    // wres = 17; // for test
+    // wres = Event_Wait(&p->finishedEvent);
+
+    sres = MY_SRes_HRESULT_FROM_WRes(wres);
+
+    if (sres != 0)
+      p->threadingErrorSRes = sres;
+
+    if (
+        // wres == 0
+        // wres != 0
+        // || p->mtc.codeRes == SZ_ERROR_MEM
+        p->isAllocError
+        || p->threadingErrorSRes != SZ_OK
+        || p->overflow)
+    {
+      // p->needContinue = True;
+    }
+    else
+      p->needContinue = False;
+    
+    if (p->needContinue)
+      return SZ_OK;
+
+    // if (sres != SZ_OK)
+    return sres;
+    // return SZ_ERROR_FAIL;
+  }
+}
+
+#endif
+
+#undef PRF

+ 202 - 0
Components/Lzma2/MtDec.h

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

+ 127 - 0
Components/Lzma2/Precomp.h

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

+ 517 - 20
Components/Lzma2/Threads.c

@@ -1,46 +1,134 @@
 /* Threads.c -- multithreading library
 /* Threads.c -- multithreading library
-2009-09-20 : Igor Pavlov : Public domain */
+2024-03-28 : Igor Pavlov : Public domain */
 
 
-#ifndef _WIN32_WCE
+#include "Precomp.h"
+
+#ifdef _WIN32
+
+#ifndef USE_THREADS_CreateThread
 #include <process.h>
 #include <process.h>
 #endif
 #endif
 
 
 #include "Threads.h"
 #include "Threads.h"
 
 
-static WRes GetError()
+static WRes GetError(void)
 {
 {
-  DWORD res = GetLastError();
-  return (res) ? (WRes)(res) : 1;
+  const DWORD res = GetLastError();
+  return res ? (WRes)res : 1;
 }
 }
 
 
-WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
-WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
+static WRes HandleToWRes(HANDLE h) { return (h != NULL) ? 0 : GetError(); }
+static WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
 
 
 WRes HandlePtr_Close(HANDLE *p)
 WRes HandlePtr_Close(HANDLE *p)
 {
 {
   if (*p != NULL)
   if (*p != NULL)
+  {
     if (!CloseHandle(*p))
     if (!CloseHandle(*p))
       return GetError();
       return GetError();
-  *p = NULL;
+    *p = NULL;
+  }
   return 0;
   return 0;
 }
 }
 
 
-WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }
+WRes Handle_WaitObject(HANDLE h)
+{
+  DWORD dw = WaitForSingleObject(h, INFINITE);
+  /*
+    (dw) result:
+    WAIT_OBJECT_0  // 0
+    WAIT_ABANDONED // 0x00000080 : is not compatible with Win32 Error space
+    WAIT_TIMEOUT   // 0x00000102 : is     compatible with Win32 Error space
+    WAIT_FAILED    // 0xFFFFFFFF
+  */
+  if (dw == WAIT_FAILED)
+  {
+    dw = GetLastError();
+    if (dw == 0)
+      return WAIT_FAILED;
+  }
+  return (WRes)dw;
+}
+
+#define Thread_Wait(p) Handle_WaitObject(*(p))
+
+WRes Thread_Wait_Close(CThread *p)
+{
+  WRes res = Thread_Wait(p);
+  WRes res2 = Thread_Close(p);
+  return (res != 0 ? res : res2);
+}
 
 
 WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
 WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
 {
 {
-  unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
-  *p =
-    #ifdef UNDER_CE
-    CreateThread(0, 0, func, param, 0, &threadId);
-    #else
-    (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
-    #endif
-    /* maybe we must use errno here, but probably GetLastError() is also OK. */
+  /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
+
+  #ifdef USE_THREADS_CreateThread
+
+  DWORD threadId;
+  *p = CreateThread(NULL, 0, func, param, 0, &threadId);
+  
+  #else
+  
+  unsigned threadId;
+  *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId));
+  
+  #endif
+
+  /* maybe we must use errno here, but probably GetLastError() is also OK. */
   return HandleToWRes(*p);
   return HandleToWRes(*p);
 }
 }
 
 
-WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
+
+WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity)
+{
+  #ifdef USE_THREADS_CreateThread
+
+  UNUSED_VAR(affinity)
+  return Thread_Create(p, func, param);
+  
+  #else
+  
+  /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
+  HANDLE h;
+  WRes wres;
+  unsigned threadId;
+  h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId));
+  *p = h;
+  wres = HandleToWRes(h);
+  if (h)
+  {
+    {
+      // DWORD_PTR prevMask =
+      SetThreadAffinityMask(h, (DWORD_PTR)affinity);
+      /*
+      if (prevMask == 0)
+      {
+        // affinity change is non-critical error, so we can ignore it
+        // wres = GetError();
+      }
+      */
+    }
+    {
+      DWORD prevSuspendCount = ResumeThread(h);
+      /* ResumeThread() returns:
+         0 : was_not_suspended
+         1 : was_resumed
+        -1 : error
+      */
+      if (prevSuspendCount == (DWORD)-1)
+        wres = GetError();
+    }
+  }
+
+  /* maybe we must use errno here, but probably GetLastError() is also OK. */
+  return wres;
+
+  #endif
+}
+
+
+static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
 {
 {
   *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
   *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
   return HandleToWRes(*p);
   return HandleToWRes(*p);
@@ -57,10 +145,22 @@ WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEven
 
 
 WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
 WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
 {
 {
+  // negative ((LONG)maxCount) is not supported in WIN32::CreateSemaphore()
   *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
   *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
   return HandleToWRes(*p);
   return HandleToWRes(*p);
 }
 }
 
 
+WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
+{
+  // if (Semaphore_IsCreated(p))
+  {
+    WRes wres = Semaphore_Close(p);
+    if (wres != 0)
+      return wres;
+  }
+  return Semaphore_Create(p, initCount, maxCount);
+}
+
 static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
 static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
   { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
   { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
 WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
 WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
@@ -69,8 +169,13 @@ WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
 
 
 WRes CriticalSection_Init(CCriticalSection *p)
 WRes CriticalSection_Init(CCriticalSection *p)
 {
 {
-  /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
+  /* InitializeCriticalSection() can raise exception:
+     Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception
+     Windows Vista+   : no exceptions */
   #ifdef _MSC_VER
   #ifdef _MSC_VER
+  #ifdef __clang__
+    #pragma GCC diagnostic ignored "-Wlanguage-extension-token"
+  #endif
   __try
   __try
   #endif
   #endif
   {
   {
@@ -78,7 +183,399 @@ WRes CriticalSection_Init(CCriticalSection *p)
     /* InitializeCriticalSectionAndSpinCount(p, 0); */
     /* InitializeCriticalSectionAndSpinCount(p, 0); */
   }
   }
   #ifdef _MSC_VER
   #ifdef _MSC_VER
-  __except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
+  __except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; }
   #endif
   #endif
   return 0;
   return 0;
 }
 }
+
+
+
+
+#else // _WIN32
+
+// ---------- POSIX ----------
+
+#if defined(__linux__) && !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
+#ifndef Z7_AFFINITY_DISABLE
+// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET
+// clang < 3.6       : unknown warning group '-Wreserved-id-macro'
+// clang 3.6 - 12.01 : gives warning "macro name is a reserved identifier"
+// clang >= 13       : do not give warning
+#if !defined(_GNU_SOURCE)
+Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
+// #define _GNU_SOURCE
+Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
+#endif // !defined(_GNU_SOURCE)
+#endif // Z7_AFFINITY_DISABLE
+#endif // __linux__
+
+#include "Threads.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef Z7_AFFINITY_SUPPORTED
+// #include <sched.h>
+#endif
+
+
+// #include <stdio.h>
+// #define PRF(p) p
+#define PRF(p)
+#define Print(s) PRF(printf("\n%s\n", s);)
+
+WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet)
+{
+  // new thread in Posix probably inherits affinity from parrent thread
+  Print("Thread_Create_With_CpuSet")
+
+  pthread_attr_t attr;
+  int ret;
+  // int ret2;
+
+  p->_created = 0;
+
+  RINOK(pthread_attr_init(&attr))
+
+  ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+  if (!ret)
+  {
+    if (cpuSet)
+    {
+      // pthread_attr_setaffinity_np() is not supported for MUSL compile.
+      // so we check for __GLIBC__ here
+#if defined(Z7_AFFINITY_SUPPORTED) && defined( __GLIBC__)
+      /*
+      printf("\n affinity :");
+      unsigned i;
+      for (i = 0; i < sizeof(*cpuSet) && i < 8; i++)
+      {
+        Byte b = *((const Byte *)cpuSet + i);
+        char temp[32];
+        #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
+        temp[0] = GET_HEX_CHAR((b & 0xF));
+        temp[1] = GET_HEX_CHAR((b >> 4));
+        // temp[0] = GET_HEX_CHAR((b >> 4));  // big-endian
+        // temp[1] = GET_HEX_CHAR((b & 0xF));  // big-endian
+        temp[2] = 0;
+        printf("%s", temp);
+      }
+      printf("\n");
+      */
+
+      // ret2 =
+      pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet);
+      // if (ret2) ret = ret2;
+#endif
+    }
+    
+    ret = pthread_create(&p->_tid, &attr, func, param);
+    
+    if (!ret)
+    {
+      p->_created = 1;
+      /*
+      if (cpuSet)
+      {
+        // ret2 =
+        pthread_setaffinity_np(p->_tid, sizeof(*cpuSet), cpuSet);
+        // if (ret2) ret = ret2;
+      }
+      */
+    }
+  }
+  // ret2 =
+  pthread_attr_destroy(&attr);
+  // if (ret2 != 0) ret = ret2;
+  return ret;
+}
+
+
+WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
+{
+  return Thread_Create_With_CpuSet(p, func, param, NULL);
+}
+
+
+WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity)
+{
+  Print("Thread_Create_WithAffinity")
+  CCpuSet cs;
+  unsigned i;
+  CpuSet_Zero(&cs);
+  for (i = 0; i < sizeof(affinity) * 8; i++)
+  {
+    if (affinity == 0)
+      break;
+    if (affinity & 1)
+    {
+      CpuSet_Set(&cs, i);
+    }
+    affinity >>= 1;
+  }
+  return Thread_Create_With_CpuSet(p, func, param, &cs);
+}
+
+
+WRes Thread_Close(CThread *p)
+{
+  // Print("Thread_Close")
+  int ret;
+  if (!p->_created)
+    return 0;
+    
+  ret = pthread_detach(p->_tid);
+  p->_tid = 0;
+  p->_created = 0;
+  return ret;
+}
+
+
+WRes Thread_Wait_Close(CThread *p)
+{
+  // Print("Thread_Wait_Close")
+  void *thread_return;
+  int ret;
+  if (!p->_created)
+    return EINVAL;
+
+  ret = pthread_join(p->_tid, &thread_return);
+  // probably we can't use that (_tid) after pthread_join(), so we close thread here
+  p->_created = 0;
+  p->_tid = 0;
+  return ret;
+}
+
+
+
+static WRes Event_Create(CEvent *p, int manualReset, int signaled)
+{
+  RINOK(pthread_mutex_init(&p->_mutex, NULL))
+  RINOK(pthread_cond_init(&p->_cond, NULL))
+  p->_manual_reset = manualReset;
+  p->_state = (signaled ? True : False);
+  p->_created = 1;
+  return 0;
+}
+
+WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled)
+  { return Event_Create(p, True, signaled); }
+WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p)
+  { return ManualResetEvent_Create(p, 0); }
+WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled)
+  { return Event_Create(p, False, signaled); }
+WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p)
+  { return AutoResetEvent_Create(p, 0); }
+
+
+#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13)
+// freebsd:
+#pragma GCC diagnostic ignored "-Wthread-safety-analysis"
+#endif
+
+WRes Event_Set(CEvent *p)
+{
+  RINOK(pthread_mutex_lock(&p->_mutex))
+  p->_state = True;
+  {
+    const int res1 = pthread_cond_broadcast(&p->_cond);
+    const int res2 = pthread_mutex_unlock(&p->_mutex);
+    return (res2 ? res2 : res1);
+  }
+}
+
+WRes Event_Reset(CEvent *p)
+{
+  RINOK(pthread_mutex_lock(&p->_mutex))
+  p->_state = False;
+  return pthread_mutex_unlock(&p->_mutex);
+}
+ 
+WRes Event_Wait(CEvent *p)
+{
+  RINOK(pthread_mutex_lock(&p->_mutex))
+  while (p->_state == False)
+  {
+    // ETIMEDOUT
+    // ret =
+    pthread_cond_wait(&p->_cond, &p->_mutex);
+    // if (ret != 0) break;
+  }
+  if (p->_manual_reset == False)
+  {
+    p->_state = False;
+  }
+  return pthread_mutex_unlock(&p->_mutex);
+}
+
+WRes Event_Close(CEvent *p)
+{
+  if (!p->_created)
+    return 0;
+  p->_created = 0;
+  {
+    const int res1 = pthread_mutex_destroy(&p->_mutex);
+    const int res2 = pthread_cond_destroy(&p->_cond);
+    return (res1 ? res1 : res2);
+  }
+}
+
+
+WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
+{
+  if (initCount > maxCount || maxCount < 1)
+    return EINVAL;
+  RINOK(pthread_mutex_init(&p->_mutex, NULL))
+  RINOK(pthread_cond_init(&p->_cond, NULL))
+  p->_count = initCount;
+  p->_maxCount = maxCount;
+  p->_created = 1;
+  return 0;
+}
+
+
+WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
+{
+  if (Semaphore_IsCreated(p))
+  {
+    /*
+    WRes wres = Semaphore_Close(p);
+    if (wres != 0)
+      return wres;
+    */
+    if (initCount > maxCount || maxCount < 1)
+      return EINVAL;
+    // return EINVAL; // for debug
+    p->_count = initCount;
+    p->_maxCount = maxCount;
+    return 0;
+  }
+  return Semaphore_Create(p, initCount, maxCount);
+}
+
+
+WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount)
+{
+  UInt32 newCount;
+  int ret;
+
+  if (releaseCount < 1)
+    return EINVAL;
+
+  RINOK(pthread_mutex_lock(&p->_mutex))
+
+  newCount = p->_count + releaseCount;
+  if (newCount > p->_maxCount)
+    ret = ERROR_TOO_MANY_POSTS; // EINVAL;
+  else
+  {
+    p->_count = newCount;
+    ret = pthread_cond_broadcast(&p->_cond);
+  }
+  RINOK(pthread_mutex_unlock(&p->_mutex))
+  return ret;
+}
+
+WRes Semaphore_Wait(CSemaphore *p)
+{
+  RINOK(pthread_mutex_lock(&p->_mutex))
+  while (p->_count < 1)
+  {
+    pthread_cond_wait(&p->_cond, &p->_mutex);
+  }
+  p->_count--;
+  return pthread_mutex_unlock(&p->_mutex);
+}
+
+WRes Semaphore_Close(CSemaphore *p)
+{
+  if (!p->_created)
+    return 0;
+  p->_created = 0;
+  {
+    const int res1 = pthread_mutex_destroy(&p->_mutex);
+    const int res2 = pthread_cond_destroy(&p->_cond);
+    return (res1 ? res1 : res2);
+  }
+}
+
+
+
+WRes CriticalSection_Init(CCriticalSection *p)
+{
+  // Print("CriticalSection_Init")
+  if (!p)
+    return EINTR;
+  return pthread_mutex_init(&p->_mutex, NULL);
+}
+
+void CriticalSection_Enter(CCriticalSection *p)
+{
+  // Print("CriticalSection_Enter")
+  if (p)
+  {
+    // int ret =
+    pthread_mutex_lock(&p->_mutex);
+  }
+}
+
+void CriticalSection_Leave(CCriticalSection *p)
+{
+  // Print("CriticalSection_Leave")
+  if (p)
+  {
+    // int ret =
+    pthread_mutex_unlock(&p->_mutex);
+  }
+}
+
+void CriticalSection_Delete(CCriticalSection *p)
+{
+  // Print("CriticalSection_Delete")
+  if (p)
+  {
+    // int ret =
+    pthread_mutex_destroy(&p->_mutex);
+  }
+}
+
+LONG InterlockedIncrement(LONG volatile *addend)
+{
+  // Print("InterlockedIncrement")
+  #ifdef USE_HACK_UNSAFE_ATOMIC
+    LONG val = *addend + 1;
+    *addend = val;
+    return val;
+  #else
+
+  #if defined(__clang__) && (__clang_major__ >= 8)
+    #pragma GCC diagnostic ignored "-Watomic-implicit-seq-cst"
+  #endif
+    return __sync_add_and_fetch(addend, 1);
+  #endif
+}
+
+LONG InterlockedDecrement(LONG volatile *addend)
+{
+  // Print("InterlockedDecrement")
+  #ifdef USE_HACK_UNSAFE_ATOMIC
+    LONG val = *addend - 1;
+    *addend = val;
+    return val;
+  #else
+    return __sync_sub_and_fetch(addend, 1);
+  #endif
+}
+
+#endif // _WIN32
+
+WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p)
+{
+  if (Event_IsCreated(p))
+    return Event_Reset(p);
+  return AutoResetEvent_CreateNotSignaled(p);
+}
+
+#undef PRF
+#undef Print

+ 206 - 15
Components/Lzma2/Threads.h

@@ -1,28 +1,153 @@
 /* Threads.h -- multithreading library
 /* Threads.h -- multithreading library
-2009-03-27 : Igor Pavlov : Public domain */
+2024-03-28 : Igor Pavlov : Public domain */
 
 
-#ifndef __7Z_THREADS_H
-#define __7Z_THREADS_H
+#ifndef ZIP7_INC_THREADS_H
+#define ZIP7_INC_THREADS_H
 
 
-#include "Types.h"
+#ifdef _WIN32
+#include "7zWindows.h"
 
 
-#ifdef __cplusplus
-extern "C" {
+#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
 #endif
 
 
+#include <pthread.h>
+
+#endif
+
+#include "7zTypes.h"
+
+EXTERN_C_BEGIN
+
+#ifdef _WIN32
+
 WRes HandlePtr_Close(HANDLE *h);
 WRes HandlePtr_Close(HANDLE *h);
 WRes Handle_WaitObject(HANDLE h);
 WRes Handle_WaitObject(HANDLE h);
 
 
 typedef HANDLE CThread;
 typedef HANDLE CThread;
-#define Thread_Construct(p) *(p) = NULL
+
+#define Thread_CONSTRUCT(p) { *(p) = NULL; }
 #define Thread_WasCreated(p) (*(p) != NULL)
 #define Thread_WasCreated(p) (*(p) != NULL)
 #define Thread_Close(p) HandlePtr_Close(p)
 #define Thread_Close(p) HandlePtr_Close(p)
-#define Thread_Wait(p) Handle_WaitObject(*(p))
-typedef unsigned THREAD_FUNC_RET_TYPE;
-#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
-#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
+// #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 *);
 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(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 HANDLE CEvent;
 typedef CEvent CAutoResetEvent;
 typedef CEvent CAutoResetEvent;
@@ -39,10 +164,12 @@ WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
 WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
 WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
 
 
 typedef HANDLE CSemaphore;
 typedef HANDLE CSemaphore;
-#define Semaphore_Construct(p) (*p) = NULL
+#define Semaphore_Construct(p) *(p) = NULL
+#define Semaphore_IsCreated(p) (*(p) != NULL)
 #define Semaphore_Close(p) HandlePtr_Close(p)
 #define Semaphore_Close(p) HandlePtr_Close(p)
 #define Semaphore_Wait(p) Handle_WaitObject(*(p))
 #define Semaphore_Wait(p) Handle_WaitObject(*(p))
 WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
 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_ReleaseN(CSemaphore *p, UInt32 num);
 WRes Semaphore_Release1(CSemaphore *p);
 WRes Semaphore_Release1(CSemaphore *p);
 
 
@@ -52,8 +179,72 @@ WRes CriticalSection_Init(CCriticalSection *p);
 #define CriticalSection_Enter(p) EnterCriticalSection(p)
 #define CriticalSection_Enter(p) EnterCriticalSection(p)
 #define CriticalSection_Leave(p) LeaveCriticalSection(p)
 #define CriticalSection_Leave(p) LeaveCriticalSection(p)
 
 
-#ifdef __cplusplus
-}
-#endif
+
+#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
 #endif

+ 0 - 236
Components/Lzma2/Types.h

@@ -1,236 +0,0 @@
-/* Types.h -- Basic types
-2010-03-11 : Igor Pavlov : Public domain */
-
-#ifndef __7Z_TYPES_H
-#define __7Z_TYPES_H
-
-#include <stddef.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#ifndef EXTERN_C_BEGIN
-#ifdef __cplusplus
-#define EXTERN_C_BEGIN extern "C" {
-#define EXTERN_C_END }
-#else
-#define EXTERN_C_BEGIN
-#define EXTERN_C_END
-#endif
-#endif
-
-EXTERN_C_BEGIN
-
-#define SZ_OK 0
-
-#define SZ_ERROR_DATA 1
-#define SZ_ERROR_MEM 2
-#define SZ_ERROR_CRC 3
-#define SZ_ERROR_UNSUPPORTED 4
-#define SZ_ERROR_PARAM 5
-#define SZ_ERROR_INPUT_EOF 6
-#define SZ_ERROR_OUTPUT_EOF 7
-#define SZ_ERROR_READ 8
-#define SZ_ERROR_WRITE 9
-#define SZ_ERROR_PROGRESS 10
-#define SZ_ERROR_FAIL 11
-#define SZ_ERROR_THREAD 12
-
-#define SZ_ERROR_ARCHIVE 16
-#define SZ_ERROR_NO_ARCHIVE 17
-
-typedef int SRes;
-
-#ifdef _WIN32
-typedef DWORD WRes;
-#else
-typedef int WRes;
-#endif
-
-#ifndef RINOK
-#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
-#endif
-
-typedef unsigned char Byte;
-typedef short Int16;
-typedef unsigned short UInt16;
-
-#ifdef _LZMA_UINT32_IS_ULONG
-typedef long Int32;
-typedef unsigned long UInt32;
-#else
-typedef int Int32;
-typedef unsigned int UInt32;
-#endif
-
-#ifdef _SZ_NO_INT_64
-
-/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
-   NOTES: Some code will work incorrectly in that case! */
-
-typedef long Int64;
-typedef unsigned long UInt64;
-
-#else
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-typedef __int64 Int64;
-typedef unsigned __int64 UInt64;
-#else
-typedef long long int Int64;
-typedef unsigned long long int UInt64;
-#endif
-
-#endif
-
-#ifdef _LZMA_NO_SYSTEM_SIZE_T
-typedef UInt32 SizeT;
-#else
-typedef size_t SizeT;
-#endif
-
-typedef int Bool;
-#define True 1
-#define False 0
-
-
-#ifdef _WIN32
-#define MY_STD_CALL __stdcall
-#else
-#define MY_STD_CALL
-#endif
-
-#ifdef _MSC_VER
-
-#if _MSC_VER >= 1300
-#define MY_NO_INLINE __declspec(noinline)
-#else
-#define MY_NO_INLINE
-#endif
-
-#define MY_CDECL __cdecl
-#define MY_FAST_CALL __fastcall
-
-#else
-
-#define MY_CDECL
-#define MY_FAST_CALL
-
-#endif
-
-
-/* The following interfaces use first parameter as pointer to structure */
-
-typedef struct
-{
-  Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
-} IByteIn;
-
-typedef struct
-{
-  void (*Write)(void *p, Byte b);
-} IByteOut;
-
-typedef struct
-{
-  SRes (*Read)(void *p, void *buf, size_t *size);
-    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
-       (output(*size) < input(*size)) is allowed */
-} ISeqInStream;
-
-/* it can return SZ_ERROR_INPUT_EOF */
-SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
-SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
-SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
-
-typedef struct
-{
-  size_t (*Write)(void *p, const void *buf, size_t size);
-    /* Returns: result - the number of actually written bytes.
-       (result < size) means error */
-} ISeqOutStream;
-
-typedef enum
-{
-  SZ_SEEK_SET = 0,
-  SZ_SEEK_CUR = 1,
-  SZ_SEEK_END = 2
-} ESzSeek;
-
-typedef struct
-{
-  SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */
-  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
-} ISeekInStream;
-
-typedef struct
-{
-  SRes (*Look)(void *p, const void **buf, size_t *size);
-    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
-       (output(*size) > input(*size)) is not allowed
-       (output(*size) < input(*size)) is allowed */
-  SRes (*Skip)(void *p, size_t offset);
-    /* offset must be <= output(*size) of Look */
-
-  SRes (*Read)(void *p, void *buf, size_t *size);
-    /* reads directly (without buffer). It's same as ISeqInStream::Read */
-  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
-} ILookInStream;
-
-SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
-SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
-
-/* reads via ILookInStream::Read */
-SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
-SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
-
-#define LookToRead_BUF_SIZE (1 << 14)
-
-typedef struct
-{
-  ILookInStream s;
-  ISeekInStream *realStream;
-  size_t pos;
-  size_t size;
-  Byte buf[LookToRead_BUF_SIZE];
-} CLookToRead;
-
-void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
-void LookToRead_Init(CLookToRead *p);
-
-typedef struct
-{
-  ISeqInStream s;
-  ILookInStream *realStream;
-} CSecToLook;
-
-void SecToLook_CreateVTable(CSecToLook *p);
-
-typedef struct
-{
-  ISeqInStream s;
-  ILookInStream *realStream;
-} CSecToRead;
-
-void SecToRead_CreateVTable(CSecToRead *p);
-
-typedef struct
-{
-  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
-    /* Returns: result. (result != SZ_OK) means break.
-       Value (UInt64)(Int64)-1 for size means unknown value. */
-} ICompressProgress;
-
-typedef struct
-{
-  void *(*Alloc)(void *p, size_t size);
-  void (*Free)(void *p, void *address); /* address can be 0 */
-} ISzAlloc;
-
-#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
-#define IAlloc_Free(p, a) (p)->Free((p), a)
-
-EXTERN_C_END
-
-#endif

+ 615 - 0
Components/Lzma2/lzma-history.txt

@@ -0,0 +1,615 @@
+HISTORY of the LZMA SDK
+-----------------------
+
+24.07          2024-06-19
+-------------------------
+- Changes in files:
+    Asm/x86/Sha256Opt.asm
+  Now it uses "READONLY" flag for constant array segment.
+  It fixes an issue where ".rodata" section in 7-Zip for x86/x64 Linux had a "WRITE" attribute.
+
+
+24.05          2024-05-14
+-------------------------
+- New switch -myv={MMNN} to set decoder compatibility version for 7z archive creating.
+  {MMNN} is 4-digit number that represents the version of 7-Zip without a dot.
+  If -myv={MMNN} switch is specified, 7-Zip will only use compression methods that can 
+  be decoded by the specified version {MMNN} of 7-Zip and newer versions.
+  If -myv={MMNN} switch is not specified, -myv=2300 is used, and 7-Zip will only
+  use compression methods that can be decoded by 7-Zip 23.00 and newer versions.
+- New switch -myfa={FilterID} to    allow 7-Zip to use the specified filter method for 7z archive creating.
+- New switch -myfd={FilterID} to disallow 7-Zip to use the specified filter method for 7z archive creating.
+
+
+24.03          2024-03-23
+-------------------------
+- 7-Zip now can use new RISCV filter for compression to 7z and xz archives.
+  RISCV filter can increase compression ratio for data containing executable
+  files compiled for RISC-V architecture.
+- The speed for LZMA and LZMA2 decompression in ARM64 version for Windows
+  was increased by 20%-60%.
+  It uses arm64 assembler code, and clang-cl is required for arm64 assembler code compiling.
+- -slmu switch : to show timestamps as UTC instead of LOCAL TIME.
+- -slsl switch : in console 7-Zip for Windows : to show file paths with 
+  linux path separator slash '/' instead of backslash separator '\'.
+- 7-Zip supports .sha256 files that use backslash path separator '\'.
+- Some bugs were fixed.
+
+
+24.01          2024-01-31
+-------------------------
+- 7-Zip uses file C/Precomp.h that is included to all c and c++ files.
+  CPP/Common/Common.h also includes C/Precomp.h.
+  C/Precomp.h defines the following macros (if _WIN32 is defined):
+    Z7_LARGE_PAGES 1
+    Z7_LONG_PATH 1
+    Z7_WIN32_WINNT_MIN  0x0500 (or higher)
+    _WIN32_WINNT        0x0500 (or higher)
+    WINVER  _WIN32_WINNT
+    UNICODE 1
+    _UNICODE 1
+  if _WIN32_WINNT is defined already, C/Precomp.h doesn't redefine it.
+
+- Speed optimizations for hash caclulation: CRC-32, CRC-64.
+- The bug was fixed: 7-Zip for Linux could fail for multivolume creation in some cases.
+- 7zr.exe for arm64 is included to LZMA SDK package.
+- Some bugs were fixed.
+
+
+23.01          2023-06-20
+-------------------------
+- 7-Zip now can use new ARM64 filter for compression to 7z and xz archives.
+  ARM64 filter can increase compression ratio for data containing executable 
+  files compiled for ARM64 (AArch64) architecture.
+  Also 7-Zip now parses executable files (that have exe and dll filename extensions) 
+  before compressing, and it selects appropriate filter for each parsed file: 
+    - BCJ or BCJ2 filter for x86 executable files,
+    - ARM64 filter for ARM64 executable files.
+  Previous versions by default used x86 filter BCJ or BCJ2 for all exe/dll files.
+- Default section size for BCJ2 filter was changed from 64 MiB to 240 MiB.
+  It can increase compression ratio for executable files larger than 64 MiB.
+- Some optimizations in filters code: BCJ, BCJ2, Swap* and opthers.
+- If 7-Zip uses BCJ2 filter for big datasets compressing, it can use additional temp 
+  files in system's TEMP folder. 7-Zip uses temp file for additional compressed 
+  data stream, if size of such compressed stream is larger than predefined limit: 
+  16 MiB in 32-bit version, 4 GiB in 64-bit version.
+- When new 7-Zip creates multivolume archive, 7-Zip keeps in open state
+  only volumes that still can be changed. Previous versions kept all volumes 
+  in open state until the end of the archive creation.
+- 7-Zip for Linux and macOS now can reduce the number of simultaneously open files,
+  when 7-Zip opens, extracts or creates multivolume archive. It allows to avoid 
+  the failures for cases with big number of volumes, bacause there is a limitation 
+  for number of open files allowed for a single program in Linux and macOS.
+- Some bugs were fixed.
+- Source code changes:
+- All external macros for compiling C/C++ code of 7-Zip now have Z7_ prefix.
+- 7-Zip COM interfaces now use new macros that allow to declare and implement COM interface.
+- The code has been modified to compile with the maximum diagnostic warning level:
+    -Wall in MSVC and -Weverything in CLANG.
+  And some warning types are disabled in 2 files:
+    - C/Compiler.h for C/C++ code warnings.
+    - CPP/Common/Common.h for C++ code warnings.
+- Linux/macOS versions of 7-Zip: IUnknown interface in new code doesn't use 
+  virtual destructor that was used in previous 7-Zip and p7zip:
+     // virtual ~IUnknown() {}
+  So 7-Zip's dynamically linked shared libraries (codecs) are not compatible 
+  between new 7-Zip for Linux/macOS and old 7-Zip (and p7zip).
+
+
+21.07          2021-12-26
+-------------------------
+- New switches: -spm and -im!{file_path} to exclude directories from processing 
+    for specified paths that don't contain path separator character at the end of path.
+- The sorting order of files in archives was slightly changed to be more consistent
+  for cases where the name of some directory is the same as the prefix part of the name
+  of another directory or file.
+
+
+21.06          2021-11-24
+-------------------------
+- Bug in LZMA encoder in file LzmaEnc.c was fixed:
+  LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly, 
+    if size value for output buffer is smaller than size required for all compressed data.
+  LzmaEnc_Encode() could work incorrectly,
+    if callback ISeqOutStream::Write() doesn't write all compressed data.
+  NCompress::NLzma::CEncoder::Code() could work incorrectly,
+    if callback ISequentialOutStream::Write() returns error code.
+- Bug in versions 21.00-21.05 was fixed:
+  7-Zip didn't set attributes of directories during archive extracting.
+
+
+21.04 beta     2021-11-02
+-------------------------
+- 7-Zip now reduces the number of working CPU threads for compression,
+  if RAM size is not enough for compression with big LZMA2 dictionary.
+- 7-Zip now can create and check "file.sha256" text files that contain the list 
+  of file names and SHA-256 checksums in format compatible with sha256sum program.
+
+
+21.03 beta     2021-07-20
+-------------------------
+- The maximum dictionary size for LZMA/LZMA2 compressing was increased to 4 GB (3840 MiB).
+- Minor speed optimizations in LZMA/LZMA2 compressing.
+
+
+21.02 alpha    2021-05-06
+-------------------------
+- The command line version of 7-Zip for macOS was released.
+- The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux 
+  was increased by 20%-60%.
+
+
+21.01 alpha    2021-03-09
+-------------------------
+- The command line version of 7-Zip for Linux was released.
+- The improvements for speed of ARM64 version using hardware CPU instructions 
+  for AES, CRC-32, SHA-1 and SHA-256.
+- Some bugs were fixed.
+
+
+20.02 alpha    2020-08-08
+-------------------------
+- The default number of LZMA2 chunks per solid block in 7z archive was increased to 64.
+  It allows to increase the compression speed for big 7z archives, if there is a big number 
+  of CPU cores and threads.
+- The speed of PPMd compressing/decompressing was increased for 7z archives.
+- The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system 
+  to modify "Last Access Time" property of source files for archiving and hashing operations. 
+- Some bugs were fixed.
+
+
+20.00 alpha    2020-02-06
+-------------------------
+- 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5, 
+  that can work faster than bt4 and hc4 match finders for the data with big redundancy.
+- The compression ratio was improved for Fast and Fastest compression levels with the 
+  following default settings:
+   - Fastest level (-mx1) : hc5 match finder with 256 KB dictionary.
+   - Fast    level (-mx3) : hc5 match finder with 4 MB dictionary.
+- Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra 
+  compression levels.
+
+
+19.00          2019-02-21
+-------------------------
+- Encryption strength for 7z archives was increased:
+  the size of random initialization vector was increased from 64-bit to 128-bit,
+  and the pseudo-random number generator was improved.
+- The bug in 7zIn.c code was fixed.
+
+
+18.06          2018-12-30
+-------------------------
+- The speed for LZMA/LZMA2 compressing was increased by 3-10%,
+  and there are minor changes in compression ratio.
+- Some bugs were fixed.
+- The bug in 7-Zip 18.02-18.05 was fixed:
+  There was memory leak in multithreading xz decoder - XzDecMt_Decode(),
+  if xz stream contains only one block.
+- The changes for MSVS compiler makefiles: 
+   - the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64)
+     instead of "CPU" macroname with values (AMD64, ARM64).
+   - the makefiles by default now use static version of the run-time library.
+
+
+18.05          2018-04-30
+-------------------------
+- The speed for LZMA/LZMA2 compressing was increased 
+    by 8% for fastest/fast compression levels and 
+    by 3% for normal/maximum compression levels.
+- Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in
+  Windows 10 because of some BUG with "Large Pages" in Windows 10. 
+  Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299).
+- The BUG was fixed in Lzma2Enc.c
+    Lzma2Enc_Encode2() function worked incorretly,
+      if (inStream == NULL) and the number of block threads is more than 1.
+
+
+18.03 beta     2018-03-04
+-------------------------
+- Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm 
+  for x64 with about 30% higher speed than main version of LZMA decoder written in C.
+- The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%.
+- 7-Zip now can use multi-threading for 7z/LZMA2 decoding,
+  if there are multiple independent data chunks in LZMA2 stream.
+- 7-Zip now can use multi-threading for xz decoding,
+  if there are multiple blocks in xz stream.
+
+
+18.01          2019-01-28
+-------------------------
+- The BUG in 17.01 - 18.00 beta was fixed:
+  XzDec.c : random block unpacking and XzUnpacker_IsBlockFinished()
+  didn't work correctly for xz archives without checksum (CRC).
+
+
+18.00 beta     2019-01-10
+-------------------------
+- The BUG in xz encoder was fixed:
+  There was memory leak of 16 KB for each file compressed with 
+  xz compression method, if additional filter was used.
+
+
+17.01 beta     2017-08-28
+-------------------------
+- Minor speed optimization for LZMA2 (xz and 7z) multi-threading compression.
+  7-Zip now uses additional memory buffers for multi-block LZMA2 compression.
+  CPU utilization was slightly improved.
+- 7-zip now creates multi-block xz archives by default. Block size can be 
+  specified with -ms[Size]{m|g} switch.
+- xz decoder now can unpack random block from multi-block xz archives.
+- 7-Zip command line: @listfile now doesn't work after -- switch.
+  Use -i@listfile before -- switch instead.
+- The BUGs were fixed:
+  7-Zip 17.00 beta crashed for commands that write anti-item to 7z archive.
+
+
+17.00 beta     2017-04-29
+-------------------------
+- NewHandler.h / NewHandler.cpp: 
+    now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900).
+- C/7zTypes.h : the names of variables in interface structures were changed (vt).
+- Some bugs were fixed. 7-Zip could crash in some cases.
+- Some internal changes in code.
+
+
+16.04          2016-10-04
+-------------------------
+- The bug was fixed in DllSecur.c.
+
+
+16.03          2016-09-28
+-------------------------
+- SFX modules now use some protection against DLL preloading attack.
+- Some bugs in 7z code were fixed.
+
+
+16.02          2016-05-21
+-------------------------
+- The BUG in 16.00 - 16.01 was fixed:
+  Split Handler (SplitHandler.cpp) returned incorrect 
+  total size value (kpidSize) for split archives.
+
+
+16.01          2016-05-19
+-------------------------	
+- Some internal changes to reduce the number of compiler warnings.
+
+
+16.00          2016-05-10
+-------------------------	
+- Some bugs were fixed.
+
+
+15.12          2015-11-19
+-------------------------	
+- The BUG in C version of 7z decoder was fixed:
+  7zDec.c : SzDecodeLzma2()
+  7z decoder could mistakenly report about decoding error for some 7z archives
+  that use LZMA2 compression method.
+  The probability to get that mistaken decoding error report was about 
+  one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size). 
+- The BUG (in 9.26-15.11) in C version of 7z decoder was fixed:
+  7zArcIn.c : SzReadHeader2()
+  7z decoder worked incorrectly for 7z archives that contain 
+  empty solid blocks, that can be placed to 7z archive, if some file is 
+  unavailable for reading during archive creation.
+
+
+15.09 beta     2015-10-16
+-------------------------	
+- The BUG in LZMA / LZMA2 encoding code was fixed.
+  The BUG in LzFind.c::MatchFinder_ReadBlock() function.
+  If input data size is larger than (4 GiB - dictionary_size),
+  the following code worked incorrectly:
+  -  LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions 
+     for compressing from memory to memory. 
+     That BUG is not related to LZMA encoder version that works via streams.
+  -  LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if 
+     default value of chunk size (CLzma2EncProps::blockSize) is changed 
+     to value larger than (4 GiB - dictionary_size).
+
+
+9.38 beta      2015-01-03
+-------------------------	
+- The BUG in 9.31-9.37 was fixed:
+  IArchiveGetRawProps interface was disabled for 7z archives.
+- The BUG in 9.26-9.36 was fixed:
+  Some code in CPP\7zip\Archive\7z\ worked correctly only under Windows.
+
+
+9.36 beta      2014-12-26
+-------------------------	
+- The BUG in command line version was fixed:
+  7-Zip created temporary archive in current folder during update archive
+  operation, if -w{Path} switch was not specified. 
+  The fixed 7-Zip creates temporary archive in folder that contains updated archive.
+- The BUG in 9.33-9.35 was fixed:
+  7-Zip silently ignored file reading errors during 7z or gz archive creation,
+  and the created archive contained only part of file that was read before error.
+  The fixed 7-Zip stops archive creation and it reports about error.
+
+
+9.35 beta      2014-12-07
+-------------------------	
+- 7zr.exe now support AES encryption.
+- SFX mudules were added to LZMA SDK
+- Some bugs were fixed.
+
+
+9.21 beta      2011-04-11
+-------------------------	
+- New class FString for file names at file systems.
+- Speed optimization in CRC code for big-endian CPUs.
+- The BUG in Lzma2Dec.c was fixed:
+    Lzma2Decode function didn't work.
+
+
+9.18 beta      2010-11-02
+-------------------------	
+- New small SFX module for installers (SfxSetup).
+
+
+9.12 beta      2010-03-24
+-------------------------
+- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work,
+  if more than 10 threads were used (or more than 20 threads in some modes).
+
+
+9.11 beta      2010-03-15
+-------------------------
+- PPMd compression method support
+   
+
+9.09           2009-12-12
+-------------------------
+- The bug was fixed:
+   Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c
+   incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8.
+- Some bugs were fixed
+
+
+9.06           2009-08-17
+-------------------------
+- Some changes in ANSI-C 7z Decoder interfaces.
+
+
+9.04           2009-05-30
+-------------------------
+- LZMA2 compression method support
+- xz format support
+
+
+4.65           2009-02-03
+-------------------------
+- Some minor fixes
+
+
+4.63           2008-12-31
+-------------------------
+- Some minor fixes
+
+
+4.61 beta      2008-11-23
+-------------------------
+- The bug in ANSI-C LZMA Decoder was fixed:
+    If encoded stream was corrupted, decoder could access memory 
+    outside of allocated range.
+- Some changes in ANSI-C 7z Decoder interfaces.
+- LZMA SDK is placed in the public domain.
+
+
+4.60 beta      2008-08-19
+-------------------------
+- Some minor fixes.
+
+
+4.59 beta      2008-08-13
+-------------------------
+- The bug was fixed:
+    LZMA Encoder in fast compression mode could access memory outside of 
+    allocated range in some rare cases.
+
+
+4.58 beta      2008-05-05
+-------------------------
+- ANSI-C LZMA Decoder was rewritten for speed optimizations.
+- ANSI-C LZMA Encoder was included to LZMA SDK.
+- C++ LZMA code now is just wrapper over ANSI-C code.
+
+
+4.57           2007-12-12
+-------------------------
+- Speed optimizations in Ñ++ LZMA Decoder. 
+- Small changes for more compatibility with some C/C++ compilers.
+
+
+4.49 beta      2007-07-05
+-------------------------
+- .7z ANSI-C Decoder:
+     - now it supports BCJ and BCJ2 filters
+     - now it supports files larger than 4 GB.
+     - now it supports "Last Write Time" field for files.
+- C++ code for .7z archives compressing/decompressing from 7-zip 
+  was included to LZMA SDK.
+  
+
+4.43           2006-06-04
+-------------------------
+- Small changes for more compatibility with some C/C++ compilers.
+  
+
+4.42           2006-05-15
+-------------------------
+- Small changes in .h files in ANSI-C version.
+  
+
+4.39 beta      2006-04-14
+-------------------------
+- The bug in versions 4.33b:4.38b was fixed:
+  C++ version of LZMA encoder could not correctly compress 
+  files larger than 2 GB with HC4 match finder (-mfhc4).
+  
+
+4.37 beta      2005-04-06
+-------------------------
+- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 
+
+
+4.35 beta      2005-03-02
+-------------------------
+- The bug was fixed in C++ version of LZMA Decoder:
+    If encoded stream was corrupted, decoder could access memory 
+    outside of allocated range.
+
+
+4.34 beta      2006-02-27
+-------------------------
+- Compressing speed and memory requirements for compressing were increased
+- LZMA now can use only these match finders: HC4, BT2, BT3, BT4
+
+
+4.32           2005-12-09
+-------------------------
+- Java version of LZMA SDK was included
+
+
+4.30           2005-11-20
+-------------------------
+- Compression ratio was improved in -a2 mode
+- Speed optimizations for compressing in -a2 mode
+- -fb switch now supports values up to 273
+- The bug in 7z_C (7zIn.c) was fixed:
+  It used Alloc/Free functions from different memory pools.
+  So if program used two memory pools, it worked incorrectly.
+- 7z_C: .7z format supporting was improved
+- LZMA# SDK (C#.NET version) was included
+
+
+4.27 (Updated) 2005-09-21
+-------------------------
+- Some GUIDs/interfaces in C++ were changed.
+ IStream.h:
+   ISequentialInStream::Read now works as old ReadPart
+   ISequentialOutStream::Write now works as old WritePart
+
+
+4.27           2005-08-07
+-------------------------
+- The bug in LzmaDecodeSize.c was fixed:
+   if _LZMA_IN_CB and _LZMA_OUT_READ were defined,
+   decompressing worked incorrectly.
+
+
+4.26           2005-08-05
+-------------------------
+- Fixes in 7z_C code and LzmaTest.c:
+  previous versions could work incorrectly,
+  if malloc(0) returns 0
+
+
+4.23           2005-06-29
+-------------------------
+- Small fixes in C++ code
+
+
+4.22           2005-06-10
+-------------------------
+- Small fixes
+
+
+4.21           2005-06-08
+-------------------------
+- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed
+- New additional version of ANSI-C LZMA Decoder with zlib-like interface:
+    - LzmaStateDecode.h
+    - LzmaStateDecode.c
+    - LzmaStateTest.c
+- ANSI-C LZMA Decoder now can decompress files larger than 4 GB
+
+
+4.17           2005-04-18
+-------------------------
+- New example for RAM->RAM compressing/decompressing: 
+  LZMA + BCJ (filter for x86 code):
+    - LzmaRam.h
+    - LzmaRam.cpp
+    - LzmaRamDecode.h
+    - LzmaRamDecode.c
+    - -f86 switch for lzma.exe
+
+
+4.16           2005-03-29
+-------------------------
+- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): 
+   If _LZMA_OUT_READ was defined, and if encoded stream was corrupted,
+   decoder could access memory outside of allocated range.
+- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster).
+  Old version of LZMA Decoder now is in file LzmaDecodeSize.c. 
+  LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c
+- Small speed optimization in LZMA C++ code
+- filter for SPARC's code was added
+- Simplified version of .7z ANSI-C Decoder was included
+
+
+4.06           2004-09-05
+-------------------------
+- The bug in v4.05 was fixed:
+    LZMA-Encoder didn't release output stream in some cases.
+
+
+4.05           2004-08-25
+-------------------------
+- Source code of filters for x86, IA-64, ARM, ARM-Thumb 
+  and PowerPC code was included to SDK
+- Some internal minor changes
+
+
+4.04           2004-07-28
+-------------------------
+- More compatibility with some C++ compilers
+
+
+4.03           2004-06-18
+-------------------------
+- "Benchmark" command was added. It measures compressing 
+  and decompressing speed and shows rating values. 
+  Also it checks hardware errors.
+
+
+4.02           2004-06-10
+-------------------------
+- C++ LZMA Encoder/Decoder code now is more portable
+  and it can be compiled by GCC on Linux.
+
+
+4.01           2004-02-15
+-------------------------
+- Some detection of data corruption was enabled.
+    LzmaDecode.c / RangeDecoderReadByte
+    .....
+    {
+      rd->ExtraBytes = 1;
+      return 0xFF;
+    }
+
+
+4.00           2004-02-13
+-------------------------
+- Original version of LZMA SDK
+
+
+
+HISTORY of the LZMA
+-------------------
+  2001-2008:  Improvements to LZMA compressing/decompressing code, 
+              keeping compatibility with original LZMA format
+  1996-2001:  Development of LZMA compression format
+
+  Some milestones:
+
+  2001-08-30: LZMA compression was added to 7-Zip
+  1999-01-02: First version of 7-Zip was released
+  
+
+End of document

+ 345 - 0
Components/Lzma2/lzma.txt

@@ -0,0 +1,345 @@
+LZMA compression
+----------------
+Version: 24.07
+
+This file describes LZMA encoding and decoding functions written in C language.
+
+LZMA is an improved version of famous LZ77 compression algorithm. 
+It was improved in way of maximum increasing of compression ratio,
+keeping high decompression speed and low memory requirements for 
+decompressing.
+
+Note: you can read also LZMA Specification (lzma-specification.txt from LZMA SDK)
+
+Also you can look source code for LZMA encoding and decoding:
+  C/Util/Lzma/LzmaUtil.c
+
+
+LZMA compressed file format
+---------------------------
+Offset Size Description
+  0     1   Special LZMA properties (lc,lp, pb in encoded form)
+  1     4   Dictionary size (little endian)
+  5     8   Uncompressed size (little endian). -1 means unknown size
+ 13         Compressed data
+
+
+
+ANSI-C LZMA Decoder
+~~~~~~~~~~~~~~~~~~~
+
+Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.
+If you want to use old interfaces you can download previous version of LZMA SDK
+from sourceforge.net site.
+
+To use ANSI-C LZMA Decoder you need the following files:
+1) LzmaDec.h + LzmaDec.c + 7zTypes.h + Precomp.h + Compiler.h
+
+Look example code:
+  C/Util/Lzma/LzmaUtil.c
+
+
+Memory requirements for LZMA decoding
+-------------------------------------
+
+Stack usage of LZMA decoding function for local variables is not 
+larger than 200-400 bytes.
+
+LZMA Decoder uses dictionary buffer and internal state structure.
+Internal state structure consumes
+  state_size = (4 + (1.5 << (lc + lp))) KB
+by default (lc=3, lp=0), state_size = 16 KB.
+
+
+How To decompress data
+----------------------
+
+LZMA Decoder (ANSI-C version) now supports 2 interfaces:
+1) Single-call Decompressing
+2) Multi-call State Decompressing (zlib-like interface)
+
+You must use external allocator:
+Example:
+void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
+void SzFree(void *p, void *address) { p = p; free(address); }
+ISzAlloc alloc = { SzAlloc, SzFree };
+
+You can use p = p; operator to disable compiler warnings.
+
+
+Single-call Decompressing
+-------------------------
+When to use: RAM->RAM decompressing
+Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h
+Compile defines: no defines
+Memory Requirements:
+  - Input buffer: compressed size
+  - Output buffer: uncompressed size
+  - LZMA Internal Structures: state_size (16 KB for default settings) 
+
+Interface:
+  int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+      const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 
+      ELzmaStatus *status, ISzAlloc *alloc);
+  In: 
+    dest     - output data
+    destLen  - output data size
+    src      - input data
+    srcLen   - input data size
+    propData - LZMA properties  (5 bytes)
+    propSize - size of propData buffer (5 bytes)
+    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).
+                           You can use LZMA_FINISH_END, when you know that 
+                           current output buffer covers last bytes of stream. 
+    alloc    - Memory allocator.
+
+  Out: 
+    destLen  - processed output size 
+    srcLen   - processed input size 
+
+  Output:
+    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).
+
+  If LZMA decoder sees end_marker before reaching output limit, it returns OK result,
+  and output value of destLen will be less than output buffer size limit.
+
+  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. */ 
+
+
+Multi-call State Decompressing (zlib-like interface)
+----------------------------------------------------
+
+When to use: file->file decompressing 
+Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h
+
+Memory Requirements:
+ - Buffer for input stream: any size (for example, 16 KB)
+ - Buffer for output stream: any size (for example, 16 KB)
+ - LZMA Internal Structures: state_size (16 KB for default settings) 
+ - LZMA dictionary (dictionary size is encoded in LZMA properties header)
+
+1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:
+   unsigned char header[LZMA_PROPS_SIZE + 8];
+   ReadFile(inFile, header, sizeof(header)
+
+2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties
+
+  CLzmaDec state;
+  LzmaDec_Constr(&state);
+  res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
+  if (res != SZ_OK)
+    return res;
+
+3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop
+
+  LzmaDec_Init(&state);
+  for (;;)
+  {
+    ... 
+    int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 
+        const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);
+    ...
+  }
+
+
+4) Free all allocated structures
+  LzmaDec_Free(&state, &g_Alloc);
+
+Look example code:
+  C/Util/Lzma/LzmaUtil.c
+
+
+How To compress data
+--------------------
+
+Compile files: 
+  7zTypes.h
+  Threads.h	
+  Threads.c	
+  LzmaEnc.h
+  LzmaEnc.c
+  LzFind.h
+  LzFind.c
+  LzFindMt.h
+  LzFindMt.c
+  LzFindOpt.c
+  LzHash.h
+
+Memory Requirements:
+  - (dictSize * 11.5 + 6 MB) + state_size
+
+Lzma Encoder can use two memory allocators:
+1) alloc - for small arrays.
+2) allocBig - for big arrays.
+
+For example, you can use Large RAM Pages (2 MB) in allocBig allocator for 
+better compression speed. Note that Windows has bad implementation for 
+Large RAM Pages. 
+It's OK to use same allocator for alloc and allocBig.
+
+
+Single-call Compression with callbacks
+--------------------------------------
+
+Look example code:
+  C/Util/Lzma/LzmaUtil.c
+
+When to use: file->file compressing 
+
+1) you must implement callback structures for interfaces:
+ISeqInStream
+ISeqOutStream
+ICompressProgress
+ISzAlloc
+
+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
+static void SzFree(void *p, void *address) {  p = p; MyFree(address); }
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+  CFileSeqInStream inStream;
+  CFileSeqOutStream outStream;
+
+  inStream.funcTable.Read = MyRead;
+  inStream.file = inFile;
+  outStream.funcTable.Write = MyWrite;
+  outStream.file = outFile;
+
+
+2) Create CLzmaEncHandle object;
+
+  CLzmaEncHandle enc;
+
+  enc = LzmaEnc_Create(&g_Alloc);
+  if (enc == 0)
+    return SZ_ERROR_MEM;
+
+
+3) initialize CLzmaEncProps properties;
+
+  LzmaEncProps_Init(&props);
+
+  Then you can change some properties in that structure.
+
+4) Send LZMA properties to LZMA Encoder
+
+  res = LzmaEnc_SetProps(enc, &props);
+
+5) Write encoded properties to header
+
+    Byte header[LZMA_PROPS_SIZE + 8];
+    size_t headerSize = LZMA_PROPS_SIZE;
+    UInt64 fileSize;
+    int i;
+
+    res = LzmaEnc_WriteProperties(enc, header, &headerSize);
+    fileSize = MyGetFileLength(inFile);
+    for (i = 0; i < 8; i++)
+      header[headerSize++] = (Byte)(fileSize >> (8 * i));
+    MyWriteFileAndCheck(outFile, header, headerSize)
+
+6) Call encoding function:
+      res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, 
+        NULL, &g_Alloc, &g_Alloc);
+
+7) Destroy LZMA Encoder Object
+  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
+
+
+If callback function return some error code, LzmaEnc_Encode also returns that code
+or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.
+
+
+Single-call RAM->RAM Compression
+--------------------------------
+
+Single-call RAM->RAM Compression is similar to Compression with callbacks,
+but you provide pointers to buffers instead of pointers to stream callbacks:
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, 
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+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)
+
+
+
+Defines
+-------
+
+Z7_LZMA_SIZE_OPT - Enable some code size optimizations in LZMA Decoder to get smaller executable code.
+
+Z7_LZMA_PROB32   - It can increase the speed on some 32-bit CPUs, but memory usage for 
+                   some structures will be doubled in that case.
+
+Z7_DECL_Int32_AS_long  - Define it if int is 16-bit on your compiler and long is 32-bit.
+
+Z7_DECL_SizeT_AS_unsigned_int  - Define it if you don't want to use size_t type.
+
+
+Defines for 7z decoder written in C
+-----------------------------------
+These defines are for 7zDec.c only (the decoder in C). 
+C++ 7z decoder doesn't uses these macros.
+
+Z7_PPMD_SUPPORT        - define it if you need PPMD method support.
+Z7_NO_METHODS_FILTERS  - do not use filters (except of BCJ2 filter).
+Z7_USE_NATIVE_BRANCH_FILTER - use filter for native ISA:
+                                 use x86 filter, if compiled to x86 executable,
+                		 use arm64 filter, if compiled to arm64 executable. 
+
+
+C++ LZMA Encoder/Decoder 
+~~~~~~~~~~~~~~~~~~~~~~~~
+C++ LZMA code use COM-like interfaces. So if you want to use it, 
+you can study basics of COM/OLE.
+C++ LZMA code is just wrapper over ANSI-C code.
+
+
+C++ Notes
+~~~~~~~~~~~~~~~~~~~~~~~~
+If you use some C++ code folders in 7-Zip (for example, C++ code for 7z archive handling),
+you must check that you correctly work with "new" operator.
+7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.
+So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator,
+if compiled by old MSVC compilers (MSVC before version VS 2010):
+
+operator new(size_t size)
+{
+  void *p = ::malloc(size);
+  if (!p)
+    throw CNewException();
+  return p;
+}
+
+If the compiler is VS 2010 or newer, NewHandler.cpp doesn't redefine "new" operator.
+Sp if you use new compiler (VS 2010 or newer), you still can include "NewHandler.cpp" 
+to compilation, and it will not redefine operator new.
+Also you can compile without "NewHandler.cpp" with new compilers. 
+If 7-zip doesn't redefine operator "new", standard exception will be used instead of CNewException. 
+Some code of 7-Zip catches any exception in internal code and converts it to HRESULT code.
+So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.
+
+---
+
+http://www.7-zip.org
+http://www.7-zip.org/sdk.html
+http://www.7-zip.org/support.html

BIN
Files/islzma.dll


BIN
Files/islzma32.exe


BIN
Files/islzma64.exe


+ 12 - 11
ISHelp/isetup.xml

@@ -4438,17 +4438,18 @@ Name: portablemode; Description: "Portable Mode"</pre></example>
 <p><tt>lzma</tt> is the method of compression employed by the <extlink href="http://www.7-zip.org/">7-Zip LZMA</extlink> compressor. It typically compresses significantly better than the <tt>zip</tt> and <tt>bzip</tt> methods. However, depending on the compression level used, it can be significantly slower at compressing, and consume a <i>lot</i> more memory. The following table summarizes the approximate memory requirements for each of the supported <tt>lzma</tt> compression levels. If a compression level isn't specified, it defaults to <tt>max</tt>.</p>
 <p><tt>lzma</tt> is the method of compression employed by the <extlink href="http://www.7-zip.org/">7-Zip LZMA</extlink> compressor. It typically compresses significantly better than the <tt>zip</tt> and <tt>bzip</tt> methods. However, depending on the compression level used, it can be significantly slower at compressing, and consume a <i>lot</i> more memory. The following table summarizes the approximate memory requirements for each of the supported <tt>lzma</tt> compression levels. If a compression level isn't specified, it defaults to <tt>max</tt>.</p>
 <indent>
 <indent>
 <table>
 <table>
-<tr><td></td><td><u>Decompression (dictionary size)</u></td><td><u>Compression (4 MB + 11 * dictionary size)</u></td></tr>
-<tr><td><tt>fast</tt> (worst)</td><td>32 KB</td><td>3 MB</td></tr>
-<tr><td><tt>normal</tt></td><td>2 MB</td><td>26 MB</td></tr>
-<tr><td><tt>max</tt> (default)</td><td>8 MB</td><td>92 MB</td></tr>
-<tr><td><tt>ultra</tt></td><td>32 MB</td><td>356 MB</td></tr>
-<tr><td><tt>ultra64</tt> (best)</td><td>64 MB</td><td>708 MB</td></tr>
-<tr><td></td><td>128 MB</td><td>1.38 GB</td></tr>
-<tr><td></td><td>256 MB</td><td>2.75 GB</td></tr>
-<tr><td></td><td>512 MB</td><td>5.5 GB</td></tr>
-<tr><td></td><td>1 GB</td><td>11 GB</td></tr>
+<tr><td></td><td><u>Decompression (dictionary size)</u></td><td><u>Compression (6 MB + 11.5 * dictionary size)</u></td></tr>
+<tr><td><tt>fast</tt> (worst)</td><td>32 KB</td><td>6 MB</td></tr>
+<tr><td><tt>normal</tt></td><td>2 MB</td><td>29 MB</td></tr>
+<tr><td><tt>max</tt> (default)</td><td>8 MB</td><td>98 MB</td></tr>
+<tr><td><tt>ultra</tt></td><td>32 MB</td><td>374 MB</td></tr>
+<tr><td><tt>ultra64</tt> (best)</td><td>64 MB</td><td>742 MB</td></tr>
+<tr><td></td><td>128 MB</td><td>1.44 GB</td></tr>
+<tr><td></td><td>256 MB</td><td>2.88 GB</td></tr>
+<tr><td></td><td>512 MB</td><td>5.76 GB</td></tr>
+<tr><td></td><td>1 GB</td><td>11.51 GB</td></tr>
 </table>
 </table>
+<p>The compression memory requirements are approximately 60% of the above when <link topic="setup_lzmamatchfinder">LZMAMatchFinder</link> is set to <tt>HC</tt> at the expense of compression ratio.</p>
 </indent>
 </indent>
 <p><tt>lzma2</tt> is the method of compression employed by the <extlink href="http://www.7-zip.org/">7-Zip LZMA2</extlink> compressor. LZMA2 is a modified version of LZMA that offers a better compression ratio for incompressible data (random data expands about 0.005%, compared to 1.35% with original LZMA), and optionally can compress multiple parts of large files in parallel, greatly increasing compression speed but with a possible reduction in compression ratio (see <link topic="setup_lzmanumblockthreads">LZMANumBlockThreads</link>). Like LZMA, it can consume a <i>lot</i> of memory; see the above table. If a compression level isn't specified, it defaults to <tt>max</tt>.</p>
 <p><tt>lzma2</tt> is the method of compression employed by the <extlink href="http://www.7-zip.org/">7-Zip LZMA2</extlink> compressor. LZMA2 is a modified version of LZMA that offers a better compression ratio for incompressible data (random data expands about 0.005%, compared to 1.35% with original LZMA), and optionally can compress multiple parts of large files in parallel, greatly increasing compression speed but with a possible reduction in compression ratio (see <link topic="setup_lzmanumblockthreads">LZMANumBlockThreads</link>). Like LZMA, it can consume a <i>lot</i> of memory; see the above table. If a compression level isn't specified, it defaults to <tt>max</tt>.</p>
 <p><tt>none</tt> specifies that no compression be used.</p>
 <p><tt>none</tt> specifies that no compression be used.</p>
@@ -5811,7 +5812,7 @@ SignTool=byparam format c:
 <tt>BT</tt> otherwise</setupdefault>
 <tt>BT</tt> otherwise</setupdefault>
 <body>
 <body>
 <p>Controls the match finder method used by the LZMA and LZMA2 compressors.</p>
 <p>Controls the match finder method used by the LZMA and LZMA2 compressors.</p>
-<p>A value of <tt>HC</tt> enables the Hash Chain method with 4 hash bytes.</p>
+<p>A value of <tt>HC</tt> enables the Hash Chain method with 5 hash bytes.</p>
 <p>A value of <tt>BT</tt> enables the Binary Tree method with 4 hash bytes.</p>
 <p>A value of <tt>BT</tt> enables the Binary Tree method with 4 hash bytes.</p>
 <p>The Binary Tree method can provide a better compression ratio at the expense of compression speed.</p>
 <p>The Binary Tree method can provide a better compression ratio at the expense of compression speed.</p>
 </body>
 </body>

+ 2 - 1
Projects/Src/ISCmplr/Compile.pas

@@ -3844,7 +3844,8 @@ begin
         CompressProps.BlockSize := StrToIntRange(Value, 1024, 262144) * 1024; //search Lzma2Enc.c for kMaxSize to see this limit: 262144*1024==1<<28
         CompressProps.BlockSize := StrToIntRange(Value, 1024, 262144) * 1024; //search Lzma2Enc.c for kMaxSize to see this limit: 262144*1024==1<<28
       end;
       end;
     ssLZMADictionarySize: begin
     ssLZMADictionarySize: begin
-        CompressProps.DictionarySize := StrToIntRange(Value, 4, 1048576) * 1024;
+        var MaxDictionarySize := 1024 shl 20; //1 GB - same as MaxDictionarySize in LZMADecomp.pas - lower than the LZMA SDK allows (search Lzma2Enc.c for kLzmaMaxHistorySize to see this limit: Cardinal(15 shl 28) = 3.8 GB) because Setup can't allocate that much memory
+        CompressProps.DictionarySize := StrToIntRange(Value, 4, MaxDictionarySize div 1024) * 1024;
       end;
       end;
     ssLZMAMatchFinder: begin
     ssLZMAMatchFinder: begin
         if CompareText(Value, 'BT') = 0 then
         if CompareText(Value, 'BT') = 0 then

+ 16 - 11
Projects/Src/ISCmplr/LZMA.pas

@@ -35,7 +35,7 @@ type
     Algorithm: Integer;
     Algorithm: Integer;
     BlockSize: Integer;
     BlockSize: Integer;
     BTMode: Integer;
     BTMode: Integer;
-    DictionarySize: Integer;
+    DictionarySize: Cardinal;
     NumBlockThreads: Integer;
     NumBlockThreads: Integer;
     NumFastBytes: Integer;
     NumFastBytes: Integer;
     NumThreads: Integer;
     NumThreads: Integer;
@@ -48,7 +48,8 @@ type
     Algorithm: Integer;
     Algorithm: Integer;
     BlockSize: Integer;
     BlockSize: Integer;
     BTMode: Integer;
     BTMode: Integer;
-    DictionarySize: Integer;
+    NumHashBytes: Integer;
+    DictionarySize: Cardinal;
     NumBlockThreads: Integer;
     NumBlockThreads: Integer;
     NumFastBytes: Integer;
     NumFastBytes: Integer;
     NumThreads: Integer;
     NumThreads: Integer;
@@ -548,16 +549,17 @@ var
   Bytes: Longint;
   Bytes: Longint;
 begin
 begin
   ProcessedSize := 0;
   ProcessedSize := 0;
-  if Size > Cardinal(High(Longint)) then begin
-    Result := E_INVALIDARG;
-    Exit;
-  end;
   P := Data;
   P := Data;
   while Size <> 0 do begin
   while Size <> 0 do begin
+    var LimitedSize: LongInt;
+    if Size > MaxLong then
+      LimitedSize := MaxLong
+    else
+      LimitedSize := Size;
     if AWrite then
     if AWrite then
-      Bytes := RingBufferWrite(FShared.OutputBuffer, P^, Size)
+      Bytes := RingBufferWrite(FShared.OutputBuffer, P^, LimitedSize)
     else
     else
-      Bytes := RingBufferRead(FShared.InputBuffer, P^, Size);
+      Bytes := RingBufferRead(FShared.InputBuffer, P^, LimitedSize);
     if Bytes = 0 then begin
     if Bytes = 0 then begin
       if AWrite then begin
       if AWrite then begin
         { Output buffer full; wait for the main thread to flush it }
         { Output buffer full; wait for the main thread to flush it }
@@ -835,10 +837,11 @@ end;
 procedure TLZMACompressor.InitializeProps(const CompressionLevel: Integer;
 procedure TLZMACompressor.InitializeProps(const CompressionLevel: Integer;
   const ACompressorProps: TCompressorProps);
   const ACompressorProps: TCompressorProps);
 const
 const
-  algorithm: array [clLZMAFast..clLZMAUltra64] of Cardinal = (0, 1, 1, 1, 1);
+  algorithm: array [clLZMAFast..clLZMAUltra64] of Integer = (0, 1, 1, 1, 1);
   dicSize: array [clLZMAFast..clLZMAUltra64] of Cardinal = (32 shl 10, 2 shl 20, 8 shl 20, 32 shl 20, 64 shl 20);
   dicSize: array [clLZMAFast..clLZMAUltra64] of Cardinal = (32 shl 10, 2 shl 20, 8 shl 20, 32 shl 20, 64 shl 20);
-  numFastBytes: array [clLZMAFast..clLZMAUltra64] of Cardinal = (32, 32, 64, 64, 64);
-  btMode: array [clLZMAFast..clLZMAUltra64] of Cardinal = (0, 1, 1, 1, 1);
+  numFastBytes: array [clLZMAFast..clLZMAUltra64] of Integer = (32, 32, 64, 64, 64);
+  btMode: array [clLZMAFast..clLZMAUltra64] of Integer = (0, 1, 1, 1, 1);
+  numHashBytes: array [Boolean] of Integer = (5, 4);
 var
 var
   EncProps: TLZMAEncoderProps;
   EncProps: TLZMAEncoderProps;
   Props: TLZMACompressorProps;
   Props: TLZMACompressorProps;
@@ -873,6 +876,8 @@ begin
     WorkerProcessFilename := Props.WorkerProcessFilename;
     WorkerProcessFilename := Props.WorkerProcessFilename;
   end;
   end;
 
 
+  EncProps.NumHashBytes := numHashBytes[EncProps.BTMode = 1];
+
   if WorkerProcessFilename <> '' then begin
   if WorkerProcessFilename <> '' then begin
     FWorker := TLZMAWorkerProcess.Create(@FEvents);
     FWorker := TLZMAWorkerProcess.Create(@FEvents);
     (FWorker as TLZMAWorkerProcess).ExeFilename := WorkerProcessFilename;
     (FWorker as TLZMAWorkerProcess).ExeFilename := WorkerProcessFilename;

+ 3 - 10
Projects/Src/ISCmplr/islzma/islzma.c

@@ -20,14 +20,6 @@ struct LZMAHandle {
 #define LZMA_HANDLE_MARKER 0x3E1A981F
 #define LZMA_HANDLE_MARKER 0x3E1A981F
 #define LZMA_HANDLE_VALID(h) ((h) && (h)->marker == LZMA_HANDLE_MARKER)
 #define LZMA_HANDLE_VALID(h) ((h) && (h)->marker == LZMA_HANDLE_MARKER)
 
 
-static void *SzBigAlloc(void *p, size_t size) { return BigAlloc(size); }
-static void SzBigFree(void *p, void *address) { BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
-static void *SzAlloc(void *p, size_t size) { return MyAlloc(size); }
-static void SzFree(void *p, void *address) { MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
 SRes __stdcall LZMA_Init(BOOL LZMA2, struct LZMAHandle **handle)
 SRes __stdcall LZMA_Init(BOOL LZMA2, struct LZMAHandle **handle)
 {
 {
 	struct LZMAHandle *h = calloc(1, sizeof(*h));
 	struct LZMAHandle *h = calloc(1, sizeof(*h));
@@ -75,10 +67,11 @@ SRes __stdcall LZMA_SetProps(struct LZMAHandle *handle,
 	props->dictSize = encProps->DictionarySize;
 	props->dictSize = encProps->DictionarySize;
 	props->fb = encProps->NumFastBytes;
 	props->fb = encProps->NumFastBytes;
 	props->btMode = encProps->BTMode;
 	props->btMode = encProps->BTMode;
+	props->numHashBytes = encProps->NumHashBytes;
 	props->numThreads = encProps->NumThreads;
 	props->numThreads = encProps->NumThreads;
 
 
 	if (handle->LZMA2) {
 	if (handle->LZMA2) {
-		props2.numBlockThreads = encProps->NumBlockThreads;
+		props2.numBlockThreads_Max = encProps->NumBlockThreads;
 		props2.blockSize = encProps->BlockSize;
 		props2.blockSize = encProps->BlockSize;
 		return Lzma2Enc_SetProps(handle->encoder2, &props2);
 		return Lzma2Enc_SetProps(handle->encoder2, &props2);
 	} else {
 	} else {
@@ -100,7 +93,7 @@ SRes __stdcall LZMA_Encode(struct LZMAHandle *handle, ISeqInStream *inStream,
 		if (outStream->Write(outStream, &props, propsSize) != propsSize) {
 		if (outStream->Write(outStream, &props, propsSize) != propsSize) {
 			return SZ_ERROR_WRITE;
 			return SZ_ERROR_WRITE;
 		};
 		};
-		return Lzma2Enc_Encode(handle->encoder2, outStream, inStream, progress);
+		return Lzma2Enc_Encode2(handle->encoder2, outStream, NULL, 0, inStream, NULL, 0, progress);
 	} else {
 	} else {
 		Byte props[LZMA_PROPS_SIZE];
 		Byte props[LZMA_PROPS_SIZE];
 		SizeT propsSize = sizeof(props);
 		SizeT propsSize = sizeof(props);

+ 2 - 1
Projects/Src/ISCmplr/islzma/islzma.h

@@ -7,7 +7,8 @@ struct LZMAEncoderProps {
 	int Algorithm;
 	int Algorithm;
 	int BlockSize;
 	int BlockSize;
 	int BTMode;
 	int BTMode;
-	int DictionarySize;
+	int NumHashBytes;
+	UInt32 DictionarySize;
 	int NumBlockThreads;
 	int NumBlockThreads;
 	int NumFastBytes;
 	int NumFastBytes;
 	int NumThreads;
 	int NumThreads;

+ 9 - 4
Projects/Src/ISCmplr/islzma/islzma.sln

@@ -1,9 +1,11 @@
 
 
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "islzma", "islzma.vcproj", "{9A22AB1E-129F-4448-A167-79B909AC4C10}"
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.10.35013.160
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "islzma", "islzma.vcxproj", "{9A22AB1E-129F-4448-A167-79B909AC4C10}"
 EndProject
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "islzma_exe", "islzma_exe.vcproj", "{A260686C-A249-40E7-8E00-EF9F1B315341}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "islzma_exe", "islzma_exe.vcxproj", "{A260686C-A249-40E7-8E00-EF9F1B315341}"
 EndProject
 EndProject
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -31,4 +33,7 @@ Global
 	GlobalSection(SolutionProperties) = preSolution
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		HideSolutionNode = FALSE
 	EndGlobalSection
 	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {151EFF25-B4E6-4039-AECE-C35209A19FC4}
+	EndGlobalSection
 EndGlobal
 EndGlobal

+ 0 - 266
Projects/Src/ISCmplr/islzma/islzma.vcproj

@@ -1,266 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="islzma"
-	ProjectGUID="{9A22AB1E-129F-4448-A167-79B909AC4C10}"
-	RootNamespace="islzma"
-	Keyword="Win32Proj"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="2"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;ISLZMA_EXPORTS"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="4"
-				CallingConvention="2"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				LinkIncremental="2"
-				ModuleDefinitionFile="islzma.def"
-				GenerateDebugInformation="true"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				BaseAddress="0x1200000"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="2"
-			CharacterSet="2"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ISLZMA_EXPORTS"
-				RuntimeLibrary="0"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-				CallingConvention="2"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				LinkIncremental="1"
-				ModuleDefinitionFile="islzma.def"
-				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				BaseAddress="0x1200000"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="SDK"
-			>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\Alloc.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\Alloc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\LzFind.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\LzFind.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\LzFindMt.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\LzFindMt.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\LzHash.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\Lzma2Enc.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\Lzma2Enc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\LzmaEnc.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\LzmaEnc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\MtCoder.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\MtCoder.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\Threads.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\Threads.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\..\Components\Lzma2\Types.h"
-				>
-			</File>
-		</Filter>
-		<File
-			RelativePath=".\islzma.c"
-			>
-		</File>
-		<File
-			RelativePath=".\islzma.def"
-			>
-		</File>
-		<File
-			RelativePath=".\islzma.h"
-			>
-		</File>
-		<File
-			RelativePath=".\islzma_dll.c"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>

+ 128 - 0
Projects/Src/ISCmplr/islzma/islzma.vcxproj

@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>17.0</VCProjectVersion>
+    <ProjectGuid>{9A22AB1E-129F-4448-A167-79B909AC4C10}</ProjectGuid>
+    <RootNamespace>islzma</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>17.0.35004.147</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ISSRCROOT)\Projects\Bin\</OutDir>
+    <IntDir>$(ShortProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(ShortProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ISLZMA_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level3</WarningLevel>
+      <CallingConvention>StdCall</CallingConvention>
+    </ClCompile>
+    <Link>
+      <ModuleDefinitionFile>islzma.def</ModuleDefinitionFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <BaseAddress>0x1200000</BaseAddress>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ISLZMA_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <PrecompiledHeader />
+      <WarningLevel>Level3</WarningLevel>
+      <CallingConvention>StdCall</CallingConvention>
+    </ClCompile>
+    <Link>
+      <ModuleDefinitionFile>islzma.def</ModuleDefinitionFile>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <BaseAddress>0x1200000</BaseAddress>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\7zStream.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Alloc.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\CpuArch.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFind.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFindMt.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFindOpt.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Lzma2Enc.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzmaEnc.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\MtCoder.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\MtDec.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Threads.c" />
+    <ClCompile Include="islzma.c" />
+    <ClCompile Include="islzma_dll.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\7zTypes.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\7zWindows.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Alloc.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Compiler.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\CpuArch.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzFind.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzFindMt.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzHash.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Lzma2Enc.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzmaEnc.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\MtCoder.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Precomp.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Threads.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Types.h" />
+    <ClInclude Include="islzma.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="islzma.def" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 93 - 0
Projects/Src/ISCmplr/islzma/islzma.vcxproj.filters

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="SDK">
+      <UniqueIdentifier>{093101f4-97ca-4829-85f2-95e38d5acd83}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Alloc.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFind.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFindMt.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Lzma2Enc.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzmaEnc.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\MtCoder.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Threads.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="islzma.c" />
+    <ClCompile Include="islzma_dll.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\CpuArch.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\MtDec.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\7zStream.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFindOpt.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Alloc.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzFind.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzFindMt.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzHash.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Lzma2Enc.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzmaEnc.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\MtCoder.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Threads.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Types.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="islzma.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\7zTypes.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\7zWindows.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Compiler.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\CpuArch.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Precomp.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="islzma.def" />
+  </ItemGroup>
+</Project>

+ 9 - 0
Projects/Src/ISCmplr/islzma/islzma.vcxproj.user

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LocalDebuggerCommand>$(ISSRCROOT)\Projects\Bin\Compil32.exe</LocalDebuggerCommand>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+    <LocalDebuggerCommandArguments>Debug.iss</LocalDebuggerCommandArguments>
+    <LocalDebuggerWorkingDirectory>$(ISSRCROOT)\Projects\Bin</LocalDebuggerWorkingDirectory>
+  </PropertyGroup>
+</Project>

+ 8 - 11
Projects/Src/ISCmplr/islzma/islzma_exe.c

@@ -1,11 +1,10 @@
 /*
 /*
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2010 Jordan Russell
+  Copyright (C) 1997-2024 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
   External EXE-based LZMA encoder
   External EXE-based LZMA encoder
-  Built on Visual Studio 2005 SP1
 
 
   Structures and functions in this file are derived from
   Structures and functions in this file are derived from
   LZMA.pas revision 1.49.2.3.
   LZMA.pas revision 1.49.2.3.
@@ -18,7 +17,7 @@
 
 
 #include <windows.h>
 #include <windows.h>
 #include <shlwapi.h>
 #include <shlwapi.h>
-#include "../../../../Components/Lzma2/Types.h"
+#include "../../../../Components/Lzma2/7zTypes.h"
 #include "islzma.h"
 #include "islzma.h"
 
 
 #define ISLZMA_EXE_VERSION 101
 #define ISLZMA_EXE_VERSION 101
@@ -164,15 +163,13 @@ static HRESULT FillBuffer(const BOOL AWrite, void *Data, size_t Size,
 	HRESULT Result;
 	HRESULT Result;
 
 
 	*ProcessedSize = 0;
 	*ProcessedSize = 0;
-	if (Size > MAXLONG) {
-		return E_INVALIDARG;
-	}
 	P = Data;
 	P = Data;
 	while (Size != 0) {
 	while (Size != 0) {
+		Longint LimitedSize = Size > MAXLONG ? MAXLONG : (Longint)Size;
 		if (AWrite) {
 		if (AWrite) {
-			Bytes = RingBufferWrite(&FShared->OutputBuffer, P, (Longint)Size);
+			Bytes = RingBufferWrite(&FShared->OutputBuffer, P, LimitedSize);
 		} else {
 		} else {
-			Bytes = RingBufferRead(&FShared->InputBuffer, P, (Longint)Size);
+			Bytes = RingBufferRead(&FShared->InputBuffer, P, LimitedSize);
 		}
 		}
 		if (Bytes == 0) {
 		if (Bytes == 0) {
 			if (AWrite) {
 			if (AWrite) {
@@ -267,7 +264,7 @@ static HRESULT ProgressMade(const UInt64 TotalBytesProcessed)
 	return Result;
 	return Result;
 }
 }
 
 
-static SRes LZMASeqInStreamReadWrapper(void *p, void *buf, size_t *size)
+static SRes LZMASeqInStreamReadWrapper(ISeqInStreamPtr p, void *buf, size_t *size)
 {
 {
 	if (Read(buf, *size, size) == S_OK) {
 	if (Read(buf, *size, size) == S_OK) {
 		return SZ_OK;
 		return SZ_OK;
@@ -276,7 +273,7 @@ static SRes LZMASeqInStreamReadWrapper(void *p, void *buf, size_t *size)
 	}
 	}
 }
 }
 
 
-static size_t LZMASeqOutStreamWriteWrapper(void *p, const void *buf, size_t size)
+static size_t LZMASeqOutStreamWriteWrapper(ISeqOutStreamPtr p, const void *buf, size_t size)
 {
 {
 	size_t Result;
 	size_t Result;
 
 
@@ -286,7 +283,7 @@ static size_t LZMASeqOutStreamWriteWrapper(void *p, const void *buf, size_t size
 	return Result;
 	return Result;
 }
 }
 
 
-static SRes LZMACompressProgressProgressWrapper(void *p, UInt64 inSize, UInt64 outSize)
+static SRes LZMACompressProgressProgressWrapper(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize)
 {
 {
 	if (ProgressMade(inSize) == S_OK) {
 	if (ProgressMade(inSize) == S_OK) {
 		return SZ_OK;
 		return SZ_OK;

+ 0 - 413
Projects/Src/ISCmplr/islzma/islzma_exe.vcproj

@@ -1,413 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8.00"
-	Name="islzma_exe"
-	ProjectGUID="{A260686C-A249-40E7-8E00-EF9F1B315341}"
-	RootNamespace="islzma_exe"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-		<Platform
-			Name="x64"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="$(SolutionDir)EXE-$(PlatformName)-$(ConfigurationName)"
-			IntermediateDirectory="EXE-$(PlatformName)-$(ConfigurationName)"
-			ConfigurationType="1"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="4"
-				CallingConvention="2"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/SUBSYSTEM:WINDOWS,5.0"
-				AdditionalDependencies="shlwapi.lib"
-				OutputFile="$(OutDir)\islzma32.exe"
-				GenerateDebugInformation="true"
-				SubSystem="2"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="$(SolutionDir)EXE-$(PlatformName)-$(ConfigurationName)"
-			IntermediateDirectory="EXE-$(PlatformName)-$(ConfigurationName)"
-			ConfigurationType="1"
-			CharacterSet="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-				CallingConvention="2"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="shlwapi.lib"
-				OutputFile="$(OutDir)\islzma64.exe"
-				GenerateDebugInformation="true"
-				SubSystem="2"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(SolutionDir)EXE-$(PlatformName)-$(ConfigurationName)"
-			IntermediateDirectory="EXE-$(PlatformName)-$(ConfigurationName)"
-			ConfigurationType="1"
-			CharacterSet="1"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
-				RuntimeLibrary="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-				CallingConvention="2"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/SUBSYSTEM:WINDOWS,5.0"
-				AdditionalDependencies="shlwapi.lib"
-				OutputFile="$(OutDir)\islzma32.exe"
-				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|x64"
-			OutputDirectory="$(SolutionDir)EXE-$(PlatformName)-$(ConfigurationName)"
-			IntermediateDirectory="EXE-$(PlatformName)-$(ConfigurationName)"
-			ConfigurationType="1"
-			CharacterSet="1"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
-				RuntimeLibrary="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-				CallingConvention="2"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="shlwapi.lib"
-				OutputFile="$(OutDir)\islzma64.exe"
-				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="SDK"
-			>
-			<File
-				RelativePath="..\C\Alloc.c"
-				>
-			</File>
-			<File
-				RelativePath="..\C\Alloc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\C\LzFind.c"
-				>
-			</File>
-			<File
-				RelativePath="..\C\LzFind.h"
-				>
-			</File>
-			<File
-				RelativePath="..\C\LzFindMt.c"
-				>
-			</File>
-			<File
-				RelativePath="..\C\LzFindMt.h"
-				>
-			</File>
-			<File
-				RelativePath="..\C\LzHash.h"
-				>
-			</File>
-			<File
-				RelativePath="..\C\Lzma2Enc.c"
-				>
-			</File>
-			<File
-				RelativePath="..\C\Lzma2Enc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\C\LzmaEnc.c"
-				>
-			</File>
-			<File
-				RelativePath="..\C\LzmaEnc.h"
-				>
-			</File>
-			<File
-				RelativePath="..\C\MtCoder.c"
-				>
-			</File>
-			<File
-				RelativePath="..\C\MtCoder.h"
-				>
-			</File>
-			<File
-				RelativePath="..\C\Threads.c"
-				>
-			</File>
-			<File
-				RelativePath="..\C\Threads.h"
-				>
-			</File>
-			<File
-				RelativePath="..\C\Types.h"
-				>
-			</File>
-		</Filter>
-		<File
-			RelativePath=".\islzma.c"
-			>
-		</File>
-		<File
-			RelativePath=".\islzma.h"
-			>
-		</File>
-		<File
-			RelativePath=".\islzma_exe.c"
-			>
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>

+ 211 - 0
Projects/Src/ISCmplr/islzma/islzma_exe.vcxproj

@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>17.0</VCProjectVersion>
+    <ProjectGuid>{A260686C-A249-40E7-8E00-EF9F1B315341}</ProjectGuid>
+    <RootNamespace>islzma_exe</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>17.0.35004.147</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <GenerateManifest>false</GenerateManifest>
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(ShortProjectName)\$(Platform)\$(Configuration)\</IntDir>
+    <TargetName>islzma32</TargetName>
+    <OutDir>$(ISSRCROOT)\Projects\Bin\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <GenerateManifest>false</GenerateManifest>
+    <TargetName>islzma64</TargetName>
+    <OutDir>$(ISSRCROOT)\Projects\Bin\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <GenerateManifest>false</GenerateManifest>
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(ShortProjectName)\$(Platform)\$(Configuration)\</IntDir>
+    <TargetName>islzma32</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <GenerateManifest>false</GenerateManifest>
+    <TargetName>islzma64</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <CallingConvention>StdCall</CallingConvention>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+    <ResourceCompile>
+      <PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <CallingConvention>StdCall</CallingConvention>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <CallingConvention>StdCall</CallingConvention>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+    <ResourceCompile>
+      <PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Midl>
+      <TargetEnvironment>X64</TargetEnvironment>
+    </Midl>
+    <ClCompile>
+      <PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level3</WarningLevel>
+      <CallingConvention>StdCall</CallingConvention>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\7zStream.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Alloc.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\CpuArch.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFind.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFindMt.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFindOpt.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Lzma2Enc.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzmaEnc.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\MtCoder.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\MtDec.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Threads.c" />
+    <ClCompile Include="islzma.c" />
+    <ClCompile Include="islzma_exe.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\7zTypes.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\7zWindows.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Alloc.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Compiler.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\CpuArch.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzFind.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzFindMt.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzHash.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Lzma2Enc.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzmaEnc.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\MtCoder.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Precomp.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Threads.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Types.h" />
+    <ClInclude Include="islzma.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="islzma_exe.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="islzma_exe32.ico" />
+    <Image Include="islzma_exe64.ico" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 106 - 0
Projects/Src/ISCmplr/islzma/islzma_exe.vcxproj.filters

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="SDK">
+      <UniqueIdentifier>{0e1d5792-191a-491f-8ce6-a6b46bd91db5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{de7af8ec-ad7f-47c4-9b9c-1b7a0307fb6c}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Alloc.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFind.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFindMt.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Lzma2Enc.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzmaEnc.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\MtCoder.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\Threads.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="islzma.c" />
+    <ClCompile Include="islzma_exe.c" />
+    <ClCompile Include="..\..\..\..\Components\Lzma2\CpuArch.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\MtDec.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\7zStream.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\Components\Lzma2\LzFindOpt.c">
+      <Filter>SDK</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Alloc.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzFind.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzFindMt.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzHash.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Lzma2Enc.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\LzmaEnc.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\MtCoder.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Threads.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Types.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="islzma.h" />
+    <ClInclude Include="..\..\..\..\Components\Lzma2\7zTypes.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\7zWindows.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Compiler.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\CpuArch.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\Components\Lzma2\Precomp.h">
+      <Filter>SDK</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="islzma_exe.rc">
+      <Filter>Resource Files</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="islzma_exe32.ico">
+      <Filter>Resource Files</Filter>
+    </Image>
+    <Image Include="islzma_exe64.ico">
+      <Filter>Resource Files</Filter>
+    </Image>
+  </ItemGroup>
+</Project>

+ 15 - 0
Projects/Src/ISCmplr/islzma/islzma_exe.vcxproj.user

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LocalDebuggerCommand>$(ISSRCROOT)\Projects\Bin\Compil32.exe</LocalDebuggerCommand>
+    <LocalDebuggerCommandArguments>Debug.iss</LocalDebuggerCommandArguments>
+    <LocalDebuggerWorkingDirectory>$(ISSRCROOT)\Projects\Bin</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LocalDebuggerCommand>$(ISSRCROOT)\Projects\Bin\Compil32.exe</LocalDebuggerCommand>
+    <LocalDebuggerCommandArguments>Debug.iss</LocalDebuggerCommandArguments>
+    <LocalDebuggerWorkingDirectory>$(ISSRCROOT)\Projects\Bin</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+</Project>

+ 17 - 5
Projects/Src/Setup/LZMADecomp.pas

@@ -35,8 +35,8 @@ type
   end;
   end;
 
 
   { Internally-used records }
   { Internally-used records }
-  TLZMA1InternalDecoderState = array[0..27] of LongWord;
-  TLZMA2InternalDecoderState = array[0..34] of LongWord;
+  TLZMA1InternalDecoderState = array[0..24] of LongWord;
+  TLZMA2InternalDecoderState = array[0..28] of LongWord;
 
 
   TLZMA1Decompressor = class(TLZMACustomDecompressor)
   TLZMA1Decompressor = class(TLZMACustomDecompressor)
   private
   private
@@ -91,7 +91,7 @@ const
   { To ensure we don't allocate inordinate amounts of memory in the event a
   { To ensure we don't allocate inordinate amounts of memory in the event a
     stream's header is corrupted, we limit the dictionary size to the maximum
     stream's header is corrupted, we limit the dictionary size to the maximum
     size the compiler currently allows. }
     size the compiler currently allows. }
-  MaxDictionarySize = 1024 shl 20;  { 1 GB }
+  MaxDictionarySize = 1024 shl 20;  { 1 GB - same as ssLZMADictionarySize allows in Compile.pas }
 
 
 { Compiled by Visual Studio 2022 using compile.bat
 { Compiled by Visual Studio 2022 using compile.bat
   To enable source debugging recompile using compile-bcc32c.bat }
   To enable source debugging recompile using compile-bcc32c.bat }
@@ -101,6 +101,7 @@ const
 function IS_LzmaDec_Init(var state: TLZMA1InternalDecoderState;
 function IS_LzmaDec_Init(var state: TLZMA1InternalDecoderState;
   stateSize: Cardinal; const props; propsSize: Cardinal;
   stateSize: Cardinal; const props; propsSize: Cardinal;
   const alloc: TLZMAISzAlloc): TLZMASRes; cdecl; external name '_IS_LzmaDec_Init';
   const alloc: TLZMAISzAlloc): TLZMASRes; cdecl; external name '_IS_LzmaDec_Init';
+function IS_LzmaDec_StateSize: Cardinal; cdecl; external name '_IS_LzmaDec_StateSize';
 function LzmaDec_DecodeToBuf(var state: TLZMA1InternalDecoderState; var dest;
 function LzmaDec_DecodeToBuf(var state: TLZMA1InternalDecoderState; var dest;
   var destLen: Cardinal; const src; var srcLen: Cardinal; finishMode: Integer;
   var destLen: Cardinal; const src; var srcLen: Cardinal; finishMode: Integer;
   var status: Integer): TLZMASRes; cdecl; external name '_LzmaDec_DecodeToBuf';
   var status: Integer): TLZMASRes; cdecl; external name '_LzmaDec_DecodeToBuf';
@@ -110,6 +111,7 @@ procedure LzmaDec_Free(var state: TLZMA1InternalDecoderState;
 function IS_Lzma2Dec_Init(var state: TLZMA2InternalDecoderState;
 function IS_Lzma2Dec_Init(var state: TLZMA2InternalDecoderState;
   stateSize: Cardinal; prop: Byte; const alloc: TLZMAISzAlloc): TLZMASRes; cdecl;
   stateSize: Cardinal; prop: Byte; const alloc: TLZMAISzAlloc): TLZMASRes; cdecl;
   external name '_IS_Lzma2Dec_Init';
   external name '_IS_Lzma2Dec_Init';
+function IS_Lzma2Dec_StateSize: Cardinal; cdecl; external name '_IS_Lzma2Dec_StateSize';
 function Lzma2Dec_DecodeToBuf(var state: TLZMA2InternalDecoderState; var dest;
 function Lzma2Dec_DecodeToBuf(var state: TLZMA2InternalDecoderState; var dest;
   var destLen: Cardinal; const src; var srcLen: Cardinal; finishMode: Integer;
   var destLen: Cardinal; const src; var srcLen: Cardinal; finishMode: Integer;
   var status: Integer): TLZMASRes; cdecl; external name '_Lzma2Dec_DecodeToBuf';
   var status: Integer): TLZMASRes; cdecl; external name '_Lzma2Dec_DecodeToBuf';
@@ -239,9 +241,14 @@ begin
   if Props.DictionarySize > LongWord(MaxDictionarySize) then
   if Props.DictionarySize > LongWord(MaxDictionarySize) then
     LZMADecompDataError(5);
     LZMADecompDataError(5);
 
 
+  var StateSize := IS_LzmaDec_StateSize;
+  var DecoderStateSize := SizeOf(FDecoderState);
+  if StateSize <> DecoderStateSize then
+    LZMADecompDataError(-StateSize);
+
   { Note: IS_LzmaDec_Init will re-use already-allocated memory if it can.
   { Note: IS_LzmaDec_Init will re-use already-allocated memory if it can.
     FDecoderState is assumed to be initialized to zero on the first call. }
     FDecoderState is assumed to be initialized to zero on the first call. }
-  case IS_LzmaDec_Init(FDecoderState, SizeOf(FDecoderState), Props,
+  case IS_LzmaDec_Init(FDecoderState, DecoderStateSize, Props,
      SizeOf(Props), LZMAAlloc) of
      SizeOf(Props), LZMAAlloc) of
     SZ_OK: ;
     SZ_OK: ;
     SZ_ERROR_MEM: OutOfMemoryError;
     SZ_ERROR_MEM: OutOfMemoryError;
@@ -284,9 +291,14 @@ begin
      (LZMA2_DIC_SIZE_FROM_PROP(Prop) > LongWord(MaxDictionarySize)) then
      (LZMA2_DIC_SIZE_FROM_PROP(Prop) > LongWord(MaxDictionarySize)) then
     LZMADecompDataError(5);
     LZMADecompDataError(5);
 
 
+  var StateSize := IS_Lzma2Dec_StateSize;
+  var DecoderStateSize := SizeOf(FDecoderState);
+  if StateSize <> DecoderStateSize then
+    LZMADecompDataError(-StateSize);
+
   { Note: IS_Lzma2Dec_Init will re-use already-allocated memory if it can.
   { Note: IS_Lzma2Dec_Init will re-use already-allocated memory if it can.
     FDecoderState is assumed to be initialized to zero on the first call. }
     FDecoderState is assumed to be initialized to zero on the first call. }
-  case IS_Lzma2Dec_Init(FDecoderState, SizeOf(FDecoderState), Prop,
+  case IS_Lzma2Dec_Init(FDecoderState, DecoderStateSize, Prop,
      LZMAAlloc) of
      LZMAAlloc) of
     SZ_OK: ;
     SZ_OK: ;
     SZ_ERROR_MEM: OutOfMemoryError;
     SZ_ERROR_MEM: OutOfMemoryError;

+ 5 - 0
Projects/Src/Setup/Lzma2Decode/ISLzma2Dec.c

@@ -23,6 +23,11 @@ SRes IS_Lzma2Dec_Init(CLzma2Dec *state, size_t stateSize, Byte prop,
 	return SZ_OK;
 	return SZ_OK;
 }
 }
 
 
+size_t IS_Lzma2Dec_StateSize()
+{
+  return sizeof(CLzma2Dec);
+}
+
 void IS_Lzma2Dec_Free(CLzma2Dec *state, ISzAlloc *alloc)
 void IS_Lzma2Dec_Free(CLzma2Dec *state, ISzAlloc *alloc)
 {
 {
 	// This exists because Lzma2Dec_Free is a macro
 	// This exists because Lzma2Dec_Free is a macro

BIN
Projects/Src/Setup/Lzma2Decode/ISLzma2Dec.obj


+ 5 - 0
Projects/Src/Setup/Lzma2Decode/ISLzmaDec.c

@@ -22,3 +22,8 @@ SRes IS_LzmaDec_Init(CLzmaDec *state, size_t stateSize, const Byte *props,
 
 
 	return SZ_OK;
 	return SZ_OK;
 }
 }
+
+size_t IS_LzmaDec_StateSize()
+{
+  return sizeof(CLzmaDec);
+}

BIN
Projects/Src/Setup/Lzma2Decode/ISLzmaDec.obj


+ 1 - 1
Projects/Src/Setup/Lzma2Decode/compile.bat

@@ -35,7 +35,7 @@ if errorlevel 1 goto exit
 echo.
 echo.
 
 
 echo - Compiling ISLzmaDec.c and ISLzma2Dec.c
 echo - Compiling ISLzmaDec.c and ISLzma2Dec.c
-cl.exe /c /O2 /Gd /GS- ISLzmaDec.c ISLzma2Dec.c
+cl.exe /c /O2 /GS- ISLzmaDec.c ISLzma2Dec.c
 if errorlevel 1 goto failed
 if errorlevel 1 goto failed
 
 
 echo Success!
 echo Success!

+ 1 - 1
Projects/Src/SetupLdr/LzmaDecode/compile.bat

@@ -35,7 +35,7 @@ if errorlevel 1 goto exit
 echo.
 echo.
 
 
 echo - Compiling LzmaDecodeInno.c
 echo - Compiling LzmaDecodeInno.c
-cl /c /O2 /D_LZMA_OUT_READ /D_LZMA_IN_CB /Gd LzmaDecodeInno.c
+cl /c /O2 /D_LZMA_OUT_READ /D_LZMA_IN_CB LzmaDecodeInno.c
 if errorlevel 1 goto failed
 if errorlevel 1 goto failed
 
 
 echo Success!
 echo Success!

+ 1 - 1
README.md

@@ -200,7 +200,7 @@ from the bzlib directory in the iscompress repository.
 from the zlib-dll directory in the iscompress repository.
 from the zlib-dll directory in the iscompress repository.
 
 
 **Files\islzma.dll**, **Files\islzma32.exe**, **Files\islzma64.exe** - Compiled
 **Files\islzma.dll**, **Files\islzma32.exe**, **Files\islzma64.exe** - Compiled
-by Visual Studio 2005 from the [Projects\Src\ISCmplr\islzma] directory.
+by Visual Studio 2022 from the [Projects\Src\ISCmplr\islzma] directory.
 
 
 **Files\isscint.dll** - Compiled by Visual Studio 2022 from Scintilla source
 **Files\isscint.dll** - Compiled by Visual Studio 2022 from Scintilla source
 code in the isscint repository.
 code in the isscint repository.

+ 3 - 2
whatsnew.htm

@@ -34,7 +34,7 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
 
 
 <p><a name="6.4.0"></a><span class="ver">6.4.0-dev </span><span class="date">(?)</span></p>
 <p><a name="6.4.0"></a><span class="ver">6.4.0-dev </span><span class="date">(?)</span></p>
 <p><span class="head2">Compiler IDE changes</span></p>
 <p><span class="head2">Compiler IDE changes</span></p>
-<p>The editor component used by the Compiler IDE has been updated from an old version of Scintilla to the latest version.</p>
+<p>Updated the Scintilla editor component used by the Compiler IDE to the latest version.</p>
 <p>Multiple selection editing has been improved:</p>
 <p>Multiple selection editing has been improved:</p>
 <ul>
 <ul>
   <li>Added new <i>Add Next Occurrence</i> menu item to the <i>Edit</i> menu to add the next occurrence of the current word or selected text as an additional selection (Shift+Alt+.).</li>
   <li>Added new <i>Add Next Occurrence</i> menu item to the <i>Edit</i> menu to add the next occurrence of the current word or selected text as an additional selection (Shift+Alt+.).</li>
@@ -80,7 +80,8 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
 </ul>
 </ul>
 <p><span class="head2">Other changes</span></p>
 <p><span class="head2">Other changes</span></p>
 <ul>
 <ul>
-  <li>The Inno Setup Preprocessor documentation has been merged into the main documentation instead of being separate.</li>
+  <li>Updated the LZMA SDK used by Inno Setup to the latest version, increasing the speed of LZMA and LZMA2 compression and decompression (respectively by 21% and 11% in a test with default settings) without changing the compression ratio. Compression memory requirements have increased by about 4%.</li>
+  <li>Merged Inno Setup Preprocessor documentation into the main documentation instead of being separate.</li>
   <li>Added a dark mode version of the documentation, automatically used by the Compiler IDE if a dark theme is chosen.</li>
   <li>Added a dark mode version of the documentation, automatically used by the Compiler IDE if a dark theme is chosen.</li>
   <li>Pascal Scripting changes:
   <li>Pascal Scripting changes:
   <ul>
   <ul>

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor