Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/C
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2007-01-20 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:49 +0300
commitd9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch)
treec722ed19b844b53042aec0c1d7d2f8381140a5ed /C
parent804edc5756fede54dbb1aefda6d39d306111938d (diff)
4.44 beta
Diffstat (limited to 'C')
-rwxr-xr-xC/7zCrc.c137
-rwxr-xr-xC/7zCrc.h31
-rwxr-xr-xC/Archive/7z/7zAlloc.c70
-rwxr-xr-xC/Archive/7z/7zBuffer.c29
-rwxr-xr-xC/Archive/7z/7zDecode.c150
-rwxr-xr-xC/Archive/7z/7zExtract.c118
-rwxr-xr-xC/Archive/7z/7zHeader.c5
-rwxr-xr-xC/Archive/7z/7zIn.c1284
-rwxr-xr-xC/Archive/7z/7zItem.c133
-rwxr-xr-xC/Archive/7z/7zMain.c358
-rwxr-xr-xC/Archive/7z/7zMethodID.c14
-rwxr-xr-xC/Archive/7z/7z_C.dsp186
-rwxr-xr-xC/Archive/7z/7z_C.dsw29
-rwxr-xr-xC/Archive/7z/makefile55
-rwxr-xr-xC/Archive/7z/makefile.gcc50
-rwxr-xr-xC/Compress/Branch/BranchARM.c26
-rwxr-xr-xC/Compress/Branch/BranchARM.h10
-rwxr-xr-xC/Compress/Branch/BranchARMThumb.c35
-rwxr-xr-xC/Compress/Branch/BranchARMThumb.h10
-rwxr-xr-xC/Compress/Branch/BranchIA64.c63
-rwxr-xr-xC/Compress/Branch/BranchIA64.h10
-rwxr-xr-xC/Compress/Branch/BranchPPC.c36
-rwxr-xr-xC/Compress/Branch/BranchPPC.h10
-rwxr-xr-xC/Compress/Branch/BranchSPARC.c36
-rwxr-xr-xC/Compress/Branch/BranchSPARC.h10
-rwxr-xr-xC/Compress/Branch/BranchTypes.h25
-rwxr-xr-xC/Compress/Branch/BranchX86.c101
-rwxr-xr-xC/Compress/Branch/BranchX86.h13
-rwxr-xr-xC/Compress/Huffman/HuffmanEncode.c146
-rwxr-xr-xC/Compress/Huffman/HuffmanEncode.h20
-rwxr-xr-xC/Compress/Lz/LzHash.h53
-rwxr-xr-xC/Compress/Lz/MatchFinder.c725
-rwxr-xr-xC/Compress/Lz/MatchFinder.h103
-rwxr-xr-xC/Compress/Lz/MatchFinderMt.c792
-rwxr-xr-xC/Compress/Lz/MatchFinderMt.h97
-rwxr-xr-xC/Compress/Lzma/LzmaDecode.c584
-rwxr-xr-xC/Compress/Lzma/LzmaDecode.h113
-rwxr-xr-xC/Compress/Lzma/LzmaDecodeSize.c712
-rwxr-xr-xC/Compress/Lzma/LzmaStateDecode.c521
-rwxr-xr-xC/Compress/Lzma/LzmaStateDecode.h96
-rwxr-xr-xC/Compress/Lzma/LzmaStateTest.c195
-rwxr-xr-xC/Compress/Lzma/LzmaTest.c342
-rwxr-xr-xC/Compress/Lzma/LzmaTypes.h45
-rwxr-xr-xC/IStream.h19
-rwxr-xr-xC/Sort.c92
-rwxr-xr-xC/Sort.h11
-rwxr-xr-xC/Threads.c97
-rwxr-xr-xC/Threads.h60
-rwxr-xr-xC/Types.h92
49 files changed, 7949 insertions, 0 deletions
diff --git a/C/7zCrc.c b/C/7zCrc.c
new file mode 100755
index 00000000..136ac2e0
--- /dev/null
+++ b/C/7zCrc.c
@@ -0,0 +1,137 @@
+/* 7zCrc.c */
+
+#include "7zCrc.h"
+
+#define kCrcPoly 0xEDB88320
+
+UInt32 g_CrcTable[256]
+
+#ifdef CRC_GENERATE_TABLE
+;
+void CrcGenerateTable()
+{
+ UInt32 i;
+ for (i = 0; i < 256; i++)
+ {
+ UInt32 r = i;
+ int j;
+ for (j = 0; j < 8; j++)
+ if (r & 1)
+ r = (r >> 1) ^ kCrcPoly;
+ else
+ r >>= 1;
+ g_CrcTable[i] = r;
+ }
+}
+
+#else
+
+= {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+
+#endif
+
+void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; }
+UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; }
+
+void CrcUpdateByte(UInt32 *crc, Byte b)
+{
+ *crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8);
+}
+
+void CrcUpdateUInt16(UInt32 *crc, UInt16 v)
+{
+ CrcUpdateByte(crc, (Byte)v);
+ CrcUpdateByte(crc, (Byte)(v >> 8));
+}
+
+void CrcUpdateUInt32(UInt32 *crc, UInt32 v)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ CrcUpdateByte(crc, (Byte)(v >> (8 * i)));
+}
+
+void CrcUpdateUInt64(UInt32 *crc, UInt64 v)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ CrcUpdateByte(crc, (Byte)(v));
+ v >>= 8;
+ }
+}
+
+void CrcUpdate(UInt32 *crc, const void *data, size_t size)
+{
+ UInt32 v = *crc;
+ const Byte *p = (const Byte *)data;
+ for (; size > 0 ; size--, p++)
+ v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8);
+ *crc = v;
+}
+
+UInt32 CrcCalculateDigest(const void *data, size_t size)
+{
+ UInt32 crc;
+ CrcInit(&crc);
+ CrcUpdate(&crc, data, size);
+ return CrcGetDigest(&crc);
+}
+
+int CrcVerifyDigest(UInt32 digest, const void *data, size_t size)
+{
+ return (CrcCalculateDigest(data, size) == digest);
+}
diff --git a/C/7zCrc.h b/C/7zCrc.h
new file mode 100755
index 00000000..370b2a0f
--- /dev/null
+++ b/C/7zCrc.h
@@ -0,0 +1,31 @@
+/* 7zCrc.h */
+
+#ifndef __7Z_CRC_H
+#define __7Z_CRC_H
+
+#include <stddef.h>
+
+#include "Types.h"
+
+extern UInt32 g_CrcTable[256];
+
+// #define CRC_GENERATE_TABLE
+
+#ifdef CRC_GENERATE_TABLE
+void CrcGenerateTable();
+#else
+#define CrcGenerateTable()
+#endif
+
+void CrcInit(UInt32 *crc);
+UInt32 CrcGetDigest(UInt32 *crc);
+void CrcUpdateByte(UInt32 *crc, Byte v);
+void CrcUpdateUInt16(UInt32 *crc, UInt16 v);
+void CrcUpdateUInt32(UInt32 *crc, UInt32 v);
+void CrcUpdateUInt64(UInt32 *crc, UInt64 v);
+void CrcUpdate(UInt32 *crc, const void *data, size_t size);
+
+UInt32 CrcCalculateDigest(const void *data, size_t size);
+int CrcVerifyDigest(UInt32 digest, const void *data, size_t size);
+
+#endif
diff --git a/C/Archive/7z/7zAlloc.c b/C/Archive/7z/7zAlloc.c
new file mode 100755
index 00000000..21bb30c7
--- /dev/null
+++ b/C/Archive/7z/7zAlloc.c
@@ -0,0 +1,70 @@
+/* 7zAlloc.c */
+
+#include <stdlib.h>
+#include "7zAlloc.h"
+
+/* #define _SZ_ALLOC_DEBUG */
+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
+
+#ifdef _SZ_ALLOC_DEBUG
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <stdio.h>
+int g_allocCount = 0;
+int g_allocCountTemp = 0;
+#endif
+
+void *SzAlloc(size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
+ g_allocCount++;
+ #endif
+ return malloc(size);
+}
+
+void SzFree(void *address)
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ {
+ g_allocCount--;
+ fprintf(stderr, "\nFree; count = %10d", g_allocCount);
+ }
+ #endif
+ free(address);
+}
+
+void *SzAllocTemp(size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef _SZ_ALLOC_DEBUG
+ fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
+ g_allocCountTemp++;
+ #ifdef _WIN32
+ return HeapAlloc(GetProcessHeap(), 0, size);
+ #endif
+ #endif
+ return malloc(size);
+}
+
+void SzFreeTemp(void *address)
+{
+ #ifdef _SZ_ALLOC_DEBUG
+ if (address != 0)
+ {
+ g_allocCountTemp--;
+ fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
+ }
+ #ifdef _WIN32
+ HeapFree(GetProcessHeap(), 0, address);
+ return;
+ #endif
+ #endif
+ free(address);
+}
diff --git a/C/Archive/7z/7zBuffer.c b/C/Archive/7z/7zBuffer.c
new file mode 100755
index 00000000..3c4b71e8
--- /dev/null
+++ b/C/Archive/7z/7zBuffer.c
@@ -0,0 +1,29 @@
+/* 7zBuffer.c */
+
+#include "7zBuffer.h"
+#include "7zAlloc.h"
+
+void SzByteBufferInit(CSzByteBuffer *buffer)
+{
+ buffer->Capacity = 0;
+ buffer->Items = 0;
+}
+
+int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size))
+{
+ buffer->Capacity = newCapacity;
+ if (newCapacity == 0)
+ {
+ buffer->Items = 0;
+ return 1;
+ }
+ buffer->Items = (Byte *)allocFunc(newCapacity);
+ return (buffer->Items != 0);
+}
+
+void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *))
+{
+ freeFunc(buffer->Items);
+ buffer->Items = 0;
+ buffer->Capacity = 0;
+}
diff --git a/C/Archive/7z/7zDecode.c b/C/Archive/7z/7zDecode.c
new file mode 100755
index 00000000..fe530384
--- /dev/null
+++ b/C/Archive/7z/7zDecode.c
@@ -0,0 +1,150 @@
+/* 7zDecode.c */
+
+#include "7zDecode.h"
+#ifdef _SZ_ONE_DIRECTORY
+#include "LzmaDecode.h"
+#else
+#include "../../Compress/Lzma/LzmaDecode.h"
+#endif
+
+CMethodID k_Copy = { { 0x0 }, 1 };
+CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+
+#ifdef _LZMA_IN_CB
+
+typedef struct _CLzmaInCallbackImp
+{
+ ILzmaInCallback InCallback;
+ ISzInStream *InStream;
+ size_t Size;
+} CLzmaInCallbackImp;
+
+int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
+{
+ CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
+ size_t processedSize;
+ SZ_RESULT res;
+ *size = 0;
+ res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize);
+ *size = (SizeT)processedSize;
+ if (processedSize > cb->Size)
+ return (int)SZE_FAIL;
+ cb->Size -= processedSize;
+ if (res == SZ_OK)
+ return 0;
+ return (int)res;
+}
+
+#endif
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+ #ifdef _LZMA_IN_CB
+ ISzInStream *inStream,
+ #else
+ const Byte *inBuffer,
+ #endif
+ Byte *outBuffer, size_t outSize,
+ size_t *outSizeProcessed, ISzAlloc *allocMain)
+{
+ UInt32 si;
+ size_t inSize = 0;
+ CCoderInfo *coder;
+ if (folder->NumPackStreams != 1)
+ return SZE_NOTIMPL;
+ if (folder->NumCoders != 1)
+ return SZE_NOTIMPL;
+ coder = folder->Coders;
+ *outSizeProcessed = 0;
+
+ for (si = 0; si < folder->NumPackStreams; si++)
+ inSize += (size_t)packSizes[si];
+
+ if (AreMethodsEqual(&coder->MethodID, &k_Copy))
+ {
+ size_t i;
+ if (inSize != outSize)
+ return SZE_DATA_ERROR;
+ #ifdef _LZMA_IN_CB
+ for (i = 0; i < inSize;)
+ {
+ size_t j;
+ void *inBuffer;
+ size_t bufferSize;
+ RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize));
+ if (bufferSize == 0)
+ return SZE_DATA_ERROR;
+ if (bufferSize > inSize - i)
+ return SZE_FAIL;
+ *outSizeProcessed += bufferSize;
+ for (j = 0; j < bufferSize && i < inSize; j++, i++)
+ outBuffer[i] = ((const Byte *)inBuffer)[j];
+ }
+ #else
+ for (i = 0; i < inSize; i++)
+ outBuffer[i] = inBuffer[i];
+ *outSizeProcessed = inSize;
+ #endif
+ return SZ_OK;
+ }
+
+ if (AreMethodsEqual(&coder->MethodID, &k_LZMA))
+ {
+ #ifdef _LZMA_IN_CB
+ CLzmaInCallbackImp lzmaCallback;
+ #else
+ SizeT inProcessed;
+ #endif
+
+ CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
+ int result;
+ SizeT outSizeProcessedLoc;
+
+ #ifdef _LZMA_IN_CB
+ lzmaCallback.Size = inSize;
+ lzmaCallback.InStream = inStream;
+ lzmaCallback.InCallback.Read = LzmaReadImp;
+ #endif
+
+ if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
+ coder->Properties.Capacity) != LZMA_RESULT_OK)
+ return SZE_FAIL;
+
+ state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (state.Probs == 0)
+ return SZE_OUTOFMEMORY;
+
+ #ifdef _LZMA_OUT_READ
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ {
+ state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
+ if (state.Dictionary == 0)
+ {
+ allocMain->Free(state.Probs);
+ return SZE_OUTOFMEMORY;
+ }
+ }
+ LzmaDecoderInit(&state);
+ #endif
+
+ result = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &lzmaCallback.InCallback,
+ #else
+ inBuffer, (SizeT)inSize, &inProcessed,
+ #endif
+ outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
+ *outSizeProcessed = (size_t)outSizeProcessedLoc;
+ allocMain->Free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ allocMain->Free(state.Dictionary);
+ #endif
+ if (result == LZMA_RESULT_DATA_ERROR)
+ return SZE_DATA_ERROR;
+ if (result != LZMA_RESULT_OK)
+ return SZE_FAIL;
+ return SZ_OK;
+ }
+ return SZE_NOTIMPL;
+}
diff --git a/C/Archive/7z/7zExtract.c b/C/Archive/7z/7zExtract.c
new file mode 100755
index 00000000..748591a5
--- /dev/null
+++ b/C/Archive/7z/7zExtract.c
@@ -0,0 +1,118 @@
+/* 7zExtract.c */
+
+#include "7zExtract.h"
+#include "7zDecode.h"
+#include "../../7zCrc.h"
+
+SZ_RESULT SzExtract(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ UInt32 fileIndex,
+ UInt32 *blockIndex,
+ Byte **outBuffer,
+ size_t *outBufferSize,
+ size_t *offset,
+ size_t *outSizeProcessed,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
+ SZ_RESULT res = SZ_OK;
+ *offset = 0;
+ *outSizeProcessed = 0;
+ if (folderIndex == (UInt32)-1)
+ {
+ allocMain->Free(*outBuffer);
+ *blockIndex = folderIndex;
+ *outBuffer = 0;
+ *outBufferSize = 0;
+ return SZ_OK;
+ }
+
+ if (*outBuffer == 0 || *blockIndex != folderIndex)
+ {
+ CFolder *folder = db->Database.Folders + folderIndex;
+ CFileSize unPackSize = SzFolderGetUnPackSize(folder);
+ #ifndef _LZMA_IN_CB
+ CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex);
+ Byte *inBuffer = 0;
+ size_t processedSize;
+ #endif
+ if (unPackSize != (size_t)unPackSize)
+ return SZE_OUTOFMEMORY;
+ *blockIndex = folderIndex;
+ allocMain->Free(*outBuffer);
+ *outBuffer = 0;
+
+ RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0)));
+
+ #ifndef _LZMA_IN_CB
+ if (packSize != 0)
+ {
+ inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize);
+ if (inBuffer == 0)
+ return SZE_OUTOFMEMORY;
+ }
+ res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize);
+ if (res == SZ_OK && processedSize != (size_t)packSize)
+ res = SZE_FAIL;
+ #endif
+ if (res == SZ_OK)
+ {
+ *outBufferSize = (size_t)unPackSize;
+ if (unPackSize != 0)
+ {
+ *outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize);
+ if (*outBuffer == 0)
+ res = SZE_OUTOFMEMORY;
+ }
+ if (res == SZ_OK)
+ {
+ size_t outRealSize;
+ res = SzDecode(db->Database.PackSizes +
+ db->FolderStartPackStreamIndex[folderIndex], folder,
+ #ifdef _LZMA_IN_CB
+ inStream,
+ #else
+ inBuffer,
+ #endif
+ *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp);
+ if (res == SZ_OK)
+ {
+ if (outRealSize == (size_t)unPackSize)
+ {
+ if (folder->UnPackCRCDefined)
+ {
+ if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize))
+ res = SZE_FAIL;
+ }
+ }
+ else
+ res = SZE_FAIL;
+ }
+ }
+ }
+ #ifndef _LZMA_IN_CB
+ allocTemp->Free(inBuffer);
+ #endif
+ }
+ if (res == SZ_OK)
+ {
+ UInt32 i;
+ CFileItem *fileItem = db->Database.Files + fileIndex;
+ *offset = 0;
+ for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
+ *offset += (UInt32)db->Database.Files[i].Size;
+ *outSizeProcessed = (size_t)fileItem->Size;
+ if (*offset + *outSizeProcessed > *outBufferSize)
+ return SZE_FAIL;
+ {
+ if (fileItem->IsFileCRCDefined)
+ {
+ if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed))
+ res = SZE_FAIL;
+ }
+ }
+ }
+ return res;
+}
diff --git a/C/Archive/7z/7zHeader.c b/C/Archive/7z/7zHeader.c
new file mode 100755
index 00000000..3be4bc27
--- /dev/null
+++ b/C/Archive/7z/7zHeader.c
@@ -0,0 +1,5 @@
+/* 7zHeader.c */
+
+#include "7zHeader.h"
+
+Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
diff --git a/C/Archive/7z/7zIn.c b/C/Archive/7z/7zIn.c
new file mode 100755
index 00000000..8f3d7cae
--- /dev/null
+++ b/C/Archive/7z/7zIn.c
@@ -0,0 +1,1284 @@
+/* 7zIn.c */
+
+#include "7zIn.h"
+#include "7zDecode.h"
+#include "../../7zCrc.h"
+
+#define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; }
+
+void SzArDbExInit(CArchiveDatabaseEx *db)
+{
+ SzArchiveDatabaseInit(&db->Database);
+ db->FolderStartPackStreamIndex = 0;
+ db->PackStreamStartPositions = 0;
+ db->FolderStartFileIndex = 0;
+ db->FileIndexToFolderIndexMap = 0;
+}
+
+void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *))
+{
+ freeFunc(db->FolderStartPackStreamIndex);
+ freeFunc(db->PackStreamStartPositions);
+ freeFunc(db->FolderStartFileIndex);
+ freeFunc(db->FileIndexToFolderIndexMap);
+ SzArchiveDatabaseFree(&db->Database, freeFunc);
+ SzArDbExInit(db);
+}
+
+/*
+CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const
+{
+ return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
+}
+
+CFileSize GetFilePackSize(int fileIndex) const
+{
+ int folderIndex = FileIndexToFolderIndexMap[fileIndex];
+ if (folderIndex >= 0)
+ {
+ const CFolder &folderInfo = Folders[folderIndex];
+ if (FolderStartFileIndex[folderIndex] == fileIndex)
+ return GetFolderFullPackSize(folderIndex);
+ }
+ return 0;
+}
+*/
+
+#define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \
+ if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; }
+
+SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
+{
+ UInt32 startPos = 0;
+ CFileSize startPosSize = 0;
+ UInt32 i;
+ UInt32 folderIndex = 0;
+ UInt32 indexInFolder = 0;
+ MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc);
+ for(i = 0; i < db->Database.NumFolders; i++)
+ {
+ db->FolderStartPackStreamIndex[i] = startPos;
+ startPos += db->Database.Folders[i].NumPackStreams;
+ }
+
+ MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc);
+
+ for(i = 0; i < db->Database.NumPackStreams; i++)
+ {
+ db->PackStreamStartPositions[i] = startPosSize;
+ startPosSize += db->Database.PackSizes[i];
+ }
+
+ MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc);
+ MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc);
+
+ for (i = 0; i < db->Database.NumFiles; i++)
+ {
+ CFileItem *file = db->Database.Files + i;
+ int emptyStream = !file->HasStream;
+ if (emptyStream && indexInFolder == 0)
+ {
+ db->FileIndexToFolderIndexMap[i] = (UInt32)-1;
+ continue;
+ }
+ if (indexInFolder == 0)
+ {
+ /*
+ v3.13 incorrectly worked with empty folders
+ v4.07: Loop for skipping empty folders
+ */
+ for (;;)
+ {
+ if (folderIndex >= db->Database.NumFolders)
+ return SZE_ARCHIVE_ERROR;
+ db->FolderStartFileIndex[folderIndex] = i;
+ if (db->Database.Folders[folderIndex].NumUnPackStreams != 0)
+ break;
+ folderIndex++;
+ }
+ }
+ db->FileIndexToFolderIndexMap[i] = folderIndex;
+ if (emptyStream)
+ continue;
+ indexInFolder++;
+ if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams)
+ {
+ folderIndex++;
+ indexInFolder = 0;
+ }
+ }
+ return SZ_OK;
+}
+
+
+CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder)
+{
+ return db->ArchiveInfo.DataStartPosition +
+ db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder];
+}
+
+CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex)
+{
+ UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex];
+ CFolder *folder = db->Database.Folders + folderIndex;
+ CFileSize size = 0;
+ UInt32 i;
+ for (i = 0; i < folder->NumPackStreams; i++)
+ size += db->Database.PackSizes[packStreamIndex + i];
+ return size;
+}
+
+
+/*
+SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector,
+ CObjectVector<CFileItem> &files, UInt64 type)
+{
+ CBoolVector boolVector;
+ RINOK(ReadBoolVector2(files.Size(), boolVector))
+
+ CStreamSwitch streamSwitch;
+ RINOK(streamSwitch.Set(this, &dataVector));
+
+ for(int i = 0; i < files.Size(); i++)
+ {
+ CFileItem &file = files[i];
+ CArchiveFileTime fileTime;
+ bool defined = boolVector[i];
+ if (defined)
+ {
+ UInt32 low, high;
+ RINOK(SzReadUInt32(low));
+ RINOK(SzReadUInt32(high));
+ fileTime.dwLowDateTime = low;
+ fileTime.dwHighDateTime = high;
+ }
+ switch(type)
+ {
+ case k7zIdCreationTime:
+ file.IsCreationTimeDefined = defined;
+ if (defined)
+ file.CreationTime = fileTime;
+ break;
+ case k7zIdLastWriteTime:
+ file.IsLastWriteTimeDefined = defined;
+ if (defined)
+ file.LastWriteTime = fileTime;
+ break;
+ case k7zIdLastAccessTime:
+ file.IsLastAccessTimeDefined = defined;
+ if (defined)
+ file.LastAccessTime = fileTime;
+ break;
+ }
+ }
+ return SZ_OK;
+}
+*/
+
+SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size)
+{
+ #ifdef _LZMA_IN_CB
+ while (size > 0)
+ {
+ void *inBufferSpec;
+ size_t processedSize;
+ const Byte *inBuffer;
+ RINOK(inStream->Read(inStream, (void **)&inBufferSpec, size, &processedSize));
+ inBuffer = (const Byte *)inBufferSpec;
+ if (processedSize == 0 || processedSize > size)
+ return SZE_FAIL;
+ size -= processedSize;
+ do
+ {
+ *data++ = *inBuffer++;
+ }
+ while (--processedSize != 0);
+ }
+ #else
+ size_t processedSize;
+ RINOK(inStream->Read(inStream, data, size, &processedSize));
+ if (processedSize != size)
+ return SZE_FAIL;
+ #endif
+ return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data)
+{
+ return SafeReadDirect(inStream, data, 1);
+}
+
+SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value)
+{
+ int i;
+ *value = 0;
+ for (i = 0; i < 4; i++)
+ {
+ Byte b;
+ RINOK(SafeReadDirectByte(inStream, &b));
+ *value |= ((UInt32)b << (8 * i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value)
+{
+ int i;
+ *value = 0;
+ for (i = 0; i < 8; i++)
+ {
+ Byte b;
+ RINOK(SafeReadDirectByte(inStream, &b));
+ *value |= ((UInt64)b << (8 * i));
+ }
+ return SZ_OK;
+}
+
+int TestSignatureCandidate(Byte *testBytes)
+{
+ size_t i;
+ for (i = 0; i < k7zSignatureSize; i++)
+ if (testBytes[i] != k7zSignature[i])
+ return 0;
+ return 1;
+}
+
+typedef struct _CSzState
+{
+ Byte *Data;
+ size_t Size;
+}CSzData;
+
+SZ_RESULT SzReadByte(CSzData *sd, Byte *b)
+{
+ if (sd->Size == 0)
+ return SZE_ARCHIVE_ERROR;
+ sd->Size--;
+ *b = *sd->Data++;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size)
+{
+ size_t i;
+ for (i = 0; i < size; i++)
+ {
+ RINOK(SzReadByte(sd, data + i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value)
+{
+ int i;
+ *value = 0;
+ for (i = 0; i < 4; i++)
+ {
+ Byte b;
+ RINOK(SzReadByte(sd, &b));
+ *value |= ((UInt32)(b) << (8 * i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value)
+{
+ Byte firstByte;
+ Byte mask = 0x80;
+ int i;
+ RINOK(SzReadByte(sd, &firstByte));
+ *value = 0;
+ for (i = 0; i < 8; i++)
+ {
+ Byte b;
+ if ((firstByte & mask) == 0)
+ {
+ UInt64 highPart = firstByte & (mask - 1);
+ *value += (highPart << (8 * i));
+ return SZ_OK;
+ }
+ RINOK(SzReadByte(sd, &b));
+ *value |= ((UInt64)b << (8 * i));
+ mask >>= 1;
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value)
+{
+ UInt64 value64;
+ RINOK(SzReadNumber(sd, &value64));
+ *value = (CFileSize)value64;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value)
+{
+ UInt64 value64;
+ RINOK(SzReadNumber(sd, &value64));
+ if (value64 >= 0x80000000)
+ return SZE_NOTIMPL;
+ if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))
+ return SZE_NOTIMPL;
+ *value = (UInt32)value64;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadID(CSzData *sd, UInt64 *value)
+{
+ return SzReadNumber(sd, value);
+}
+
+SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size)
+{
+ if (size > sd->Size)
+ return SZE_ARCHIVE_ERROR;
+ sd->Size -= (size_t)size;
+ sd->Data += (size_t)size;
+ return SZ_OK;
+}
+
+SZ_RESULT SzSkeepData(CSzData *sd)
+{
+ UInt64 size;
+ RINOK(SzReadNumber(sd, &size));
+ return SzSkeepDataSize(sd, size);
+}
+
+SZ_RESULT SzReadArchiveProperties(CSzData *sd)
+{
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ break;
+ SzSkeepData(sd);
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute)
+{
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == attribute)
+ return SZ_OK;
+ if (type == k7zIdEnd)
+ return SZE_ARCHIVE_ERROR;
+ RINOK(SzSkeepData(sd));
+ }
+}
+
+SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+ Byte b = 0;
+ Byte mask = 0;
+ size_t i;
+ MY_ALLOC(Byte, *v, numItems, allocFunc);
+ for (i = 0; i < numItems; i++)
+ {
+ if (mask == 0)
+ {
+ RINOK(SzReadByte(sd, &b));
+ mask = 0x80;
+ }
+ (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);
+ mask >>= 1;
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+ Byte allAreDefined;
+ size_t i;
+ RINOK(SzReadByte(sd, &allAreDefined));
+ if (allAreDefined == 0)
+ return SzReadBoolVector(sd, numItems, v, allocFunc);
+ MY_ALLOC(Byte, *v, numItems, allocFunc);
+ for(i = 0; i < numItems; i++)
+ (*v)[i] = 1;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadHashDigests(
+ CSzData *sd,
+ size_t numItems,
+ Byte **digestsDefined,
+ UInt32 **digests,
+ void * (*allocFunc)(size_t size))
+{
+ size_t i;
+ RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc));
+ MY_ALLOC(UInt32, *digests, numItems, allocFunc);
+ for(i = 0; i < numItems; i++)
+ if ((*digestsDefined)[i])
+ {
+ RINOK(SzReadUInt32(sd, (*digests) + i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadPackInfo(
+ CSzData *sd,
+ CFileSize *dataOffset,
+ UInt32 *numPackStreams,
+ CFileSize **packSizes,
+ Byte **packCRCsDefined,
+ UInt32 **packCRCs,
+ void * (*allocFunc)(size_t size))
+{
+ UInt32 i;
+ RINOK(SzReadSize(sd, dataOffset));
+ RINOK(SzReadNumber32(sd, numPackStreams));
+
+ RINOK(SzWaitAttribute(sd, k7zIdSize));
+
+ MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc);
+
+ for(i = 0; i < *numPackStreams; i++)
+ {
+ RINOK(SzReadSize(sd, (*packSizes) + i));
+ }
+
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ break;
+ if (type == k7zIdCRC)
+ {
+ RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc));
+ continue;
+ }
+ RINOK(SzSkeepData(sd));
+ }
+ if (*packCRCsDefined == 0)
+ {
+ MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc);
+ MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc);
+ for(i = 0; i < *numPackStreams; i++)
+ {
+ (*packCRCsDefined)[i] = 0;
+ (*packCRCs)[i] = 0;
+ }
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadSwitch(CSzData *sd)
+{
+ Byte external;
+ RINOK(SzReadByte(sd, &external));
+ return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR;
+}
+
+SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size))
+{
+ UInt32 numCoders;
+ UInt32 numBindPairs;
+ UInt32 numPackedStreams;
+ UInt32 i;
+ UInt32 numInStreams = 0;
+ UInt32 numOutStreams = 0;
+ RINOK(SzReadNumber32(sd, &numCoders));
+ folder->NumCoders = numCoders;
+
+ MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc);
+
+ for (i = 0; i < numCoders; i++)
+ SzCoderInfoInit(folder->Coders + i);
+
+ for (i = 0; i < numCoders; i++)
+ {
+ Byte mainByte;
+ CCoderInfo *coder = folder->Coders + i;
+ {
+ RINOK(SzReadByte(sd, &mainByte));
+ coder->MethodID.IDSize = (Byte)(mainByte & 0xF);
+ RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize));
+ if ((mainByte & 0x10) != 0)
+ {
+ RINOK(SzReadNumber32(sd, &coder->NumInStreams));
+ RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
+ }
+ else
+ {
+ coder->NumInStreams = 1;
+ coder->NumOutStreams = 1;
+ }
+ if ((mainByte & 0x20) != 0)
+ {
+ UInt64 propertiesSize = 0;
+ RINOK(SzReadNumber(sd, &propertiesSize));
+ if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc))
+ return SZE_OUTOFMEMORY;
+ RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize));
+ }
+ }
+ while ((mainByte & 0x80) != 0)
+ {
+ RINOK(SzReadByte(sd, &mainByte));
+ RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
+ if ((mainByte & 0x10) != 0)
+ {
+ UInt32 n;
+ RINOK(SzReadNumber32(sd, &n));
+ RINOK(SzReadNumber32(sd, &n));
+ }
+ if ((mainByte & 0x20) != 0)
+ {
+ UInt64 propertiesSize = 0;
+ RINOK(SzReadNumber(sd, &propertiesSize));
+ RINOK(SzSkeepDataSize(sd, propertiesSize));
+ }
+ }
+ numInStreams += (UInt32)coder->NumInStreams;
+ numOutStreams += (UInt32)coder->NumOutStreams;
+ }
+
+ numBindPairs = numOutStreams - 1;
+ folder->NumBindPairs = numBindPairs;
+
+
+ MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc);
+
+ for (i = 0; i < numBindPairs; i++)
+ {
+ CBindPair *bindPair = folder->BindPairs + i;;
+ RINOK(SzReadNumber32(sd, &bindPair->InIndex));
+ RINOK(SzReadNumber32(sd, &bindPair->OutIndex));
+ }
+
+ numPackedStreams = numInStreams - (UInt32)numBindPairs;
+
+ folder->NumPackStreams = numPackedStreams;
+ MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc);
+
+ if (numPackedStreams == 1)
+ {
+ UInt32 j;
+ UInt32 pi = 0;
+ for (j = 0; j < numInStreams; j++)
+ if (SzFolderFindBindPairForInStream(folder, j) < 0)
+ {
+ folder->PackStreams[pi++] = j;
+ break;
+ }
+ }
+ else
+ for(i = 0; i < numPackedStreams; i++)
+ {
+ RINOK(SzReadNumber32(sd, folder->PackStreams + i));
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadUnPackInfo(
+ CSzData *sd,
+ UInt32 *numFolders,
+ CFolder **folders, /* for allocFunc */
+ void * (*allocFunc)(size_t size),
+ ISzAlloc *allocTemp)
+{
+ UInt32 i;
+ RINOK(SzWaitAttribute(sd, k7zIdFolder));
+ RINOK(SzReadNumber32(sd, numFolders));
+ {
+ RINOK(SzReadSwitch(sd));
+
+ MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc);
+
+ for(i = 0; i < *numFolders; i++)
+ SzFolderInit((*folders) + i);
+
+ for(i = 0; i < *numFolders; i++)
+ {
+ RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc));
+ }
+ }
+
+ RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize));
+
+ for(i = 0; i < *numFolders; i++)
+ {
+ UInt32 j;
+ CFolder *folder = (*folders) + i;
+ UInt32 numOutStreams = SzFolderGetNumOutStreams(folder);
+
+ MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc);
+
+ for(j = 0; j < numOutStreams; j++)
+ {
+ RINOK(SzReadSize(sd, folder->UnPackSizes + j));
+ }
+ }
+
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ return SZ_OK;
+ if (type == k7zIdCRC)
+ {
+ SZ_RESULT res;
+ Byte *crcsDefined = 0;
+ UInt32 *crcs = 0;
+ res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc);
+ if (res == SZ_OK)
+ {
+ for(i = 0; i < *numFolders; i++)
+ {
+ CFolder *folder = (*folders) + i;
+ folder->UnPackCRCDefined = crcsDefined[i];
+ folder->UnPackCRC = crcs[i];
+ }
+ }
+ allocTemp->Free(crcs);
+ allocTemp->Free(crcsDefined);
+ RINOK(res);
+ continue;
+ }
+ RINOK(SzSkeepData(sd));
+ }
+}
+
+SZ_RESULT SzReadSubStreamsInfo(
+ CSzData *sd,
+ UInt32 numFolders,
+ CFolder *folders,
+ UInt32 *numUnPackStreams,
+ CFileSize **unPackSizes,
+ Byte **digestsDefined,
+ UInt32 **digests,
+ ISzAlloc *allocTemp)
+{
+ UInt64 type = 0;
+ UInt32 i;
+ UInt32 si = 0;
+ UInt32 numDigests = 0;
+
+ for(i = 0; i < numFolders; i++)
+ folders[i].NumUnPackStreams = 1;
+ *numUnPackStreams = numFolders;
+
+ for (;;)
+ {
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdNumUnPackStream)
+ {
+ *numUnPackStreams = 0;
+ for(i = 0; i < numFolders; i++)
+ {
+ UInt32 numStreams;
+ RINOK(SzReadNumber32(sd, &numStreams));
+ folders[i].NumUnPackStreams = numStreams;
+ *numUnPackStreams += numStreams;
+ }
+ continue;
+ }
+ if (type == k7zIdCRC || type == k7zIdSize)
+ break;
+ if (type == k7zIdEnd)
+ break;
+ RINOK(SzSkeepData(sd));
+ }
+
+ if (*numUnPackStreams == 0)
+ {
+ *unPackSizes = 0;
+ *digestsDefined = 0;
+ *digests = 0;
+ }
+ else
+ {
+ *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize));
+ RINOM(*unPackSizes);
+ *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte));
+ RINOM(*digestsDefined);
+ *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32));
+ RINOM(*digests);
+ }
+
+ for(i = 0; i < numFolders; i++)
+ {
+ /*
+ v3.13 incorrectly worked with empty folders
+ v4.07: we check that folder is empty
+ */
+ CFileSize sum = 0;
+ UInt32 j;
+ UInt32 numSubstreams = folders[i].NumUnPackStreams;
+ if (numSubstreams == 0)
+ continue;
+ if (type == k7zIdSize)
+ for (j = 1; j < numSubstreams; j++)
+ {
+ CFileSize size;
+ RINOK(SzReadSize(sd, &size));
+ (*unPackSizes)[si++] = size;
+ sum += size;
+ }
+ (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum;
+ }
+ if (type == k7zIdSize)
+ {
+ RINOK(SzReadID(sd, &type));
+ }
+
+ for(i = 0; i < *numUnPackStreams; i++)
+ {
+ (*digestsDefined)[i] = 0;
+ (*digests)[i] = 0;
+ }
+
+
+ for(i = 0; i < numFolders; i++)
+ {
+ UInt32 numSubstreams = folders[i].NumUnPackStreams;
+ if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
+ numDigests += numSubstreams;
+ }
+
+
+ si = 0;
+ for (;;)
+ {
+ if (type == k7zIdCRC)
+ {
+ int digestIndex = 0;
+ Byte *digestsDefined2 = 0;
+ UInt32 *digests2 = 0;
+ SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc);
+ if (res == SZ_OK)
+ {
+ for (i = 0; i < numFolders; i++)
+ {
+ CFolder *folder = folders + i;
+ UInt32 numSubstreams = folder->NumUnPackStreams;
+ if (numSubstreams == 1 && folder->UnPackCRCDefined)
+ {
+ (*digestsDefined)[si] = 1;
+ (*digests)[si] = folder->UnPackCRC;
+ si++;
+ }
+ else
+ {
+ UInt32 j;
+ for (j = 0; j < numSubstreams; j++, digestIndex++)
+ {
+ (*digestsDefined)[si] = digestsDefined2[digestIndex];
+ (*digests)[si] = digests2[digestIndex];
+ si++;
+ }
+ }
+ }
+ }
+ allocTemp->Free(digestsDefined2);
+ allocTemp->Free(digests2);
+ RINOK(res);
+ }
+ else if (type == k7zIdEnd)
+ return SZ_OK;
+ else
+ {
+ RINOK(SzSkeepData(sd));
+ }
+ RINOK(SzReadID(sd, &type));
+ }
+}
+
+
+SZ_RESULT SzReadStreamsInfo(
+ CSzData *sd,
+ CFileSize *dataOffset,
+ CArchiveDatabase *db,
+ UInt32 *numUnPackStreams,
+ CFileSize **unPackSizes, /* allocTemp */
+ Byte **digestsDefined, /* allocTemp */
+ UInt32 **digests, /* allocTemp */
+ void * (*allocFunc)(size_t size),
+ ISzAlloc *allocTemp)
+{
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(SzReadID(sd, &type));
+ if ((UInt64)(int)type != type)
+ return SZE_FAIL;
+ switch((int)type)
+ {
+ case k7zIdEnd:
+ return SZ_OK;
+ case k7zIdPackInfo:
+ {
+ RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams,
+ &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc));
+ break;
+ }
+ case k7zIdUnPackInfo:
+ {
+ RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp));
+ break;
+ }
+ case k7zIdSubStreamsInfo:
+ {
+ RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders,
+ numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp));
+ break;
+ }
+ default:
+ return SZE_FAIL;
+ }
+ }
+}
+
+Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files,
+ void * (*allocFunc)(size_t size))
+{
+ UInt32 i;
+ for(i = 0; i < numFiles; i++)
+ {
+ UInt32 len = 0;
+ UInt32 pos = 0;
+ CFileItem *file = files + i;
+ while(pos + 2 <= sd->Size)
+ {
+ int numAdds;
+ UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+ pos += 2;
+ len++;
+ if (value == 0)
+ break;
+ if (value < 0x80)
+ continue;
+ if (value >= 0xD800 && value < 0xE000)
+ {
+ UInt32 c2;
+ if (value >= 0xDC00)
+ return SZE_ARCHIVE_ERROR;
+ if (pos + 2 > sd->Size)
+ return SZE_ARCHIVE_ERROR;
+ c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+ pos += 2;
+ if (c2 < 0xDC00 || c2 >= 0xE000)
+ return SZE_ARCHIVE_ERROR;
+ value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+ }
+ for (numAdds = 1; numAdds < 5; numAdds++)
+ if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+ break;
+ len += numAdds;
+ }
+
+ MY_ALLOC(char, file->Name, (size_t)len, allocFunc);
+
+ len = 0;
+ while(2 <= sd->Size)
+ {
+ int numAdds;
+ UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+ SzSkeepDataSize(sd, 2);
+ if (value < 0x80)
+ {
+ file->Name[len++] = (char)value;
+ if (value == 0)
+ break;
+ continue;
+ }
+ if (value >= 0xD800 && value < 0xE000)
+ {
+ UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+ SzSkeepDataSize(sd, 2);
+ value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+ }
+ for (numAdds = 1; numAdds < 5; numAdds++)
+ if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+ break;
+ file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
+ do
+ {
+ numAdds--;
+ file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
+ }
+ while(numAdds > 0);
+
+ len += numAdds;
+ }
+ }
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadHeader2(
+ CSzData *sd,
+ CArchiveDatabaseEx *db, /* allocMain */
+ CFileSize **unPackSizes, /* allocTemp */
+ Byte **digestsDefined, /* allocTemp */
+ UInt32 **digests, /* allocTemp */
+ Byte **emptyStreamVector, /* allocTemp */
+ Byte **emptyFileVector, /* allocTemp */
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ UInt64 type;
+ UInt32 numUnPackStreams = 0;
+ UInt32 numFiles = 0;
+ CFileItem *files = 0;
+ UInt32 numEmptyStreams = 0;
+ UInt32 i;
+
+ RINOK(SzReadID(sd, &type));
+
+ if (type == k7zIdArchiveProperties)
+ {
+ RINOK(SzReadArchiveProperties(sd));
+ RINOK(SzReadID(sd, &type));
+ }
+
+
+ if (type == k7zIdMainStreamsInfo)
+ {
+ RINOK(SzReadStreamsInfo(sd,
+ &db->ArchiveInfo.DataStartPosition,
+ &db->Database,
+ &numUnPackStreams,
+ unPackSizes,
+ digestsDefined,
+ digests, allocMain->Alloc, allocTemp));
+ db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader;
+ RINOK(SzReadID(sd, &type));
+ }
+
+ if (type == k7zIdEnd)
+ return SZ_OK;
+ if (type != k7zIdFilesInfo)
+ return SZE_ARCHIVE_ERROR;
+
+ RINOK(SzReadNumber32(sd, &numFiles));
+ db->Database.NumFiles = numFiles;
+
+ MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc);
+
+ db->Database.Files = files;
+ for(i = 0; i < numFiles; i++)
+ SzFileInit(files + i);
+
+ for (;;)
+ {
+ UInt64 type;
+ UInt64 size;
+ RINOK(SzReadID(sd, &type));
+ if (type == k7zIdEnd)
+ break;
+ RINOK(SzReadNumber(sd, &size));
+
+ if ((UInt64)(int)type != type)
+ {
+ RINOK(SzSkeepDataSize(sd, size));
+ }
+ else
+ switch((int)type)
+ {
+ case k7zIdName:
+ {
+ RINOK(SzReadSwitch(sd));
+ RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc))
+ break;
+ }
+ case k7zIdEmptyStream:
+ {
+ RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc));
+ numEmptyStreams = 0;
+ for (i = 0; i < numFiles; i++)
+ if ((*emptyStreamVector)[i])
+ numEmptyStreams++;
+ break;
+ }
+ case k7zIdEmptyFile:
+ {
+ RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc));
+ break;
+ }
+ default:
+ {
+ RINOK(SzSkeepDataSize(sd, size));
+ }
+ }
+ }
+
+ {
+ UInt32 emptyFileIndex = 0;
+ UInt32 sizeIndex = 0;
+ for(i = 0; i < numFiles; i++)
+ {
+ CFileItem *file = files + i;
+ file->IsAnti = 0;
+ if (*emptyStreamVector == 0)
+ file->HasStream = 1;
+ else
+ file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);
+ if(file->HasStream)
+ {
+ file->IsDirectory = 0;
+ file->Size = (*unPackSizes)[sizeIndex];
+ file->FileCRC = (*digests)[sizeIndex];
+ file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex];
+ sizeIndex++;
+ }
+ else
+ {
+ if (*emptyFileVector == 0)
+ file->IsDirectory = 1;
+ else
+ file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
+ emptyFileIndex++;
+ file->Size = 0;
+ file->IsFileCRCDefined = 0;
+ }
+ }
+ }
+ return SzArDbExFill(db, allocMain->Alloc);
+}
+
+SZ_RESULT SzReadHeader(
+ CSzData *sd,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ CFileSize *unPackSizes = 0;
+ Byte *digestsDefined = 0;
+ UInt32 *digests = 0;
+ Byte *emptyStreamVector = 0;
+ Byte *emptyFileVector = 0;
+ SZ_RESULT res = SzReadHeader2(sd, db,
+ &unPackSizes, &digestsDefined, &digests,
+ &emptyStreamVector, &emptyFileVector,
+ allocMain, allocTemp);
+ allocTemp->Free(unPackSizes);
+ allocTemp->Free(digestsDefined);
+ allocTemp->Free(digests);
+ allocTemp->Free(emptyStreamVector);
+ allocTemp->Free(emptyFileVector);
+ return res;
+}
+
+SZ_RESULT SzReadAndDecodePackedStreams2(
+ ISzInStream *inStream,
+ CSzData *sd,
+ CSzByteBuffer *outBuffer,
+ CFileSize baseOffset,
+ CArchiveDatabase *db,
+ CFileSize **unPackSizes,
+ Byte **digestsDefined,
+ UInt32 **digests,
+ #ifndef _LZMA_IN_CB
+ Byte **inBuffer,
+ #endif
+ ISzAlloc *allocTemp)
+{
+
+ UInt32 numUnPackStreams = 0;
+ CFileSize dataStartPos;
+ CFolder *folder;
+ #ifndef _LZMA_IN_CB
+ CFileSize packSize = 0;
+ UInt32 i = 0;
+ #endif
+ CFileSize unPackSize;
+ size_t outRealSize;
+ SZ_RESULT res;
+
+ RINOK(SzReadStreamsInfo(sd, &dataStartPos, db,
+ &numUnPackStreams, unPackSizes, digestsDefined, digests,
+ allocTemp->Alloc, allocTemp));
+
+ dataStartPos += baseOffset;
+ if (db->NumFolders != 1)
+ return SZE_ARCHIVE_ERROR;
+
+ folder = db->Folders;
+ unPackSize = SzFolderGetUnPackSize(folder);
+
+ RINOK(inStream->Seek(inStream, dataStartPos));
+
+ #ifndef _LZMA_IN_CB
+ for (i = 0; i < db->NumPackStreams; i++)
+ packSize += db->PackSizes[i];
+
+ MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc);
+
+ RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize));
+ #endif
+
+ if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc))
+ return SZE_OUTOFMEMORY;
+
+ res = SzDecode(db->PackSizes, folder,
+ #ifdef _LZMA_IN_CB
+ inStream,
+ #else
+ *inBuffer,
+ #endif
+ outBuffer->Items, (size_t)unPackSize,
+ &outRealSize, allocTemp);
+ RINOK(res)
+ if (outRealSize != (UInt32)unPackSize)
+ return SZE_FAIL;
+ if (folder->UnPackCRCDefined)
+ if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize))
+ return SZE_FAIL;
+ return SZ_OK;
+}
+
+SZ_RESULT SzReadAndDecodePackedStreams(
+ ISzInStream *inStream,
+ CSzData *sd,
+ CSzByteBuffer *outBuffer,
+ CFileSize baseOffset,
+ ISzAlloc *allocTemp)
+{
+ CArchiveDatabase db;
+ CFileSize *unPackSizes = 0;
+ Byte *digestsDefined = 0;
+ UInt32 *digests = 0;
+ #ifndef _LZMA_IN_CB
+ Byte *inBuffer = 0;
+ #endif
+ SZ_RESULT res;
+ SzArchiveDatabaseInit(&db);
+ res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,
+ &db, &unPackSizes, &digestsDefined, &digests,
+ #ifndef _LZMA_IN_CB
+ &inBuffer,
+ #endif
+ allocTemp);
+ SzArchiveDatabaseFree(&db, allocTemp->Free);
+ allocTemp->Free(unPackSizes);
+ allocTemp->Free(digestsDefined);
+ allocTemp->Free(digests);
+ #ifndef _LZMA_IN_CB
+ allocTemp->Free(inBuffer);
+ #endif
+ return res;
+}
+
+SZ_RESULT SzArchiveOpen2(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ Byte signature[k7zSignatureSize];
+ Byte version;
+ UInt32 crcFromArchive;
+ UInt64 nextHeaderOffset;
+ UInt64 nextHeaderSize;
+ UInt32 nextHeaderCRC;
+ UInt32 crc;
+ CFileSize pos = 0;
+ CSzByteBuffer buffer;
+ CSzData sd;
+ SZ_RESULT res;
+
+ RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize));
+
+ if (!TestSignatureCandidate(signature))
+ return SZE_ARCHIVE_ERROR;
+
+ /*
+ db.Clear();
+ db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
+ */
+ RINOK(SafeReadDirectByte(inStream, &version));
+ if (version != k7zMajorVersion)
+ return SZE_ARCHIVE_ERROR;
+ RINOK(SafeReadDirectByte(inStream, &version));
+
+ RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive));
+
+ CrcInit(&crc);
+ RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset));
+ CrcUpdateUInt64(&crc, nextHeaderOffset);
+ RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize));
+ CrcUpdateUInt64(&crc, nextHeaderSize);
+ RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC));
+ CrcUpdateUInt32(&crc, nextHeaderCRC);
+
+ pos = k7zStartHeaderSize;
+ db->ArchiveInfo.StartPositionAfterHeader = pos;
+
+ if (CrcGetDigest(&crc) != crcFromArchive)
+ return SZE_ARCHIVE_ERROR;
+
+ if (nextHeaderSize == 0)
+ return SZ_OK;
+
+ RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset)));
+
+ if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc))
+ return SZE_OUTOFMEMORY;
+
+ res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize);
+ if (res == SZ_OK)
+ {
+ res = SZE_ARCHIVE_ERROR;
+ if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize))
+ {
+ for (;;)
+ {
+ UInt64 type;
+ sd.Data = buffer.Items;
+ sd.Size = buffer.Capacity;
+ res = SzReadID(&sd, &type);
+ if (res != SZ_OK)
+ break;
+ if (type == k7zIdHeader)
+ {
+ res = SzReadHeader(&sd, db, allocMain, allocTemp);
+ break;
+ }
+ if (type != k7zIdEncodedHeader)
+ {
+ res = SZE_ARCHIVE_ERROR;
+ break;
+ }
+ {
+ CSzByteBuffer outBuffer;
+ res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer,
+ db->ArchiveInfo.StartPositionAfterHeader,
+ allocTemp);
+ if (res != SZ_OK)
+ {
+ SzByteBufferFree(&outBuffer, allocTemp->Free);
+ break;
+ }
+ SzByteBufferFree(&buffer, allocTemp->Free);
+ buffer.Items = outBuffer.Items;
+ buffer.Capacity = outBuffer.Capacity;
+ }
+ }
+ }
+ }
+ SzByteBufferFree(&buffer, allocTemp->Free);
+ return res;
+}
+
+SZ_RESULT SzArchiveOpen(
+ ISzInStream *inStream,
+ CArchiveDatabaseEx *db,
+ ISzAlloc *allocMain,
+ ISzAlloc *allocTemp)
+{
+ SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp);
+ if (res != SZ_OK)
+ SzArDbExFree(db, allocMain->Free);
+ return res;
+}
diff --git a/C/Archive/7z/7zItem.c b/C/Archive/7z/7zItem.c
new file mode 100755
index 00000000..2a408050
--- /dev/null
+++ b/C/Archive/7z/7zItem.c
@@ -0,0 +1,133 @@
+/* 7zItem.c */
+
+#include "7zItem.h"
+#include "7zAlloc.h"
+
+void SzCoderInfoInit(CCoderInfo *coder)
+{
+ SzByteBufferInit(&coder->Properties);
+}
+
+void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p))
+{
+ SzByteBufferFree(&coder->Properties, freeFunc);
+ SzCoderInfoInit(coder);
+}
+
+void SzFolderInit(CFolder *folder)
+{
+ folder->NumCoders = 0;
+ folder->Coders = 0;
+ folder->NumBindPairs = 0;
+ folder->BindPairs = 0;
+ folder->NumPackStreams = 0;
+ folder->PackStreams = 0;
+ folder->UnPackSizes = 0;
+ folder->UnPackCRCDefined = 0;
+ folder->UnPackCRC = 0;
+ folder->NumUnPackStreams = 0;
+}
+
+void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p))
+{
+ UInt32 i;
+ for (i = 0; i < folder->NumCoders; i++)
+ SzCoderInfoFree(&folder->Coders[i], freeFunc);
+ freeFunc(folder->Coders);
+ freeFunc(folder->BindPairs);
+ freeFunc(folder->PackStreams);
+ freeFunc(folder->UnPackSizes);
+ SzFolderInit(folder);
+}
+
+UInt32 SzFolderGetNumOutStreams(CFolder *folder)
+{
+ UInt32 result = 0;
+ UInt32 i;
+ for (i = 0; i < folder->NumCoders; i++)
+ result += folder->Coders[i].NumOutStreams;
+ return result;
+}
+
+int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex)
+{
+ UInt32 i;
+ for(i = 0; i < folder->NumBindPairs; i++)
+ if (folder->BindPairs[i].InIndex == inStreamIndex)
+ return i;
+ return -1;
+}
+
+
+int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex)
+{
+ UInt32 i;
+ for(i = 0; i < folder->NumBindPairs; i++)
+ if (folder->BindPairs[i].OutIndex == outStreamIndex)
+ return i;
+ return -1;
+}
+
+CFileSize SzFolderGetUnPackSize(CFolder *folder)
+{
+ int i = (int)SzFolderGetNumOutStreams(folder);
+ if (i == 0)
+ return 0;
+ for (i--; i >= 0; i--)
+ if (SzFolderFindBindPairForOutStream(folder, i) < 0)
+ return folder->UnPackSizes[i];
+ /* throw 1; */
+ return 0;
+}
+
+/*
+int FindPackStreamArrayIndex(int inStreamIndex) const
+{
+ for(int i = 0; i < PackStreams.Size(); i++)
+ if (PackStreams[i] == inStreamIndex)
+ return i;
+ return -1;
+}
+*/
+
+void SzFileInit(CFileItem *fileItem)
+{
+ fileItem->IsFileCRCDefined = 0;
+ fileItem->HasStream = 1;
+ fileItem->IsDirectory = 0;
+ fileItem->IsAnti = 0;
+ fileItem->Name = 0;
+}
+
+void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p))
+{
+ freeFunc(fileItem->Name);
+ SzFileInit(fileItem);
+}
+
+void SzArchiveDatabaseInit(CArchiveDatabase *db)
+{
+ db->NumPackStreams = 0;
+ db->PackSizes = 0;
+ db->PackCRCsDefined = 0;
+ db->PackCRCs = 0;
+ db->NumFolders = 0;
+ db->Folders = 0;
+ db->NumFiles = 0;
+ db->Files = 0;
+}
+
+void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *))
+{
+ UInt32 i;
+ for (i = 0; i < db->NumFolders; i++)
+ SzFolderFree(&db->Folders[i], freeFunc);
+ for (i = 0; i < db->NumFiles; i++)
+ SzFileFree(&db->Files[i], freeFunc);
+ freeFunc(db->PackSizes);
+ freeFunc(db->PackCRCsDefined);
+ freeFunc(db->PackCRCs);
+ freeFunc(db->Folders);
+ freeFunc(db->Files);
+ SzArchiveDatabaseInit(db);
+}
diff --git a/C/Archive/7z/7zMain.c b/C/Archive/7z/7zMain.c
new file mode 100755
index 00000000..0a789639
--- /dev/null
+++ b/C/Archive/7z/7zMain.c
@@ -0,0 +1,358 @@
+/*
+7zMain.c
+Test application for 7z Decoder
+LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+#define USE_WINDOWS_FUNCTIONS
+#endif
+
+#ifdef USE_WINDOWS_FUNCTIONS
+#include <windows.h>
+#endif
+
+#include "7zIn.h"
+#include "7zExtract.h"
+
+#include "../../7zCrc.h"
+
+
+#ifdef USE_WINDOWS_FUNCTIONS
+typedef HANDLE MY_FILE_HANDLE;
+#else
+typedef FILE *MY_FILE_HANDLE;
+#endif
+
+void ConvertNumberToString(CFileSize value, char *s)
+{
+ char temp[32];
+ int pos = 0;
+ do
+ {
+ temp[pos++] = (char)('0' + (int)(value % 10));
+ value /= 10;
+ }
+ while (value != 0);
+ do
+ *s++ = temp[--pos];
+ while(pos > 0);
+ *s = '\0';
+}
+
+
+#ifdef USE_WINDOWS_FUNCTIONS
+// ReadFile and WriteFile functions in Windows have BUG:
+// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
+// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
+// (Insufficient system resources exist to complete the requested service).
+#define kChunkSizeMax (1 << 24)
+#endif
+
+size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef USE_WINDOWS_FUNCTIONS
+ {
+ size_t processedSize = 0;
+ do
+ {
+ DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
+ DWORD processedLoc = 0;
+ BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL);
+ data = (void *)((unsigned char *)data + processedLoc);
+ size -= processedLoc;
+ processedSize += processedLoc;
+ if (!res || processedLoc == 0)
+ break;
+ }
+ while (size > 0);
+ return processedSize;
+ }
+ #else
+ return fread(data, 1, size, file);
+ #endif
+}
+
+size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ #ifdef USE_WINDOWS_FUNCTIONS
+ {
+ size_t processedSize = 0;
+ do
+ {
+ DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
+ DWORD processedLoc = 0;
+ BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL);
+ data = (void *)((unsigned char *)data + processedLoc);
+ size -= processedLoc;
+ processedSize += processedLoc;
+ if (!res)
+ break;
+ }
+ while (size > 0);
+ return processedSize;
+ }
+ #else
+ return fwrite(data, 1, size, file);
+ #endif
+}
+
+int MyCloseFile(MY_FILE_HANDLE file)
+{
+ #ifdef USE_WINDOWS_FUNCTIONS
+ return (CloseHandle(file) != FALSE) ? 0 : 1;
+ #else
+ return fclose(file);
+ #endif
+}
+
+typedef struct _CFileInStream
+{
+ ISzInStream InStream;
+ MY_FILE_HANDLE File;
+} CFileInStream;
+
+#ifdef _LZMA_IN_CB
+
+#define kBufferSize (1 << 12)
+Byte g_Buffer[kBufferSize];
+
+SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
+{
+ CFileInStream *s = (CFileInStream *)object;
+ size_t processedSizeLoc;
+ if (maxRequiredSize > kBufferSize)
+ maxRequiredSize = kBufferSize;
+ processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize);
+ *buffer = g_Buffer;
+ if (processedSize != 0)
+ *processedSize = processedSizeLoc;
+ return SZ_OK;
+}
+
+#else
+
+SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize)
+{
+ CFileInStream *s = (CFileInStream *)object;
+ size_t processedSizeLoc = MyReadFile(s->File, buffer, size);
+ if (processedSize != 0)
+ *processedSize = processedSizeLoc;
+ return SZ_OK;
+}
+
+#endif
+
+SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
+{
+ CFileInStream *s = (CFileInStream *)object;
+
+ #ifdef USE_WINDOWS_FUNCTIONS
+ {
+ LARGE_INTEGER value;
+ value.LowPart = (DWORD)pos;
+ value.HighPart = (LONG)(pos >> 32);
+ value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN);
+ if (value.LowPart == 0xFFFFFFFF)
+ if(GetLastError() != NO_ERROR)
+ return SZE_FAIL;
+ return SZ_OK;
+ }
+ #else
+ int res = fseek(s->File, (long)pos, SEEK_SET);
+ if (res == 0)
+ return SZ_OK;
+ return SZE_FAIL;
+ #endif
+}
+
+void PrintError(char *sz)
+{
+ printf("\nERROR: %s\n", sz);
+}
+
+int main(int numargs, char *args[])
+{
+ CFileInStream archiveStream;
+ CArchiveDatabaseEx db;
+ SZ_RESULT res;
+ ISzAlloc allocImp;
+ ISzAlloc allocTempImp;
+
+ printf("\n7z ANSI-C Decoder 4.44 Copyright (c) 1999-2006 Igor Pavlov 2006-08-27\n");
+ if (numargs == 1)
+ {
+ printf(
+ "\nUsage: 7zDec <command> <archive_name>\n\n"
+ "<Commands>\n"
+ " e: Extract files from archive\n"
+ " l: List contents of archive\n"
+ " t: Test integrity of archive\n");
+ return 0;
+ }
+ if (numargs < 3)
+ {
+ PrintError("incorrect command");
+ return 1;
+ }
+
+ archiveStream.File =
+ #ifdef USE_WINDOWS_FUNCTIONS
+ CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (archiveStream.File == INVALID_HANDLE_VALUE)
+ #else
+ archiveStream.File = fopen(args[2], "rb");
+ if (archiveStream.File == 0)
+ #endif
+ {
+ PrintError("can not open input file");
+ return 1;
+ }
+
+ archiveStream.InStream.Read = SzFileReadImp;
+ archiveStream.InStream.Seek = SzFileSeekImp;
+
+ allocImp.Alloc = SzAlloc;
+ allocImp.Free = SzFree;
+
+ allocTempImp.Alloc = SzAllocTemp;
+ allocTempImp.Free = SzFreeTemp;
+
+ CrcGenerateTable();
+
+ SzArDbExInit(&db);
+ res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
+ if (res == SZ_OK)
+ {
+ char *command = args[1];
+ int listCommand = 0;
+ int testCommand = 0;
+ int extractCommand = 0;
+ if (strcmp(command, "l") == 0)
+ listCommand = 1;
+ if (strcmp(command, "t") == 0)
+ testCommand = 1;
+ else if (strcmp(command, "e") == 0)
+ extractCommand = 1;
+
+ if (listCommand)
+ {
+ UInt32 i;
+ for (i = 0; i < db.Database.NumFiles; i++)
+ {
+ CFileItem *f = db.Database.Files + i;
+ char s[32];
+ ConvertNumberToString(f->Size, s);
+ printf("%10s %s\n", s, f->Name);
+ }
+ }
+ else if (testCommand || extractCommand)
+ {
+ UInt32 i;
+
+ /*
+ if you need cache, use these 3 variables.
+ if you use external function, you can make these variable as static.
+ */
+ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
+ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
+ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
+
+ printf("\n");
+ for (i = 0; i < db.Database.NumFiles; i++)
+ {
+ size_t offset;
+ size_t outSizeProcessed;
+ CFileItem *f = db.Database.Files + i;
+ if (f->IsDirectory)
+ printf("Directory ");
+ else
+ printf(testCommand ?
+ "Testing ":
+ "Extracting");
+ printf(" %s", f->Name);
+ if (f->IsDirectory)
+ {
+ printf("\n");
+ continue;
+ }
+ res = SzExtract(&archiveStream.InStream, &db, i,
+ &blockIndex, &outBuffer, &outBufferSize,
+ &offset, &outSizeProcessed,
+ &allocImp, &allocTempImp);
+ if (res != SZ_OK)
+ break;
+ if (!testCommand)
+ {
+ MY_FILE_HANDLE outputHandle;
+ UInt32 processedSize;
+ char *fileName = f->Name;
+ size_t nameLen = strlen(f->Name);
+ for (; nameLen > 0; nameLen--)
+ if (f->Name[nameLen - 1] == '/')
+ {
+ fileName = f->Name + nameLen;
+ break;
+ }
+
+ outputHandle =
+ #ifdef USE_WINDOWS_FUNCTIONS
+ CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (outputHandle == INVALID_HANDLE_VALUE)
+ #else
+ fopen(fileName, "wb+");
+ if (outputHandle == 0)
+ #endif
+ {
+ PrintError("can not open output file");
+ res = SZE_FAIL;
+ break;
+ }
+ processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed);
+ if (processedSize != outSizeProcessed)
+ {
+ PrintError("can not write output file");
+ res = SZE_FAIL;
+ break;
+ }
+ if (MyCloseFile(outputHandle))
+ {
+ PrintError("can not close output file");
+ res = SZE_FAIL;
+ break;
+ }
+ }
+ printf("\n");
+ }
+ allocImp.Free(outBuffer);
+ }
+ else
+ {
+ PrintError("incorrect command");
+ res = SZE_FAIL;
+ }
+ }
+ SzArDbExFree(&db, allocImp.Free);
+
+ MyCloseFile(archiveStream.File);
+ if (res == SZ_OK)
+ {
+ printf("\nEverything is Ok\n");
+ return 0;
+ }
+ if (res == SZE_OUTOFMEMORY)
+ PrintError("can not allocate memory");
+ else
+ printf("\nERROR #%d\n", res);
+ return 1;
+}
diff --git a/C/Archive/7z/7zMethodID.c b/C/Archive/7z/7zMethodID.c
new file mode 100755
index 00000000..5047359f
--- /dev/null
+++ b/C/Archive/7z/7zMethodID.c
@@ -0,0 +1,14 @@
+/* 7zMethodID.c */
+
+#include "7zMethodID.h"
+
+int AreMethodsEqual(CMethodID *a1, CMethodID *a2)
+{
+ int i;
+ if (a1->IDSize != a2->IDSize)
+ return 0;
+ for (i = 0; i < a1->IDSize; i++)
+ if (a1->ID[i] != a2->ID[i])
+ return 0;
+ return 1;
+}
diff --git a/C/Archive/7z/7z_C.dsp b/C/Archive/7z/7z_C.dsp
new file mode 100755
index 00000000..699384ef
--- /dev/null
+++ b/C/Archive/7z/7z_C.dsp
@@ -0,0 +1,186 @@
+# Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=7z_C - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "7z_C.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "7z_C - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /D "_SZ_FILE_SIZE_64" /YX /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe"
+
+!ELSEIF "$(CFG)" == "7z_C - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /D "_SZ_FILE_SIZE_64" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "7z_C - Win32 Release"
+# Name "7z_C - Win32 Debug"
+# Begin Group "LZMA"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma\LzmaDecode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma\LzmaDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma\LzmaTypes.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\7zCrc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zCrc.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\7zAlloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zAlloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zBuffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zExtract.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zExtract.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zItem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zTypes.h
+# End Source File
+# End Target
+# End Project
diff --git a/C/Archive/7z/7z_C.dsw b/C/Archive/7z/7z_C.dsw
new file mode 100755
index 00000000..6fd39621
--- /dev/null
+++ b/C/Archive/7z/7z_C.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "7z_C"=.\7z_C.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/C/Archive/7z/makefile b/C/Archive/7z/makefile
new file mode 100755
index 00000000..9ce2c346
--- /dev/null
+++ b/C/Archive/7z/makefile
@@ -0,0 +1,55 @@
+PROG = 7zDec.exe
+
+!IFNDEF O
+!IFDEF CPU
+O=$(CPU)
+!ELSE
+O=O
+!ENDIF
+!ENDIF
+
+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS-
+CFLAGS_O1 = $(CFLAGS) -O1
+CFLAGS_O2 = $(CFLAGS) -O2
+
+LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98
+
+PROGPATH = $O\$(PROG)
+
+COMPL_O1 = $(CPP) $(CFLAGS_O1) $**
+COMPL_O2 = $(CPP) $(CFLAGS_O2) $**
+COMPL = $(CPP) $(CFLAGS_O1) $**
+
+
+7Z_OBJS = \
+ $O\7zAlloc.obj \
+ $O\7zBuffer.obj \
+ $O\7zCrc.obj \
+ $O\7zDecode.obj \
+ $O\7zExtract.obj \
+ $O\7zHeader.obj \
+ $O\7zIn.obj \
+ $O\7zItem.obj \
+ $O\7zMain.obj \
+ $O\7zMethodID.obj \
+
+OBJS = \
+ $(7Z_OBJS) \
+ $O\LzmaDecode.obj \
+
+all: $(PROGPATH)
+
+clean:
+ -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch
+
+$O:
+ if not exist "$O" mkdir "$O"
+
+$(PROGPATH): $O $(OBJS)
+ link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
+
+
+$(7Z_OBJS): $(*B).c
+ $(COMPL)
+$O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c
+ $(COMPL_O2)
diff --git a/C/Archive/7z/makefile.gcc b/C/Archive/7z/makefile.gcc
new file mode 100755
index 00000000..21b7df47
--- /dev/null
+++ b/C/Archive/7z/makefile.gcc
@@ -0,0 +1,50 @@
+PROG = 7zDec
+CXX = g++
+LIB =
+RM = rm -f
+CFLAGS = -c -O2 -Wall
+
+OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
+
+7zAlloc.o: 7zAlloc.c
+ $(CXX) $(CFLAGS) 7zAlloc.c
+
+7zBuffer.o: 7zBuffer.c
+ $(CXX) $(CFLAGS) 7zBuffer.c
+
+7zCrc.o: 7zCrc.c
+ $(CXX) $(CFLAGS) 7zCrc.c
+
+7zDecode.o: 7zDecode.c
+ $(CXX) $(CFLAGS) 7zDecode.c
+
+7zExtract.o: 7zExtract.c
+ $(CXX) $(CFLAGS) 7zExtract.c
+
+7zHeader.o: 7zHeader.c
+ $(CXX) $(CFLAGS) 7zHeader.c
+
+7zIn.o: 7zIn.c
+ $(CXX) $(CFLAGS) 7zIn.c
+
+7zItem.o: 7zItem.c
+ $(CXX) $(CFLAGS) 7zItem.c
+
+7zMain.o: 7zMain.c
+ $(CXX) $(CFLAGS) 7zMain.c
+
+7zMethodID.o: 7zMethodID.c
+ $(CXX) $(CFLAGS) 7zMethodID.c
+
+LzmaDecode.o: ../../Compress/LZMA_C/LzmaDecode.c
+ $(CXX) $(CFLAGS) ../../Compress/LZMA_C/LzmaDecode.c
+
+
+clean:
+ -$(RM) $(PROG) $(OBJS)
+
diff --git a/C/Compress/Branch/BranchARM.c b/C/Compress/Branch/BranchARM.c
new file mode 100755
index 00000000..6d4e3672
--- /dev/null
+++ b/C/Compress/Branch/BranchARM.c
@@ -0,0 +1,26 @@
+/* BranchARM.c */
+
+#include "BranchARM.h"
+
+UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ if (data[i + 3] == 0xEB)
+ {
+ UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]);
+ src <<= 2;
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + 8 + src;
+ else
+ dest = src - (nowPos + i + 8);
+ dest >>= 2;
+ data[i + 2] = (Byte)(dest >> 16);
+ data[i + 1] = (Byte)(dest >> 8);
+ data[i + 0] = (Byte)dest;
+ }
+ }
+ return i;
+}
diff --git a/C/Compress/Branch/BranchARM.h b/C/Compress/Branch/BranchARM.h
new file mode 100755
index 00000000..02eb1b47
--- /dev/null
+++ b/C/Compress/Branch/BranchARM.h
@@ -0,0 +1,10 @@
+// BranchARM.h
+
+#ifndef __BRANCH_ARM_H
+#define __BRANCH_ARM_H
+
+#include "BranchTypes.h"
+
+UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/C/Compress/Branch/BranchARMThumb.c b/C/Compress/Branch/BranchARMThumb.c
new file mode 100755
index 00000000..aab9c7a1
--- /dev/null
+++ b/C/Compress/Branch/BranchARMThumb.c
@@ -0,0 +1,35 @@
+/* BranchARMThumb.c */
+
+#include "BranchARMThumb.h"
+
+UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 2)
+ {
+ if ((data[i + 1] & 0xF8) == 0xF0 &&
+ (data[i + 3] & 0xF8) == 0xF8)
+ {
+ UInt32 src =
+ ((data[i + 1] & 0x7) << 19) |
+ (data[i + 0] << 11) |
+ ((data[i + 3] & 0x7) << 8) |
+ (data[i + 2]);
+
+ src <<= 1;
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + 4 + src;
+ else
+ dest = src - (nowPos + i + 4);
+ dest >>= 1;
+
+ data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
+ data[i + 0] = (Byte)(dest >> 11);
+ data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
+ data[i + 2] = (Byte)dest;
+ i += 2;
+ }
+ }
+ return i;
+}
diff --git a/C/Compress/Branch/BranchARMThumb.h b/C/Compress/Branch/BranchARMThumb.h
new file mode 100755
index 00000000..d67e6e5a
--- /dev/null
+++ b/C/Compress/Branch/BranchARMThumb.h
@@ -0,0 +1,10 @@
+// BranchARMThumb.h
+
+#ifndef __BRANCH_ARM_THUMB_H
+#define __BRANCH_ARM_THUMB_H
+
+#include "BranchTypes.h"
+
+UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/C/Compress/Branch/BranchIA64.c b/C/Compress/Branch/BranchIA64.c
new file mode 100755
index 00000000..e7775564
--- /dev/null
+++ b/C/Compress/Branch/BranchIA64.c
@@ -0,0 +1,63 @@
+/* BranchIA64.c */
+
+#include "BranchIA64.h"
+
+const Byte kBranchTable[32] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 6, 6, 0, 0, 7, 7,
+ 4, 4, 0, 0, 4, 4, 0, 0
+};
+
+UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 16 <= size; i += 16)
+ {
+ UInt32 instrTemplate = data[i] & 0x1F;
+ UInt32 mask = kBranchTable[instrTemplate];
+ UInt32 bitPos = 5;
+ for (int slot = 0; slot < 3; slot++, bitPos += 41)
+ {
+ if (((mask >> slot) & 1) == 0)
+ continue;
+ UInt32 bytePos = (bitPos >> 3);
+ UInt32 bitRes = bitPos & 0x7;
+ UInt64 instruction = 0;
+ int j;
+ for (j = 0; j < 6; j++)
+ instruction += (UInt64)(data[i + j + bytePos]) << (8 * j);
+
+ UInt64 instNorm = instruction >> bitRes;
+ if (((instNorm >> 37) & 0xF) == 0x5
+ && ((instNorm >> 9) & 0x7) == 0
+ /* && (instNorm & 0x3F)== 0 */
+ )
+ {
+ UInt32 src = UInt32((instNorm >> 13) & 0xFFFFF);
+ src |= ((instNorm >> 36) & 1) << 20;
+
+ src <<= 4;
+
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + src;
+ else
+ dest = src - (nowPos + i);
+
+ dest >>= 4;
+
+ instNorm &= ~(UInt64(0x8FFFFF) << 13);
+ instNorm |= (UInt64(dest & 0xFFFFF) << 13);
+ instNorm |= (UInt64(dest & 0x100000) << (36 - 20));
+
+ instruction &= (1 << bitRes) - 1;
+ instruction |= (instNorm << bitRes);
+ for (j = 0; j < 6; j++)
+ data[i + j + bytePos] = Byte(instruction >> (8 * j));
+ }
+ }
+ }
+ return i;
+}
diff --git a/C/Compress/Branch/BranchIA64.h b/C/Compress/Branch/BranchIA64.h
new file mode 100755
index 00000000..b7757fe9
--- /dev/null
+++ b/C/Compress/Branch/BranchIA64.h
@@ -0,0 +1,10 @@
+// BranchIA64.h
+
+#ifndef __BRANCH_IA64_H
+#define __BRANCH_IA64_H
+
+#include "BranchTypes.h"
+
+UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/C/Compress/Branch/BranchPPC.c b/C/Compress/Branch/BranchPPC.c
new file mode 100755
index 00000000..b3e5703f
--- /dev/null
+++ b/C/Compress/Branch/BranchPPC.c
@@ -0,0 +1,36 @@
+/* BranchPPC.c */
+
+#include "BranchPPC.h"
+
+UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ /* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */
+ if ((data[i] >> 2) == 0x12 &&
+ (
+ (data[i + 3] & 3) == 1
+ /* || (data[i+3] & 3) == 3 */
+ )
+ )
+ {
+ UInt32 src = ((data[i + 0] & 3) << 24) |
+ (data[i + 1] << 16) |
+ (data[i + 2] << 8) |
+ (data[i + 3] & (~3));
+
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + src;
+ else
+ dest = src - (nowPos + i);
+ data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
+ data[i + 1] = (Byte)(dest >> 16);
+ data[i + 2] = (Byte)(dest >> 8);
+ data[i + 3] &= 0x3;
+ data[i + 3] |= dest;
+ }
+ }
+ return i;
+}
diff --git a/C/Compress/Branch/BranchPPC.h b/C/Compress/Branch/BranchPPC.h
new file mode 100755
index 00000000..c02bba19
--- /dev/null
+++ b/C/Compress/Branch/BranchPPC.h
@@ -0,0 +1,10 @@
+// BranchPPC.h
+
+#ifndef __BRANCH_PPC_H
+#define __BRANCH_PPC_H
+
+#include "BranchTypes.h"
+
+UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/C/Compress/Branch/BranchSPARC.c b/C/Compress/Branch/BranchSPARC.c
new file mode 100755
index 00000000..c175875b
--- /dev/null
+++ b/C/Compress/Branch/BranchSPARC.c
@@ -0,0 +1,36 @@
+/* BranchSPARC.c */
+
+#include "BranchSPARC.h"
+
+UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+ UInt32 i;
+ for (i = 0; i + 4 <= size; i += 4)
+ {
+ if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 ||
+ data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)
+ {
+ UInt32 src =
+ ((UInt32)data[i + 0] << 24) |
+ ((UInt32)data[i + 1] << 16) |
+ ((UInt32)data[i + 2] << 8) |
+ ((UInt32)data[i + 3]);
+
+ src <<= 2;
+ UInt32 dest;
+ if (encoding)
+ dest = nowPos + i + src;
+ else
+ dest = src - (nowPos + i);
+ dest >>= 2;
+
+ dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
+
+ data[i + 0] = (Byte)(dest >> 24);
+ data[i + 1] = (Byte)(dest >> 16);
+ data[i + 2] = (Byte)(dest >> 8);
+ data[i + 3] = (Byte)dest;
+ }
+ }
+ return i;
+}
diff --git a/C/Compress/Branch/BranchSPARC.h b/C/Compress/Branch/BranchSPARC.h
new file mode 100755
index 00000000..fbe9e673
--- /dev/null
+++ b/C/Compress/Branch/BranchSPARC.h
@@ -0,0 +1,10 @@
+// BranchSPARC.h
+
+#ifndef __BRANCH_SPARC_H
+#define __BRANCH_SPARC_H
+
+#include "BranchTypes.h"
+
+UInt32 SPARC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif
diff --git a/C/Compress/Branch/BranchTypes.h b/C/Compress/Branch/BranchTypes.h
new file mode 100755
index 00000000..f7ad3abc
--- /dev/null
+++ b/C/Compress/Branch/BranchTypes.h
@@ -0,0 +1,25 @@
+/* BranchTypes.h */
+
+#ifndef __BRANCHTYPES_H
+#define __BRANCHTYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif
+
+#endif
diff --git a/C/Compress/Branch/BranchX86.c b/C/Compress/Branch/BranchX86.c
new file mode 100755
index 00000000..c3f455b8
--- /dev/null
+++ b/C/Compress/Branch/BranchX86.c
@@ -0,0 +1,101 @@
+/* BranchX86.c */
+
+#include "BranchX86.h"
+
+/*
+static int inline Test86MSByte(Byte b)
+{
+ return (b == 0 || b == 0xFF);
+}
+*/
+#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
+
+const int kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
+const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
+
+/*
+void x86_Convert_Init(UInt32 *prevMask, UInt32 *prevPos)
+{
+ *prevMask = 0;
+ *prevPos = (UInt32)(-5);
+}
+*/
+
+UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos,
+ UInt32 *prevMask, UInt32 *prevPos, int encoding)
+{
+ UInt32 bufferPos = 0;
+ UInt32 limit;
+
+ if (endPos < 5)
+ return 0;
+
+ if (nowPos - *prevPos > 5)
+ *prevPos = nowPos - 5;
+
+ limit = endPos - 5;
+ while(bufferPos <= limit)
+ {
+ Byte b = buffer[bufferPos];
+ UInt32 offset;
+ if (b != 0xE8 && b != 0xE9)
+ {
+ bufferPos++;
+ continue;
+ }
+ offset = (nowPos + bufferPos - *prevPos);
+ *prevPos = (nowPos + bufferPos);
+ if (offset > 5)
+ *prevMask = 0;
+ else
+ {
+ UInt32 i;
+ for (i = 0; i < offset; i++)
+ {
+ *prevMask &= 0x77;
+ *prevMask <<= 1;
+ }
+ }
+ b = buffer[bufferPos + 4];
+ if (Test86MSByte(b) && kMaskToAllowedStatus[(*prevMask >> 1) & 0x7] &&
+ (*prevMask >> 1) < 0x10)
+ {
+ UInt32 src =
+ ((UInt32)(b) << 24) |
+ ((UInt32)(buffer[bufferPos + 3]) << 16) |
+ ((UInt32)(buffer[bufferPos + 2]) << 8) |
+ (buffer[bufferPos + 1]);
+
+ UInt32 dest;
+ for (;;)
+ {
+ UInt32 index;
+ if (encoding)
+ dest = (nowPos + bufferPos + 5) + src;
+ else
+ dest = src - (nowPos + bufferPos + 5);
+ if (*prevMask == 0)
+ break;
+ index = kMaskToBitNumber[*prevMask >> 1];
+ b = (Byte)(dest >> (24 - index * 8));
+ if (!Test86MSByte(b))
+ break;
+ src = dest ^ ((1 << (32 - index * 8)) - 1);
+ }
+ buffer[bufferPos + 4] = (Byte)(~(((dest >> 24) & 1) - 1));
+ buffer[bufferPos + 3] = (Byte)(dest >> 16);
+ buffer[bufferPos + 2] = (Byte)(dest >> 8);
+ buffer[bufferPos + 1] = (Byte)dest;
+ bufferPos += 5;
+ *prevMask = 0;
+ }
+ else
+ {
+ bufferPos++;
+ *prevMask |= 1;
+ if (Test86MSByte(b))
+ *prevMask |= 0x10;
+ }
+ }
+ return bufferPos;
+}
diff --git a/C/Compress/Branch/BranchX86.h b/C/Compress/Branch/BranchX86.h
new file mode 100755
index 00000000..25c1ae51
--- /dev/null
+++ b/C/Compress/Branch/BranchX86.h
@@ -0,0 +1,13 @@
+/* BranchX86.h */
+
+#ifndef __BRANCHX86_H
+#define __BRANCHX86_H
+
+#include "BranchTypes.h"
+
+#define x86_Convert_Init(prevMask, prevPos) { prevMask = 0; prevPos = (UInt32)(-5); }
+
+UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos,
+ UInt32 *prevMask, UInt32 *prevPos, int encoding);
+
+#endif
diff --git a/C/Compress/Huffman/HuffmanEncode.c b/C/Compress/Huffman/HuffmanEncode.c
new file mode 100755
index 00000000..3168db2d
--- /dev/null
+++ b/C/Compress/Huffman/HuffmanEncode.c
@@ -0,0 +1,146 @@
+// Compression/HuffmanEncode.c
+
+#include "HuffmanEncode.h"
+#include "../../Sort.h"
+
+#define kMaxLen 16
+#define NUM_BITS 10
+#define MASK ((1 << NUM_BITS) - 1)
+
+#define NUM_COUNTERS 64
+
+// use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M
+#define HUFFMAN_SPEED_OPT
+
+void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen)
+{
+ UInt32 num = 0;
+ // if (maxLen > 10) maxLen = 10;
+ {
+ UInt32 i;
+
+ #ifdef HUFFMAN_SPEED_OPT
+
+ UInt32 counters[NUM_COUNTERS];
+ for (i = 0; i < NUM_COUNTERS; i++)
+ counters[i] = 0;
+ for (i = 0; i < numSymbols; i++)
+ {
+ UInt32 freq = freqs[i];
+ counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++;
+ }
+
+ for (i = 1; i < NUM_COUNTERS; i++)
+ {
+ UInt32 temp = counters[i];
+ counters[i] = num;
+ num += temp;
+ }
+
+ for (i = 0; i < numSymbols; i++)
+ {
+ UInt32 freq = freqs[i];
+ if (freq == 0)
+ lens[i] = 0;
+ else
+ p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS);
+ }
+ counters[0] = 0;
+ HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]);
+
+ #else
+
+ for (i = 0; i < numSymbols; i++)
+ {
+ UInt32 freq = freqs[i];
+ if (freq == 0)
+ lens[i] = 0;
+ else
+ p[num++] = i | (freq << NUM_BITS);
+ }
+ HeapSort(p, num);
+
+ #endif
+ }
+
+ if (num < 2)
+ {
+ int minCode = 0;
+ int maxCode = 1;
+ if (num == 1)
+ {
+ maxCode = p[0] & MASK;
+ if (maxCode == 0)
+ maxCode++;
+ }
+ p[minCode] = 0;
+ p[maxCode] = 1;
+ lens[minCode] = lens[maxCode] = 1;
+ return;
+ }
+
+ {
+ UInt32 b, e, i;
+
+ i = b = e = 0;
+ do
+ {
+ UInt32 n, m, freq;
+ n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
+ freq = (p[n] & ~MASK);
+ p[n] = (p[n] & MASK) | (e << NUM_BITS);
+ m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
+ freq += (p[m] & ~MASK);
+ p[m] = (p[m] & MASK) | (e << NUM_BITS);
+ p[e] = (p[e] & MASK) | freq;
+ e++;
+ }
+ while (num - e > 1);
+
+ {
+ UInt32 lenCounters[kMaxLen + 1];
+ for (i = 0; i <= kMaxLen; i++)
+ lenCounters[i] = 0;
+
+ p[--e] &= MASK;
+ lenCounters[1] = 2;
+ while (e > 0)
+ {
+ UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;
+ p[e] = (p[e] & MASK) | (len << NUM_BITS);
+ if (len >= maxLen)
+ for (len = maxLen - 1; lenCounters[len] == 0; len--);
+ lenCounters[len]--;
+ lenCounters[len + 1] += 2;
+ }
+
+ {
+ UInt32 len;
+ i = 0;
+ for (len = maxLen; len != 0; len--)
+ {
+ UInt32 num;
+ for (num = lenCounters[len]; num != 0; num--)
+ lens[p[i++] & MASK] = (Byte)len;
+ }
+ }
+
+ {
+ UInt32 nextCodes[kMaxLen + 1];
+ {
+ UInt32 code = 0;
+ UInt32 len;
+ for (len = 1; len <= kMaxLen; len++)
+ nextCodes[len] = code = (code + lenCounters[len - 1]) << 1;
+ }
+ // if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1;
+
+ {
+ UInt32 i;
+ for (i = 0; i < numSymbols; i++)
+ p[i] = nextCodes[lens[i]]++;
+ }
+ }
+ }
+ }
+}
diff --git a/C/Compress/Huffman/HuffmanEncode.h b/C/Compress/Huffman/HuffmanEncode.h
new file mode 100755
index 00000000..dfd2f0ab
--- /dev/null
+++ b/C/Compress/Huffman/HuffmanEncode.h
@@ -0,0 +1,20 @@
+// Compress/HuffmanEncode.h
+
+#ifndef __COMPRESS_HUFFMANENCODE_H
+#define __COMPRESS_HUFFMANENCODE_H
+
+#include "../../Types.h"
+
+#define HUFFMAN_TEMP_SIZE(num) (num * 2)
+
+/*
+Conditions:
+ num <= 1024 = 2 ^ NUM_BITS
+ Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS)
+ maxLen <= 16 = kMaxLen
+ Num_Items(p) >= HUFFMAN_TEMP_SIZE(num)
+*/
+
+void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
+
+#endif
diff --git a/C/Compress/Lz/LzHash.h b/C/Compress/Lz/LzHash.h
new file mode 100755
index 00000000..87c28365
--- /dev/null
+++ b/C/Compress/Lz/LzHash.h
@@ -0,0 +1,53 @@
+/* LzHash.h */
+
+#ifndef __C_LZHASH_H
+#define __C_LZHASH_H
+
+#define kHash2Size (1 << 10)
+#define kHash3Size (1 << 16)
+#define kHash4Size (1 << 20)
+
+#define kFix3HashSize (kHash2Size)
+#define kFix4HashSize (kHash2Size + kHash3Size)
+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
+
+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
+
+#define HASH3_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
+
+#define HASH4_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & p->hashMask; }
+
+#define HASH5_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)); \
+ hashValue = (hash4Value ^ (g_CrcTable[cur[4]] << 3)) & p->hashMask; \
+ hash4Value &= (kHash4Size - 1); }
+
+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ g_CrcTable[cur[2]]) & 0xFFFF; */
+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ g_CrcTable[cur[1]]) & 0xFFFF;
+
+
+#define MT_HASH2_CALC \
+ hash2Value = (g_CrcTable[cur[0]] ^ cur[1]) & (kHash2Size - 1);
+
+#define MT_HASH3_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
+
+#define MT_HASH4_CALC { \
+ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & (kHash4Size - 1); }
+
+#endif
diff --git a/C/Compress/Lz/MatchFinder.c b/C/Compress/Lz/MatchFinder.c
new file mode 100755
index 00000000..4580c52b
--- /dev/null
+++ b/C/Compress/Lz/MatchFinder.c
@@ -0,0 +1,725 @@
+/* MatchFinder.c */
+/* Please call InitCrcTable before */
+
+#include <string.h>
+
+#include "MatchFinder.h"
+#include "LzHash.h"
+
+#include "../../7zCrc.h"
+
+#define kEmptyHashValue 0
+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
+#define kNormalizeMask (~(kNormalizeStepMin - 1))
+#define kMaxHistorySize ((UInt32)3 << 30)
+
+#define kStartMaxLen 3
+
+void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+ if (!p->directInput)
+ {
+ alloc->Free(p->bufferBase);
+ p->bufferBase = 0;
+ }
+}
+
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
+
+int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
+{
+ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
+ if (p->directInput)
+ {
+ p->blockSize = blockSize;
+ return 1;
+ }
+ if (p->bufferBase == 0 || p->blockSize != blockSize)
+ {
+ LzInWindow_Free(p, alloc);
+ p->blockSize = blockSize;
+ p->bufferBase = (Byte *)alloc->Alloc(blockSize);
+ }
+ return (p->bufferBase != 0);
+}
+
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer + p->pos; }
+Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[(size_t)p->pos + index]; }
+
+UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
+
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
+{
+ p->buffer += subValue;
+ p->posLimit -= subValue;
+ p->pos -= subValue;
+ p->streamPos -= subValue;
+}
+
+void MatchFinder_ReadBlock(CMatchFinder *p)
+{
+ if (p->streamEndWasReached || p->result != SZ_OK)
+ return;
+ for (;;)
+ {
+ Byte *dest = (p->buffer + p->pos + (p->streamPos - p->pos));
+ UInt32 numReadBytes;
+ UInt32 size = (UInt32)(p->bufferBase + p->blockSize - dest);
+ if (size == 0)
+ return;
+ p->result = p->stream->Read(p->stream, dest, size, &numReadBytes);
+ if (p->result != SZ_OK)
+ return;
+ if (numReadBytes == 0)
+ {
+ p->streamEndWasReached = 1;
+ return;
+ }
+ p->streamPos += numReadBytes;
+ if (p->streamPos - p->pos > p->keepSizeAfter)
+ return;
+ }
+}
+
+void MatchFinder_MoveBlock(CMatchFinder *p)
+{
+ memmove(p->bufferBase,
+ p->buffer + p->pos - p->keepSizeBefore,
+ p->streamPos - p->pos + p->keepSizeBefore);
+ p->buffer = p->bufferBase + p->keepSizeBefore - p->pos;
+}
+
+
+int MatchFinder_NeedMove(CMatchFinder *p)
+{
+ /* if (p->streamEndWasReached) return 0; */
+ return ((size_t)(p->bufferBase + p->blockSize - (p->buffer + p->pos)) <= p->keepSizeAfter);
+}
+
+void MatchFinder_ReadIfRequired(CMatchFinder *p)
+{
+ if (p->streamEndWasReached)
+ return;
+ if (p->keepSizeAfter >= p->streamPos - p->pos)
+ MatchFinder_ReadBlock(p);
+}
+
+void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
+{
+ if (MatchFinder_NeedMove(p))
+ MatchFinder_MoveBlock(p);
+ MatchFinder_ReadBlock(p);
+}
+
+void MatchFinder_SetDefaultSettings(CMatchFinder *p)
+{
+ p->cutValue = 32;
+ p->btMode = 1;
+ p->numHashBytes = 4;
+ /* p->skipModeBits = 0; */
+ p->directInput = 0;
+ p->bigHash = 0;
+}
+
+void MatchFinder_Construct(CMatchFinder *p)
+{
+ p->bufferBase = 0;
+ p->directInput = 0;
+ p->hash = 0;
+ MatchFinder_SetDefaultSettings(p);
+}
+
+void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
+{
+ alloc->Free(p->hash);
+ p->hash = 0;
+}
+
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+ MatchFinder_FreeThisClassMemory(p, alloc);
+ LzInWindow_Free(p, alloc);
+}
+
+CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
+{
+ size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
+ if (sizeInBytes / sizeof(CLzRef) != num)
+ return 0;
+ return (CLzRef *)alloc->Alloc(sizeInBytes);
+}
+
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+ ISzAlloc *alloc)
+{
+ UInt32 sizeReserv;
+ if (historySize > kMaxHistorySize)
+ {
+ MatchFinder_Free(p, alloc);
+ return 0;
+ }
+ sizeReserv = historySize >> 1;
+ if (historySize > ((UInt32)2 << 30))
+ sizeReserv = historySize >> 2;
+ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 12);
+
+ p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
+ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
+ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
+ if (LzInWindow_Create(p, sizeReserv, alloc))
+ {
+ UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
+ UInt32 hs;
+ p->matchMaxLen = matchMaxLen;
+ {
+ p->fixedHashSize = 0;
+ if (p->numHashBytes == 2)
+ hs = (1 << 16) - 1;
+ else
+ {
+ hs = historySize - 1;
+ hs |= (hs >> 1);
+ hs |= (hs >> 2);
+ hs |= (hs >> 4);
+ hs |= (hs >> 8);
+ hs >>= 1;
+ /* hs >>= p->skipModeBits; */
+ hs |= 0xFFFF; /* don't change it! It's required for Deflate */
+ if (hs > (1 << 24))
+ {
+ if (p->numHashBytes == 3)
+ hs = (1 << 24) - 1;
+ else
+ hs >>= 1;
+ }
+ }
+ p->hashMask = hs;
+ hs++;
+ if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
+ if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
+ if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
+ hs += p->fixedHashSize;
+ }
+
+ {
+ UInt32 prevSize = p->hashSizeSum + p->numSons;
+ UInt32 newSize;
+ p->historySize = historySize;
+ p->hashSizeSum = hs;
+ p->cyclicBufferSize = newCyclicBufferSize;
+ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
+ newSize = p->hashSizeSum + p->numSons;
+ if (p->hash != 0 && prevSize == newSize)
+ return 1;
+ MatchFinder_FreeThisClassMemory(p, alloc);
+ p->hash = AllocRefs(newSize, alloc);
+ if (p->hash != 0)
+ {
+ p->son = p->hash + p->hashSizeSum;
+ return 1;
+ }
+ }
+ }
+ MatchFinder_Free(p, alloc);
+ return 0;
+}
+
+void MatchFinder_SetLimits(CMatchFinder *p)
+{
+ UInt32 limit = kMaxValForNormalize - p->pos;
+ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
+ if (limit2 < limit)
+ limit = limit2;
+ limit2 = p->streamPos - p->pos;
+ if (limit2 <= p->keepSizeAfter)
+ {
+ if (limit2 > 0)
+ limit2 = 1;
+ }
+ else
+ limit2 -= p->keepSizeAfter;
+ if (limit2 < limit)
+ limit = limit2;
+ {
+ UInt32 lenLimit = p->streamPos - p->pos;
+ if (lenLimit > p->matchMaxLen)
+ lenLimit = p->matchMaxLen;
+ p->lenLimit = lenLimit;
+ }
+ p->posLimit = p->pos + limit;
+}
+
+void MatchFinder_Init(CMatchFinder *p)
+{
+ UInt32 i;
+ for(i = 0; i < p->hashSizeSum; i++)
+ p->hash[i] = kEmptyHashValue;
+ p->cyclicBufferPos = 0;
+ p->buffer = p->bufferBase - p->cyclicBufferSize;
+ p->pos = p->streamPos = p->cyclicBufferSize;
+ p->result = SZ_OK;
+ p->streamEndWasReached = 0;
+ MatchFinder_ReadBlock(p);
+ MatchFinder_SetLimits(p);
+}
+
+UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
+{
+ return (p->pos - p->historySize - 1) & kNormalizeMask;
+}
+
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
+{
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ {
+ UInt32 value = items[i];
+ if (value <= subValue)
+ value = kEmptyHashValue;
+ else
+ value -= subValue;
+ items[i] = value;
+ }
+}
+
+void MatchFinder_Normalize(CMatchFinder *p)
+{
+ UInt32 subValue = MatchFinder_GetSubValue(p);
+ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
+ MatchFinder_ReduceOffsets(p, subValue);
+}
+
+void MatchFinder_CheckLimits(CMatchFinder *p)
+{
+ if (p->pos == kMaxValForNormalize)
+ MatchFinder_Normalize(p);
+ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
+ MatchFinder_CheckAndMoveAndRead(p);
+ if (p->cyclicBufferPos == p->cyclicBufferSize)
+ p->cyclicBufferPos = 0;
+ MatchFinder_SetLimits(p);
+}
+
+UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+ UInt32 *distances, UInt32 maxLen)
+{
+ son[_cyclicBufferPos] = curMatch;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ return distances;
+ {
+ const Byte *pb = buffer + curMatch;
+ const Byte *cur = buffer + pos;
+ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+ if (pb[maxLen] == cur[maxLen] && *pb == *cur)
+ {
+ UInt32 len = 0;
+ while(++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len)
+ {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ return distances;
+ }
+ }
+ }
+ }
+}
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+ UInt32 *distances, UInt32 maxLen)
+{
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ return distances;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = buffer + curMatch;
+ const Byte *cur = buffer + pos;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len])
+ {
+ if (++len != lenLimit && pb[len] == cur[len])
+ while(++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len)
+ {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return distances;
+ }
+ }
+ }
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+}
+
+void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
+{
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ return;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = buffer + curMatch;
+ const Byte *cur = buffer + pos;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len])
+ {
+ while(++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ {
+ if (len == lenLimit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return;
+ }
+ }
+ }
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+}
+
+#define MOVE_POS \
+ ++p->cyclicBufferPos; \
+ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
+
+#define MOVE_POS_RET MOVE_POS return offset;
+
+void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
+
+#define GET_MATCHES_HEADER2(minLen, ret_op) \
+ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
+ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
+ cur = p->buffer + p->pos;
+
+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
+#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
+
+#define GET_MATCHES_FOOTER(offset, maxLen) \
+ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, p->pos, p->buffer, p->son, p->cyclicBufferPos, \
+ p->cyclicBufferSize, p->cutValue, distances + offset, maxLen) - distances); MOVE_POS_RET;
+
+#define SKIP_FOOTER \
+ SkipMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->son, \
+ p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue); MOVE_POS;
+
+UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(2)
+ HASH2_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = 0;
+ GET_MATCHES_FOOTER(offset, 1)
+}
+
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = 0;
+ GET_MATCHES_FOOTER(offset, 2)
+}
+
+UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value, matchMinPos, curMatch2, maxLen, offset;
+ GET_MATCHES_HEADER(3)
+
+ HASH3_CALC;
+
+ curMatch2 = p->hash[hash2Value];
+ curMatch = p->hash[kFix3HashSize + hashValue];
+
+ p->hash[hash2Value] =
+ p->hash[kFix3HashSize + hashValue] = p->pos;
+
+ matchMinPos = p->pos - p->cyclicBufferSize;
+
+ maxLen = 2;
+ offset = 0;
+ if (curMatch2 > matchMinPos && p->buffer[curMatch2] == cur[0])
+ {
+ for (; maxLen != lenLimit; maxLen++)
+ if (p->buffer[curMatch2 + maxLen] != cur[maxLen])
+ break;
+ distances[0] = maxLen;
+ distances[1] = p->pos - curMatch2 - 1;
+ offset = 2;
+ if (maxLen == lenLimit)
+ {
+ SkipMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->son,
+ p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue);
+ MOVE_POS_RET;
+ }
+ }
+ GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, matchMinPos, curMatch2, curMatch3, maxLen, offset;
+ GET_MATCHES_HEADER(4)
+
+ HASH4_CALC;
+
+ curMatch2 = p->hash[ hash2Value];
+ curMatch3 = p->hash[kFix3HashSize + hash3Value];
+ curMatch = p->hash[kFix4HashSize + hashValue];
+
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+
+ matchMinPos = p->pos - p->cyclicBufferSize;
+ maxLen = 1;
+ offset = 0;
+ if (curMatch2 > matchMinPos && p->buffer[curMatch2] == cur[0])
+ {
+ distances[0] = maxLen = 2;
+ distances[1] = p->pos - curMatch2 - 1;
+ offset = 2;
+ }
+ if (curMatch2 != curMatch3 && curMatch3 > matchMinPos && p->buffer[curMatch3] == cur[0])
+ {
+ maxLen = 3;
+ distances[offset + 1] = p->pos - curMatch3 - 1;
+ offset += 2;
+ curMatch2 = curMatch3;
+ }
+ if (offset != 0)
+ {
+ for (; maxLen != lenLimit; maxLen++)
+ if (p->buffer[curMatch2 + maxLen] != cur[maxLen])
+ break;
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit)
+ {
+ SkipMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->son,
+ p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue);
+ MOVE_POS_RET;
+ }
+ }
+ if (maxLen < 3)
+ maxLen = 3;
+ GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, matchMinPos, curMatch2, curMatch3, maxLen, offset;
+ GET_MATCHES_HEADER(4)
+
+ HASH4_CALC;
+
+ curMatch2 = p->hash[ hash2Value];
+ curMatch3 = p->hash[kFix3HashSize + hash3Value];
+ curMatch = p->hash[kFix4HashSize + hashValue];
+
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+
+ matchMinPos = p->pos - p->cyclicBufferSize;
+ maxLen = 1;
+ offset = 0;
+ if (curMatch2 > matchMinPos && p->buffer[curMatch2] == cur[0])
+ {
+ distances[0] = maxLen = 2;
+ distances[1] = p->pos - curMatch2 - 1;
+ offset = 2;
+ }
+ if (curMatch2 != curMatch3 && curMatch3 > matchMinPos && p->buffer[curMatch3] == cur[0])
+ {
+ maxLen = 3;
+ distances[offset + 1] = p->pos - curMatch3 - 1;
+ offset += 2;
+ curMatch2 = curMatch3;
+ }
+ if (offset != 0)
+ {
+ for (; maxLen != lenLimit; maxLen++)
+ if (p->buffer[curMatch2 + maxLen] != cur[maxLen])
+ break;
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit)
+ {
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS_RET;
+ }
+ }
+ if (maxLen < 3)
+ maxLen = 3;
+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->son,
+ p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
+ distances + offset, maxLen) - (distances));
+ MOVE_POS_RET
+}
+
+void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ SKIP_HEADER(2)
+ HASH2_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ SKIP_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 hash2Value;
+ SKIP_HEADER(3)
+ HASH3_CALC;
+ curMatch = p->hash[kFix3HashSize + hashValue];
+ p->hash[hash2Value] =
+ p->hash[kFix3HashSize + hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 hash2Value, hash3Value;
+ SKIP_HEADER(4)
+ HASH4_CALC;
+ curMatch = p->hash[kFix4HashSize + hashValue];
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] = p->pos;
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+
+void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 hash2Value, hash3Value;
+ SKIP_HEADER(4)
+ HASH4_CALC;
+ curMatch = p->hash[kFix4HashSize + hashValue];
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS
+ }
+ while (--num != 0);
+}
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
+{
+ vTable->Init = (Mf_Init_Func)MatchFinder_Init;
+ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
+ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
+ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
+ if (!p->btMode)
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
+ }
+ else if (p->numHashBytes == 2)
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
+ }
+ else if (p->numHashBytes == 3)
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
+ }
+ else
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
+ }
+}
diff --git a/C/Compress/Lz/MatchFinder.h b/C/Compress/Lz/MatchFinder.h
new file mode 100755
index 00000000..43906312
--- /dev/null
+++ b/C/Compress/Lz/MatchFinder.h
@@ -0,0 +1,103 @@
+/* MatchFinder.h */
+
+#ifndef __MATCHFINDER_H
+#define __MATCHFINDER_H
+
+#include "../../IStream.h"
+
+typedef UInt32 CLzRef;
+
+typedef struct _CMatchFinder
+{
+ Byte *buffer;
+ UInt32 pos;
+ UInt32 posLimit;
+ UInt32 streamPos;
+ UInt32 lenLimit;
+
+ UInt32 cyclicBufferPos;
+ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
+
+ UInt32 matchMaxLen;
+ CLzRef *hash;
+ CLzRef *son;
+ UInt32 hashMask;
+ UInt32 cutValue;
+
+ Byte *bufferBase;
+ ISeqInStream *stream;
+ int streamEndWasReached;
+
+ UInt32 blockSize;
+ UInt32 keepSizeBefore;
+ UInt32 keepSizeAfter;
+
+ UInt32 numHashBytes;
+ int directInput;
+ int btMode;
+ /* int skipModeBits; */
+ int bigHash;
+ UInt32 historySize;
+ UInt32 fixedHashSize;
+ UInt32 hashSizeSum;
+ UInt32 numSons;
+
+ HRes result;
+} CMatchFinder;
+
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer + (p)->pos)
+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(size_t)(p)->pos + (Int32)(index)])
+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
+
+int MatchFinder_NeedMove(CMatchFinder *p);
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
+void MatchFinder_MoveBlock(CMatchFinder *p);
+void MatchFinder_ReadIfRequired(CMatchFinder *p);
+
+void MatchFinder_Construct(CMatchFinder *p);
+
+/* Conditions:
+ historySize <= 3 GB
+ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
+*/
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+ ISzAlloc *alloc);
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+ UInt32 *distances, UInt32 maxLen);
+
+/*
+Conditions:
+ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
+ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
+*/
+
+typedef void (*Mf_Init_Func)(void *object);
+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
+typedef void (*Mf_Skip_Func)(void *object, UInt32);
+
+typedef struct _IMatchFinder
+{
+ Mf_Init_Func Init;
+ Mf_GetIndexByte_Func GetIndexByte;
+ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
+ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
+ Mf_GetMatches_Func GetMatches;
+ Mf_Skip_Func Skip;
+} IMatchFinder;
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+
+void MatchFinder_Init(CMatchFinder *p);
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+
+#endif
diff --git a/C/Compress/Lz/MatchFinderMt.c b/C/Compress/Lz/MatchFinderMt.c
new file mode 100755
index 00000000..4ab90d9a
--- /dev/null
+++ b/C/Compress/Lz/MatchFinderMt.c
@@ -0,0 +1,792 @@
+/* MatchFinderMt.c */
+
+#include <stdio.h>
+#include "../../7zCrc.h"
+#include "LzHash.h"
+
+#include "MatchFinderMt.h"
+
+void MtSync_Construct(CMtSync *p)
+{
+ p->wasCreated = False;
+ p->csWasInitialized = False;
+ p->csWasEntered = False;
+ Thread_Construct(&p->thread);
+ Event_Construct(&p->canStart);
+ Event_Construct(&p->wasStarted);
+ Event_Construct(&p->wasStopped);
+ Semaphore_Construct(&p->freeSemaphore);
+ Semaphore_Construct(&p->filledSemaphore);
+}
+
+void MtSync_GetNextBlock(CMtSync *p)
+{
+ if (p->needStart)
+ {
+ p->numProcessedBlocks = 1;
+ p->needStart = False;
+ p->stopWriting = False;
+ p->exit = False;
+ Event_Reset(&p->wasStarted);
+ Event_Reset(&p->wasStopped);
+
+ Event_Set(&p->canStart);
+ Event_Wait(&p->wasStarted);
+ }
+ else
+ {
+ CriticalSection_Leave(&p->cs);
+ p->csWasEntered = False;
+ p->numProcessedBlocks++;
+ Semaphore_Release1(&p->freeSemaphore);
+ }
+ Semaphore_Wait(&p->filledSemaphore);
+ CriticalSection_Enter(&p->cs);
+ p->csWasEntered = True;
+}
+
+/* MtSync_StopWriting must be called if Writing was started */
+
+void MtSync_StopWriting(CMtSync *p)
+{
+ UInt32 myNumBlocks = p->numProcessedBlocks;
+ if (!Thread_WasCreated(&p->thread) || p->needStart)
+ return;
+ p->stopWriting = True;
+ if (p->csWasEntered)
+ {
+ CriticalSection_Leave(&p->cs);
+ p->csWasEntered = False;
+ }
+ Semaphore_Release1(&p->freeSemaphore);
+
+ Event_Wait(&p->wasStopped);
+
+ while (myNumBlocks++ != p->numProcessedBlocks)
+ {
+ Semaphore_Wait(&p->filledSemaphore);
+ Semaphore_Release1(&p->freeSemaphore);
+ }
+ p->needStart = True;
+}
+
+void MtSync_Destruct(CMtSync *p)
+{
+ if (Thread_WasCreated(&p->thread))
+ {
+ MtSync_StopWriting(p);
+ p->exit = True;
+ if (p->needStart)
+ Event_Set(&p->canStart);
+ Thread_Wait(&p->thread);
+ Thread_Close(&p->thread);
+ }
+ if (p->csWasInitialized)
+ {
+ CriticalSection_Delete(&p->cs);
+ p->csWasInitialized = False;
+ }
+
+ Event_Close(&p->canStart);
+ Event_Close(&p->wasStarted);
+ Event_Close(&p->wasStopped);
+ Semaphore_Close(&p->freeSemaphore);
+ Semaphore_Close(&p->filledSemaphore);
+
+ p->wasCreated = False;
+}
+
+HRes MtSync_Create2(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
+{
+ if (p->wasCreated)
+ return SZ_OK;
+
+ RINOK(CriticalSection_Init(&p->cs));
+ p->csWasInitialized = True;
+
+ RINOK(AutoResetEvent_CreateNotSignaled(&p->canStart));
+ RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
+ RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
+
+ RINOK(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
+ RINOK(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
+
+ p->needStart = True;
+
+ RINOK(Thread_Create(&p->thread, startAddress, obj));
+ p->wasCreated = True;
+ return SZ_OK;
+}
+
+HRes MtSync_Create(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
+{
+ HRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
+ if (res != SZ_OK)
+ MtSync_Destruct(p);
+ return res;
+}
+
+
+void MtSync_Init(CMtSync *p) { p->needStart = True; }
+
+#define kMtMaxValForNormalize 0xFFFFFFFF
+
+/*
+Notes:
+instead of "size_t pos" we can use "UInt32 pos".
+But MSVC++ compilers have BUG:
+sometimes they use signed extending: (size_t)pos was compiled to "movsxd r10, edx"
+*/
+
+#define DEF_GetHeads(name, v) \
+static void GetHeads ## name(const Byte *buffer, size_t pos, \
+UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \
+for (; numHeads != 0; numHeads--) { const Byte *p = buffer + (size_t)pos; \
+const UInt32 value = (v); *heads++ = (UInt32)pos - hash[value]; hash[value] = (UInt32)(pos++); } }
+
+DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask)
+DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
+DEF_GetHeads(4, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5)) & hashMask)
+DEF_GetHeads(4b, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
+DEF_GetHeads(5, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5) ^ (g_CrcTable[p[4]] << 3)) & hashMask)
+
+void HashThreadFunc(CMatchFinderMt *mt)
+{
+ CMtSync *p = &mt->hashSync;
+ for (;;)
+ {
+ UInt32 numProcessedBlocks = 0;
+ Event_Wait(&p->canStart);
+ Event_Set(&p->wasStarted);
+ for (;;)
+ {
+ if (p->exit)
+ return;
+ if (p->stopWriting)
+ {
+ p->numProcessedBlocks = numProcessedBlocks;
+ Event_Set(&p->wasStopped);
+ break;
+ }
+
+ {
+ CMatchFinder *mf = mt->MatchFinder;
+ if (MatchFinder_NeedMove(mf))
+ {
+ CriticalSection_Enter(&mt->btSync.cs);
+ CriticalSection_Enter(&mt->hashSync.cs);
+ {
+ const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
+ const Byte *afterPtr;
+ MatchFinder_MoveBlock(mf);
+ afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
+ mt->pointerToCurPos -= beforePtr - afterPtr;
+ mt->buffer -= beforePtr - afterPtr;
+ }
+ CriticalSection_Leave(&mt->btSync.cs);
+ CriticalSection_Leave(&mt->hashSync.cs);
+ continue;
+ }
+
+ Semaphore_Wait(&p->freeSemaphore);
+
+ MatchFinder_ReadIfRequired(mf);
+ if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))
+ {
+ UInt32 subValue = (mf->pos - mf->historySize - 1);
+ MatchFinder_ReduceOffsets(mf, subValue);
+ MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
+ }
+ {
+ UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
+ UInt32 num = mf->streamPos - mf->pos;
+ heads[0] = 2;
+ heads[1] = num;
+ if (num >= mf->numHashBytes)
+ {
+ num = num - mf->numHashBytes + 1;
+ if (num > kMtHashBlockSize - 2)
+ num = kMtHashBlockSize - 2;
+ mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num);
+ heads[0] += num;
+ }
+ mf->pos += num;
+ }
+ }
+
+ Semaphore_Release1(&p->filledSemaphore);
+ }
+ }
+}
+
+void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
+{
+ MtSync_GetNextBlock(&p->hashSync);
+ p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
+ p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];
+ p->hashNumAvail = p->hashBuf[p->hashBufPos++];
+}
+
+#define kEmptyHashValue 0
+
+/* #define MFMT_GM_INLINE */
+
+#ifdef MFMT_GM_INLINE
+
+#if _MSC_VER >= 1300
+#define NO_INLINE __declspec(noinline) __fastcall
+#else
+#ifdef _MSC_VER
+#define NO_INLINE __fastcall
+#endif
+#endif
+
+Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *buffer, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+ UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
+{
+ do
+ {
+ UInt32 *distances = _distances + 1;
+ UInt32 curMatch = pos - *hash++;
+
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ UInt32 cutValue = _cutValue;
+ UInt32 maxLen = _maxLen;
+ for (;;)
+ {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ break;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = buffer + curMatch;
+ const Byte *cur = buffer + pos;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len])
+ {
+ while(++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len)
+ {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ break;
+ }
+ }
+ }
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+ pos++;
+ _cyclicBufferPos++;
+ {
+ UInt32 num = (UInt32)(distances - _distances);
+ *_distances = num - 1;
+ _distances += num;
+ limit -= num;
+ }
+ }
+ while (limit > 0 && --size != 0);
+ *posRes = pos;
+ return limit;
+}
+
+#endif
+
+void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
+{
+ UInt32 numProcessed = 0;
+ UInt32 curPos = 2;
+ UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
+ distances[1] = p->hashNumAvail;
+ while (curPos < limit)
+ {
+ if (p->hashBufPos == p->hashBufPosLimit)
+ {
+ MatchFinderMt_GetNextBlock_Hash(p);
+ distances[1] = numProcessed + p->hashNumAvail;
+ if (p->hashNumAvail >= p->numHashBytes)
+ continue;
+ for (; p->hashNumAvail != 0; p->hashNumAvail--)
+ distances[curPos++] = 0;
+ break;
+ }
+ {
+ UInt32 size = p->hashBufPosLimit - p->hashBufPos;
+ UInt32 lenLimit = p->matchMaxLen;
+ UInt32 pos = p->pos;
+ UInt32 cyclicBufferPos = p->cyclicBufferPos;
+ if (lenLimit >= p->hashNumAvail)
+ lenLimit = p->hashNumAvail;
+ {
+ UInt32 size2 = p->hashNumAvail - lenLimit + 1;
+ if (size2 < size)
+ size = size2;
+ size2 = p->cyclicBufferSize - cyclicBufferPos;
+ if (size2 < size)
+ size = size2;
+ }
+ #ifndef MFMT_GM_INLINE
+ while (curPos < limit && size-- != 0)
+ {
+ UInt32 *startDistances = distances + curPos;
+ UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
+ pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
+ startDistances + 1, p->numHashBytes - 1) - startDistances);
+ *startDistances = num - 1;
+ curPos += num;
+ cyclicBufferPos++;
+ pos++;
+ }
+ #else
+ {
+ UInt32 posRes;
+ curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
+ distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
+ p->hashBufPos += posRes - pos;
+ cyclicBufferPos += posRes - pos;
+ pos = posRes;
+ }
+ #endif
+
+ numProcessed += pos - p->pos;
+ p->hashNumAvail -= pos - p->pos;
+ p->pos = pos;
+ if (cyclicBufferPos == p->cyclicBufferSize)
+ cyclicBufferPos = 0;
+ p->cyclicBufferPos = cyclicBufferPos;
+ }
+ }
+ distances[0] = curPos;
+}
+
+void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
+{
+ CMtSync *sync = &p->hashSync;
+ if (!sync->needStart)
+ {
+ CriticalSection_Enter(&sync->cs);
+ sync->csWasEntered = True;
+ }
+
+ BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);
+
+ if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
+ {
+ UInt32 subValue = p->pos - p->cyclicBufferSize;
+ MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
+ p->pos -= subValue;
+ p->buffer += subValue;
+ }
+
+ if (!sync->needStart)
+ {
+ CriticalSection_Leave(&sync->cs);
+ sync->csWasEntered = False;
+ }
+}
+
+void BtThreadFunc(CMatchFinderMt *mt)
+{
+ CMtSync *p = &mt->btSync;
+ for (;;)
+ {
+ UInt32 blockIndex = 0;
+ Event_Wait(&p->canStart);
+ Event_Set(&p->wasStarted);
+ for (;;)
+ {
+ if (p->exit)
+ return;
+ if (p->stopWriting)
+ {
+ p->numProcessedBlocks = blockIndex;
+ MtSync_StopWriting(&mt->hashSync);
+ Event_Set(&p->wasStopped);
+ break;
+ }
+ Semaphore_Wait(&p->freeSemaphore);
+ BtFillBlock(mt, blockIndex++);
+ Semaphore_Release1(&p->filledSemaphore);
+ }
+ }
+}
+
+void MatchFinderMt_Construct(CMatchFinderMt *p)
+{
+ p->hashBuf = 0;
+ MtSync_Construct(&p->hashSync);
+ MtSync_Construct(&p->btSync);
+}
+
+void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
+{
+ alloc->Free(p->hashBuf);
+ p->hashBuf = 0;
+}
+
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
+{
+ MtSync_Destruct(&p->hashSync);
+ MtSync_Destruct(&p->btSync);
+ MatchFinderMt_FreeMem(p, alloc);
+}
+
+#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
+#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
+
+static unsigned StdCall HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
+static unsigned StdCall BtThreadFunc2(void *p) { BtThreadFunc((CMatchFinderMt *)p); return 0; }
+
+HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
+{
+ CMatchFinder *mf = p->MatchFinder;
+ p->historySize = historySize;
+ if (kMtBtBlockSize <= matchMaxLen * 4)
+ return E_INVALIDARG;
+ if (p->hashBuf == 0)
+ {
+ p->hashBuf = (UInt32 *)alloc->Alloc((kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
+ if (p->hashBuf == 0)
+ return SZE_OUTOFMEMORY;
+ p->btBuf = p->hashBuf + kHashBufferSize;
+ }
+ keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
+ keepAddBufferAfter += kMtHashBlockSize;
+ if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
+ return SZE_OUTOFMEMORY;
+
+ RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
+ RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
+ return SZ_OK;
+}
+
+/* Call it after ReleaseStream / SetStream */
+void MatchFinderMt_Init(CMatchFinderMt *p)
+{
+ CMatchFinder *mf = p->MatchFinder;
+ p->btBufPos = p->btBufPosLimit = 0;
+ p->hashBufPos = p->hashBufPosLimit = 0;
+ MatchFinder_Init(mf);
+ p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
+ p->btNumAvailBytes = 0;
+ p->lzPos = p->historySize + 1;
+
+ p->hash = mf->hash;
+ p->fixedHashSize = mf->fixedHashSize;
+
+ p->son = mf->son;
+ p->matchMaxLen = mf->matchMaxLen;
+ p->numHashBytes = mf->numHashBytes;
+ p->pos = mf->pos;
+ p->buffer = mf->buffer;
+ p->cyclicBufferPos = mf->cyclicBufferPos;
+ p->cyclicBufferSize = mf->cyclicBufferSize;
+ p->cutValue = mf->cutValue;
+}
+
+/* ReleaseStream is required to finish multithreading */
+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
+{
+ MtSync_StopWriting(&p->btSync);
+ /* p->MatchFinder->ReleaseStream(); */
+}
+
+void MatchFinderMt_Normalize(CMatchFinderMt *p)
+{
+ MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
+ p->lzPos = p->historySize + 1;
+}
+
+void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
+{
+ UInt32 blockIndex;
+ MtSync_GetNextBlock(&p->btSync);
+ blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);
+ p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
+ p->btBufPosLimit += p->btBuf[p->btBufPos++];
+ p->btNumAvailBytes = p->btBuf[p->btBufPos++];
+ if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
+ MatchFinderMt_Normalize(p);
+}
+
+const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
+{
+ return p->pointerToCurPos;
+}
+
+#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
+
+UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
+{
+ GET_NEXT_BLOCK_IF_REQUIRED;
+ return p->btNumAvailBytes;
+}
+
+Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
+{
+ return p->pointerToCurPos[index];
+}
+
+UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+{
+ UInt32 hash2Value, curMatch2;
+ UInt32 *hash = p->hash;
+ const Byte *cur = p->pointerToCurPos;
+ UInt32 lzPos = p->lzPos;
+ MT_HASH2_CALC
+
+ curMatch2 = hash[hash2Value];
+ hash[hash2Value] = lzPos;
+
+ if (curMatch2 >= matchMinPos)
+ if (cur[(size_t)curMatch2 - lzPos] == cur[0])
+ {
+ *distances++ = 2;
+ *distances++ = lzPos - curMatch2 - 1;
+ }
+ return distances;
+}
+
+UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
+ UInt32 *hash = p->hash;
+ const Byte *cur = p->pointerToCurPos;
+ UInt32 lzPos = p->lzPos;
+ MT_HASH3_CALC
+
+ curMatch2 = hash[ hash2Value];
+ curMatch3 = hash[kFix3HashSize + hash3Value];
+
+ hash[ hash2Value] =
+ hash[kFix3HashSize + hash3Value] =
+ lzPos;
+
+ if (curMatch2 >= matchMinPos && cur[(size_t)curMatch2 - lzPos] == cur[0])
+ {
+ distances[1] = lzPos - curMatch2 - 1;
+ if (cur[(size_t)curMatch2 - lzPos + 2] == cur[2])
+ {
+ distances[0] = 3;
+ return distances + 2;
+ }
+ distances[0] = 2;
+ distances += 2;
+ }
+ if (curMatch3 >= matchMinPos && cur[(size_t)curMatch3 - lzPos] == cur[0])
+ {
+ *distances++ = 3;
+ *distances++ = lzPos - curMatch3 - 1;
+ }
+ return distances;
+}
+
+/*
+UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+{
+ UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
+ UInt32 *hash = p->hash;
+ const Byte *cur = p->pointerToCurPos;
+ UInt32 lzPos = p->lzPos;
+ MT_HASH4_CALC
+
+ curMatch2 = hash[ hash2Value];
+ curMatch3 = hash[kFix3HashSize + hash3Value];
+ curMatch4 = hash[kFix4HashSize + hash4Value];
+
+ hash[ hash2Value] =
+ hash[kFix3HashSize + hash3Value] =
+ hash[kFix4HashSize + hash4Value] =
+ lzPos;
+
+ if (curMatch2 >= matchMinPos && cur[(size_t)curMatch2 - lzPos] == cur[0])
+ {
+ distances[1] = lzPos - curMatch2 - 1;
+ if (cur[(size_t)curMatch2 - lzPos + 2] == cur[2])
+ {
+ distances[0] = (cur[(size_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
+ return distances + 2;
+ }
+ distances[0] = 2;
+ distances += 2;
+ }
+ if (curMatch3 >= matchMinPos && cur[(size_t)curMatch3 - lzPos] == cur[0])
+ {
+ distances[1] = lzPos - curMatch3 - 1;
+ if (cur[(size_t)curMatch3 - lzPos + 3] == cur[3])
+ {
+ distances[0] = 4;
+ return distances + 2;
+ }
+ distances[0] = 3;
+ distances += 2;
+ }
+
+ if (curMatch4 >= matchMinPos)
+ if (
+ cur[(size_t)curMatch4 - lzPos] == cur[0] &&
+ cur[(size_t)curMatch4 - lzPos + 3] == cur[3]
+ )
+ {
+ *distances++ = 4;
+ *distances++ = lzPos - curMatch4 - 1;
+ }
+ return distances;
+}
+*/
+
+#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
+
+UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
+{
+ const UInt32 *btBuf = p->btBuf + p->btBufPos;
+ UInt32 len = *btBuf++;
+ p->btBufPos += 1 + len;
+ p->btNumAvailBytes--;
+ {
+ UInt32 i;
+ for (i = 0; i < len; i += 2)
+ {
+ *distances++ = *btBuf++;
+ *distances++ = *btBuf++;
+ }
+ }
+ INCREASE_LZ_POS
+ return len;
+}
+
+UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
+{
+ const UInt32 *btBuf = p->btBuf + p->btBufPos;
+ UInt32 len = *btBuf++;
+ p->btBufPos += 1 + len;
+
+ if (len == 0)
+ {
+ if (p->btNumAvailBytes-- >= 4)
+ len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
+ }
+ else
+ {
+ /* Condition: there are matches in btBuf with length < p->numHashBytes */
+ UInt32 *distances2;
+ p->btNumAvailBytes--;
+ distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
+ do
+ {
+ *distances2++ = *btBuf++;
+ *distances2++ = *btBuf++;
+ }
+ while ((len -= 2) != 0);
+ len = (UInt32)(distances2 - (distances));
+ }
+ INCREASE_LZ_POS
+ return len;
+}
+
+#define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED
+#define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
+#define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while(--num != 0);
+
+void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER2 { p->btNumAvailBytes--;
+ SKIP_FOOTER
+}
+
+void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER(2)
+ UInt32 hash2Value;
+ MT_HASH2_CALC
+ hash[hash2Value] = p->lzPos;
+ SKIP_FOOTER
+}
+
+void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER(3)
+ UInt32 hash2Value, hash3Value;
+ MT_HASH3_CALC
+ hash[kFix3HashSize + hash3Value] =
+ hash[ hash2Value] =
+ p->lzPos;
+ SKIP_FOOTER
+}
+
+/*
+void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
+{
+ SKIP_HEADER(4)
+ UInt32 hash2Value, hash3Value, hash4Value;
+ MT_HASH4_CALC
+ hash[kFix4HashSize + hash4Value] =
+ hash[kFix3HashSize + hash3Value] =
+ hash[ hash2Value] =
+ p->lzPos;
+ SKIP_FOOTER
+}
+*/
+
+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
+{
+ vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
+ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
+ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
+ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
+ vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
+ switch(p->MatchFinder->numHashBytes)
+ {
+ case 2:
+ p->GetHeadsFunc = GetHeads2;
+ p->MixMatchesFunc = (Mf_Mix_Matches)0;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
+ vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
+ break;
+ case 3:
+ p->GetHeadsFunc = GetHeads3;
+ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;
+ break;
+ default:
+ /* case 4: */
+ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
+ /* p->GetHeadsFunc = GetHeads4; */
+ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
+ break;
+ /*
+ default:
+ p->GetHeadsFunc = GetHeads5;
+ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
+ vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;
+ break;
+ */
+ }
+}
diff --git a/C/Compress/Lz/MatchFinderMt.h b/C/Compress/Lz/MatchFinderMt.h
new file mode 100755
index 00000000..a99cc45f
--- /dev/null
+++ b/C/Compress/Lz/MatchFinderMt.h
@@ -0,0 +1,97 @@
+/* MatchFinderMt.h */
+
+#ifndef __MATCHFINDERMT_H
+#define __MATCHFINDERMT_H
+
+#include "../../Threads.h"
+#include "MatchFinder.h"
+
+#define _LZ_MT
+
+#define kMtHashBlockSize (1 << 13)
+#define kMtHashNumBlocks (1 << 3)
+#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)
+
+#define kMtBtBlockSize (1 << 14)
+#define kMtBtNumBlocks (1 << 6)
+#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)
+
+typedef struct _CMtSync
+{
+ Bool wasCreated;
+ Bool needStart;
+ Bool exit;
+ Bool stopWriting;
+
+ CThread thread;
+ CAutoResetEvent canStart;
+ CAutoResetEvent wasStarted;
+ CAutoResetEvent wasStopped;
+ CSemaphore freeSemaphore;
+ CSemaphore filledSemaphore;
+ Bool csWasInitialized;
+ Bool csWasEntered;
+ CCriticalSection cs;
+ UInt32 numProcessedBlocks;
+} CMtSync;
+
+typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
+
+/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
+#define kMtCacheLineDummy 128
+
+typedef void (*Mf_GetHeads)(const Byte *buffer, size_t pos,
+ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads);
+
+typedef struct _CMatchFinderMt
+{
+ /* LZ */
+ const Byte *pointerToCurPos;
+ UInt32 *btBuf;
+ UInt32 btBufPos;
+ UInt32 btBufPosLimit;
+ UInt32 lzPos;
+ UInt32 btNumAvailBytes;
+
+ UInt32 *hash;
+ UInt32 fixedHashSize;
+ UInt32 historySize;
+
+ Mf_Mix_Matches MixMatchesFunc;
+
+ /* LZ + BT */
+ CMtSync btSync;
+ Byte btDummy[kMtCacheLineDummy];
+
+ /* BT */
+ UInt32 *hashBuf;
+ UInt32 hashBufPos;
+ UInt32 hashBufPosLimit;
+ UInt32 hashNumAvail;
+
+ CLzRef *son;
+ UInt32 matchMaxLen;
+ UInt32 numHashBytes;
+ UInt32 pos;
+ Byte *buffer; // Pointer to virtual Buffer begin
+ UInt32 cyclicBufferPos;
+ UInt32 cyclicBufferSize; // it must be historySize + 1
+ UInt32 cutValue;
+
+ /* BT + Hash */
+ CMtSync hashSync;
+ /* Byte hashDummy[kMtCacheLineDummy]; */
+
+ /* Hash */
+ Mf_GetHeads GetHeadsFunc;
+ CMatchFinder *MatchFinder;
+} CMatchFinderMt;
+
+void MatchFinderMt_Construct(CMatchFinderMt *p);
+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
+HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);
+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
+
+#endif
diff --git a/C/Compress/Lzma/LzmaDecode.c b/C/Compress/Lzma/LzmaDecode.c
new file mode 100755
index 00000000..cb834537
--- /dev/null
+++ b/C/Compress/Lzma/LzmaDecode.c
@@ -0,0 +1,584 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder (optimized for Speed version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+
+ #ifdef _LZMA_OUT_READ
+
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ const Byte *Buffer = vs->Buffer;
+ const Byte *BufferLim = vs->BufferLim;
+ #else
+ const Byte *Buffer = inStream;
+ const Byte *BufferLim = inStream + inSize;
+ #endif
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+
+ #endif /* _LZMA_OUT_READ */
+
+ while(nowPos < outSize)
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (Byte)symbol;
+
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ UpdateBit0(prob);
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < kNumLitStates ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ RC_NORMALIZE;
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/C/Compress/Lzma/LzmaDecode.h b/C/Compress/Lzma/LzmaDecode.h
new file mode 100755
index 00000000..2870eeb9
--- /dev/null
+++ b/C/Compress/Lzma/LzmaDecode.h
@@ -0,0 +1,113 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+#include "LzmaTypes.h"
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ #ifdef _LZMA_OUT_READ
+ UInt32 DictionarySize;
+ #endif
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+
+ #ifdef _LZMA_IN_CB
+ const unsigned char *Buffer;
+ const unsigned char *BufferLim;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ unsigned char *Dictionary;
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen;
+ unsigned char TempDictionary[4];
+ #endif
+} CLzmaDecoderState;
+
+#ifdef _LZMA_OUT_READ
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
+#endif
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif
diff --git a/C/Compress/Lzma/LzmaDecodeSize.c b/C/Compress/Lzma/LzmaDecodeSize.c
new file mode 100755
index 00000000..a3a5eb9d
--- /dev/null
+++ b/C/Compress/Lzma/LzmaDecodeSize.c
@@ -0,0 +1,712 @@
+/*
+ LzmaDecodeSize.c
+ LZMA Decoder (optimized for Size version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ int Result;
+ #endif
+ int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+ if (rd->Buffer == rd->BufferLim)
+ {
+ #ifdef _LZMA_IN_CB
+ SizeT size;
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+ rd->BufferLim = rd->Buffer + size;
+ if (size == 0)
+ #endif
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+ }
+ return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd
+ #ifndef _LZMA_IN_CB
+ , const Byte *stream, SizeT bufferSize
+ #endif
+ )
+{
+ int i;
+ #ifdef _LZMA_IN_CB
+ rd->Buffer = rd->BufferLim = 0;
+ #else
+ rd->Buffer = stream;
+ rd->BufferLim = stream + bufferSize;
+ #endif
+ rd->ExtraBytes = 0;
+ rd->Code = 0;
+ rd->Range = (0xFFFFFFFF);
+ for(i = 0; i < 5; i++)
+ rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+ RC_INIT_VAR
+ UInt32 result = 0;
+ int i;
+ for (i = numTotalBits; i != 0; i--)
+ {
+ /* UInt32 t; */
+ range >>= 1;
+
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ /*
+ t = (code - range) >> 31;
+ t &= 1;
+ code -= range & (t - 1);
+ result = (result + result) | (1 - t);
+ */
+ RC_NORMALIZE
+ }
+ RC_FLUSH_VAR
+ return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+ if (rd->Code < bound)
+ {
+ rd->Range = bound;
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rd->Range -= bound;
+ rd->Code -= bound;
+ *prob -= (*prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 1;
+ }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+ if (code < bound) \
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+ RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = numLevels; i != 0; i--)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT(prob, mi)
+ #else
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ int symbol = 0;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = 0; i < numLevels; i++)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+ #else
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
+ mi = mi + mi + bit;
+ symbol |= (bit << i);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ int bit;
+ int matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ #ifdef _LZMA_LOC_OPT
+ {
+ CProb *prob = probs + 0x100 + (matchBit << 8) + symbol;
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+ }
+ #else
+ bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd);
+ symbol = (symbol << 1) | bit;
+ #endif
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+ return RangeDecoderBitTreeDecode(p + LenLow +
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
+ return kLenNumLowSymbols + kLenNumMidSymbols +
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+ CRangeDecoder rd;
+
+ #ifdef _LZMA_OUT_READ
+
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ rd.Range = vs->Range;
+ rd.Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ rd.InCallback = InCallback;
+ rd.Buffer = vs->Buffer;
+ rd.BufferLim = vs->BufferLim;
+ #else
+ rd.Buffer = inStream;
+ rd.BufferLim = inStream + inSize;
+ #endif
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ RangeDecoderInit(&rd
+ #ifndef _LZMA_IN_CB
+ , inStream, inSize
+ #endif
+ );
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #ifdef _LZMA_IN_CB
+ rd.Result = LZMA_RESULT_OK;
+ #endif
+ rd.ExtraBytes = 0;
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ rd.InCallback = InCallback;
+ #endif
+ RangeDecoderInit(&rd
+ #ifndef _LZMA_IN_CB
+ , inStream, inSize
+ #endif
+ );
+
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+
+ #endif /* _LZMA_OUT_READ */
+
+
+ while(nowPos < outSize)
+ {
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ Byte matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+ }
+ else
+ previousByte = LzmaLiteralDecode(probs, &rd);
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+ {
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+ {
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < 7 ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+ distance = rep1;
+ else
+ {
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+ state = state < 7 ? 8 : 11;
+ }
+ else
+ {
+ int posSlot;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < 7 ? 7 : 10;
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 += RangeDecoderReverseBitTreeDecode(
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+ }
+ else
+ {
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = rd.Range;
+ vs->Code = rd.Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = rd.Buffer;
+ vs->BufferLim = rd.BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(rd.Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/C/Compress/Lzma/LzmaStateDecode.c b/C/Compress/Lzma/LzmaStateDecode.c
new file mode 100755
index 00000000..e50f88b5
--- /dev/null
+++ b/C/Compress/Lzma/LzmaStateDecode.c
@@ -0,0 +1,521 @@
+/*
+ LzmaStateDecode.c
+ LZMA Decoder (State version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaStateDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }}
+
+#define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+/* kRequiredInBufferSize = number of required input bytes for worst case:
+ longest match with longest distance.
+ kLzmaInBufferSize must be larger than kRequiredInBufferSize
+ 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE)
+*/
+
+#define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8)
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ return LZMA_RESULT_OK;
+ }
+}
+
+int LzmaDecode(
+ CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+ int finishDecoding)
+{
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+
+ unsigned char *Buffer = vs->Buffer;
+ int BufferSize = vs->BufferSize; /* don't change it to unsigned int */
+ CProb *p = vs->Probs;
+
+ int state = vs->State;
+ unsigned char previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ SizeT nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ unsigned char *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ unsigned char tempDictionary[4];
+
+ (*inSizeProcessed) = 0;
+ (*outSizeProcessed) = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+ {
+ Buffer[BufferSize++] = *inStream++;
+ (*inSizeProcessed)++;
+ inSize--;
+ }
+ if (BufferSize < 5)
+ {
+ vs->BufferSize = BufferSize;
+ return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK;
+ }
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ RC_INIT;
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ while(1)
+ {
+ int bufferPos = (int)(Buffer - vs->Buffer);
+ if (BufferSize - bufferPos < kRequiredInBufferSize)
+ {
+ int i;
+ BufferSize -= bufferPos;
+ if (BufferSize < 0)
+ return LZMA_RESULT_DATA_ERROR;
+ for (i = 0; i < BufferSize; i++)
+ vs->Buffer[i] = Buffer[i];
+ Buffer = vs->Buffer;
+ while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+ {
+ Buffer[BufferSize++] = *inStream++;
+ (*inSizeProcessed)++;
+ inSize--;
+ }
+ if (BufferSize < kRequiredInBufferSize && !finishDecoding)
+ break;
+ }
+ if (nowPos >= outSize)
+ break;
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)((nowPos + globalPos) & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (unsigned char)symbol;
+
+ outStream[nowPos++] = previousByte;
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ UInt32 pos;
+ UpdateBit0(prob);
+ if (distanceLimit == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ state = state < kNumLitStates ? 9 : 11;
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ if (rep0 > distanceLimit)
+ return LZMA_RESULT_DATA_ERROR;
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+
+ do
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ }
+ RC_NORMALIZE;
+
+ BufferSize -= (int)(Buffer - vs->Buffer);
+ if (BufferSize < 0)
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ int i;
+ for (i = 0; i < BufferSize; i++)
+ vs->Buffer[i] = Buffer[i];
+ }
+ vs->BufferSize = BufferSize;
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = (UInt32)(globalPos + nowPos);
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+
+ (*outSizeProcessed) = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/C/Compress/Lzma/LzmaStateDecode.h b/C/Compress/Lzma/LzmaStateDecode.h
new file mode 100755
index 00000000..26490d61
--- /dev/null
+++ b/C/Compress/Lzma/LzmaStateDecode.h
@@ -0,0 +1,96 @@
+/*
+ LzmaStateDecode.h
+ LZMA Decoder interface (State version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMASTATEDECODE_H
+#define __LZMASTATEDECODE_H
+
+#include "LzmaTypes.h"
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ UInt32 DictionarySize;
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp)))
+
+#define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+ unsigned char *Dictionary;
+
+ unsigned char Buffer[kLzmaInBufferSize];
+ int BufferSize;
+
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen; /* -2: decoder needs internal initialization
+ -1: stream was finished,
+ 0: ok
+ > 0: need to write RemainLen bytes as match Reps[0],
+ */
+ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */
+} CLzmaDecoderState;
+
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; }
+
+/* LzmaDecode: decoding from input stream to output stream.
+ If finishDecoding != 0, then there are no more bytes in input stream
+ after inStream[inSize - 1]. */
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+ int finishDecoding);
+
+#endif
diff --git a/C/Compress/Lzma/LzmaStateTest.c b/C/Compress/Lzma/LzmaStateTest.c
new file mode 100755
index 00000000..5df4e438
--- /dev/null
+++ b/C/Compress/Lzma/LzmaStateTest.c
@@ -0,0 +1,195 @@
+/*
+LzmaStateTest.c
+Test application for LZMA Decoder (State version)
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-02)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "LzmaStateDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+#define kInBufferSize (1 << 15)
+#define kOutBufferSize (1 << 15)
+
+unsigned char g_InBuffer[kInBufferSize];
+unsigned char g_OutBuffer[kOutBufferSize];
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+ { return fread(data, 1, size, file); }
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+ { return (MyReadFile(file, data, size) == size); }
+
+int PrintError(char *buffer, const char *message)
+{
+ sprintf(buffer + strlen(buffer), "\nError: ");
+ sprintf(buffer + strlen(buffer), message);
+ return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+ /* We use two 32-bit integers to construct 64-bit integer for file size.
+ You can remove outSizeHigh, if you don't need >= 4GB supporting,
+ or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+ UInt32 outSize = 0;
+ UInt32 outSizeHigh = 0;
+
+ int waitEOS = 1;
+ /* waitEOS = 1, if there is no uncompressed size in headers,
+ so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+ int i;
+ int res = 0;
+ CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */
+ unsigned char properties[LZMA_PROPERTIES_SIZE];
+ SizeT inAvail = 0;
+ unsigned char *inBuffer = 0;
+
+ if (sizeof(UInt32) < 4)
+ return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+ /* Read LZMA properties for compressed stream */
+
+ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+ return PrintError(rs, kCantReadMessage);
+
+ /* Read uncompressed size */
+
+ for (i = 0; i < 8; i++)
+ {
+ unsigned char b;
+ if (!MyReadFileAndCheck(inFile, &b, 1))
+ return PrintError(rs, kCantReadMessage);
+ if (b != 0xFF)
+ waitEOS = 0;
+ if (i < 4)
+ outSize += (UInt32)(b) << (i * 8);
+ else
+ outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+ }
+
+ /* Decode LZMA properties and allocate memory */
+
+ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return PrintError(rs, "Incorrect stream properties");
+ state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (state.Probs == 0)
+ return PrintError(rs, kCantAllocateMessage);
+
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ {
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+ if (state.Dictionary == 0)
+ {
+ free(state.Probs);
+ return PrintError(rs, kCantAllocateMessage);
+ }
+ }
+
+ /* Decompress */
+
+ LzmaDecoderInit(&state);
+
+ do
+ {
+ SizeT inProcessed, outProcessed;
+ int finishDecoding;
+ UInt32 outAvail = kOutBufferSize;
+ if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+ outAvail = outSize;
+ if (inAvail == 0)
+ {
+ inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize);
+ inBuffer = g_InBuffer;
+ }
+ finishDecoding = (inAvail == 0);
+ res = LzmaDecode(&state,
+ inBuffer, inAvail, &inProcessed,
+ g_OutBuffer, outAvail, &outProcessed,
+ finishDecoding);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ break;
+ }
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+
+ if (outFile != 0)
+ if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed)
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ break;
+ }
+
+ if (outSize < outProcessed)
+ outSizeHigh--;
+ outSize -= (UInt32)outProcessed;
+ outSize &= 0xFFFFFFFF;
+
+ if (outProcessed == 0 && finishDecoding)
+ {
+ if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+ res = 1;
+ break;
+ }
+ }
+ while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
+
+ free(state.Dictionary);
+ free(state.Probs);
+ return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+ FILE *inFile = 0;
+ FILE *outFile = 0;
+ int res;
+
+ sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n");
+ if (numArgs < 2 || numArgs > 3)
+ {
+ sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
+ return 1;
+ }
+
+ inFile = fopen(args[1], "rb");
+ if (inFile == 0)
+ return PrintError(rs, "Can not open input file");
+
+ if (numArgs > 2)
+ {
+ outFile = fopen(args[2], "wb+");
+ if (outFile == 0)
+ return PrintError(rs, "Can not open output file");
+ }
+
+ res = main3(inFile, outFile, rs);
+
+ if (outFile != 0)
+ fclose(outFile);
+ fclose(inFile);
+ return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+ char rs[800] = { 0 };
+ int res = main2(numArgs, args, rs);
+ printf(rs);
+ return res;
+}
diff --git a/C/Compress/Lzma/LzmaTest.c b/C/Compress/Lzma/LzmaTest.c
new file mode 100755
index 00000000..f95a753b
--- /dev/null
+++ b/C/Compress/Lzma/LzmaTest.c
@@ -0,0 +1,342 @@
+/*
+LzmaTest.c
+Test application for LZMA Decoder
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-05)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "LzmaDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ return fread(data, 1, size, file);
+}
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+ { return (MyReadFile(file, data, size) == size);}
+
+size_t MyWriteFile(FILE *file, const void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ return fwrite(data, 1, size, file);
+}
+
+int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)
+ { return (MyWriteFile(file, data, size) == size); }
+
+#ifdef _LZMA_IN_CB
+#define kInBufferSize (1 << 15)
+typedef struct _CBuffer
+{
+ ILzmaInCallback InCallback;
+ FILE *File;
+ unsigned char Buffer[kInBufferSize];
+} CBuffer;
+
+int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
+{
+ CBuffer *b = (CBuffer *)object;
+ *buffer = b->Buffer;
+ *size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize);
+ return LZMA_RESULT_OK;
+}
+CBuffer g_InBuffer;
+
+#endif
+
+#ifdef _LZMA_OUT_READ
+#define kOutBufferSize (1 << 15)
+unsigned char g_OutBuffer[kOutBufferSize];
+#endif
+
+int PrintError(char *buffer, const char *message)
+{
+ sprintf(buffer + strlen(buffer), "\nError: ");
+ sprintf(buffer + strlen(buffer), message);
+ return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+ /* We use two 32-bit integers to construct 64-bit integer for file size.
+ You can remove outSizeHigh, if you don't need >= 4GB supporting,
+ or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+ UInt32 outSize = 0;
+ UInt32 outSizeHigh = 0;
+ #ifndef _LZMA_OUT_READ
+ SizeT outSizeFull;
+ unsigned char *outStream;
+ #endif
+
+ int waitEOS = 1;
+ /* waitEOS = 1, if there is no uncompressed size in headers,
+ so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+ #ifndef _LZMA_IN_CB
+ SizeT compressedSize;
+ unsigned char *inStream;
+ #endif
+
+ CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
+ unsigned char properties[LZMA_PROPERTIES_SIZE];
+
+ int res;
+
+ #ifdef _LZMA_IN_CB
+ g_InBuffer.File = inFile;
+ #endif
+
+ if (sizeof(UInt32) < 4)
+ return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+ #ifndef _LZMA_IN_CB
+ {
+ long length;
+ fseek(inFile, 0, SEEK_END);
+ length = ftell(inFile);
+ fseek(inFile, 0, SEEK_SET);
+ if ((long)(SizeT)length != length)
+ return PrintError(rs, "Too big compressed stream");
+ compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
+ }
+ #endif
+
+ /* Read LZMA properties for compressed stream */
+
+ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+ return PrintError(rs, kCantReadMessage);
+
+ /* Read uncompressed size */
+
+ {
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ unsigned char b;
+ if (!MyReadFileAndCheck(inFile, &b, 1))
+ return PrintError(rs, kCantReadMessage);
+ if (b != 0xFF)
+ waitEOS = 0;
+ if (i < 4)
+ outSize += (UInt32)(b) << (i * 8);
+ else
+ outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+ }
+
+ #ifndef _LZMA_OUT_READ
+ if (waitEOS)
+ return PrintError(rs, "Stream with EOS marker is not supported");
+ outSizeFull = (SizeT)outSize;
+ if (sizeof(SizeT) >= 8)
+ outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
+ else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
+ return PrintError(rs, "Too big uncompressed stream");
+ #endif
+ }
+
+ /* Decode LZMA properties and allocate memory */
+
+ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return PrintError(rs, "Incorrect stream properties");
+ state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+
+ #ifdef _LZMA_OUT_READ
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+ #else
+ if (outSizeFull == 0)
+ outStream = 0;
+ else
+ outStream = (unsigned char *)malloc(outSizeFull);
+ #endif
+
+ #ifndef _LZMA_IN_CB
+ if (compressedSize == 0)
+ inStream = 0;
+ else
+ inStream = (unsigned char *)malloc(compressedSize);
+ #endif
+
+ if (state.Probs == 0
+ #ifdef _LZMA_OUT_READ
+ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0)
+ #else
+ || (outStream == 0 && outSizeFull != 0)
+ #endif
+ #ifndef _LZMA_IN_CB
+ || (inStream == 0 && compressedSize != 0)
+ #endif
+ )
+ {
+ free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ free(state.Dictionary);
+ #else
+ free(outStream);
+ #endif
+ #ifndef _LZMA_IN_CB
+ free(inStream);
+ #endif
+ return PrintError(rs, kCantAllocateMessage);
+ }
+
+ /* Decompress */
+
+ #ifdef _LZMA_IN_CB
+ g_InBuffer.InCallback.Read = LzmaReadCompressed;
+ #else
+ if (!MyReadFileAndCheck(inFile, inStream, compressedSize))
+ return PrintError(rs, kCantReadMessage);
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inAvail = compressedSize;
+ const unsigned char *inBuffer = inStream;
+ #endif
+ LzmaDecoderInit(&state);
+ do
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inProcessed;
+ #endif
+ SizeT outProcessed;
+ SizeT outAvail = kOutBufferSize;
+ if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+ outAvail = (SizeT)outSize;
+ res = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &g_InBuffer.InCallback,
+ #else
+ inBuffer, inAvail, &inProcessed,
+ #endif
+ g_OutBuffer, outAvail, &outProcessed);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ break;
+ }
+ #ifndef _LZMA_IN_CB
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+ #endif
+
+ if (outFile != 0)
+ if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed))
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ break;
+ }
+
+ if (outSize < outProcessed)
+ outSizeHigh--;
+ outSize -= (UInt32)outProcessed;
+ outSize &= 0xFFFFFFFF;
+
+ if (outProcessed == 0)
+ {
+ if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+ res = 1;
+ break;
+ }
+ }
+ while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
+ }
+
+ #else
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inProcessed;
+ #endif
+ SizeT outProcessed;
+ res = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &g_InBuffer.InCallback,
+ #else
+ inStream, compressedSize, &inProcessed,
+ #endif
+ outStream, outSizeFull, &outProcessed);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ }
+ else if (outFile != 0)
+ {
+ if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed))
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ }
+ }
+ }
+ #endif
+
+ free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ free(state.Dictionary);
+ #else
+ free(outStream);
+ #endif
+ #ifndef _LZMA_IN_CB
+ free(inStream);
+ #endif
+ return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+ FILE *inFile = 0;
+ FILE *outFile = 0;
+ int res;
+
+ sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n");
+ if (numArgs < 2 || numArgs > 3)
+ {
+ sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
+ return 1;
+ }
+
+ inFile = fopen(args[1], "rb");
+ if (inFile == 0)
+ return PrintError(rs, "Can not open input file");
+
+ if (numArgs > 2)
+ {
+ outFile = fopen(args[2], "wb+");
+ if (outFile == 0)
+ return PrintError(rs, "Can not open output file");
+ }
+
+ res = main3(inFile, outFile, rs);
+
+ if (outFile != 0)
+ fclose(outFile);
+ fclose(inFile);
+ return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+ char rs[800] = { 0 };
+ int res = main2(numArgs, args, rs);
+ printf(rs);
+ return res;
+}
diff --git a/C/Compress/Lzma/LzmaTypes.h b/C/Compress/Lzma/LzmaTypes.h
new file mode 100755
index 00000000..288c5e45
--- /dev/null
+++ b/C/Compress/Lzma/LzmaTypes.h
@@ -0,0 +1,45 @@
+/*
+LzmaTypes.h
+
+Types for LZMA Decoder
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.40 (2006-05-01)
+*/
+
+#ifndef __LZMATYPES_H
+#define __LZMATYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif
+
+/* #define _LZMA_SYSTEM_SIZE_T */
+/* Use system's size_t. You can use it to enable 64-bit sizes supporting */
+
+#ifndef _7ZIP_SIZET_DEFINED
+#define _7ZIP_SIZET_DEFINED
+#ifdef _LZMA_SYSTEM_SIZE_T
+#include <stddef.h>
+typedef size_t SizeT;
+#else
+typedef UInt32 SizeT;
+#endif
+#endif
+
+#endif
diff --git a/C/IStream.h b/C/IStream.h
new file mode 100755
index 00000000..29c46f5f
--- /dev/null
+++ b/C/IStream.h
@@ -0,0 +1,19 @@
+// IStream.h
+
+#ifndef __C_ISTREAM_H
+#define __C_ISTREAM_H
+
+#include "Types.h"
+
+typedef struct _ISeqInStream
+{
+ HRes (*Read)(void *object, void *data, UInt32 size, UInt32 *processedSize);
+} ISeqInStream;
+
+typedef struct _ISzAlloc
+{
+ void *(*Alloc)(size_t size);
+ void (*Free)(void *address); /* address can be 0 */
+} ISzAlloc;
+
+#endif
diff --git a/C/Sort.c b/C/Sort.c
new file mode 100755
index 00000000..b30cd6ab
--- /dev/null
+++ b/C/Sort.c
@@ -0,0 +1,92 @@
+/* Sort.c */
+
+#include "Sort.h"
+
+#define HeapSortDown(p, k, size, temp) \
+ { for (;;) { \
+ UInt32 s = (k << 1); \
+ if (s > size) break; \
+ if (s < size && p[s + 1] > p[s]) s++; \
+ if (temp >= p[s]) break; \
+ p[k] = p[s]; k = s; \
+ } p[k] = temp; }
+
+void HeapSort(UInt32 *p, UInt32 size)
+{
+ if (size <= 1)
+ return;
+ p--;
+ {
+ UInt32 i = size / 2;
+ do
+ {
+ UInt32 temp = p[i];
+ UInt32 k = i;
+ HeapSortDown(p, k, size, temp)
+ }
+ while(--i != 0);
+ }
+ /*
+ do
+ {
+ UInt32 k = 1;
+ UInt32 temp = p[size];
+ p[size--] = p[1];
+ HeapSortDown(p, k, size, temp)
+ }
+ while (size > 1);
+ */
+ while (size > 3)
+ {
+ UInt32 temp = p[size];
+ UInt32 k = (p[3] > p[2]) ? 3 : 2;
+ p[size--] = p[1];
+ p[1] = p[k];
+ HeapSortDown(p, k, size, temp)
+ }
+ {
+ UInt32 temp = p[size];
+ p[size] = p[1];
+ if (size > 2 && p[2] < temp)
+ {
+ p[1] = p[2];
+ p[2] = temp;
+ }
+ else
+ p[1] = temp;
+ }
+}
+
+/*
+#define HeapSortRefDown(p, vals, n, size, temp) \
+ { UInt32 k = n; UInt32 val = vals[temp]; for (;;) { \
+ UInt32 s = (k << 1); \
+ if (s > size) break; \
+ if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \
+ if (val >= vals[p[s]]) break; \
+ p[k] = p[s]; k = s; \
+ } p[k] = temp; }
+
+void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size)
+{
+ if (size <= 1)
+ return;
+ p--;
+ {
+ UInt32 i = size / 2;
+ do
+ {
+ UInt32 temp = p[i];
+ HeapSortRefDown(p, vals, i, size, temp);
+ }
+ while(--i != 0);
+ }
+ do
+ {
+ UInt32 temp = p[size];
+ p[size--] = p[1];
+ HeapSortRefDown(p, vals, 1, size, temp);
+ }
+ while (size > 1);
+}
+*/ \ No newline at end of file
diff --git a/C/Sort.h b/C/Sort.h
new file mode 100755
index 00000000..896243c1
--- /dev/null
+++ b/C/Sort.h
@@ -0,0 +1,11 @@
+/* Sort.h */
+
+#ifndef __7Z_Sort_H
+#define __7Z_Sort_H
+
+#include "Types.h"
+
+void HeapSort(UInt32 *p, UInt32 size);
+/* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */
+
+#endif
diff --git a/C/Threads.c b/C/Threads.c
new file mode 100755
index 00000000..dcf63dcf
--- /dev/null
+++ b/C/Threads.c
@@ -0,0 +1,97 @@
+/* Threads.c */
+
+#include "Threads.h"
+#include <process.h>
+
+HRes GetError()
+{
+ DWORD res = GetLastError();
+ return (res) ? (HRes)(res) : SZE_FAIL;
+}
+
+HRes BoolToHRes(int v) { return v ? SZ_OK : GetError(); }
+HRes BOOLToHRes(BOOL v) { return v ? SZ_OK : GetError(); }
+
+HRes MyCloseHandle(HANDLE *h)
+{
+ if (*h != NULL)
+ if (!CloseHandle(*h))
+ return GetError();
+ *h = NULL;
+ return SZ_OK;
+}
+
+HRes Thread_Create(CThread *thread, unsigned (StdCall *startAddress)(void *), LPVOID parameter)
+{
+ /* DWORD threadId; */
+ thread->handle =
+ /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */
+ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, NULL);
+ /* maybe we must use errno here, but probably GetLastError() is also OK. */
+ return BoolToHRes(thread->handle != 0);
+}
+
+HRes WaitObject(HANDLE h)
+{
+ return (HRes)WaitForSingleObject(h, INFINITE);
+}
+
+HRes Thread_Wait(CThread *thread)
+{
+ if (thread->handle == NULL)
+ return 1;
+ return WaitObject(thread->handle);
+}
+
+HRes Thread_Close(CThread *thread)
+{
+ return MyCloseHandle(&thread->handle);
+}
+
+HRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled)
+{
+ p->handle = CreateEvent(NULL, FALSE, (initialSignaled ? TRUE : FALSE), NULL);
+ return BoolToHRes(p->handle != 0);
+}
+
+HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }
+HRes Event_Set(CEvent *p) { return BOOLToHRes(SetEvent(p->handle)); }
+HRes Event_Reset(CEvent *p) { return BOOLToHRes(ResetEvent(p->handle)); }
+HRes Event_Wait(CEvent *p) { return WaitObject(p->handle); }
+HRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); }
+
+
+HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount)
+{
+ p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL);
+ return BoolToHRes(p->handle != 0);
+}
+
+HRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
+{
+ return BOOLToHRes(ReleaseSemaphore(p->handle, releaseCount, previousCount));
+}
+HRes Semaphore_ReleaseN(CSemaphore *p, LONG releaseCount)
+{
+ return Semaphore_Release(p, releaseCount, NULL);
+}
+HRes Semaphore_Release1(CSemaphore *p)
+{
+ return Semaphore_ReleaseN(p, 1);
+}
+
+HRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); }
+HRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); }
+
+HRes CriticalSection_Init(CCriticalSection *p)
+{
+ /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
+ __try
+ {
+ InitializeCriticalSection(p);
+ // InitializeCriticalSectionAndSpinCount(p, 0);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) { return SZE_OUTOFMEMORY; }
+ return SZ_OK;
+}
+
diff --git a/C/Threads.h b/C/Threads.h
new file mode 100755
index 00000000..fec9e6d5
--- /dev/null
+++ b/C/Threads.h
@@ -0,0 +1,60 @@
+/* Thresds.h */
+
+#ifndef __7Z_THRESDS_H
+#define __7Z_THRESDS_H
+
+#include <windows.h>
+
+#include "Types.h"
+
+typedef struct _CThread
+{
+ HANDLE handle;
+} CThread;
+
+#define Thread_Construct(thread) (thread)->handle = NULL
+#define Thread_WasCreated(thread) ((thread)->handle != NULL)
+
+HRes Thread_Create(CThread *thread, unsigned (StdCall *startAddress)(void *), LPVOID parameter);
+HRes Thread_Wait(CThread *thread);
+HRes Thread_Close(CThread *thread);
+
+typedef struct _CEvent
+{
+ HANDLE handle;
+} CEvent;
+
+typedef CEvent CAutoResetEvent;
+
+#define Event_Construct(event) (event)->handle = NULL
+
+HRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled);
+HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event);
+HRes Event_Set(CEvent *event);
+HRes Event_Reset(CEvent *event);
+HRes Event_Wait(CEvent *event);
+HRes Event_Close(CEvent *event);
+
+
+typedef struct _CSemaphore
+{
+ HANDLE handle;
+} CSemaphore;
+
+#define Semaphore_Construct(p) (p)->handle = NULL
+
+HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount);
+HRes Semaphore_Release1(CSemaphore *p);
+HRes Semaphore_Wait(CSemaphore *p);
+HRes Semaphore_Close(CSemaphore *p);
+
+
+typedef CRITICAL_SECTION CCriticalSection;
+
+HRes CriticalSection_Init(CCriticalSection *p);
+#define CriticalSection_Delete(p) DeleteCriticalSection(p)
+#define CriticalSection_Enter(p) EnterCriticalSection(p)
+#define CriticalSection_Leave(p) LeaveCriticalSection(p)
+
+#endif
+
diff --git a/C/Types.h b/C/Types.h
new file mode 100755
index 00000000..9052a030
--- /dev/null
+++ b/C/Types.h
@@ -0,0 +1,92 @@
+/* 7zTypes.h */
+
+#ifndef __C_TYPES_H
+#define __C_TYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif
+
+#ifndef _7ZIP_INT32_DEFINED
+#define _7ZIP_INT32_DEFINED
+#ifdef _LZMA_INT32_IS_ULONG
+typedef long Int32;
+#else
+typedef int Int32;
+#endif
+#endif
+
+/* #define _SZ_NO_INT_64 */
+/* define it your compiler doesn't support long long int */
+
+#ifndef _7ZIP_UINT64_DEFINED
+#define _7ZIP_UINT64_DEFINED
+#ifdef _SZ_NO_INT_64
+typedef unsigned long UInt64;
+#else
+#ifdef _MSC_VER
+typedef unsigned __int64 UInt64;
+#else
+typedef unsigned long long int UInt64;
+#endif
+#endif
+#endif
+
+
+/* #define _SZ_FILE_SIZE_64 */
+/* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/
+
+#ifndef CFileSize
+#ifdef _SZ_FILE_SIZE_64
+typedef UInt64 CFileSize;
+#else
+typedef UInt32 CFileSize;
+#endif
+#endif
+
+#define SZ_RESULT int
+
+typedef int HRes;
+#define RES_OK (0)
+
+#define SZ_OK (0)
+#define SZE_DATA_ERROR (1)
+#define SZE_CRC_ERROR (3)
+#define SZE_ARCHIVE_ERROR (6)
+
+#define SZE_OUTOFMEMORY (0x8007000EL)
+#define SZE_NOTIMPL (0x80004001L)
+#define SZE_FAIL (0x80004005L)
+#define SZE_INVALIDARG (0x80070057L)
+
+
+#ifndef RINOK
+#define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; }
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+#ifdef _MSC_VER
+#define StdCall __stdcall
+#else
+#define StdCall
+#endif
+
+#endif