Lightly modified commit of lzma sdk version 9.20.

The only change from stock lzma sdk is the removal of two
.exe files, which we don't need.

Change-Id: I46287cbc416161e93b449761ebe531acd758cf95
diff --git a/7zC.txt b/7zC.txt
new file mode 100755
index 0000000..4ff6325
--- /dev/null
+++ b/7zC.txt
@@ -0,0 +1,194 @@
+7z ANSI-C Decoder 4.62

+----------------------

+

+7z ANSI-C provides 7z/LZMA decoding.

+7z ANSI-C version is simplified version ported from C++ code.

+

+LZMA is default and general compression method of 7z format

+in 7-Zip compression program (www.7-zip.org). LZMA provides high 

+compression ratio and very fast decompression.

+

+

+LICENSE

+-------

+

+7z ANSI-C Decoder is part of the LZMA SDK.

+LZMA SDK is written and placed in the public domain by Igor Pavlov.

+

+Files

+---------------------

+

+7zDecode.*   - Low level 7z decoding

+7zExtract.*  - High level 7z decoding

+7zHeader.*   - .7z format constants

+7zIn.*       - .7z archive opening

+7zItem.*     - .7z structures

+7zMain.c     - Test application

+

+

+How To Use

+----------

+

+You must download 7-Zip program from www.7-zip.org.

+

+You can create .7z archive with 7z.exe or 7za.exe:

+

+  7za.exe a archive.7z *.htm -r -mx -m0fb=255

+

+If you have big number of files in archive, and you need fast extracting, 

+you can use partly-solid archives:

+  

+  7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K

+

+In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 

+512KB for extracting one file from such archive.

+

+

+Limitations of current version of 7z ANSI-C Decoder

+---------------------------------------------------

+

+ - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive.

+ - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters.

+ - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.

+ 

+These limitations will be fixed in future versions.

+

+

+Using 7z ANSI-C Decoder Test application:

+-----------------------------------------

+

+Usage: 7zDec <command> <archive_name>

+

+<Command>:

+  e: Extract files from archive

+  l: List contents of archive

+  t: Test integrity of archive

+

+Example: 

+

+  7zDec l archive.7z

+

+lists contents of archive.7z

+

+  7zDec e archive.7z

+

+extracts files from archive.7z to current folder.

+

+

+How to use .7z Decoder

+----------------------

+

+Memory allocation

+~~~~~~~~~~~~~~~~~

+

+7z Decoder uses two memory pools:

+1) Temporary pool

+2) Main pool

+Such scheme can allow you to avoid fragmentation of allocated blocks.

+

+

+Steps for using 7z decoder

+--------------------------

+

+Use code at 7zMain.c as example.

+

+1) Declare variables:

+  inStream                 /* implements ILookInStream interface */

+  CSzArEx db;              /* 7z archive database structure */

+  ISzAlloc allocImp;       /* memory functions for main pool */

+  ISzAlloc allocTempImp;   /* memory functions for temporary pool */

+

+2) call CrcGenerateTable(); function to initialize CRC structures.

+

+3) call SzArEx_Init(&db); function to initialize db structures.

+

+4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive

+

+This function opens archive "inStream" and reads headers to "db".

+All items in "db" will be allocated with "allocMain" functions.

+SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions.

+

+5) List items or Extract items

+

+  Listing code:

+  ~~~~~~~~~~~~~

+    {

+      UInt32 i;

+      for (i = 0; i < db.db.NumFiles; i++)

+      {

+        CFileItem *f = db.db.Files + i;

+        printf("%10d  %s\n", (int)f->Size, f->Name);

+      }

+    }

+

+  Extracting code:

+  ~~~~~~~~~~~~~~~~

+

+  SZ_RESULT SzAr_Extract(

+    CArchiveDatabaseEx *db,

+    ILookInStream *inStream, 

+    UInt32 fileIndex,         /* index of file */

+    UInt32 *blockIndex,       /* index of solid block */

+    Byte **outBuffer,         /* pointer to pointer to output buffer (allocated with allocMain) */

+    size_t *outBufferSize,    /* buffer size for output buffer */

+    size_t *offset,           /* offset of stream for required file in *outBuffer */

+    size_t *outSizeProcessed, /* size of file in *outBuffer */

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp);

+

+  If you need to decompress more than one file, you can send these values from previous call:

+    blockIndex, 

+    outBuffer, 

+    outBufferSize,

+  You can consider "outBuffer" as cache of solid block. If your archive is solid, 

+  it will increase decompression speed.

+

+  After decompressing you must free "outBuffer":

+  allocImp.Free(outBuffer);

+

+6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db".

+

+

+

+

+Memory requirements for .7z decoding 

+------------------------------------

+

+Memory usage for Archive opening:

+  - Temporary pool:

+     - Memory for uncompressed .7z headers

+     - some other temporary blocks

+  - Main pool:

+     - Memory for database: 

+       Estimated size of one file structures in solid archive:

+         - Size (4 or 8 Bytes)

+         - CRC32 (4 bytes)

+         - LastWriteTime (8 bytes)

+         - Some file information (4 bytes)

+         - File Name (variable length) + pointer + allocation structures

+

+Memory usage for archive Decompressing:

+  - Temporary pool:

+     - Memory for LZMA decompressing structures

+  - Main pool:

+     - Memory for decompressed solid block

+     - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these 

+       temprorary buffers can be about 15% of solid block size. 

+  

+

+7z Decoder doesn't allocate memory for compressed blocks. 

+Instead of this, you must allocate buffer with desired 

+size before calling 7z Decoder. Use 7zMain.c as example.

+

+

+Defines

+-------

+

+_SZ_ALLOC_DEBUG   - define it if you want to debug alloc/free operations to stderr.

+

+

+---

+

+http://www.7-zip.org

+http://www.7-zip.org/sdk.html

+http://www.7-zip.org/support.html

diff --git a/7zFormat.txt b/7zFormat.txt
new file mode 100755
index 0000000..f084c05
--- /dev/null
+++ b/7zFormat.txt
@@ -0,0 +1,471 @@
+7z Format description (2.30 Beta 25)

+-----------------------------------

+

+This file contains description of 7z archive format. 

+7z archive can contain files compressed with any method.

+See "Methods.txt" for description for defined compressing methods.

+

+

+Format structure Overview

+-------------------------

+

+Some fields can be optional.

+

+Archive structure

+~~~~~~~~~~~~~~~~~  

+SignatureHeader

+[PackedStreams]

+[PackedStreamsForHeaders]

+[

+  Header 

+  or 

+  {

+    Packed Header

+    HeaderInfo

+  }

+]

+

+

+

+Header structure

+~~~~~~~~~~~~~~~~  

+{

+  ArchiveProperties

+  AdditionalStreams

+  {

+    PackInfo

+    {

+      PackPos

+      NumPackStreams

+      Sizes[NumPackStreams]

+      CRCs[NumPackStreams]

+    }

+    CodersInfo

+    {

+      NumFolders

+      Folders[NumFolders]

+      {

+        NumCoders

+        CodersInfo[NumCoders]

+        {

+          ID

+          NumInStreams;

+          NumOutStreams;

+          PropertiesSize

+          Properties[PropertiesSize]

+        }

+        NumBindPairs

+        BindPairsInfo[NumBindPairs]

+        {

+          InIndex;

+          OutIndex;

+        }

+        PackedIndices

+      }

+      UnPackSize[Folders][Folders.NumOutstreams]

+      CRCs[NumFolders]

+    }

+    SubStreamsInfo

+    {

+      NumUnPackStreamsInFolders[NumFolders];

+      UnPackSizes[]

+      CRCs[]

+    }

+  }

+  MainStreamsInfo

+  {

+    (Same as in AdditionalStreams)

+  }

+  FilesInfo

+  {

+    NumFiles

+    Properties[]

+    {

+      ID

+      Size

+      Data

+    }

+  }

+}

+

+HeaderInfo structure

+~~~~~~~~~~~~~~~~~~~~

+{

+  (Same as in AdditionalStreams)

+}

+

+

+

+Notes about Notation and encoding

+---------------------------------

+

+7z uses little endian encoding.

+

+7z archive format has optional headers that are marked as

+[]

+Header

+[]

+

+REAL_UINT64 means real UINT64.

+

+UINT64 means real UINT64 encoded with the following scheme:

+

+  Size of encoding sequence depends from first byte:

+  First_Byte  Extra_Bytes        Value

+  (binary)   

+  0xxxxxxx               : ( xxxxxxx           )

+  10xxxxxx    BYTE y[1]  : (  xxxxxx << (8 * 1)) + y

+  110xxxxx    BYTE y[2]  : (   xxxxx << (8 * 2)) + y

+  ...

+  1111110x    BYTE y[6]  : (       x << (8 * 6)) + y

+  11111110    BYTE y[7]  :                         y

+  11111111    BYTE y[8]  :                         y

+

+

+

+Property IDs

+------------

+

+0x00 = kEnd,

+

+0x01 = kHeader,

+

+0x02 = kArchiveProperties,

+    

+0x03 = kAdditionalStreamsInfo,

+0x04 = kMainStreamsInfo,

+0x05 = kFilesInfo,

+    

+0x06 = kPackInfo,

+0x07 = kUnPackInfo,

+0x08 = kSubStreamsInfo,

+

+0x09 = kSize,

+0x0A = kCRC,

+

+0x0B = kFolder,

+

+0x0C = kCodersUnPackSize,

+0x0D = kNumUnPackStream,

+

+0x0E = kEmptyStream,

+0x0F = kEmptyFile,

+0x10 = kAnti,

+

+0x11 = kName,

+0x12 = kCreationTime,

+0x13 = kLastAccessTime,

+0x14 = kLastWriteTime,

+0x15 = kWinAttributes,

+0x16 = kComment,

+

+0x17 = kEncodedHeader,

+

+

+7z format headers

+-----------------

+

+SignatureHeader

+~~~~~~~~~~~~~~~

+  BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

+

+  ArchiveVersion

+  {

+    BYTE Major;   // now = 0

+    BYTE Minor;   // now = 2

+  };

+

+  UINT32 StartHeaderCRC;

+

+  StartHeader

+  {

+    REAL_UINT64 NextHeaderOffset

+    REAL_UINT64 NextHeaderSize

+    UINT32 NextHeaderCRC

+  }

+

+

+...........................

+

+

+ArchiveProperties

+~~~~~~~~~~~~~~~~~

+BYTE NID::kArchiveProperties (0x02)

+for (;;)

+{

+  BYTE PropertyType;

+  if (aType == 0)

+    break;

+  UINT64 PropertySize;

+  BYTE PropertyData[PropertySize];

+}

+

+

+Digests (NumStreams)

+~~~~~~~~~~~~~~~~~~~~~

+  BYTE AllAreDefined

+  if (AllAreDefined == 0)

+  {

+    for(NumStreams)

+      BIT Defined

+  }

+  UINT32 CRCs[NumDefined]

+

+

+PackInfo

+~~~~~~~~~~~~

+  BYTE NID::kPackInfo  (0x06)

+  UINT64 PackPos

+  UINT64 NumPackStreams

+

+  []

+  BYTE NID::kSize    (0x09)

+  UINT64 PackSizes[NumPackStreams]

+  []

+

+  []

+  BYTE NID::kCRC      (0x0A)

+  PackStreamDigests[NumPackStreams]

+  []

+

+  BYTE NID::kEnd

+

+

+Folder

+~~~~~~

+  UINT64 NumCoders;

+  for (NumCoders)

+  {

+    BYTE 

+    {

+      0:3 DecompressionMethod.IDSize

+      4:

+        0 - IsSimple

+        1 - Is not simple

+      5:

+        0 - No Attributes

+        1 - There Are Attributes

+      7:

+        0 - Last Method in Alternative_Method_List

+        1 - There are more alternative methods

+    } 

+    BYTE DecompressionMethod.ID[DecompressionMethod.IDSize]

+    if (!IsSimple)

+    {

+      UINT64 NumInStreams;

+      UINT64 NumOutStreams;

+    }

+    if (DecompressionMethod[0] != 0)

+    {

+      UINT64 PropertiesSize

+      BYTE Properties[PropertiesSize]

+    }

+  }

+    

+  NumBindPairs = NumOutStreamsTotal - 1;

+

+  for (NumBindPairs)

+  {

+    UINT64 InIndex;

+    UINT64 OutIndex;

+  }

+

+  NumPackedStreams = NumInStreamsTotal - NumBindPairs;

+  if (NumPackedStreams > 1)

+    for(NumPackedStreams)

+    {

+      UINT64 Index;

+    };

+

+

+

+

+Coders Info

+~~~~~~~~~~~

+

+  BYTE NID::kUnPackInfo  (0x07)

+

+

+  BYTE NID::kFolder  (0x0B)

+  UINT64 NumFolders

+  BYTE External

+  switch(External)

+  {

+    case 0:

+      Folders[NumFolders]

+    case 1:

+      UINT64 DataStreamIndex

+  }

+

+

+  BYTE ID::kCodersUnPackSize  (0x0C)

+  for(Folders)

+    for(Folder.NumOutStreams)

+     UINT64 UnPackSize;

+

+

+  []

+  BYTE NID::kCRC   (0x0A)

+  UnPackDigests[NumFolders]

+  []

+

+  

+

+  BYTE NID::kEnd

+

+

+

+SubStreams Info

+~~~~~~~~~~~~~~

+  BYTE NID::kSubStreamsInfo; (0x08)

+

+  []

+  BYTE NID::kNumUnPackStream; (0x0D)

+  UINT64 NumUnPackStreamsInFolders[NumFolders];

+  []

+

+

+  []

+  BYTE NID::kSize  (0x09)

+  UINT64 UnPackSizes[]

+  []

+

+

+  []

+  BYTE NID::kCRC  (0x0A)

+  Digests[Number of streams with unknown CRC]

+  []

+

+  

+  BYTE NID::kEnd

+

+

+Streams Info

+~~~~~~~~~~~~

+

+  []

+  PackInfo

+  []

+

+

+  []

+  CodersInfo

+  []

+

+

+  []

+  SubStreamsInfo

+  []

+

+  BYTE NID::kEnd

+

+

+FilesInfo

+~~~~~~~~~

+  BYTE NID::kFilesInfo;  (0x05)

+  UINT64 NumFiles

+

+  for (;;)

+  {

+    BYTE PropertyType;

+    if (aType == 0)

+      break;

+

+    UINT64 Size;

+

+    switch(PropertyType)

+    {

+      kEmptyStream:   (0x0E)

+        for(NumFiles)

+          BIT IsEmptyStream

+

+      kEmptyFile:     (0x0F)

+        for(EmptyStreams)

+          BIT IsEmptyFile

+

+      kAnti:          (0x10)

+        for(EmptyStreams)

+          BIT IsAntiFile

+      

+      case kCreationTime:   (0x12)

+      case kLastAccessTime: (0x13)

+      case kLastWriteTime:  (0x14)

+        BYTE AllAreDefined

+        if (AllAreDefined == 0)

+        {

+          for(NumFiles)

+            BIT TimeDefined

+        }

+        BYTE External;

+        if(External != 0)

+          UINT64 DataIndex

+        []

+        for(Definded Items)

+          UINT32 Time

+        []

+      

+      kNames:     (0x11)

+        BYTE External;

+        if(External != 0)

+          UINT64 DataIndex

+        []

+        for(Files)

+        {

+          wchar_t Names[NameSize];

+          wchar_t 0;

+        }

+        []

+

+      kAttributes:  (0x15)

+        BYTE AllAreDefined

+        if (AllAreDefined == 0)

+        {

+          for(NumFiles)

+            BIT AttributesAreDefined

+        }

+        BYTE External;

+        if(External != 0)

+          UINT64 DataIndex

+        []

+        for(Definded Attributes)

+          UINT32 Attributes

+        []

+    }

+  }

+

+

+Header

+~~~~~~

+  BYTE NID::kHeader (0x01)

+

+  []

+  ArchiveProperties

+  []

+

+  []

+  BYTE NID::kAdditionalStreamsInfo; (0x03)

+  StreamsInfo

+  []

+

+  []

+  BYTE NID::kMainStreamsInfo;    (0x04)

+  StreamsInfo

+  []

+

+  []

+  FilesInfo

+  []

+

+  BYTE NID::kEnd

+

+

+HeaderInfo

+~~~~~~~~~~

+  []

+  BYTE NID::kEncodedHeader; (0x17)

+  StreamsInfo for Encoded Header

+  []

+

+

+---

+End of document

diff --git a/Asm/arm/7zCrcOpt.asm b/Asm/arm/7zCrcOpt.asm
new file mode 100755
index 0000000..f008d65
--- /dev/null
+++ b/Asm/arm/7zCrcOpt.asm
@@ -0,0 +1,100 @@
+	CODE32

+

+	EXPORT	|CrcUpdateT4@16|

+

+	AREA	|.text|, CODE, ARM

+

+	MACRO

+	CRC32_STEP_1

+

+	ldrb    r4, [r1], #1

+	subs    r2, r2, #1

+	eor     r4, r4, r0

+	and     r4, r4, #0xFF

+	ldr     r4, [r3, +r4, lsl #2]

+	eor     r0, r4, r0, lsr #8

+

+	MEND

+

+

+	MACRO

+	CRC32_STEP_4 $STREAM_WORD

+	

+	eor     r7, r7, r8

+	eor     r7, r7, r9

+	eor     r0, r0, r7

+	eor     r0, r0, $STREAM_WORD

+	ldr     $STREAM_WORD, [r1], #4

+	

+	and     r7, r0, #0xFF

+	and     r8, r0, #0xFF00

+	and     r9, r0, #0xFF0000

+	and     r0, r0, #0xFF000000

+

+	ldr     r7, [r6, +r7, lsl #2]

+	ldr     r8, [r5, +r8, lsr #6]

+	ldr     r9, [r4, +r9, lsr #14]

+	ldr     r0, [r3, +r0, lsr #22]

+	

+	MEND

+

+

+|CrcUpdateT4@16| PROC

+

+	stmdb   sp!, {r4-r11, lr}

+	cmp     r2, #0

+	beq     |$fin|

+

+|$v1|

+	tst     r1, #7

+	beq     |$v2|

+	CRC32_STEP_1

+	bne     |$v1|

+

+|$v2|

+	cmp     r2, #16

+	blo     |$v3|

+

+	ldr     r10, [r1], #4

+	ldr     r11, [r1], #4

+

+	add     r4, r3, #0x400 

+	add     r5, r3, #0x800

+	add     r6, r3, #0xC00

+

+	mov     r7, #0

+	mov     r8, #0

+	mov     r9, #0

+

+	sub     r2, r2, #16

+

+|$loop|

+	; pld     [r1, #0x40]

+

+	CRC32_STEP_4 r10

+	CRC32_STEP_4 r11

+

+	subs    r2, r2, #8

+	bhs     |$loop|

+

+	sub     r1, r1, #8

+	add     r2, r2, #16

+

+	eor     r7, r7, r8

+	eor     r7, r7, r9

+	eor     r0, r0, r7

+

+|$v3|

+	cmp     r2, #0

+	beq     |$fin|

+

+|$v4|

+	CRC32_STEP_1

+	bne     |$v4|

+

+|$fin|

+	ldmia   sp!, {r4-r11, pc}

+

+|CrcUpdateT4@16| ENDP

+

+	END

diff --git a/Asm/x86/7zAsm.asm b/Asm/x86/7zAsm.asm
new file mode 100755
index 0000000..5a5f271
--- /dev/null
+++ b/Asm/x86/7zAsm.asm
@@ -0,0 +1,93 @@
+; 7zAsm.asm -- ASM macros

+; 2009-12-12 : Igor Pavlov : Public domain

+

+MY_ASM_START macro

+  ifdef x64

+    .code

+  else

+    .386

+    .model flat

+    _TEXT$00 SEGMENT PARA PUBLIC 'CODE'

+  endif

+endm

+

+MY_PROC macro name:req, numParams:req

+  align 16

+  proc_numParams equ numParams

+  ifdef x64

+    proc_name equ name

+    name PROC

+  else

+    proc_fastcall_name equ @CatStr(@,name,@, %numParams * 4)

+    public proc_fastcall_name

+    proc_fastcall_name:

+  endif

+endm

+

+MY_ENDP macro

+  ifdef x64

+    ret

+    proc_name ENDP

+  else

+    ret (proc_numParams - 2) * 4

+  endif

+endm

+

+ifdef x64

+  REG_SIZE equ 8

+else

+  REG_SIZE equ 4

+endif

+

+  x0 equ EAX

+  x1 equ ECX

+  x2 equ EDX

+  x3 equ EBX

+  x4 equ ESP

+  x5 equ EBP

+  x6 equ ESI

+  x7 equ EDI

+

+  x0_L equ AL

+  x1_L equ CL

+  x2_L equ DL

+  x3_L equ BL

+

+  x0_H equ AH

+  x1_H equ CH

+  x2_H equ DH

+  x3_H equ BH

+

+ifdef x64

+  r0 equ RAX

+  r1 equ RCX

+  r2 equ RDX

+  r3 equ RBX

+  r4 equ RSP

+  r5 equ RBP

+  r6 equ RSI

+  r7 equ RDI

+else

+  r0 equ x0

+  r1 equ x1

+  r2 equ x2

+  r3 equ x3

+  r4 equ x4

+  r5 equ x5

+  r6 equ x6

+  r7 equ x7

+endif

+

+MY_PUSH_4_REGS macro

+    push    r3

+    push    r5

+    push    r6

+    push    r7

+endm

+

+MY_POP_4_REGS macro

+    pop     r7

+    pop     r6

+    pop     r5

+    pop     r3

+endm

diff --git a/Asm/x86/7zCrcOpt.asm b/Asm/x86/7zCrcOpt.asm
new file mode 100755
index 0000000..2de5171
--- /dev/null
+++ b/Asm/x86/7zCrcOpt.asm
@@ -0,0 +1,147 @@
+; 7zCrcOpt.asm -- CRC32 calculation : optimized version

+; 2009-12-12 : Igor Pavlov : Public domain

+

+include 7zAsm.asm

+

+MY_ASM_START

+

+rD   equ  r2

+rN   equ  r7

+

+ifdef x64

+    num_VAR     equ r8

+    table_VAR   equ r9

+else

+    data_size   equ (REG_SIZE * 5)

+    crc_table   equ (REG_SIZE + data_size)

+    num_VAR     equ [r4 + data_size]

+    table_VAR   equ [r4 + crc_table]

+endif

+

+SRCDAT  equ  rN + rD + 4 *

+

+CRC macro op:req, dest:req, src:req, t:req

+    op      dest, DWORD PTR [r5 + src * 4 + 0400h * t]

+endm

+

+CRC_XOR macro dest:req, src:req, t:req

+    CRC xor, dest, src, t

+endm

+

+CRC_MOV macro dest:req, src:req, t:req

+    CRC mov, dest, src, t

+endm

+

+CRC1b macro

+    movzx   x6, BYTE PTR [rD]

+    inc     rD

+    movzx   x3, x0_L

+    xor     x6, x3

+    shr     x0, 8

+    CRC     xor, x0, r6, 0

+    dec     rN

+endm

+

+MY_PROLOG macro crc_end:req

+    MY_PUSH_4_REGS

+    

+    mov     x0, x1

+    mov     rN, num_VAR

+    mov     r5, table_VAR

+    test    rN, rN

+    jz      crc_end

+  @@:

+    test    rD, 7

+    jz      @F

+    CRC1b

+    jnz     @B

+  @@:

+    cmp     rN, 16

+    jb      crc_end

+    add     rN, rD

+    mov     num_VAR, rN

+    sub     rN, 8

+    and     rN, NOT 7

+    sub     rD, rN

+    xor     x0, [SRCDAT 0]

+endm

+

+MY_EPILOG macro crc_end:req

+    xor     x0, [SRCDAT 0]

+    mov     rD, rN

+    mov     rN, num_VAR

+    sub     rN, rD

+  crc_end:

+    test    rN, rN

+    jz      @F

+    CRC1b

+    jmp     crc_end

+  @@:

+    MY_POP_4_REGS

+endm

+

+MY_PROC CrcUpdateT8, 4

+    MY_PROLOG crc_end_8

+    mov     x1, [SRCDAT 1]

+    align 16

+  main_loop_8:

+    mov     x6, [SRCDAT 2]

+    movzx   x3, x1_L

+    CRC_XOR x6, r3, 3

+    movzx   x3, x1_H

+    CRC_XOR x6, r3, 2

+    shr     x1, 16

+    movzx   x3, x1_L

+    movzx   x1, x1_H

+    CRC_XOR x6, r3, 1

+    movzx   x3, x0_L

+    CRC_XOR x6, r1, 0

+

+    mov     x1, [SRCDAT 3]

+    CRC_XOR x6, r3, 7

+    movzx   x3, x0_H

+    shr     x0, 16

+    CRC_XOR x6, r3, 6

+    movzx   x3, x0_L

+    CRC_XOR x6, r3, 5

+    movzx   x3, x0_H

+    CRC_MOV x0, r3, 4

+    xor     x0, x6

+    add     rD, 8

+    jnz     main_loop_8

+

+    MY_EPILOG crc_end_8

+MY_ENDP

+

+MY_PROC CrcUpdateT4, 4

+    MY_PROLOG crc_end_4

+    align 16

+  main_loop_4:

+    movzx   x1, x0_L

+    movzx   x3, x0_H

+    shr     x0, 16

+    movzx   x6, x0_H

+    and     x0, 0FFh

+    CRC_MOV x1, r1, 3

+    xor     x1, [SRCDAT 1]

+    CRC_XOR x1, r3, 2

+    CRC_XOR x1, r6, 0

+    CRC_XOR x1, r0, 1

+ 

+    movzx   x0, x1_L

+    movzx   x3, x1_H

+    shr     x1, 16

+    movzx   x6, x1_H

+    and     x1, 0FFh

+    CRC_MOV x0, r0, 3

+    xor     x0, [SRCDAT 2]

+    CRC_XOR x0, r3, 2

+    CRC_XOR x0, r6, 0

+    CRC_XOR x0, r1, 1

+    add     rD, 8

+    jnz     main_loop_4

+

+    MY_EPILOG crc_end_4

+MY_ENDP

+

+end

diff --git a/Asm/x86/AesOpt.asm b/Asm/x86/AesOpt.asm
new file mode 100755
index 0000000..c32e48f
--- /dev/null
+++ b/Asm/x86/AesOpt.asm
@@ -0,0 +1,237 @@
+; AesOpt.asm -- Intel's AES.

+; 2009-12-12 : Igor Pavlov : Public domain

+

+include 7zAsm.asm

+

+MY_ASM_START

+

+ifndef x64

+    .xmm

+endif

+

+ifdef x64

+    num     equ r8

+else

+    num     equ [r4 + REG_SIZE * 4]

+endif

+

+rD equ r2

+rN equ r0

+

+MY_PROLOG macro reg:req

+    ifdef x64

+    movdqa  [r4 + 8], xmm6

+    movdqa  [r4 + 8 + 16], xmm7

+    endif

+

+    push    r3

+    push    r5

+    push    r6

+

+    mov     rN, num

+    mov     x6, [r1 + 16]

+    shl     x6, 5

+

+    movdqa  reg, [r1]

+    add     r1, 32

+endm

+

+MY_EPILOG macro

+    pop     r6

+    pop     r5

+    pop     r3

+

+    ifdef x64

+    movdqa  xmm6, [r4 + 8]

+    movdqa  xmm7, [r4 + 8 + 16]

+    endif

+

+    MY_ENDP

+endm

+

+ways equ 4

+ways16 equ (ways * 16)

+

+OP_W macro op, op2

+    i = 0

+    rept ways

+    op @CatStr(xmm,%i), op2

+    i = i + 1

+    endm

+endm

+

+LOAD_OP macro op:req, offs:req

+    op      xmm0, [r1 + r3 offs]

+endm

+  

+LOAD_OP_W macro op:req, offs:req

+    movdqa  xmm7, [r1 + r3 offs]

+    OP_W    op, xmm7

+endm

+

+

+; ---------- AES-CBC Decode ----------

+

+CBC_DEC_UPDATE macro reg, offs

+    pxor    reg, xmm6

+    movdqa  xmm6, [rD + offs]

+    movdqa  [rD + offs], reg

+endm

+

+DECODE macro op:req

+    op      aesdec, +16

+  @@:

+    op      aesdec, +0

+    op      aesdec, -16

+    sub     x3, 32

+    jnz     @B

+    op      aesdeclast, +0

+endm

+

+MY_PROC AesCbc_Decode_Intel, 3

+    MY_PROLOG xmm6

+

+    sub     x6, 32

+

+    jmp     check2

+

+  align 16

+  nextBlocks2:

+    mov     x3, x6

+    OP_W    movdqa, [rD + i * 16]

+    LOAD_OP_W  pxor, +32

+    DECODE  LOAD_OP_W

+    OP_W    CBC_DEC_UPDATE, i * 16

+    add     rD, ways16

+  check2:

+    sub     rN, ways

+    jnc     nextBlocks2

+

+    add     rN, ways

+    jmp     check

+

+  nextBlock:

+    mov     x3, x6

+    movdqa  xmm1, [rD]

+    LOAD_OP movdqa, +32

+    pxor    xmm0, xmm1

+    DECODE  LOAD_OP

+    pxor    xmm0, xmm6

+    movdqa  [rD], xmm0

+    movdqa  xmm6, xmm1

+    add     rD, 16

+  check:

+    sub     rN, 1

+    jnc     nextBlock

+

+    movdqa  [r1 - 32], xmm6

+    MY_EPILOG

+

+

+; ---------- AES-CBC Encode ----------

+

+ENCODE macro op:req

+    op      aesenc, -16

+  @@:

+    op      aesenc, +0

+    op      aesenc, +16

+    add     r3, 32

+    jnz     @B

+    op      aesenclast, +0

+endm

+

+MY_PROC AesCbc_Encode_Intel, 3

+    MY_PROLOG xmm0

+

+    add     r1, r6

+    neg     r6

+    add     r6, 32

+

+    jmp     check_e

+

+  align 16

+  nextBlock_e:

+    mov     r3, r6

+    pxor    xmm0, [rD]

+    pxor    xmm0, [r1 + r3 - 32]

+    ENCODE  LOAD_OP

+    movdqa  [rD], xmm0

+    add     rD, 16

+  check_e:

+    sub     rN, 1

+    jnc     nextBlock_e

+

+    movdqa  [r1 + r6 - 64], xmm0

+    MY_EPILOG

+

+

+; ---------- AES-CTR ----------

+

+XOR_UPD_1 macro reg, offs

+    pxor    reg, [rD + offs]

+endm

+

+XOR_UPD_2 macro reg, offs

+    movdqa  [rD + offs], reg

+endm

+

+MY_PROC AesCtr_Code_Intel, 3

+    MY_PROLOG xmm6

+

+    mov     r5, r4

+    shr     r5, 4

+    dec     r5

+    shl     r5, 4

+

+    mov     DWORD PTR [r5], 1

+    mov     DWORD PTR [r5 + 4], 0

+    mov     DWORD PTR [r5 + 8], 0

+    mov     DWORD PTR [r5 + 12], 0

+    

+    add     r1, r6

+    neg     r6

+    add     r6, 32

+

+    jmp     check2_c

+

+  align 16

+  nextBlocks2_c:

+    movdqa  xmm7, [r5]

+

+    i = 0

+    rept ways

+    paddq   xmm6, xmm7

+    movdqa  @CatStr(xmm,%i), xmm6

+    i = i + 1

+    endm

+

+    mov     r3, r6

+    LOAD_OP_W  pxor, -32

+    ENCODE  LOAD_OP_W

+    OP_W    XOR_UPD_1, i * 16

+    OP_W    XOR_UPD_2, i * 16

+    add     rD, ways16

+  check2_c:

+    sub     rN, ways

+    jnc     nextBlocks2_c

+

+    add     rN, ways

+    jmp     check_c

+

+  nextBlock_c:

+    paddq   xmm6, [r5]

+    mov     r3, r6

+    movdqa  xmm0, [r1 + r3 - 32]

+    pxor    xmm0, xmm6

+    ENCODE  LOAD_OP

+    XOR_UPD_1 xmm0, 0

+    XOR_UPD_2 xmm0, 0

+    add     rD, 16

+  check_c:

+    sub     rN, 1

+    jnc     nextBlock_c

+

+    movdqa  [r1 + r6 - 64], xmm6

+    MY_EPILOG

+

+end

diff --git a/C/7z.h b/C/7z.h
new file mode 100755
index 0000000..b7edd3b
--- /dev/null
+++ b/C/7z.h
@@ -0,0 +1,203 @@
+/* 7z.h -- 7z interface

+2010-03-11 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_H

+#define __7Z_H

+

+#include "7zBuf.h"

+

+EXTERN_C_BEGIN

+

+#define k7zStartHeaderSize 0x20

+#define k7zSignatureSize 6

+extern Byte k7zSignature[k7zSignatureSize];

+#define k7zMajorVersion 0

+

+enum EIdEnum

+{

+  k7zIdEnd,

+  k7zIdHeader,

+  k7zIdArchiveProperties,

+  k7zIdAdditionalStreamsInfo,

+  k7zIdMainStreamsInfo,

+  k7zIdFilesInfo,

+  k7zIdPackInfo,

+  k7zIdUnpackInfo,

+  k7zIdSubStreamsInfo,

+  k7zIdSize,

+  k7zIdCRC,

+  k7zIdFolder,

+  k7zIdCodersUnpackSize,

+  k7zIdNumUnpackStream,

+  k7zIdEmptyStream,

+  k7zIdEmptyFile,

+  k7zIdAnti,

+  k7zIdName,

+  k7zIdCTime,

+  k7zIdATime,

+  k7zIdMTime,

+  k7zIdWinAttributes,

+  k7zIdComment,

+  k7zIdEncodedHeader,

+  k7zIdStartPos,

+  k7zIdDummy

+};

+

+typedef struct

+{

+  UInt32 NumInStreams;

+  UInt32 NumOutStreams;

+  UInt64 MethodID;

+  CBuf Props;

+} CSzCoderInfo;

+

+void SzCoderInfo_Init(CSzCoderInfo *p);

+void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);

+

+typedef struct

+{

+  UInt32 InIndex;

+  UInt32 OutIndex;

+} CSzBindPair;

+

+typedef struct

+{

+  CSzCoderInfo *Coders;

+  CSzBindPair *BindPairs;

+  UInt32 *PackStreams;

+  UInt64 *UnpackSizes;

+  UInt32 NumCoders;

+  UInt32 NumBindPairs;

+  UInt32 NumPackStreams;

+  int UnpackCRCDefined;

+  UInt32 UnpackCRC;

+

+  UInt32 NumUnpackStreams;

+} CSzFolder;

+

+void SzFolder_Init(CSzFolder *p);

+UInt64 SzFolder_GetUnpackSize(CSzFolder *p);

+int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);

+UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);

+UInt64 SzFolder_GetUnpackSize(CSzFolder *p);

+

+SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,

+    ILookInStream *stream, UInt64 startPos,

+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);

+

+typedef struct

+{

+  UInt32 Low;

+  UInt32 High;

+} CNtfsFileTime;

+

+typedef struct

+{

+  CNtfsFileTime MTime;

+  UInt64 Size;

+  UInt32 Crc;

+  UInt32 Attrib;

+  Byte HasStream;

+  Byte IsDir;

+  Byte IsAnti;

+  Byte CrcDefined;

+  Byte MTimeDefined;

+  Byte AttribDefined;

+} CSzFileItem;

+

+void SzFile_Init(CSzFileItem *p);

+

+typedef struct

+{

+  UInt64 *PackSizes;

+  Byte *PackCRCsDefined;

+  UInt32 *PackCRCs;

+  CSzFolder *Folders;

+  CSzFileItem *Files;

+  UInt32 NumPackStreams;

+  UInt32 NumFolders;

+  UInt32 NumFiles;

+} CSzAr;

+

+void SzAr_Init(CSzAr *p);

+void SzAr_Free(CSzAr *p, ISzAlloc *alloc);

+

+

+/*

+  SzExtract extracts file from archive

+

+  *outBuffer must be 0 before first call for each new archive.

+

+  Extracting cache:

+    If you need to decompress more than one file, you can send

+    these values from previous call:

+      *blockIndex,

+      *outBuffer,

+      *outBufferSize

+    You can consider "*outBuffer" as cache of solid block. If your archive is solid,

+    it will increase decompression speed.

+  

+    If you use external function, you can declare these 3 cache variables

+    (blockIndex, outBuffer, outBufferSize) as static in that external function.

+    

+    Free *outBuffer and set *outBuffer to 0, if you want to flush cache.

+*/

+

+typedef struct

+{

+  CSzAr db;

+  

+  UInt64 startPosAfterHeader;

+  UInt64 dataPos;

+

+  UInt32 *FolderStartPackStreamIndex;

+  UInt64 *PackStreamStartPositions;

+  UInt32 *FolderStartFileIndex;

+  UInt32 *FileIndexToFolderIndexMap;

+

+  size_t *FileNameOffsets; /* in 2-byte steps */

+  CBuf FileNames;  /* UTF-16-LE */

+} CSzArEx;

+

+void SzArEx_Init(CSzArEx *p);

+void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);

+UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);

+int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);

+

+/*

+if dest == NULL, the return value specifies the required size of the buffer,

+  in 16-bit characters, including the null-terminating character.

+if dest != NULL, the return value specifies the number of 16-bit characters that

+  are written to the dest, including the null-terminating character. */

+

+size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);

+

+SRes SzArEx_Extract(

+    const CSzArEx *db,

+    ILookInStream *inStream,

+    UInt32 fileIndex,         /* index of file */

+    UInt32 *blockIndex,       /* index of solid block */

+    Byte **outBuffer,         /* pointer to pointer to output buffer (allocated with allocMain) */

+    size_t *outBufferSize,    /* buffer size for output buffer */

+    size_t *offset,           /* offset of stream for required file in *outBuffer */

+    size_t *outSizeProcessed, /* size of file in *outBuffer */

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp);

+

+

+/*

+SzArEx_Open Errors:

+SZ_ERROR_NO_ARCHIVE

+SZ_ERROR_ARCHIVE

+SZ_ERROR_UNSUPPORTED

+SZ_ERROR_MEM

+SZ_ERROR_CRC

+SZ_ERROR_INPUT_EOF

+SZ_ERROR_FAIL

+*/

+

+SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);

+

+EXTERN_C_END

+

+#endif

diff --git a/C/7zAlloc.c b/C/7zAlloc.c
new file mode 100755
index 0000000..8874496
--- /dev/null
+++ b/C/7zAlloc.c
@@ -0,0 +1,76 @@
+/* 7zAlloc.c -- Allocation functions

+2010-10-29 : Igor Pavlov : Public domain */

+

+#include "7zAlloc.h"

+

+/* #define _SZ_ALLOC_DEBUG */

+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */

+

+#ifdef _SZ_ALLOC_DEBUG

+

+#ifdef _WIN32

+#include <windows.h>

+#endif

+

+#include <stdio.h>

+int g_allocCount = 0;

+int g_allocCountTemp = 0;

+

+#endif

+

+void *SzAlloc(void *p, size_t size)

+{

+  p = p;

+  if (size == 0)

+    return 0;

+  #ifdef _SZ_ALLOC_DEBUG

+  fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);

+  g_allocCount++;

+  #endif

+  return malloc(size);

+}

+

+void SzFree(void *p, void *address)

+{

+  p = p;

+  #ifdef _SZ_ALLOC_DEBUG

+  if (address != 0)

+  {

+    g_allocCount--;

+    fprintf(stderr, "\nFree; count = %10d", g_allocCount);

+  }

+  #endif

+  free(address);

+}

+

+void *SzAllocTemp(void *p, size_t size)

+{

+  p = p;

+  if (size == 0)

+    return 0;

+  #ifdef _SZ_ALLOC_DEBUG

+  fprintf(stderr, "\nAlloc_temp %10d bytes;  count = %10d", size, g_allocCountTemp);

+  g_allocCountTemp++;

+  #ifdef _WIN32

+  return HeapAlloc(GetProcessHeap(), 0, size);

+  #endif

+  #endif

+  return malloc(size);

+}

+

+void SzFreeTemp(void *p, void *address)

+{

+  p = p;

+  #ifdef _SZ_ALLOC_DEBUG

+  if (address != 0)

+  {

+    g_allocCountTemp--;

+    fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);

+  }

+  #ifdef _WIN32

+  HeapFree(GetProcessHeap(), 0, address);

+  return;

+  #endif

+  #endif

+  free(address);

+}

diff --git a/C/7zAlloc.h b/C/7zAlloc.h
new file mode 100755
index 0000000..860f116
--- /dev/null
+++ b/C/7zAlloc.h
@@ -0,0 +1,15 @@
+/* 7zAlloc.h -- Allocation functions

+2010-10-29 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_ALLOC_H

+#define __7Z_ALLOC_H

+

+#include <stdlib.h>

+

+void *SzAlloc(void *p, size_t size);

+void SzFree(void *p, void *address);

+

+void *SzAllocTemp(void *p, size_t size);

+void SzFreeTemp(void *p, void *address);

+

+#endif

diff --git a/C/7zBuf.c b/C/7zBuf.c
new file mode 100755
index 0000000..a35fa2f
--- /dev/null
+++ b/C/7zBuf.c
@@ -0,0 +1,36 @@
+/* 7zBuf.c -- Byte Buffer

+2008-03-28

+Igor Pavlov

+Public domain */

+

+#include "7zBuf.h"

+

+void Buf_Init(CBuf *p)

+{

+  p->data = 0;

+  p->size = 0;

+}

+

+int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)

+{

+  p->size = 0;

+  if (size == 0)

+  {

+    p->data = 0;

+    return 1;

+  }

+  p->data = (Byte *)alloc->Alloc(alloc, size);

+  if (p->data != 0)

+  {

+    p->size = size;

+    return 1;

+  }

+  return 0;

+}

+

+void Buf_Free(CBuf *p, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, p->data);

+  p->data = 0;

+  p->size = 0;

+}

diff --git a/C/7zBuf.h b/C/7zBuf.h
new file mode 100755
index 0000000..88ff0c2
--- /dev/null
+++ b/C/7zBuf.h
@@ -0,0 +1,39 @@
+/* 7zBuf.h -- Byte Buffer

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_BUF_H

+#define __7Z_BUF_H

+

+#include "Types.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+typedef struct

+{

+  Byte *data;

+  size_t size;

+} CBuf;

+

+void Buf_Init(CBuf *p);

+int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);

+void Buf_Free(CBuf *p, ISzAlloc *alloc);

+

+typedef struct

+{

+  Byte *data;

+  size_t size;

+  size_t pos;

+} CDynBuf;

+

+void DynBuf_Construct(CDynBuf *p);

+void DynBuf_SeekToBeg(CDynBuf *p);

+int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);

+void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/7zBuf2.c b/C/7zBuf2.c
new file mode 100755
index 0000000..1c8b931
--- /dev/null
+++ b/C/7zBuf2.c
@@ -0,0 +1,45 @@
+/* 7zBuf2.c -- Byte Buffer

+2008-10-04 : Igor Pavlov : Public domain */

+

+#include <string.h>

+#include "7zBuf.h"

+

+void DynBuf_Construct(CDynBuf *p)

+{

+  p->data = 0;

+  p->size = 0;

+  p->pos = 0;

+}

+

+void DynBuf_SeekToBeg(CDynBuf *p)

+{

+  p->pos = 0;

+}

+

+int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)

+{

+  if (size > p->size - p->pos)

+  {

+    size_t newSize = p->pos + size;

+    Byte *data;

+    newSize += newSize / 4;

+    data = (Byte *)alloc->Alloc(alloc, newSize);

+    if (data == 0)

+      return 0;

+    p->size = newSize;

+    memcpy(data, p->data, p->pos);

+    alloc->Free(alloc, p->data);

+    p->data = data;

+  }

+  memcpy(p->data + p->pos, buf, size);

+  p->pos += size;

+  return 1;

+}

+

+void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, p->data);

+  p->data = 0;

+  p->size = 0;

+  p->pos = 0;

+}

diff --git a/C/7zCrc.c b/C/7zCrc.c
new file mode 100755
index 0000000..5801dab
--- /dev/null
+++ b/C/7zCrc.c
@@ -0,0 +1,74 @@
+/* 7zCrc.c -- CRC32 calculation

+2009-11-23 : Igor Pavlov : Public domain */

+

+#include "7zCrc.h"

+#include "CpuArch.h"

+

+#define kCrcPoly 0xEDB88320

+

+#ifdef MY_CPU_LE

+#define CRC_NUM_TABLES 8

+#else

+#define CRC_NUM_TABLES 1

+#endif

+

+typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);

+

+static CRC_FUNC g_CrcUpdate;

+UInt32 g_CrcTable[256 * CRC_NUM_TABLES];

+

+#if CRC_NUM_TABLES == 1

+

+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))

+

+static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)

+{

+  const Byte *p = (const Byte *)data;

+  for (; size > 0; size--, p++)

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  return v;

+}

+

+#else

+

+UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);

+UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);

+

+#endif

+

+UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)

+{

+  return g_CrcUpdate(v, data, size, g_CrcTable);

+}

+

+UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)

+{

+  return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;

+}

+

+void MY_FAST_CALL CrcGenerateTable()

+{

+  UInt32 i;

+  for (i = 0; i < 256; i++)

+  {

+    UInt32 r = i;

+    unsigned j;

+    for (j = 0; j < 8; j++)

+      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));

+    g_CrcTable[i] = r;

+  }

+  #if CRC_NUM_TABLES == 1

+  g_CrcUpdate = CrcUpdateT1;

+  #else

+  for (; i < 256 * CRC_NUM_TABLES; i++)

+  {

+    UInt32 r = g_CrcTable[i - 256];

+    g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);

+  }

+  g_CrcUpdate = CrcUpdateT4;

+  #ifdef MY_CPU_X86_OR_AMD64

+  if (!CPU_Is_InOrder())

+    g_CrcUpdate = CrcUpdateT8;

+  #endif

+  #endif

+}

diff --git a/C/7zCrc.h b/C/7zCrc.h
new file mode 100755
index 0000000..4a1ec38
--- /dev/null
+++ b/C/7zCrc.h
@@ -0,0 +1,25 @@
+/* 7zCrc.h -- CRC32 calculation

+2009-11-21 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_CRC_H

+#define __7Z_CRC_H

+

+#include "Types.h"

+

+EXTERN_C_BEGIN

+

+extern UInt32 g_CrcTable[];

+

+/* Call CrcGenerateTable one time before other CRC functions */

+void MY_FAST_CALL CrcGenerateTable(void);

+

+#define CRC_INIT_VAL 0xFFFFFFFF

+#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)

+#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))

+

+UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);

+UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);

+

+EXTERN_C_END

+

+#endif

diff --git a/C/7zCrcOpt.c b/C/7zCrcOpt.c
new file mode 100755
index 0000000..6205d71
--- /dev/null
+++ b/C/7zCrcOpt.c
@@ -0,0 +1,34 @@
+/* 7zCrcOpt.c -- CRC32 calculation : optimized version

+2009-11-23 : Igor Pavlov : Public domain */

+

+#include "CpuArch.h"

+

+#ifdef MY_CPU_LE

+

+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))

+

+UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)

+{

+  const Byte *p = (const Byte *)data;

+  for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  for (; size >= 4; size -= 4, p += 4)

+  {

+    v ^= *(const UInt32 *)p;

+    v =

+      table[0x300 + (v & 0xFF)] ^

+      table[0x200 + ((v >> 8) & 0xFF)] ^

+      table[0x100 + ((v >> 16) & 0xFF)] ^

+      table[0x000 + ((v >> 24))];

+  }

+  for (; size > 0; size--, p++)

+    v = CRC_UPDATE_BYTE_2(v, *p);

+  return v;

+}

+

+UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)

+{

+  return CrcUpdateT4(v, data, size, table);

+}

+

+#endif

diff --git a/C/7zDec.c b/C/7zDec.c
new file mode 100755
index 0000000..3386807
--- /dev/null
+++ b/C/7zDec.c
@@ -0,0 +1,470 @@
+/* 7zDec.c -- Decoding from 7z folder

+2010-11-02 : Igor Pavlov : Public domain */

+

+#include <string.h>

+

+/* #define _7ZIP_PPMD_SUPPPORT */

+

+#include "7z.h"

+

+#include "Bcj2.h"

+#include "Bra.h"

+#include "CpuArch.h"

+#include "LzmaDec.h"

+#include "Lzma2Dec.h"

+#ifdef _7ZIP_PPMD_SUPPPORT

+#include "Ppmd7.h"

+#endif

+

+#define k_Copy 0

+#define k_LZMA2 0x21

+#define k_LZMA  0x30101

+#define k_BCJ   0x03030103

+#define k_PPC   0x03030205

+#define k_ARM   0x03030501

+#define k_ARMT  0x03030701

+#define k_SPARC 0x03030805

+#define k_BCJ2  0x0303011B

+

+#ifdef _7ZIP_PPMD_SUPPPORT

+

+#define k_PPMD 0x30401

+

+typedef struct

+{

+  IByteIn p;

+  const Byte *cur;

+  const Byte *end;

+  const Byte *begin;

+  UInt64 processed;

+  Bool extra;

+  SRes res;

+  ILookInStream *inStream;

+} CByteInToLook;

+

+static Byte ReadByte(void *pp)

+{

+  CByteInToLook *p = (CByteInToLook *)pp;

+  if (p->cur != p->end)

+    return *p->cur++;

+  if (p->res == SZ_OK)

+  {

+    size_t size = p->cur - p->begin;

+    p->processed += size;

+    p->res = p->inStream->Skip(p->inStream, size);

+    size = (1 << 25);

+    p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);

+    p->cur = p->begin;

+    p->end = p->begin + size;

+    if (size != 0)

+      return *p->cur++;;

+  }

+  p->extra = True;

+  return 0;

+}

+

+static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,

+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)

+{

+  CPpmd7 ppmd;

+  CByteInToLook s;

+  SRes res = SZ_OK;

+

+  s.p.Read = ReadByte;

+  s.inStream = inStream;

+  s.begin = s.end = s.cur = NULL;

+  s.extra = False;

+  s.res = SZ_OK;

+  s.processed = 0;

+

+  if (coder->Props.size != 5)

+    return SZ_ERROR_UNSUPPORTED;

+

+  {

+    unsigned order = coder->Props.data[0];

+    UInt32 memSize = GetUi32(coder->Props.data + 1);

+    if (order < PPMD7_MIN_ORDER ||

+        order > PPMD7_MAX_ORDER ||

+        memSize < PPMD7_MIN_MEM_SIZE ||

+        memSize > PPMD7_MAX_MEM_SIZE)

+      return SZ_ERROR_UNSUPPORTED;

+    Ppmd7_Construct(&ppmd);

+    if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))

+      return SZ_ERROR_MEM;

+    Ppmd7_Init(&ppmd, order);

+  }

+  {

+    CPpmd7z_RangeDec rc;

+    Ppmd7z_RangeDec_CreateVTable(&rc);

+    rc.Stream = &s.p;

+    if (!Ppmd7z_RangeDec_Init(&rc))

+      res = SZ_ERROR_DATA;

+    else if (s.extra)

+      res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);

+    else

+    {

+      SizeT i;

+      for (i = 0; i < outSize; i++)

+      {

+        int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);

+        if (s.extra || sym < 0)

+          break;

+        outBuffer[i] = (Byte)sym;

+      }

+      if (i != outSize)

+        res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);

+      else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))

+        res = SZ_ERROR_DATA;

+    }

+  }

+  Ppmd7_Free(&ppmd, allocMain);

+  return res;

+}

+

+#endif

+

+

+static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,

+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)

+{

+  CLzmaDec state;

+  SRes res = SZ_OK;

+

+  LzmaDec_Construct(&state);

+  RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));

+  state.dic = outBuffer;

+  state.dicBufSize = outSize;

+  LzmaDec_Init(&state);

+

+  for (;;)

+  {

+    Byte *inBuf = NULL;

+    size_t lookahead = (1 << 18);

+    if (lookahead > inSize)

+      lookahead = (size_t)inSize;

+    res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);

+    if (res != SZ_OK)

+      break;

+

+    {

+      SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;

+      ELzmaStatus status;

+      res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);

+      lookahead -= inProcessed;

+      inSize -= inProcessed;

+      if (res != SZ_OK)

+        break;

+      if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))

+      {

+        if (state.dicBufSize != outSize || lookahead != 0 ||

+            (status != LZMA_STATUS_FINISHED_WITH_MARK &&

+             status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))

+          res = SZ_ERROR_DATA;

+        break;

+      }

+      res = inStream->Skip((void *)inStream, inProcessed);

+      if (res != SZ_OK)

+        break;

+    }

+  }

+

+  LzmaDec_FreeProbs(&state, allocMain);

+  return res;

+}

+

+static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,

+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)

+{

+  CLzma2Dec state;

+  SRes res = SZ_OK;

+

+  Lzma2Dec_Construct(&state);

+  if (coder->Props.size != 1)

+    return SZ_ERROR_DATA;

+  RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));

+  state.decoder.dic = outBuffer;

+  state.decoder.dicBufSize = outSize;

+  Lzma2Dec_Init(&state);

+

+  for (;;)

+  {

+    Byte *inBuf = NULL;

+    size_t lookahead = (1 << 18);

+    if (lookahead > inSize)

+      lookahead = (size_t)inSize;

+    res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);

+    if (res != SZ_OK)

+      break;

+

+    {

+      SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;

+      ELzmaStatus status;

+      res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);

+      lookahead -= inProcessed;

+      inSize -= inProcessed;

+      if (res != SZ_OK)

+        break;

+      if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))

+      {

+        if (state.decoder.dicBufSize != outSize || lookahead != 0 ||

+            (status != LZMA_STATUS_FINISHED_WITH_MARK))

+          res = SZ_ERROR_DATA;

+        break;

+      }

+      res = inStream->Skip((void *)inStream, inProcessed);

+      if (res != SZ_OK)

+        break;

+    }

+  }

+

+  Lzma2Dec_FreeProbs(&state, allocMain);

+  return res;

+}

+

+static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)

+{

+  while (inSize > 0)

+  {

+    void *inBuf;

+    size_t curSize = (1 << 18);

+    if (curSize > inSize)

+      curSize = (size_t)inSize;

+    RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));

+    if (curSize == 0)

+      return SZ_ERROR_INPUT_EOF;

+    memcpy(outBuffer, inBuf, curSize);

+    outBuffer += curSize;

+    inSize -= curSize;

+    RINOK(inStream->Skip((void *)inStream, curSize));

+  }

+  return SZ_OK;

+}

+

+static Bool IS_MAIN_METHOD(UInt32 m)

+{

+  switch(m)

+  {

+    case k_Copy:

+    case k_LZMA:

+    case k_LZMA2:

+    #ifdef _7ZIP_PPMD_SUPPPORT

+    case k_PPMD:

+    #endif

+      return True;

+  }

+  return False;

+}

+

+static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)

+{

+  return

+      c->NumInStreams == 1 &&

+      c->NumOutStreams == 1 &&

+      c->MethodID <= (UInt32)0xFFFFFFFF &&

+      IS_MAIN_METHOD((UInt32)c->MethodID);

+}

+

+#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)

+

+static SRes CheckSupportedFolder(const CSzFolder *f)

+{

+  if (f->NumCoders < 1 || f->NumCoders > 4)

+    return SZ_ERROR_UNSUPPORTED;

+  if (!IS_SUPPORTED_CODER(&f->Coders[0]))

+    return SZ_ERROR_UNSUPPORTED;

+  if (f->NumCoders == 1)

+  {

+    if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)

+      return SZ_ERROR_UNSUPPORTED;

+    return SZ_OK;

+  }

+  if (f->NumCoders == 2)

+  {

+    CSzCoderInfo *c = &f->Coders[1];

+    if (c->MethodID > (UInt32)0xFFFFFFFF ||

+        c->NumInStreams != 1 ||

+        c->NumOutStreams != 1 ||

+        f->NumPackStreams != 1 ||

+        f->PackStreams[0] != 0 ||

+        f->NumBindPairs != 1 ||

+        f->BindPairs[0].InIndex != 1 ||

+        f->BindPairs[0].OutIndex != 0)

+      return SZ_ERROR_UNSUPPORTED;

+    switch ((UInt32)c->MethodID)

+    {

+      case k_BCJ:

+      case k_ARM:

+        break;

+      default:

+        return SZ_ERROR_UNSUPPORTED;

+    }

+    return SZ_OK;

+  }

+  if (f->NumCoders == 4)

+  {

+    if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||

+        !IS_SUPPORTED_CODER(&f->Coders[2]) ||

+        !IS_BCJ2(&f->Coders[3]))

+      return SZ_ERROR_UNSUPPORTED;

+    if (f->NumPackStreams != 4 ||

+        f->PackStreams[0] != 2 ||

+        f->PackStreams[1] != 6 ||

+        f->PackStreams[2] != 1 ||

+        f->PackStreams[3] != 0 ||

+        f->NumBindPairs != 3 ||

+        f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||

+        f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||

+        f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)

+      return SZ_ERROR_UNSUPPORTED;

+    return SZ_OK;

+  }

+  return SZ_ERROR_UNSUPPORTED;

+}

+

+static UInt64 GetSum(const UInt64 *values, UInt32 index)

+{

+  UInt64 sum = 0;

+  UInt32 i;

+  for (i = 0; i < index; i++)

+    sum += values[i];

+  return sum;

+}

+

+#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;

+

+static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,

+    ILookInStream *inStream, UInt64 startPos,

+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,

+    Byte *tempBuf[])

+{

+  UInt32 ci;

+  SizeT tempSizes[3] = { 0, 0, 0};

+  SizeT tempSize3 = 0;

+  Byte *tempBuf3 = 0;

+

+  RINOK(CheckSupportedFolder(folder));

+

+  for (ci = 0; ci < folder->NumCoders; ci++)

+  {

+    CSzCoderInfo *coder = &folder->Coders[ci];

+

+    if (IS_MAIN_METHOD((UInt32)coder->MethodID))

+    {

+      UInt32 si = 0;

+      UInt64 offset;

+      UInt64 inSize;

+      Byte *outBufCur = outBuffer;

+      SizeT outSizeCur = outSize;

+      if (folder->NumCoders == 4)

+      {

+        UInt32 indices[] = { 3, 2, 0 };

+        UInt64 unpackSize = folder->UnpackSizes[ci];

+        si = indices[ci];

+        if (ci < 2)

+        {

+          Byte *temp;

+          outSizeCur = (SizeT)unpackSize;

+          if (outSizeCur != unpackSize)

+            return SZ_ERROR_MEM;

+          temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);

+          if (temp == 0 && outSizeCur != 0)

+            return SZ_ERROR_MEM;

+          outBufCur = tempBuf[1 - ci] = temp;

+          tempSizes[1 - ci] = outSizeCur;

+        }

+        else if (ci == 2)

+        {

+          if (unpackSize > outSize) /* check it */

+            return SZ_ERROR_PARAM;

+          tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);

+          tempSize3 = outSizeCur = (SizeT)unpackSize;

+        }

+        else

+          return SZ_ERROR_UNSUPPORTED;

+      }

+      offset = GetSum(packSizes, si);

+      inSize = packSizes[si];

+      RINOK(LookInStream_SeekTo(inStream, startPos + offset));

+

+      if (coder->MethodID == k_Copy)

+      {

+        if (inSize != outSizeCur) /* check it */

+          return SZ_ERROR_DATA;

+        RINOK(SzDecodeCopy(inSize, inStream, outBufCur));

+      }

+      else if (coder->MethodID == k_LZMA)

+      {

+        RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));

+      }

+      else if (coder->MethodID == k_LZMA2)

+      {

+        RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));

+      }

+      else

+      {

+        #ifdef _7ZIP_PPMD_SUPPPORT

+        RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));

+        #else

+        return SZ_ERROR_UNSUPPORTED;

+        #endif

+      }

+    }

+    else if (coder->MethodID == k_BCJ2)

+    {

+      UInt64 offset = GetSum(packSizes, 1);

+      UInt64 s3Size = packSizes[1];

+      SRes res;

+      if (ci != 3)

+        return SZ_ERROR_UNSUPPORTED;

+      RINOK(LookInStream_SeekTo(inStream, startPos + offset));

+      tempSizes[2] = (SizeT)s3Size;

+      if (tempSizes[2] != s3Size)

+        return SZ_ERROR_MEM;

+      tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);

+      if (tempBuf[2] == 0 && tempSizes[2] != 0)

+        return SZ_ERROR_MEM;

+      res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);

+      RINOK(res)

+

+      res = Bcj2_Decode(

+          tempBuf3, tempSize3,

+          tempBuf[0], tempSizes[0],

+          tempBuf[1], tempSizes[1],

+          tempBuf[2], tempSizes[2],

+          outBuffer, outSize);

+      RINOK(res)

+    }

+    else

+    {

+      if (ci != 1)

+        return SZ_ERROR_UNSUPPORTED;

+      switch(coder->MethodID)

+      {

+        case k_BCJ:

+        {

+          UInt32 state;

+          x86_Convert_Init(state);

+          x86_Convert(outBuffer, outSize, 0, &state, 0);

+          break;

+        }

+        CASE_BRA_CONV(ARM)

+        default:

+          return SZ_ERROR_UNSUPPORTED;

+      }

+    }

+  }

+  return SZ_OK;

+}

+

+SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,

+    ILookInStream *inStream, UInt64 startPos,

+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)

+{

+  Byte *tempBuf[3] = { 0, 0, 0};

+  int i;

+  SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,

+      outBuffer, (SizeT)outSize, allocMain, tempBuf);

+  for (i = 0; i < 3; i++)

+    IAlloc_Free(allocMain, tempBuf[i]);

+  return res;

+}

diff --git a/C/7zFile.c b/C/7zFile.c
new file mode 100755
index 0000000..6d82c79
--- /dev/null
+++ b/C/7zFile.c
@@ -0,0 +1,284 @@
+/* 7zFile.c -- File IO

+2009-11-24 : Igor Pavlov : Public domain */

+

+#include "7zFile.h"

+

+#ifndef USE_WINDOWS_FILE

+

+#ifndef UNDER_CE

+#include <errno.h>

+#endif

+

+#else

+

+/*

+   ReadFile and WriteFile functions in Windows have BUG:

+   If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)

+   from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES

+   (Insufficient system resources exist to complete the requested service).

+   Probably in some version of Windows there are problems with other sizes:

+   for 32 MB (maybe also for 16 MB).

+   And message can be "Network connection was lost"

+*/

+

+#define kChunkSizeMax (1 << 22)

+

+#endif

+

+void File_Construct(CSzFile *p)

+{

+  #ifdef USE_WINDOWS_FILE

+  p->handle = INVALID_HANDLE_VALUE;

+  #else

+  p->file = NULL;

+  #endif

+}

+

+#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)

+static WRes File_Open(CSzFile *p, const char *name, int writeMode)

+{

+  #ifdef USE_WINDOWS_FILE

+  p->handle = CreateFileA(name,

+      writeMode ? GENERIC_WRITE : GENERIC_READ,

+      FILE_SHARE_READ, NULL,

+      writeMode ? CREATE_ALWAYS : OPEN_EXISTING,

+      FILE_ATTRIBUTE_NORMAL, NULL);

+  return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();

+  #else

+  p->file = fopen(name, writeMode ? "wb+" : "rb");

+  return (p->file != 0) ? 0 :

+    #ifdef UNDER_CE

+    2; /* ENOENT */

+    #else

+    errno;

+    #endif

+  #endif

+}

+

+WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }

+WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }

+#endif

+

+#ifdef USE_WINDOWS_FILE

+static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)

+{

+  p->handle = CreateFileW(name,

+      writeMode ? GENERIC_WRITE : GENERIC_READ,

+      FILE_SHARE_READ, NULL,

+      writeMode ? CREATE_ALWAYS : OPEN_EXISTING,

+      FILE_ATTRIBUTE_NORMAL, NULL);

+  return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();

+}

+WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }

+WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }

+#endif

+

+WRes File_Close(CSzFile *p)

+{

+  #ifdef USE_WINDOWS_FILE

+  if (p->handle != INVALID_HANDLE_VALUE)

+  {

+    if (!CloseHandle(p->handle))

+      return GetLastError();

+    p->handle = INVALID_HANDLE_VALUE;

+  }

+  #else

+  if (p->file != NULL)

+  {

+    int res = fclose(p->file);

+    if (res != 0)

+      return res;

+    p->file = NULL;

+  }

+  #endif

+  return 0;

+}

+

+WRes File_Read(CSzFile *p, void *data, size_t *size)

+{

+  size_t originalSize = *size;

+  if (originalSize == 0)

+    return 0;

+

+  #ifdef USE_WINDOWS_FILE

+

+  *size = 0;

+  do

+  {

+    DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;

+    DWORD processed = 0;

+    BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);

+    data = (void *)((Byte *)data + processed);

+    originalSize -= processed;

+    *size += processed;

+    if (!res)

+      return GetLastError();

+    if (processed == 0)

+      break;

+  }

+  while (originalSize > 0);

+  return 0;

+

+  #else

+  

+  *size = fread(data, 1, originalSize, p->file);

+  if (*size == originalSize)

+    return 0;

+  return ferror(p->file);

+  

+  #endif

+}

+

+WRes File_Write(CSzFile *p, const void *data, size_t *size)

+{

+  size_t originalSize = *size;

+  if (originalSize == 0)

+    return 0;

+  

+  #ifdef USE_WINDOWS_FILE

+

+  *size = 0;

+  do

+  {

+    DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;

+    DWORD processed = 0;

+    BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);

+    data = (void *)((Byte *)data + processed);

+    originalSize -= processed;

+    *size += processed;

+    if (!res)

+      return GetLastError();

+    if (processed == 0)

+      break;

+  }

+  while (originalSize > 0);

+  return 0;

+

+  #else

+

+  *size = fwrite(data, 1, originalSize, p->file);

+  if (*size == originalSize)

+    return 0;

+  return ferror(p->file);

+  

+  #endif

+}

+

+WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)

+{

+  #ifdef USE_WINDOWS_FILE

+

+  LARGE_INTEGER value;

+  DWORD moveMethod;

+  value.LowPart = (DWORD)*pos;

+  value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */

+  switch (origin)

+  {

+    case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;

+    case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;

+    case SZ_SEEK_END: moveMethod = FILE_END; break;

+    default: return ERROR_INVALID_PARAMETER;

+  }

+  value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);

+  if (value.LowPart == 0xFFFFFFFF)

+  {

+    WRes res = GetLastError();

+    if (res != NO_ERROR)

+      return res;

+  }

+  *pos = ((Int64)value.HighPart << 32) | value.LowPart;

+  return 0;

+

+  #else

+  

+  int moveMethod;

+  int res;

+  switch (origin)

+  {

+    case SZ_SEEK_SET: moveMethod = SEEK_SET; break;

+    case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;

+    case SZ_SEEK_END: moveMethod = SEEK_END; break;

+    default: return 1;

+  }

+  res = fseek(p->file, (long)*pos, moveMethod);

+  *pos = ftell(p->file);

+  return res;

+  

+  #endif

+}

+

+WRes File_GetLength(CSzFile *p, UInt64 *length)

+{

+  #ifdef USE_WINDOWS_FILE

+  

+  DWORD sizeHigh;

+  DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);

+  if (sizeLow == 0xFFFFFFFF)

+  {

+    DWORD res = GetLastError();

+    if (res != NO_ERROR)

+      return res;

+  }

+  *length = (((UInt64)sizeHigh) << 32) + sizeLow;

+  return 0;

+  

+  #else

+  

+  long pos = ftell(p->file);

+  int res = fseek(p->file, 0, SEEK_END);

+  *length = ftell(p->file);

+  fseek(p->file, pos, SEEK_SET);

+  return res;

+  

+  #endif

+}

+

+

+/* ---------- FileSeqInStream ---------- */

+

+static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)

+{

+  CFileSeqInStream *p = (CFileSeqInStream *)pp;

+  return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;

+}

+

+void FileSeqInStream_CreateVTable(CFileSeqInStream *p)

+{

+  p->s.Read = FileSeqInStream_Read;

+}

+

+

+/* ---------- FileInStream ---------- */

+

+static SRes FileInStream_Read(void *pp, void *buf, size_t *size)

+{

+  CFileInStream *p = (CFileInStream *)pp;

+  return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;

+}

+

+static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)

+{

+  CFileInStream *p = (CFileInStream *)pp;

+  return File_Seek(&p->file, pos, origin);

+}

+

+void FileInStream_CreateVTable(CFileInStream *p)

+{

+  p->s.Read = FileInStream_Read;

+  p->s.Seek = FileInStream_Seek;

+}

+

+

+/* ---------- FileOutStream ---------- */

+

+static size_t FileOutStream_Write(void *pp, const void *data, size_t size)

+{

+  CFileOutStream *p = (CFileOutStream *)pp;

+  File_Write(&p->file, data, &size);

+  return size;

+}

+

+void FileOutStream_CreateVTable(CFileOutStream *p)

+{

+  p->s.Write = FileOutStream_Write;

+}

diff --git a/C/7zFile.h b/C/7zFile.h
new file mode 100755
index 0000000..5d85787
--- /dev/null
+++ b/C/7zFile.h
@@ -0,0 +1,83 @@
+/* 7zFile.h -- File IO

+2009-11-24 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_FILE_H

+#define __7Z_FILE_H

+

+#ifdef _WIN32

+#define USE_WINDOWS_FILE

+#endif

+

+#ifdef USE_WINDOWS_FILE

+#include <windows.h>

+#else

+#include <stdio.h>

+#endif

+

+#include "Types.h"

+

+EXTERN_C_BEGIN

+

+/* ---------- File ---------- */

+

+typedef struct

+{

+  #ifdef USE_WINDOWS_FILE

+  HANDLE handle;

+  #else

+  FILE *file;

+  #endif

+} CSzFile;

+

+void File_Construct(CSzFile *p);

+#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)

+WRes InFile_Open(CSzFile *p, const char *name);

+WRes OutFile_Open(CSzFile *p, const char *name);

+#endif

+#ifdef USE_WINDOWS_FILE

+WRes InFile_OpenW(CSzFile *p, const WCHAR *name);

+WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);

+#endif

+WRes File_Close(CSzFile *p);

+

+/* reads max(*size, remain file's size) bytes */

+WRes File_Read(CSzFile *p, void *data, size_t *size);

+

+/* writes *size bytes */

+WRes File_Write(CSzFile *p, const void *data, size_t *size);

+

+WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);

+WRes File_GetLength(CSzFile *p, UInt64 *length);

+

+

+/* ---------- FileInStream ---------- */

+

+typedef struct

+{

+  ISeqInStream s;

+  CSzFile file;

+} CFileSeqInStream;

+

+void FileSeqInStream_CreateVTable(CFileSeqInStream *p);

+

+

+typedef struct

+{

+  ISeekInStream s;

+  CSzFile file;

+} CFileInStream;

+

+void FileInStream_CreateVTable(CFileInStream *p);

+

+

+typedef struct

+{

+  ISeqOutStream s;

+  CSzFile file;

+} CFileOutStream;

+

+void FileOutStream_CreateVTable(CFileOutStream *p);

+

+EXTERN_C_END

+

+#endif

diff --git a/C/7zIn.c b/C/7zIn.c
new file mode 100755
index 0000000..f1a4492
--- /dev/null
+++ b/C/7zIn.c
@@ -0,0 +1,1402 @@
+/* 7zIn.c -- 7z Input functions

+2010-10-29 : Igor Pavlov : Public domain */

+

+#include <string.h>

+

+#include "7z.h"

+#include "7zCrc.h"

+#include "CpuArch.h"

+

+Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

+

+#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; }

+

+#define NUM_FOLDER_CODERS_MAX 32

+#define NUM_CODER_STREAMS_MAX 32

+

+void SzCoderInfo_Init(CSzCoderInfo *p)

+{

+  Buf_Init(&p->Props);

+}

+

+void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)

+{

+  Buf_Free(&p->Props, alloc);

+  SzCoderInfo_Init(p);

+}

+

+void SzFolder_Init(CSzFolder *p)

+{

+  p->Coders = 0;

+  p->BindPairs = 0;

+  p->PackStreams = 0;

+  p->UnpackSizes = 0;

+  p->NumCoders = 0;

+  p->NumBindPairs = 0;

+  p->NumPackStreams = 0;

+  p->UnpackCRCDefined = 0;

+  p->UnpackCRC = 0;

+  p->NumUnpackStreams = 0;

+}

+

+void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)

+{

+  UInt32 i;

+  if (p->Coders)

+    for (i = 0; i < p->NumCoders; i++)

+      SzCoderInfo_Free(&p->Coders[i], alloc);

+  IAlloc_Free(alloc, p->Coders);

+  IAlloc_Free(alloc, p->BindPairs);

+  IAlloc_Free(alloc, p->PackStreams);

+  IAlloc_Free(alloc, p->UnpackSizes);

+  SzFolder_Init(p);

+}

+

+UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)

+{

+  UInt32 result = 0;

+  UInt32 i;

+  for (i = 0; i < p->NumCoders; i++)

+    result += p->Coders[i].NumOutStreams;

+  return result;

+}

+

+int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)

+{

+  UInt32 i;

+  for (i = 0; i < p->NumBindPairs; i++)

+    if (p->BindPairs[i].InIndex == inStreamIndex)

+      return i;

+  return -1;

+}

+

+

+int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)

+{

+  UInt32 i;

+  for (i = 0; i < p->NumBindPairs; i++)

+    if (p->BindPairs[i].OutIndex == outStreamIndex)

+      return i;

+  return -1;

+}

+

+UInt64 SzFolder_GetUnpackSize(CSzFolder *p)

+{

+  int i = (int)SzFolder_GetNumOutStreams(p);

+  if (i == 0)

+    return 0;

+  for (i--; i >= 0; i--)

+    if (SzFolder_FindBindPairForOutStream(p, i) < 0)

+      return p->UnpackSizes[i];

+  /* throw 1; */

+  return 0;

+}

+

+void SzFile_Init(CSzFileItem *p)

+{

+  p->HasStream = 1;

+  p->IsDir = 0;

+  p->IsAnti = 0;

+  p->CrcDefined = 0;

+  p->MTimeDefined = 0;

+}

+

+void SzAr_Init(CSzAr *p)

+{

+  p->PackSizes = 0;

+  p->PackCRCsDefined = 0;

+  p->PackCRCs = 0;

+  p->Folders = 0;

+  p->Files = 0;

+  p->NumPackStreams = 0;

+  p->NumFolders = 0;

+  p->NumFiles = 0;

+}

+

+void SzAr_Free(CSzAr *p, ISzAlloc *alloc)

+{

+  UInt32 i;

+  if (p->Folders)

+    for (i = 0; i < p->NumFolders; i++)

+      SzFolder_Free(&p->Folders[i], alloc);

+

+  IAlloc_Free(alloc, p->PackSizes);

+  IAlloc_Free(alloc, p->PackCRCsDefined);

+  IAlloc_Free(alloc, p->PackCRCs);

+  IAlloc_Free(alloc, p->Folders);

+  IAlloc_Free(alloc, p->Files);

+  SzAr_Init(p);

+}

+

+

+void SzArEx_Init(CSzArEx *p)

+{

+  SzAr_Init(&p->db);

+  p->FolderStartPackStreamIndex = 0;

+  p->PackStreamStartPositions = 0;

+  p->FolderStartFileIndex = 0;

+  p->FileIndexToFolderIndexMap = 0;

+  p->FileNameOffsets = 0;

+  Buf_Init(&p->FileNames);

+}

+

+void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)

+{

+  IAlloc_Free(alloc, p->FolderStartPackStreamIndex);

+  IAlloc_Free(alloc, p->PackStreamStartPositions);

+  IAlloc_Free(alloc, p->FolderStartFileIndex);

+  IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);

+

+  IAlloc_Free(alloc, p->FileNameOffsets);

+  Buf_Free(&p->FileNames, alloc);

+

+  SzAr_Free(&p->db, alloc);

+  SzArEx_Init(p);

+}

+

+/*

+UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const

+{

+  return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];

+}

+

+UInt64 GetFilePackSize(int fileIndex) const

+{

+  int folderIndex = FileIndexToFolderIndexMap[fileIndex];

+  if (folderIndex >= 0)

+  {

+    const CSzFolder &folderInfo = Folders[folderIndex];

+    if (FolderStartFileIndex[folderIndex] == fileIndex)

+    return GetFolderFullPackSize(folderIndex);

+  }

+  return 0;

+}

+*/

+

+#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \

+  if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; }

+

+static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc)

+{

+  UInt32 startPos = 0;

+  UInt64 startPosSize = 0;

+  UInt32 i;

+  UInt32 folderIndex = 0;

+  UInt32 indexInFolder = 0;

+  MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc);

+  for (i = 0; i < p->db.NumFolders; i++)

+  {

+    p->FolderStartPackStreamIndex[i] = startPos;

+    startPos += p->db.Folders[i].NumPackStreams;

+  }

+

+  MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc);

+

+  for (i = 0; i < p->db.NumPackStreams; i++)

+  {

+    p->PackStreamStartPositions[i] = startPosSize;

+    startPosSize += p->db.PackSizes[i];

+  }

+

+  MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc);

+  MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc);

+

+  for (i = 0; i < p->db.NumFiles; i++)

+  {

+    CSzFileItem *file = p->db.Files + i;

+    int emptyStream = !file->HasStream;

+    if (emptyStream && indexInFolder == 0)

+    {

+      p->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 >= p->db.NumFolders)

+          return SZ_ERROR_ARCHIVE;

+        p->FolderStartFileIndex[folderIndex] = i;

+        if (p->db.Folders[folderIndex].NumUnpackStreams != 0)

+          break;

+        folderIndex++;

+      }

+    }

+    p->FileIndexToFolderIndexMap[i] = folderIndex;

+    if (emptyStream)

+      continue;

+    indexInFolder++;

+    if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams)

+    {

+      folderIndex++;

+      indexInFolder = 0;

+    }

+  }

+  return SZ_OK;

+}

+

+

+UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder)

+{

+  return p->dataPos +

+    p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder];

+}

+

+int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize)

+{

+  UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex];

+  CSzFolder *folder = p->db.Folders + folderIndex;

+  UInt64 size = 0;

+  UInt32 i;

+  for (i = 0; i < folder->NumPackStreams; i++)

+  {

+    UInt64 t = size + p->db.PackSizes[packStreamIndex + i];

+    if (t < size) /* check it */

+      return SZ_ERROR_FAIL;

+    size = t;

+  }

+  *resSize = size;

+  return SZ_OK;

+}

+

+

+/*

+SRes SzReadTime(const CObjectVector<CBuf> &dataVector,

+    CObjectVector<CSzFileItem> &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++)

+  {

+    CSzFileItem &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 k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break;

+      case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break;

+      case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break;

+    }

+  }

+  return SZ_OK;

+}

+*/

+

+static 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;

+

+static SRes SzReadByte(CSzData *sd, Byte *b)

+{

+  if (sd->Size == 0)

+    return SZ_ERROR_ARCHIVE;

+  sd->Size--;

+  *b = *sd->Data++;

+  return SZ_OK;

+}

+

+static SRes 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;

+}

+

+static SRes 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;

+}

+

+static SRes 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;

+}

+

+static SRes SzReadNumber32(CSzData *sd, UInt32 *value)

+{

+  UInt64 value64;

+  RINOK(SzReadNumber(sd, &value64));

+  if (value64 >= 0x80000000)

+    return SZ_ERROR_UNSUPPORTED;

+  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))

+    return SZ_ERROR_UNSUPPORTED;

+  *value = (UInt32)value64;

+  return SZ_OK;

+}

+

+static SRes SzReadID(CSzData *sd, UInt64 *value)

+{

+  return SzReadNumber(sd, value);

+}

+

+static SRes SzSkeepDataSize(CSzData *sd, UInt64 size)

+{

+  if (size > sd->Size)

+    return SZ_ERROR_ARCHIVE;

+  sd->Size -= (size_t)size;

+  sd->Data += (size_t)size;

+  return SZ_OK;

+}

+

+static SRes SzSkeepData(CSzData *sd)

+{

+  UInt64 size;

+  RINOK(SzReadNumber(sd, &size));

+  return SzSkeepDataSize(sd, size);

+}

+

+static SRes SzReadArchiveProperties(CSzData *sd)

+{

+  for (;;)

+  {

+    UInt64 type;

+    RINOK(SzReadID(sd, &type));

+    if (type == k7zIdEnd)

+      break;

+    SzSkeepData(sd);

+  }

+  return SZ_OK;

+}

+

+static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute)

+{

+  for (;;)

+  {

+    UInt64 type;

+    RINOK(SzReadID(sd, &type));

+    if (type == attribute)

+      return SZ_OK;

+    if (type == k7zIdEnd)

+      return SZ_ERROR_ARCHIVE;

+    RINOK(SzSkeepData(sd));

+  }

+}

+

+static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)

+{

+  Byte b = 0;

+  Byte mask = 0;

+  size_t i;

+  MY_ALLOC(Byte, *v, numItems, alloc);

+  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;

+}

+

+static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)

+{

+  Byte allAreDefined;

+  size_t i;

+  RINOK(SzReadByte(sd, &allAreDefined));

+  if (allAreDefined == 0)

+    return SzReadBoolVector(sd, numItems, v, alloc);

+  MY_ALLOC(Byte, *v, numItems, alloc);

+  for (i = 0; i < numItems; i++)

+    (*v)[i] = 1;

+  return SZ_OK;

+}

+

+static SRes SzReadHashDigests(

+    CSzData *sd,

+    size_t numItems,

+    Byte **digestsDefined,

+    UInt32 **digests,

+    ISzAlloc *alloc)

+{

+  size_t i;

+  RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc));

+  MY_ALLOC(UInt32, *digests, numItems, alloc);

+  for (i = 0; i < numItems; i++)

+    if ((*digestsDefined)[i])

+    {

+      RINOK(SzReadUInt32(sd, (*digests) + i));

+    }

+  return SZ_OK;

+}

+

+static SRes SzReadPackInfo(

+    CSzData *sd,

+    UInt64 *dataOffset,

+    UInt32 *numPackStreams,

+    UInt64 **packSizes,

+    Byte **packCRCsDefined,

+    UInt32 **packCRCs,

+    ISzAlloc *alloc)

+{

+  UInt32 i;

+  RINOK(SzReadNumber(sd, dataOffset));

+  RINOK(SzReadNumber32(sd, numPackStreams));

+

+  RINOK(SzWaitAttribute(sd, k7zIdSize));

+

+  MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc);

+

+  for (i = 0; i < *numPackStreams; i++)

+  {

+    RINOK(SzReadNumber(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, alloc));

+      continue;

+    }

+    RINOK(SzSkeepData(sd));

+  }

+  if (*packCRCsDefined == 0)

+  {

+    MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc);

+    MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc);

+    for (i = 0; i < *numPackStreams; i++)

+    {

+      (*packCRCsDefined)[i] = 0;

+      (*packCRCs)[i] = 0;

+    }

+  }

+  return SZ_OK;

+}

+

+static SRes SzReadSwitch(CSzData *sd)

+{

+  Byte external;

+  RINOK(SzReadByte(sd, &external));

+  return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;

+}

+

+static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)

+{

+  UInt32 numCoders, numBindPairs, numPackStreams, i;

+  UInt32 numInStreams = 0, numOutStreams = 0;

+  

+  RINOK(SzReadNumber32(sd, &numCoders));

+  if (numCoders > NUM_FOLDER_CODERS_MAX)

+    return SZ_ERROR_UNSUPPORTED;

+  folder->NumCoders = numCoders;

+  

+  MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc);

+

+  for (i = 0; i < numCoders; i++)

+    SzCoderInfo_Init(folder->Coders + i);

+

+  for (i = 0; i < numCoders; i++)

+  {

+    Byte mainByte;

+    CSzCoderInfo *coder = folder->Coders + i;

+    {

+      unsigned idSize, j;

+      Byte longID[15];

+      RINOK(SzReadByte(sd, &mainByte));

+      idSize = (unsigned)(mainByte & 0xF);

+      RINOK(SzReadBytes(sd, longID, idSize));

+      if (idSize > sizeof(coder->MethodID))

+        return SZ_ERROR_UNSUPPORTED;

+      coder->MethodID = 0;

+      for (j = 0; j < idSize; j++)

+        coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j);

+

+      if ((mainByte & 0x10) != 0)

+      {

+        RINOK(SzReadNumber32(sd, &coder->NumInStreams));

+        RINOK(SzReadNumber32(sd, &coder->NumOutStreams));

+        if (coder->NumInStreams > NUM_CODER_STREAMS_MAX ||

+            coder->NumOutStreams > NUM_CODER_STREAMS_MAX)

+          return SZ_ERROR_UNSUPPORTED;

+      }

+      else

+      {

+        coder->NumInStreams = 1;

+        coder->NumOutStreams = 1;

+      }

+      if ((mainByte & 0x20) != 0)

+      {

+        UInt64 propertiesSize = 0;

+        RINOK(SzReadNumber(sd, &propertiesSize));

+        if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc))

+          return SZ_ERROR_MEM;

+        RINOK(SzReadBytes(sd, coder->Props.data, (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 += coder->NumInStreams;

+    numOutStreams += coder->NumOutStreams;

+  }

+

+  if (numOutStreams == 0)

+    return SZ_ERROR_UNSUPPORTED;

+

+  folder->NumBindPairs = numBindPairs = numOutStreams - 1;

+  MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);

+

+  for (i = 0; i < numBindPairs; i++)

+  {

+    CSzBindPair *bp = folder->BindPairs + i;

+    RINOK(SzReadNumber32(sd, &bp->InIndex));

+    RINOK(SzReadNumber32(sd, &bp->OutIndex));

+  }

+

+  if (numInStreams < numBindPairs)

+    return SZ_ERROR_UNSUPPORTED;

+

+  folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs;

+  MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc);

+

+  if (numPackStreams == 1)

+  {

+    for (i = 0; i < numInStreams ; i++)

+      if (SzFolder_FindBindPairForInStream(folder, i) < 0)

+        break;

+    if (i == numInStreams)

+      return SZ_ERROR_UNSUPPORTED;

+    folder->PackStreams[0] = i;

+  }

+  else

+    for (i = 0; i < numPackStreams; i++)

+    {

+      RINOK(SzReadNumber32(sd, folder->PackStreams + i));

+    }

+  return SZ_OK;

+}

+

+static SRes SzReadUnpackInfo(

+    CSzData *sd,

+    UInt32 *numFolders,

+    CSzFolder **folders,  /* for alloc */

+    ISzAlloc *alloc,

+    ISzAlloc *allocTemp)

+{

+  UInt32 i;

+  RINOK(SzWaitAttribute(sd, k7zIdFolder));

+  RINOK(SzReadNumber32(sd, numFolders));

+  {

+    RINOK(SzReadSwitch(sd));

+

+    MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc);

+

+    for (i = 0; i < *numFolders; i++)

+      SzFolder_Init((*folders) + i);

+

+    for (i = 0; i < *numFolders; i++)

+    {

+      RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc));

+    }

+  }

+

+  RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize));

+

+  for (i = 0; i < *numFolders; i++)

+  {

+    UInt32 j;

+    CSzFolder *folder = (*folders) + i;

+    UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder);

+

+    MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc);

+

+    for (j = 0; j < numOutStreams; j++)

+    {

+      RINOK(SzReadNumber(sd, folder->UnpackSizes + j));

+    }

+  }

+

+  for (;;)

+  {

+    UInt64 type;

+    RINOK(SzReadID(sd, &type));

+    if (type == k7zIdEnd)

+      return SZ_OK;

+    if (type == k7zIdCRC)

+    {

+      SRes res;

+      Byte *crcsDefined = 0;

+      UInt32 *crcs = 0;

+      res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp);

+      if (res == SZ_OK)

+      {

+        for (i = 0; i < *numFolders; i++)

+        {

+          CSzFolder *folder = (*folders) + i;

+          folder->UnpackCRCDefined = crcsDefined[i];

+          folder->UnpackCRC = crcs[i];

+        }

+      }

+      IAlloc_Free(allocTemp, crcs);

+      IAlloc_Free(allocTemp, crcsDefined);

+      RINOK(res);

+      continue;

+    }

+    RINOK(SzSkeepData(sd));

+  }

+}

+

+static SRes SzReadSubStreamsInfo(

+    CSzData *sd,

+    UInt32 numFolders,

+    CSzFolder *folders,

+    UInt32 *numUnpackStreams,

+    UInt64 **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 = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64));

+    RINOM(*unpackSizes);

+    *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte));

+    RINOM(*digestsDefined);

+    *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (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

+    */

+    UInt64 sum = 0;

+    UInt32 j;

+    UInt32 numSubstreams = folders[i].NumUnpackStreams;

+    if (numSubstreams == 0)

+      continue;

+    if (type == k7zIdSize)

+    for (j = 1; j < numSubstreams; j++)

+    {

+      UInt64 size;

+      RINOK(SzReadNumber(sd, &size));

+      (*unpackSizes)[si++] = size;

+      sum += size;

+    }

+    (*unpackSizes)[si++] = SzFolder_GetUnpackSize(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;

+      SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp);

+      if (res == SZ_OK)

+      {

+        for (i = 0; i < numFolders; i++)

+        {

+          CSzFolder *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++;

+            }

+          }

+        }

+      }

+      IAlloc_Free(allocTemp, digestsDefined2);

+      IAlloc_Free(allocTemp, digests2);

+      RINOK(res);

+    }

+    else if (type == k7zIdEnd)

+      return SZ_OK;

+    else

+    {

+      RINOK(SzSkeepData(sd));

+    }

+    RINOK(SzReadID(sd, &type));

+  }

+}

+

+

+static SRes SzReadStreamsInfo(

+    CSzData *sd,

+    UInt64 *dataOffset,

+    CSzAr *p,

+    UInt32 *numUnpackStreams,

+    UInt64 **unpackSizes, /* allocTemp */

+    Byte **digestsDefined,   /* allocTemp */

+    UInt32 **digests,        /* allocTemp */

+    ISzAlloc *alloc,

+    ISzAlloc *allocTemp)

+{

+  for (;;)

+  {

+    UInt64 type;

+    RINOK(SzReadID(sd, &type));

+    if ((UInt64)(int)type != type)

+      return SZ_ERROR_UNSUPPORTED;

+    switch((int)type)

+    {

+      case k7zIdEnd:

+        return SZ_OK;

+      case k7zIdPackInfo:

+      {

+        RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams,

+            &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc));

+        break;

+      }

+      case k7zIdUnpackInfo:

+      {

+        RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp));

+        break;

+      }

+      case k7zIdSubStreamsInfo:

+      {

+        RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders,

+            numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp));

+        break;

+      }

+      default:

+        return SZ_ERROR_UNSUPPORTED;

+    }

+  }

+}

+

+size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)

+{

+  size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];

+  if (dest != 0)

+  {

+    size_t i;

+    const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2);

+    for (i = 0; i < len; i++)

+      dest[i] = GetUi16(src + i * 2);

+  }

+  return len;

+}

+

+static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes)

+{

+  UInt32 i;

+  size_t pos = 0;

+  for (i = 0; i < numFiles; i++)

+  {

+    sizes[i] = pos;

+    for (;;)

+    {

+      if (pos >= size)

+        return SZ_ERROR_ARCHIVE;

+      if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0)

+        break;

+      pos++;

+    }

+    pos++;

+  }

+  sizes[i] = pos;

+  return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;

+}

+

+static SRes SzReadHeader2(

+    CSzArEx *p,   /* allocMain */

+    CSzData *sd,

+    UInt64 **unpackSizes,  /* allocTemp */

+    Byte **digestsDefined,    /* allocTemp */

+    UInt32 **digests,         /* allocTemp */

+    Byte **emptyStreamVector, /* allocTemp */

+    Byte **emptyFileVector,   /* allocTemp */

+    Byte **lwtVector,         /* allocTemp */

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp)

+{

+  UInt64 type;

+  UInt32 numUnpackStreams = 0;

+  UInt32 numFiles = 0;

+  CSzFileItem *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,

+        &p->dataPos,

+        &p->db,

+        &numUnpackStreams,

+        unpackSizes,

+        digestsDefined,

+        digests, allocMain, allocTemp));

+    p->dataPos += p->startPosAfterHeader;

+    RINOK(SzReadID(sd, &type));

+  }

+

+  if (type == k7zIdEnd)

+    return SZ_OK;

+  if (type != k7zIdFilesInfo)

+    return SZ_ERROR_ARCHIVE;

+  

+  RINOK(SzReadNumber32(sd, &numFiles));

+  p->db.NumFiles = numFiles;

+

+  MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain);

+

+  p->db.Files = files;

+  for (i = 0; i < numFiles; i++)

+    SzFile_Init(files + i);

+

+  for (;;)

+  {

+    UInt64 type;

+    UInt64 size;

+    RINOK(SzReadID(sd, &type));

+    if (type == k7zIdEnd)

+      break;

+    RINOK(SzReadNumber(sd, &size));

+    if (size > sd->Size)

+      return SZ_ERROR_ARCHIVE;

+    if ((UInt64)(int)type != type)

+    {

+      RINOK(SzSkeepDataSize(sd, size));

+    }

+    else

+    switch((int)type)

+    {

+      case k7zIdName:

+      {

+        size_t namesSize;

+        RINOK(SzReadSwitch(sd));

+        namesSize = (size_t)size - 1;

+        if ((namesSize & 1) != 0)

+          return SZ_ERROR_ARCHIVE;

+        if (!Buf_Create(&p->FileNames, namesSize, allocMain))

+          return SZ_ERROR_MEM;

+        MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);

+        memcpy(p->FileNames.data, sd->Data, namesSize);

+        RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets))

+        RINOK(SzSkeepDataSize(sd, namesSize));

+        break;

+      }

+      case k7zIdEmptyStream:

+      {

+        RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp));

+        numEmptyStreams = 0;

+        for (i = 0; i < numFiles; i++)

+          if ((*emptyStreamVector)[i])

+            numEmptyStreams++;

+        break;

+      }

+      case k7zIdEmptyFile:

+      {

+        RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));

+        break;

+      }

+      case k7zIdWinAttributes:

+      {

+        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));

+        RINOK(SzReadSwitch(sd));

+        for (i = 0; i < numFiles; i++)

+        {

+          CSzFileItem *f = &files[i];

+          Byte defined = (*lwtVector)[i];

+          f->AttribDefined = defined;

+          f->Attrib = 0;

+          if (defined)

+          {

+            RINOK(SzReadUInt32(sd, &f->Attrib));

+          }

+        }

+        IAlloc_Free(allocTemp, *lwtVector);

+        *lwtVector = NULL;

+        break;

+      }

+      case k7zIdMTime:

+      {

+        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));

+        RINOK(SzReadSwitch(sd));

+        for (i = 0; i < numFiles; i++)

+        {

+          CSzFileItem *f = &files[i];

+          Byte defined = (*lwtVector)[i];

+          f->MTimeDefined = defined;

+          f->MTime.Low = f->MTime.High = 0;

+          if (defined)

+          {

+            RINOK(SzReadUInt32(sd, &f->MTime.Low));

+            RINOK(SzReadUInt32(sd, &f->MTime.High));

+          }

+        }

+        IAlloc_Free(allocTemp, *lwtVector);

+        *lwtVector = NULL;

+        break;

+      }

+      default:

+      {

+        RINOK(SzSkeepDataSize(sd, size));

+      }

+    }

+  }

+

+  {

+    UInt32 emptyFileIndex = 0;

+    UInt32 sizeIndex = 0;

+    for (i = 0; i < numFiles; i++)

+    {

+      CSzFileItem *file = files + i;

+      file->IsAnti = 0;

+      if (*emptyStreamVector == 0)

+        file->HasStream = 1;

+      else

+        file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);

+      if (file->HasStream)

+      {

+        file->IsDir = 0;

+        file->Size = (*unpackSizes)[sizeIndex];

+        file->Crc = (*digests)[sizeIndex];

+        file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex];

+        sizeIndex++;

+      }

+      else

+      {

+        if (*emptyFileVector == 0)

+          file->IsDir = 1;

+        else

+          file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);

+        emptyFileIndex++;

+        file->Size = 0;

+        file->Crc = 0;

+        file->CrcDefined = 0;

+      }

+    }

+  }

+  return SzArEx_Fill(p, allocMain);

+}

+

+static SRes SzReadHeader(

+    CSzArEx *p,

+    CSzData *sd,

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp)

+{

+  UInt64 *unpackSizes = 0;

+  Byte *digestsDefined = 0;

+  UInt32 *digests = 0;

+  Byte *emptyStreamVector = 0;

+  Byte *emptyFileVector = 0;

+  Byte *lwtVector = 0;

+  SRes res = SzReadHeader2(p, sd,

+      &unpackSizes, &digestsDefined, &digests,

+      &emptyStreamVector, &emptyFileVector, &lwtVector,

+      allocMain, allocTemp);

+  IAlloc_Free(allocTemp, unpackSizes);

+  IAlloc_Free(allocTemp, digestsDefined);

+  IAlloc_Free(allocTemp, digests);

+  IAlloc_Free(allocTemp, emptyStreamVector);

+  IAlloc_Free(allocTemp, emptyFileVector);

+  IAlloc_Free(allocTemp, lwtVector);

+  return res;

+}

+

+static SRes SzReadAndDecodePackedStreams2(

+    ILookInStream *inStream,

+    CSzData *sd,

+    CBuf *outBuffer,

+    UInt64 baseOffset,

+    CSzAr *p,

+    UInt64 **unpackSizes,

+    Byte **digestsDefined,

+    UInt32 **digests,

+    ISzAlloc *allocTemp)

+{

+

+  UInt32 numUnpackStreams = 0;

+  UInt64 dataStartPos;

+  CSzFolder *folder;

+  UInt64 unpackSize;

+  SRes res;

+

+  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,

+      &numUnpackStreams,  unpackSizes, digestsDefined, digests,

+      allocTemp, allocTemp));

+  

+  dataStartPos += baseOffset;

+  if (p->NumFolders != 1)

+    return SZ_ERROR_ARCHIVE;

+

+  folder = p->Folders;

+  unpackSize = SzFolder_GetUnpackSize(folder);

+  

+  RINOK(LookInStream_SeekTo(inStream, dataStartPos));

+

+  if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))

+    return SZ_ERROR_MEM;

+  

+  res = SzFolder_Decode(folder, p->PackSizes,

+          inStream, dataStartPos,

+          outBuffer->data, (size_t)unpackSize, allocTemp);

+  RINOK(res);

+  if (folder->UnpackCRCDefined)

+    if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC)

+      return SZ_ERROR_CRC;

+  return SZ_OK;

+}

+

+static SRes SzReadAndDecodePackedStreams(

+    ILookInStream *inStream,

+    CSzData *sd,

+    CBuf *outBuffer,

+    UInt64 baseOffset,

+    ISzAlloc *allocTemp)

+{

+  CSzAr p;

+  UInt64 *unpackSizes = 0;

+  Byte *digestsDefined = 0;

+  UInt32 *digests = 0;

+  SRes res;

+  SzAr_Init(&p);

+  res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,

+    &p, &unpackSizes, &digestsDefined, &digests,

+    allocTemp);

+  SzAr_Free(&p, allocTemp);

+  IAlloc_Free(allocTemp, unpackSizes);

+  IAlloc_Free(allocTemp, digestsDefined);

+  IAlloc_Free(allocTemp, digests);

+  return res;

+}

+

+static SRes SzArEx_Open2(

+    CSzArEx *p,

+    ILookInStream *inStream,

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp)

+{

+  Byte header[k7zStartHeaderSize];

+  Int64 startArcPos;

+  UInt64 nextHeaderOffset, nextHeaderSize;

+  size_t nextHeaderSizeT;

+  UInt32 nextHeaderCRC;

+  CBuf buffer;

+  SRes res;

+

+  startArcPos = 0;

+  RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));

+

+  RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));

+

+  if (!TestSignatureCandidate(header))

+    return SZ_ERROR_NO_ARCHIVE;

+  if (header[6] != k7zMajorVersion)

+    return SZ_ERROR_UNSUPPORTED;

+

+  nextHeaderOffset = GetUi64(header + 12);

+  nextHeaderSize = GetUi64(header + 20);

+  nextHeaderCRC = GetUi32(header + 28);

+

+  p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;

+  

+  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))

+    return SZ_ERROR_CRC;

+

+  nextHeaderSizeT = (size_t)nextHeaderSize;

+  if (nextHeaderSizeT != nextHeaderSize)

+    return SZ_ERROR_MEM;

+  if (nextHeaderSizeT == 0)

+    return SZ_OK;

+  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||

+      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)

+    return SZ_ERROR_NO_ARCHIVE;

+

+  {

+    Int64 pos = 0;

+    RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));

+    if ((UInt64)pos < startArcPos + nextHeaderOffset ||

+        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||

+        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)

+      return SZ_ERROR_INPUT_EOF;

+  }

+

+  RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));

+

+  if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))

+    return SZ_ERROR_MEM;

+

+  res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT);

+  if (res == SZ_OK)

+  {

+    res = SZ_ERROR_ARCHIVE;

+    if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC)

+    {

+      CSzData sd;

+      UInt64 type;

+      sd.Data = buffer.data;

+      sd.Size = buffer.size;

+      res = SzReadID(&sd, &type);

+      if (res == SZ_OK)

+      {

+        if (type == k7zIdEncodedHeader)

+        {

+          CBuf outBuffer;

+          Buf_Init(&outBuffer);

+          res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp);

+          if (res != SZ_OK)

+            Buf_Free(&outBuffer, allocTemp);

+          else

+          {

+            Buf_Free(&buffer, allocTemp);

+            buffer.data = outBuffer.data;

+            buffer.size = outBuffer.size;

+            sd.Data = buffer.data;

+            sd.Size = buffer.size;

+            res = SzReadID(&sd, &type);

+          }

+        }

+      }

+      if (res == SZ_OK)

+      {

+        if (type == k7zIdHeader)

+          res = SzReadHeader(p, &sd, allocMain, allocTemp);

+        else

+          res = SZ_ERROR_UNSUPPORTED;

+      }

+    }

+  }

+  Buf_Free(&buffer, allocTemp);

+  return res;

+}

+

+SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp)

+{

+  SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);

+  if (res != SZ_OK)

+    SzArEx_Free(p, allocMain);

+  return res;

+}

+

+SRes SzArEx_Extract(

+    const CSzArEx *p,

+    ILookInStream *inStream,

+    UInt32 fileIndex,

+    UInt32 *blockIndex,

+    Byte **outBuffer,

+    size_t *outBufferSize,

+    size_t *offset,

+    size_t *outSizeProcessed,

+    ISzAlloc *allocMain,

+    ISzAlloc *allocTemp)

+{

+  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];

+  SRes res = SZ_OK;

+  *offset = 0;

+  *outSizeProcessed = 0;

+  if (folderIndex == (UInt32)-1)

+  {

+    IAlloc_Free(allocMain, *outBuffer);

+    *blockIndex = folderIndex;

+    *outBuffer = 0;

+    *outBufferSize = 0;

+    return SZ_OK;

+  }

+

+  if (*outBuffer == 0 || *blockIndex != folderIndex)

+  {

+    CSzFolder *folder = p->db.Folders + folderIndex;

+    UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);

+    size_t unpackSize = (size_t)unpackSizeSpec;

+    UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);

+

+    if (unpackSize != unpackSizeSpec)

+      return SZ_ERROR_MEM;

+    *blockIndex = folderIndex;

+    IAlloc_Free(allocMain, *outBuffer);

+    *outBuffer = 0;

+    

+    RINOK(LookInStream_SeekTo(inStream, startOffset));

+    

+    if (res == SZ_OK)

+    {

+      *outBufferSize = unpackSize;

+      if (unpackSize != 0)

+      {

+        *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);

+        if (*outBuffer == 0)

+          res = SZ_ERROR_MEM;

+      }

+      if (res == SZ_OK)

+      {

+        res = SzFolder_Decode(folder,

+          p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],

+          inStream, startOffset,

+          *outBuffer, unpackSize, allocTemp);

+        if (res == SZ_OK)

+        {

+          if (folder->UnpackCRCDefined)

+          {

+            if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)

+              res = SZ_ERROR_CRC;

+          }

+        }

+      }

+    }

+  }

+  if (res == SZ_OK)

+  {

+    UInt32 i;

+    CSzFileItem *fileItem = p->db.Files + fileIndex;

+    *offset = 0;

+    for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)

+      *offset += (UInt32)p->db.Files[i].Size;

+    *outSizeProcessed = (size_t)fileItem->Size;

+    if (*offset + *outSizeProcessed > *outBufferSize)

+      return SZ_ERROR_FAIL;

+    if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc)

+      res = SZ_ERROR_CRC;

+  }

+  return res;

+}

diff --git a/C/7zStream.c b/C/7zStream.c
new file mode 100755
index 0000000..f0959fb
--- /dev/null
+++ b/C/7zStream.c
@@ -0,0 +1,169 @@
+/* 7zStream.c -- 7z Stream functions

+2010-03-11 : Igor Pavlov : Public domain */

+

+#include <string.h>

+

+#include "Types.h"

+

+SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)

+{

+  while (size != 0)

+  {

+    size_t processed = size;

+    RINOK(stream->Read(stream, buf, &processed));

+    if (processed == 0)

+      return errorType;

+    buf = (void *)((Byte *)buf + processed);

+    size -= processed;

+  }

+  return SZ_OK;

+}

+

+SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)

+{

+  return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);

+}

+

+SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)

+{

+  size_t processed = 1;

+  RINOK(stream->Read(stream, buf, &processed));

+  return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;

+}

+

+SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)

+{

+  Int64 t = offset;

+  return stream->Seek(stream, &t, SZ_SEEK_SET);

+}

+

+SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)

+{

+  const void *lookBuf;

+  if (*size == 0)

+    return SZ_OK;

+  RINOK(stream->Look(stream, &lookBuf, size));

+  memcpy(buf, lookBuf, *size);

+  return stream->Skip(stream, *size);

+}

+

+SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)

+{

+  while (size != 0)

+  {

+    size_t processed = size;

+    RINOK(stream->Read(stream, buf, &processed));

+    if (processed == 0)

+      return errorType;

+    buf = (void *)((Byte *)buf + processed);

+    size -= processed;

+  }

+  return SZ_OK;

+}

+

+SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)

+{

+  return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);

+}

+

+static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)

+{

+  SRes res = SZ_OK;

+  CLookToRead *p = (CLookToRead *)pp;

+  size_t size2 = p->size - p->pos;

+  if (size2 == 0 && *size > 0)

+  {

+    p->pos = 0;

+    size2 = LookToRead_BUF_SIZE;

+    res = p->realStream->Read(p->realStream, p->buf, &size2);

+    p->size = size2;

+  }

+  if (size2 < *size)

+    *size = size2;

+  *buf = p->buf + p->pos;

+  return res;

+}

+

+static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)

+{

+  SRes res = SZ_OK;

+  CLookToRead *p = (CLookToRead *)pp;

+  size_t size2 = p->size - p->pos;

+  if (size2 == 0 && *size > 0)

+  {

+    p->pos = 0;

+    if (*size > LookToRead_BUF_SIZE)

+      *size = LookToRead_BUF_SIZE;

+    res = p->realStream->Read(p->realStream, p->buf, size);

+    size2 = p->size = *size;

+  }

+  if (size2 < *size)

+    *size = size2;

+  *buf = p->buf + p->pos;

+  return res;

+}

+

+static SRes LookToRead_Skip(void *pp, size_t offset)

+{

+  CLookToRead *p = (CLookToRead *)pp;

+  p->pos += offset;

+  return SZ_OK;

+}

+

+static SRes LookToRead_Read(void *pp, void *buf, size_t *size)

+{

+  CLookToRead *p = (CLookToRead *)pp;

+  size_t rem = p->size - p->pos;

+  if (rem == 0)

+    return p->realStream->Read(p->realStream, buf, size);

+  if (rem > *size)

+    rem = *size;

+  memcpy(buf, p->buf + p->pos, rem);

+  p->pos += rem;

+  *size = rem;

+  return SZ_OK;

+}

+

+static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)

+{

+  CLookToRead *p = (CLookToRead *)pp;

+  p->pos = p->size = 0;

+  return p->realStream->Seek(p->realStream, pos, origin);

+}

+

+void LookToRead_CreateVTable(CLookToRead *p, int lookahead)

+{

+  p->s.Look = lookahead ?

+      LookToRead_Look_Lookahead :

+      LookToRead_Look_Exact;

+  p->s.Skip = LookToRead_Skip;

+  p->s.Read = LookToRead_Read;

+  p->s.Seek = LookToRead_Seek;

+}

+

+void LookToRead_Init(CLookToRead *p)

+{

+  p->pos = p->size = 0;

+}

+

+static SRes SecToLook_Read(void *pp, void *buf, size_t *size)

+{

+  CSecToLook *p = (CSecToLook *)pp;

+  return LookInStream_LookRead(p->realStream, buf, size);

+}

+

+void SecToLook_CreateVTable(CSecToLook *p)

+{

+  p->s.Read = SecToLook_Read;

+}

+

+static SRes SecToRead_Read(void *pp, void *buf, size_t *size)

+{

+  CSecToRead *p = (CSecToRead *)pp;

+  return p->realStream->Read(p->realStream, buf, size);

+}

+

+void SecToRead_CreateVTable(CSecToRead *p)

+{

+  p->s.Read = SecToRead_Read;

+}

diff --git a/C/7zVersion.h b/C/7zVersion.h
new file mode 100755
index 0000000..d4ac470
--- /dev/null
+++ b/C/7zVersion.h
@@ -0,0 +1,7 @@
+#define MY_VER_MAJOR 9

+#define MY_VER_MINOR 20

+#define MY_VER_BUILD 0

+#define MY_VERSION "9.20"

+#define MY_DATE "2010-11-18"

+#define MY_COPYRIGHT ": Igor Pavlov : Public domain"

+#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

diff --git a/C/Alloc.c b/C/Alloc.c
new file mode 100755
index 0000000..bb24a77
--- /dev/null
+++ b/C/Alloc.c
@@ -0,0 +1,127 @@
+/* Alloc.c -- Memory allocation functions

+2008-09-24

+Igor Pavlov

+Public domain */

+

+#ifdef _WIN32

+#include <windows.h>

+#endif

+#include <stdlib.h>

+

+#include "Alloc.h"

+

+/* #define _SZ_ALLOC_DEBUG */

+

+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */

+#ifdef _SZ_ALLOC_DEBUG

+#include <stdio.h>

+int g_allocCount = 0;

+int g_allocCountMid = 0;

+int g_allocCountBig = 0;

+#endif

+

+void *MyAlloc(size_t size)

+{

+  if (size == 0)

+    return 0;

+  #ifdef _SZ_ALLOC_DEBUG

+  {

+    void *p = malloc(size);

+    fprintf(stderr, "\nAlloc %10d bytes, count = %10d,  addr = %8X", size, g_allocCount++, (unsigned)p);

+    return p;

+  }

+  #else

+  return malloc(size);

+  #endif

+}

+

+void MyFree(void *address)

+{

+  #ifdef _SZ_ALLOC_DEBUG

+  if (address != 0)

+    fprintf(stderr, "\nFree; count = %10d,  addr = %8X", --g_allocCount, (unsigned)address);

+  #endif

+  free(address);

+}

+

+#ifdef _WIN32

+

+void *MidAlloc(size_t size)

+{

+  if (size == 0)

+    return 0;

+  #ifdef _SZ_ALLOC_DEBUG

+  fprintf(stderr, "\nAlloc_Mid %10d bytes;  count = %10d", size, g_allocCountMid++);

+  #endif

+  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);

+}

+

+void MidFree(void *address)

+{

+  #ifdef _SZ_ALLOC_DEBUG

+  if (address != 0)

+    fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);

+  #endif

+  if (address == 0)

+    return;

+  VirtualFree(address, 0, MEM_RELEASE);

+}

+

+#ifndef MEM_LARGE_PAGES

+#undef _7ZIP_LARGE_PAGES

+#endif

+

+#ifdef _7ZIP_LARGE_PAGES

+SIZE_T g_LargePageSize = 0;

+typedef SIZE_T (WINAPI *GetLargePageMinimumP)();

+#endif

+

+void SetLargePageSize()

+{

+  #ifdef _7ZIP_LARGE_PAGES

+  SIZE_T size = 0;

+  GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)

+        GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");

+  if (largePageMinimum == 0)

+    return;

+  size = largePageMinimum();

+  if (size == 0 || (size & (size - 1)) != 0)

+    return;

+  g_LargePageSize = size;

+  #endif

+}

+

+

+void *BigAlloc(size_t size)

+{

+  if (size == 0)

+    return 0;

+  #ifdef _SZ_ALLOC_DEBUG

+  fprintf(stderr, "\nAlloc_Big %10d bytes;  count = %10d", size, g_allocCountBig++);

+  #endif

+  

+  #ifdef _7ZIP_LARGE_PAGES

+  if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))

+  {

+    void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),

+        MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);

+    if (res != 0)

+      return res;

+  }

+  #endif

+  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);

+}

+

+void BigFree(void *address)

+{

+  #ifdef _SZ_ALLOC_DEBUG

+  if (address != 0)

+    fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);

+  #endif

+  

+  if (address == 0)

+    return;

+  VirtualFree(address, 0, MEM_RELEASE);

+}

+

+#endif

diff --git a/C/Alloc.h b/C/Alloc.h
new file mode 100755
index 0000000..6b3f034
--- /dev/null
+++ b/C/Alloc.h
@@ -0,0 +1,38 @@
+/* Alloc.h -- Memory allocation functions

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __COMMON_ALLOC_H

+#define __COMMON_ALLOC_H

+

+#include <stddef.h>

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+void *MyAlloc(size_t size);

+void MyFree(void *address);

+

+#ifdef _WIN32

+

+void SetLargePageSize();

+

+void *MidAlloc(size_t size);

+void MidFree(void *address);

+void *BigAlloc(size_t size);

+void BigFree(void *address);

+

+#else

+

+#define MidAlloc(size) MyAlloc(size)

+#define MidFree(address) MyFree(address)

+#define BigAlloc(size) MyAlloc(size)

+#define BigFree(address) MyFree(address)

+

+#endif

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/Bcj2.c b/C/Bcj2.c
new file mode 100755
index 0000000..474bdd4
--- /dev/null
+++ b/C/Bcj2.c
@@ -0,0 +1,132 @@
+/* Bcj2.c -- Converter for x86 code (BCJ2)

+2008-10-04 : Igor Pavlov : Public domain */

+

+#include "Bcj2.h"

+

+#ifdef _LZMA_PROB32

+#define CProb UInt32

+#else

+#define CProb UInt16

+#endif

+

+#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)

+#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))

+

+#define kNumTopBits 24

+#define kTopValue ((UInt32)1 << kNumTopBits)

+

+#define kNumBitModelTotalBits 11

+#define kBitModelTotal (1 << kNumBitModelTotalBits)

+#define kNumMoveBits 5

+

+#define RC_READ_BYTE (*buffer++)

+#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }

+#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \

+  { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}

+

+#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }

+

+#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)

+#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;

+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;

+

+int Bcj2_Decode(

+    const Byte *buf0, SizeT size0,

+    const Byte *buf1, SizeT size1,

+    const Byte *buf2, SizeT size2,

+    const Byte *buf3, SizeT size3,

+    Byte *outBuf, SizeT outSize)

+{

+  CProb p[256 + 2];

+  SizeT inPos = 0, outPos = 0;

+

+  const Byte *buffer, *bufferLim;

+  UInt32 range, code;

+  Byte prevByte = 0;

+

+  unsigned int i;

+  for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)

+    p[i] = kBitModelTotal >> 1;

+

+  buffer = buf3;

+  bufferLim = buffer + size3;

+  RC_INIT2

+

+  if (outSize == 0)

+    return SZ_OK;

+

+  for (;;)

+  {

+    Byte b;

+    CProb *prob;

+    UInt32 bound;

+    UInt32 ttt;

+

+    SizeT limit = size0 - inPos;

+    if (outSize - outPos < limit)

+      limit = outSize - outPos;

+    while (limit != 0)

+    {

+      Byte b = buf0[inPos];

+      outBuf[outPos++] = b;

+      if (IsJ(prevByte, b))

+        break;

+      inPos++;

+      prevByte = b;

+      limit--;

+    }

+

+    if (limit == 0 || outPos == outSize)

+      break;

+

+    b = buf0[inPos++];

+

+    if (b == 0xE8)

+      prob = p + prevByte;

+    else if (b == 0xE9)

+      prob = p + 256;

+    else

+      prob = p + 257;

+

+    IF_BIT_0(prob)

+    {

+      UPDATE_0(prob)

+      prevByte = b;

+    }

+    else

+    {

+      UInt32 dest;

+      const Byte *v;

+      UPDATE_1(prob)

+      if (b == 0xE8)

+      {

+        v = buf1;

+        if (size1 < 4)

+          return SZ_ERROR_DATA;

+        buf1 += 4;

+        size1 -= 4;

+      }

+      else

+      {

+        v = buf2;

+        if (size2 < 4)

+          return SZ_ERROR_DATA;

+        buf2 += 4;

+        size2 -= 4;

+      }

+      dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |

+          ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);

+      outBuf[outPos++] = (Byte)dest;

+      if (outPos == outSize)

+        break;

+      outBuf[outPos++] = (Byte)(dest >> 8);

+      if (outPos == outSize)

+        break;

+      outBuf[outPos++] = (Byte)(dest >> 16);

+      if (outPos == outSize)

+        break;

+      outBuf[outPos++] = prevByte = (Byte)(dest >> 24);

+    }

+  }

+  return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;

+}

diff --git a/C/Bcj2.h b/C/Bcj2.h
new file mode 100755
index 0000000..d9d857b
--- /dev/null
+++ b/C/Bcj2.h
@@ -0,0 +1,38 @@
+/* Bcj2.h -- Converter for x86 code (BCJ2)

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __BCJ2_H

+#define __BCJ2_H

+

+#include "Types.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+/*

+Conditions:

+  outSize <= FullOutputSize,

+  where FullOutputSize is full size of output stream of x86_2 filter.

+

+If buf0 overlaps outBuf, there are two required conditions:

+  1) (buf0 >= outBuf)

+  2) (buf0 + size0 >= outBuf + FullOutputSize).

+

+Returns:

+  SZ_OK

+  SZ_ERROR_DATA - Data error

+*/

+

+int Bcj2_Decode(

+    const Byte *buf0, SizeT size0,

+    const Byte *buf1, SizeT size1,

+    const Byte *buf2, SizeT size2,

+    const Byte *buf3, SizeT size3,

+    Byte *outBuf, SizeT outSize);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/Bra.c b/C/Bra.c
new file mode 100755
index 0000000..2a0f147
--- /dev/null
+++ b/C/Bra.c
@@ -0,0 +1,133 @@
+/* Bra.c -- Converters for RISC code

+2010-04-16 : Igor Pavlov : Public domain */

+

+#include "Bra.h"

+

+SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)

+{

+  SizeT i;

+  if (size < 4)

+    return 0;

+  size -= 4;

+  ip += 8;

+  for (i = 0; i <= size; i += 4)

+  {

+    if (data[i + 3] == 0xEB)

+    {

+      UInt32 dest;

+      UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);

+      src <<= 2;

+      if (encoding)

+        dest = ip + (UInt32)i + src;

+      else

+        dest = src - (ip + (UInt32)i);

+      dest >>= 2;

+      data[i + 2] = (Byte)(dest >> 16);

+      data[i + 1] = (Byte)(dest >> 8);

+      data[i + 0] = (Byte)dest;

+    }

+  }

+  return i;

+}

+

+SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)

+{

+  SizeT i;

+  if (size < 4)

+    return 0;

+  size -= 4;

+  ip += 4;

+  for (i = 0; i <= size; i += 2)

+  {

+    if ((data[i + 1] & 0xF8) == 0xF0 &&

+        (data[i + 3] & 0xF8) == 0xF8)

+    {

+      UInt32 dest;

+      UInt32 src =

+        (((UInt32)data[i + 1] & 0x7) << 19) |

+        ((UInt32)data[i + 0] << 11) |

+        (((UInt32)data[i + 3] & 0x7) << 8) |

+        (data[i + 2]);

+      

+      src <<= 1;

+      if (encoding)

+        dest = ip + (UInt32)i + src;

+      else

+        dest = src - (ip + (UInt32)i);

+      dest >>= 1;

+      

+      data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));

+      data[i + 0] = (Byte)(dest >> 11);

+      data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));

+      data[i + 2] = (Byte)dest;

+      i += 2;

+    }

+  }

+  return i;

+}

+

+SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)

+{

+  SizeT i;

+  if (size < 4)

+    return 0;

+  size -= 4;

+  for (i = 0; i <= size; i += 4)

+  {

+    if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)

+    {

+      UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |

+        ((UInt32)data[i + 1] << 16) |

+        ((UInt32)data[i + 2] << 8) |

+        ((UInt32)data[i + 3] & (~3));

+      

+      UInt32 dest;

+      if (encoding)

+        dest = ip + (UInt32)i + src;

+      else

+        dest = src - (ip + (UInt32)i);

+      data[i + 0] = (Byte)(0x48 | ((dest >> 24) &  0x3));

+      data[i + 1] = (Byte)(dest >> 16);

+      data[i + 2] = (Byte)(dest >> 8);

+      data[i + 3] &= 0x3;

+      data[i + 3] |= dest;

+    }

+  }

+  return i;

+}

+

+SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)

+{

+  UInt32 i;

+  if (size < 4)

+    return 0;

+  size -= 4;

+  for (i = 0; i <= size; i += 4)

+  {

+    if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||

+        (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))

+    {

+      UInt32 src =

+        ((UInt32)data[i + 0] << 24) |

+        ((UInt32)data[i + 1] << 16) |

+        ((UInt32)data[i + 2] << 8) |

+        ((UInt32)data[i + 3]);

+      UInt32 dest;

+      

+      src <<= 2;

+      if (encoding)

+        dest = ip + i + src;

+      else

+        dest = src - (ip + i);

+      dest >>= 2;

+      

+      dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;

+

+      data[i + 0] = (Byte)(dest >> 24);

+      data[i + 1] = (Byte)(dest >> 16);

+      data[i + 2] = (Byte)(dest >> 8);

+      data[i + 3] = (Byte)dest;

+    }

+  }

+  return i;

+}

diff --git a/C/Bra.h b/C/Bra.h
new file mode 100755
index 0000000..9c91e33
--- /dev/null
+++ b/C/Bra.h
@@ -0,0 +1,68 @@
+/* Bra.h -- Branch converters for executables

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __BRA_H

+#define __BRA_H

+

+#include "Types.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+/*

+These functions convert relative addresses to absolute addresses

+in CALL instructions to increase the compression ratio.

+  

+  In:

+    data     - data buffer

+    size     - size of data

+    ip       - current virtual Instruction Pinter (IP) value

+    state    - state variable for x86 converter

+    encoding - 0 (for decoding), 1 (for encoding)

+  

+  Out:

+    state    - state variable for x86 converter

+

+  Returns:

+    The number of processed bytes. If you call these functions with multiple calls,

+    you must start next call with first byte after block of processed bytes.

+  

+  Type   Endian  Alignment  LookAhead

+  

+  x86    little      1          4

+  ARMT   little      2          2

+  ARM    little      4          0

+  PPC     big        4          0

+  SPARC   big        4          0

+  IA64   little     16          0

+

+  size must be >= Alignment + LookAhead, if it's not last block.

+  If (size < Alignment + LookAhead), converter returns 0.

+

+  Example:

+

+    UInt32 ip = 0;

+    for ()

+    {

+      ; size must be >= Alignment + LookAhead, if it's not last block

+      SizeT processed = Convert(data, size, ip, 1);

+      data += processed;

+      size -= processed;

+      ip += processed;

+    }

+*/

+

+#define x86_Convert_Init(state) { state = 0; }

+SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);

+SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);

+SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);

+SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);

+SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);

+SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/Bra86.c b/C/Bra86.c
new file mode 100755
index 0000000..93566cb
--- /dev/null
+++ b/C/Bra86.c
@@ -0,0 +1,85 @@
+/* Bra86.c -- Converter for x86 code (BCJ)

+2008-10-04 : Igor Pavlov : Public domain */

+

+#include "Bra.h"

+

+#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)

+

+const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};

+const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};

+

+SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)

+{

+  SizeT bufferPos = 0, prevPosT;

+  UInt32 prevMask = *state & 0x7;

+  if (size < 5)

+    return 0;

+  ip += 5;

+  prevPosT = (SizeT)0 - 1;

+

+  for (;;)

+  {

+    Byte *p = data + bufferPos;

+    Byte *limit = data + size - 4;

+    for (; p < limit; p++)

+      if ((*p & 0xFE) == 0xE8)

+        break;

+    bufferPos = (SizeT)(p - data);

+    if (p >= limit)

+      break;

+    prevPosT = bufferPos - prevPosT;

+    if (prevPosT > 3)

+      prevMask = 0;

+    else

+    {

+      prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;

+      if (prevMask != 0)

+      {

+        Byte b = p[4 - kMaskToBitNumber[prevMask]];

+        if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))

+        {

+          prevPosT = bufferPos;

+          prevMask = ((prevMask << 1) & 0x7) | 1;

+          bufferPos++;

+          continue;

+        }

+      }

+    }

+    prevPosT = bufferPos;

+

+    if (Test86MSByte(p[4]))

+    {

+      UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);

+      UInt32 dest;

+      for (;;)

+      {

+        Byte b;

+        int index;

+        if (encoding)

+          dest = (ip + (UInt32)bufferPos) + src;

+        else

+          dest = src - (ip + (UInt32)bufferPos);

+        if (prevMask == 0)

+          break;

+        index = kMaskToBitNumber[prevMask] * 8;

+        b = (Byte)(dest >> (24 - index));

+        if (!Test86MSByte(b))

+          break;

+        src = dest ^ ((1 << (32 - index)) - 1);

+      }

+      p[4] = (Byte)(~(((dest >> 24) & 1) - 1));

+      p[3] = (Byte)(dest >> 16);

+      p[2] = (Byte)(dest >> 8);

+      p[1] = (Byte)dest;

+      bufferPos += 5;

+    }

+    else

+    {

+      prevMask = ((prevMask << 1) & 0x7) | 1;

+      bufferPos++;

+    }

+  }

+  prevPosT = bufferPos - prevPosT;

+  *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));

+  return bufferPos;

+}

diff --git a/C/BraIA64.c b/C/BraIA64.c
new file mode 100755
index 0000000..f359f16
--- /dev/null
+++ b/C/BraIA64.c
@@ -0,0 +1,67 @@
+/* BraIA64.c -- Converter for IA-64 code

+2008-10-04 : Igor Pavlov : Public domain */

+

+#include "Bra.h"

+

+static const Byte kBranchTable[32] =

+{

+  0, 0, 0, 0, 0, 0, 0, 0,

+  0, 0, 0, 0, 0, 0, 0, 0,

+  4, 4, 6, 6, 0, 0, 7, 7,

+  4, 4, 0, 0, 4, 4, 0, 0

+};

+

+SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)

+{

+  SizeT i;

+  if (size < 16)

+    return 0;

+  size -= 16;

+  for (i = 0; i <= size; i += 16)

+  {

+    UInt32 instrTemplate = data[i] & 0x1F;

+    UInt32 mask = kBranchTable[instrTemplate];

+    UInt32 bitPos = 5;

+    int slot;

+    for (slot = 0; slot < 3; slot++, bitPos += 41)

+    {

+      UInt32 bytePos, bitRes;

+      UInt64 instruction, instNorm;

+      int j;

+      if (((mask >> slot) & 1) == 0)

+        continue;

+      bytePos = (bitPos >> 3);

+      bitRes = bitPos & 0x7;

+      instruction = 0;

+      for (j = 0; j < 6; j++)

+        instruction += (UInt64)data[i + j + bytePos] << (8 * j);

+

+      instNorm = instruction >> bitRes;

+      if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0)

+      {

+        UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);

+        UInt32 dest;

+        src |= ((UInt32)(instNorm >> 36) & 1) << 20;

+        

+        src <<= 4;

+        

+        if (encoding)

+          dest = ip + (UInt32)i + src;

+        else

+          dest = src - (ip + (UInt32)i);

+        

+        dest >>= 4;

+        

+        instNorm &= ~((UInt64)(0x8FFFFF) << 13);

+        instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);

+        instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));

+        

+        instruction &= (1 << bitRes) - 1;

+        instruction |= (instNorm << bitRes);

+        for (j = 0; j < 6; j++)

+          data[i + j + bytePos] = (Byte)(instruction >> (8 * j));

+      }

+    }

+  }

+  return i;

+}

diff --git a/C/CpuArch.c b/C/CpuArch.c
new file mode 100755
index 0000000..36e7680
--- /dev/null
+++ b/C/CpuArch.c
@@ -0,0 +1,168 @@
+/* CpuArch.c -- CPU specific code

+2010-10-26: Igor Pavlov : Public domain */

+

+#include "CpuArch.h"

+

+#ifdef MY_CPU_X86_OR_AMD64

+

+#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)

+#define USE_ASM

+#endif

+

+#if defined(USE_ASM) && !defined(MY_CPU_AMD64)

+static UInt32 CheckFlag(UInt32 flag)

+{

+  #ifdef _MSC_VER

+  __asm pushfd;

+  __asm pop EAX;

+  __asm mov EDX, EAX;

+  __asm xor EAX, flag;

+  __asm push EAX;

+  __asm popfd;

+  __asm pushfd;

+  __asm pop EAX;

+  __asm xor EAX, EDX;

+  __asm push EDX;

+  __asm popfd;

+  __asm and flag, EAX;

+  #else

+  __asm__ __volatile__ (

+    "pushf\n\t"

+    "pop  %%EAX\n\t"

+    "movl %%EAX,%%EDX\n\t"

+    "xorl %0,%%EAX\n\t"

+    "push %%EAX\n\t"

+    "popf\n\t"

+    "pushf\n\t"

+    "pop  %%EAX\n\t"

+    "xorl %%EDX,%%EAX\n\t"

+    "push %%EDX\n\t"

+    "popf\n\t"

+    "andl %%EAX, %0\n\t":

+    "=c" (flag) : "c" (flag));

+  #endif

+  return flag;

+}

+#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;

+#else

+#define CHECK_CPUID_IS_SUPPORTED

+#endif

+

+static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)

+{

+  #ifdef USE_ASM

+

+  #ifdef _MSC_VER

+

+  UInt32 a2, b2, c2, d2;

+  __asm xor EBX, EBX;

+  __asm xor ECX, ECX;

+  __asm xor EDX, EDX;

+  __asm mov EAX, function;

+  __asm cpuid;

+  __asm mov a2, EAX;

+  __asm mov b2, EBX;

+  __asm mov c2, ECX;

+  __asm mov d2, EDX;

+

+  *a = a2;

+  *b = b2;

+  *c = c2;

+  *d = d2;

+

+  #else

+

+  __asm__ __volatile__ (

+    "cpuid"

+    : "=a" (*a) ,

+      "=b" (*b) ,

+      "=c" (*c) ,

+      "=d" (*d)

+    : "0" (function)) ;

+

+  #endif

+  

+  #else

+

+  int CPUInfo[4];

+  __cpuid(CPUInfo, function);

+  *a = CPUInfo[0];

+  *b = CPUInfo[1];

+  *c = CPUInfo[2];

+  *d = CPUInfo[3];

+

+  #endif

+}

+

+Bool x86cpuid_CheckAndRead(Cx86cpuid *p)

+{

+  CHECK_CPUID_IS_SUPPORTED

+  MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);

+  MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);

+  return True;

+}

+

+static UInt32 kVendors[][3] =

+{

+  { 0x756E6547, 0x49656E69, 0x6C65746E},

+  { 0x68747541, 0x69746E65, 0x444D4163},

+  { 0x746E6543, 0x48727561, 0x736C7561}

+};

+

+int x86cpuid_GetFirm(const Cx86cpuid *p)

+{

+  unsigned i;

+  for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)

+  {

+    const UInt32 *v = kVendors[i];

+    if (v[0] == p->vendor[0] &&

+        v[1] == p->vendor[1] &&

+        v[2] == p->vendor[2])

+      return (int)i;

+  }

+  return -1;

+}

+

+Bool CPU_Is_InOrder()

+{

+  Cx86cpuid p;

+  int firm;

+  UInt32 family, model;

+  if (!x86cpuid_CheckAndRead(&p))

+    return True;

+  family = x86cpuid_GetFamily(&p);

+  model = x86cpuid_GetModel(&p);

+  firm = x86cpuid_GetFirm(&p);

+  switch (firm)

+  {

+    case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));

+    case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));

+    case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));

+  }

+  return True;

+}

+

+#if !defined(MY_CPU_AMD64) && defined(_WIN32)

+static Bool CPU_Sys_Is_SSE_Supported()

+{

+  OSVERSIONINFO vi;

+  vi.dwOSVersionInfoSize = sizeof(vi);

+  if (!GetVersionEx(&vi))

+    return False;

+  return (vi.dwMajorVersion >= 5);

+}

+#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;

+#else

+#define CHECK_SYS_SSE_SUPPORT

+#endif

+

+Bool CPU_Is_Aes_Supported()

+{

+  Cx86cpuid p;

+  CHECK_SYS_SSE_SUPPORT

+  if (!x86cpuid_CheckAndRead(&p))

+    return False;

+  return (p.c >> 25) & 1;

+}

+

+#endif

diff --git a/C/CpuArch.h b/C/CpuArch.h
new file mode 100755
index 0000000..0a709bb
--- /dev/null
+++ b/C/CpuArch.h
@@ -0,0 +1,155 @@
+/* CpuArch.h -- CPU specific code

+2010-10-26: Igor Pavlov : Public domain */

+

+#ifndef __CPU_ARCH_H

+#define __CPU_ARCH_H

+

+#include "Types.h"

+

+EXTERN_C_BEGIN

+

+/*

+MY_CPU_LE means that CPU is LITTLE ENDIAN.

+If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).

+

+MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.

+If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.

+*/

+

+#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)

+#define MY_CPU_AMD64

+#endif

+

+#if defined(MY_CPU_AMD64) || defined(_M_IA64)

+#define MY_CPU_64BIT

+#endif

+

+#if defined(_M_IX86) || defined(__i386__)

+#define MY_CPU_X86

+#endif

+

+#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)

+#define MY_CPU_X86_OR_AMD64

+#endif

+

+#if defined(MY_CPU_X86) || defined(_M_ARM)

+#define MY_CPU_32BIT

+#endif

+

+#if defined(_WIN32) && defined(_M_ARM)

+#define MY_CPU_ARM_LE

+#endif

+

+#if defined(_WIN32) && defined(_M_IA64)

+#define MY_CPU_IA64_LE

+#endif

+

+#if defined(MY_CPU_X86_OR_AMD64)

+#define MY_CPU_LE_UNALIGN

+#endif

+

+#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE)  || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)

+#define MY_CPU_LE

+#endif

+

+#if defined(__BIG_ENDIAN__)

+#define MY_CPU_BE

+#endif

+

+#if defined(MY_CPU_LE) && defined(MY_CPU_BE)

+Stop_Compiling_Bad_Endian

+#endif

+

+#ifdef MY_CPU_LE_UNALIGN

+

+#define GetUi16(p) (*(const UInt16 *)(p))

+#define GetUi32(p) (*(const UInt32 *)(p))

+#define GetUi64(p) (*(const UInt64 *)(p))

+#define SetUi16(p, d) *(UInt16 *)(p) = (d);

+#define SetUi32(p, d) *(UInt32 *)(p) = (d);

+#define SetUi64(p, d) *(UInt64 *)(p) = (d);

+

+#else

+

+#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))

+

+#define GetUi32(p) ( \

+             ((const Byte *)(p))[0]        | \

+    ((UInt32)((const Byte *)(p))[1] <<  8) | \

+    ((UInt32)((const Byte *)(p))[2] << 16) | \

+    ((UInt32)((const Byte *)(p))[3] << 24))

+

+#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))

+

+#define SetUi16(p, d) { UInt32 _x_ = (d); \

+    ((Byte *)(p))[0] = (Byte)_x_; \

+    ((Byte *)(p))[1] = (Byte)(_x_ >> 8); }

+

+#define SetUi32(p, d) { UInt32 _x_ = (d); \

+    ((Byte *)(p))[0] = (Byte)_x_; \

+    ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \

+    ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \

+    ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }

+

+#define SetUi64(p, d) { UInt64 _x64_ = (d); \

+    SetUi32(p, (UInt32)_x64_); \

+    SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }

+

+#endif

+

+#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)

+

+#pragma intrinsic(_byteswap_ulong)

+#pragma intrinsic(_byteswap_uint64)

+#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))

+#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))

+

+#else

+

+#define GetBe32(p) ( \

+    ((UInt32)((const Byte *)(p))[0] << 24) | \

+    ((UInt32)((const Byte *)(p))[1] << 16) | \

+    ((UInt32)((const Byte *)(p))[2] <<  8) | \

+             ((const Byte *)(p))[3] )

+

+#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))

+

+#endif

+

+#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])

+

+

+#ifdef MY_CPU_X86_OR_AMD64

+

+typedef struct

+{

+  UInt32 maxFunc;

+  UInt32 vendor[3];

+  UInt32 ver;

+  UInt32 b;

+  UInt32 c;

+  UInt32 d;

+} Cx86cpuid;

+

+enum

+{

+  CPU_FIRM_INTEL,

+  CPU_FIRM_AMD,

+  CPU_FIRM_VIA

+};

+

+Bool x86cpuid_CheckAndRead(Cx86cpuid *p);

+int x86cpuid_GetFirm(const Cx86cpuid *p);

+

+#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)

+#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)

+#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)

+

+Bool CPU_Is_InOrder();

+Bool CPU_Is_Aes_Supported();

+

+#endif

+

+EXTERN_C_END

+

+#endif

diff --git a/C/Delta.c b/C/Delta.c
new file mode 100755
index 0000000..93c93a1
--- /dev/null
+++ b/C/Delta.c
@@ -0,0 +1,62 @@
+/* Delta.c -- Delta converter

+2009-05-26 : Igor Pavlov : Public domain */

+

+#include "Delta.h"

+

+void Delta_Init(Byte *state)

+{

+  unsigned i;

+  for (i = 0; i < DELTA_STATE_SIZE; i++)

+    state[i] = 0;

+}

+

+static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)

+{

+  unsigned i;

+  for (i = 0; i < size; i++)

+    dest[i] = src[i];

+}

+

+void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)

+{

+  Byte buf[DELTA_STATE_SIZE];

+  unsigned j = 0;

+  MyMemCpy(buf, state, delta);

+  {

+    SizeT i;

+    for (i = 0; i < size;)

+    {

+      for (j = 0; j < delta && i < size; i++, j++)

+      {

+        Byte b = data[i];

+        data[i] = (Byte)(b - buf[j]);

+        buf[j] = b;

+      }

+    }

+  }

+  if (j == delta)

+    j = 0;

+  MyMemCpy(state, buf + j, delta - j);

+  MyMemCpy(state + delta - j, buf, j);

+}

+

+void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)

+{

+  Byte buf[DELTA_STATE_SIZE];

+  unsigned j = 0;

+  MyMemCpy(buf, state, delta);

+  {

+    SizeT i;

+    for (i = 0; i < size;)

+    {

+      for (j = 0; j < delta && i < size; i++, j++)

+      {

+        buf[j] = data[i] = (Byte)(buf[j] + data[i]);

+      }

+    }

+  }

+  if (j == delta)

+    j = 0;

+  MyMemCpy(state, buf + j, delta - j);

+  MyMemCpy(state + delta - j, buf, j);

+}

diff --git a/C/Delta.h b/C/Delta.h
new file mode 100755
index 0000000..776cd45
--- /dev/null
+++ b/C/Delta.h
@@ -0,0 +1,23 @@
+/* Delta.h -- Delta converter

+2009-04-15 : Igor Pavlov : Public domain */

+

+#ifndef __DELTA_H

+#define __DELTA_H

+

+#include "Types.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#define DELTA_STATE_SIZE 256

+

+void Delta_Init(Byte *state);

+void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);

+void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/LzFind.c b/C/LzFind.c
new file mode 100755
index 0000000..f6c9e66
--- /dev/null
+++ b/C/LzFind.c
@@ -0,0 +1,761 @@
+/* LzFind.c -- Match finder for LZ algorithms

+2009-04-22 : Igor Pavlov : Public domain */

+

+#include <string.h>

+

+#include "LzFind.h"

+#include "LzHash.h"

+

+#define kEmptyHashValue 0

+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)

+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */

+#define kNormalizeMask (~(kNormalizeStepMin - 1))

+#define kMaxHistorySize ((UInt32)3 << 30)

+

+#define kStartMaxLen 3

+

+static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)

+{

+  if (!p->directInput)

+  {

+    alloc->Free(alloc, p->bufferBase);

+    p->bufferBase = 0;

+  }

+}

+

+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */

+

+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)

+{

+  UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;

+  if (p->directInput)

+  {

+    p->blockSize = blockSize;

+    return 1;

+  }

+  if (p->bufferBase == 0 || p->blockSize != blockSize)

+  {

+    LzInWindow_Free(p, alloc);

+    p->blockSize = blockSize;

+    p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);

+  }

+  return (p->bufferBase != 0);

+}

+

+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }

+Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }

+

+UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }

+

+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)

+{

+  p->posLimit -= subValue;

+  p->pos -= subValue;

+  p->streamPos -= subValue;

+}

+

+static void MatchFinder_ReadBlock(CMatchFinder *p)

+{

+  if (p->streamEndWasReached || p->result != SZ_OK)

+    return;

+  if (p->directInput)

+  {

+    UInt32 curSize = 0xFFFFFFFF - p->streamPos;

+    if (curSize > p->directInputRem)

+      curSize = (UInt32)p->directInputRem;

+    p->directInputRem -= curSize;

+    p->streamPos += curSize;

+    if (p->directInputRem == 0)

+      p->streamEndWasReached = 1;

+    return;

+  }

+  for (;;)

+  {

+    Byte *dest = p->buffer + (p->streamPos - p->pos);

+    size_t size = (p->bufferBase + p->blockSize - dest);

+    if (size == 0)

+      return;

+    p->result = p->stream->Read(p->stream, dest, &size);

+    if (p->result != SZ_OK)

+      return;

+    if (size == 0)

+    {

+      p->streamEndWasReached = 1;

+      return;

+    }

+    p->streamPos += (UInt32)size;

+    if (p->streamPos - p->pos > p->keepSizeAfter)

+      return;

+  }

+}

+

+void MatchFinder_MoveBlock(CMatchFinder *p)

+{

+  memmove(p->bufferBase,

+    p->buffer - p->keepSizeBefore,

+    (size_t)(p->streamPos - p->pos + p->keepSizeBefore));

+  p->buffer = p->bufferBase + p->keepSizeBefore;

+}

+

+int MatchFinder_NeedMove(CMatchFinder *p)

+{

+  if (p->directInput)

+    return 0;

+  /* if (p->streamEndWasReached) return 0; */

+  return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);

+}

+

+void MatchFinder_ReadIfRequired(CMatchFinder *p)

+{

+  if (p->streamEndWasReached)

+    return;

+  if (p->keepSizeAfter >= p->streamPos - p->pos)

+    MatchFinder_ReadBlock(p);

+}

+

+static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)

+{

+  if (MatchFinder_NeedMove(p))

+    MatchFinder_MoveBlock(p);

+  MatchFinder_ReadBlock(p);

+}

+

+static void MatchFinder_SetDefaultSettings(CMatchFinder *p)

+{

+  p->cutValue = 32;

+  p->btMode = 1;

+  p->numHashBytes = 4;

+  p->bigHash = 0;

+}

+

+#define kCrcPoly 0xEDB88320

+

+void MatchFinder_Construct(CMatchFinder *p)

+{

+  UInt32 i;

+  p->bufferBase = 0;

+  p->directInput = 0;

+  p->hash = 0;

+  MatchFinder_SetDefaultSettings(p);

+

+  for (i = 0; i < 256; i++)

+  {

+    UInt32 r = i;

+    int j;

+    for (j = 0; j < 8; j++)

+      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));

+    p->crc[i] = r;

+  }

+}

+

+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, p->hash);

+  p->hash = 0;

+}

+

+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)

+{

+  MatchFinder_FreeThisClassMemory(p, alloc);

+  LzInWindow_Free(p, alloc);

+}

+

+static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)

+{

+  size_t sizeInBytes = (size_t)num * sizeof(CLzRef);

+  if (sizeInBytes / sizeof(CLzRef) != num)

+    return 0;

+  return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);

+}

+

+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,

+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,

+    ISzAlloc *alloc)

+{

+  UInt32 sizeReserv;

+  if (historySize > kMaxHistorySize)

+  {

+    MatchFinder_Free(p, alloc);

+    return 0;

+  }

+  sizeReserv = historySize >> 1;

+  if (historySize > ((UInt32)2 << 30))

+    sizeReserv = historySize >> 2;

+  sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);

+

+  p->keepSizeBefore = historySize + keepAddBufferBefore + 1;

+  p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;

+  /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */

+  if (LzInWindow_Create(p, sizeReserv, alloc))

+  {

+    UInt32 newCyclicBufferSize = historySize + 1;

+    UInt32 hs;

+    p->matchMaxLen = matchMaxLen;

+    {

+      p->fixedHashSize = 0;

+      if (p->numHashBytes == 2)

+        hs = (1 << 16) - 1;

+      else

+      {

+        hs = historySize - 1;

+        hs |= (hs >> 1);

+        hs |= (hs >> 2);

+        hs |= (hs >> 4);

+        hs |= (hs >> 8);

+        hs >>= 1;

+        hs |= 0xFFFF; /* don't change it! It's required for Deflate */

+        if (hs > (1 << 24))

+        {

+          if (p->numHashBytes == 3)

+            hs = (1 << 24) - 1;

+          else

+            hs >>= 1;

+        }

+      }

+      p->hashMask = hs;

+      hs++;

+      if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;

+      if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;

+      if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;

+      hs += p->fixedHashSize;

+    }

+

+    {

+      UInt32 prevSize = p->hashSizeSum + p->numSons;

+      UInt32 newSize;

+      p->historySize = historySize;

+      p->hashSizeSum = hs;

+      p->cyclicBufferSize = newCyclicBufferSize;

+      p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);

+      newSize = p->hashSizeSum + p->numSons;

+      if (p->hash != 0 && prevSize == newSize)

+        return 1;

+      MatchFinder_FreeThisClassMemory(p, alloc);

+      p->hash = AllocRefs(newSize, alloc);

+      if (p->hash != 0)

+      {

+        p->son = p->hash + p->hashSizeSum;

+        return 1;

+      }

+    }

+  }

+  MatchFinder_Free(p, alloc);

+  return 0;

+}

+

+static void MatchFinder_SetLimits(CMatchFinder *p)

+{

+  UInt32 limit = kMaxValForNormalize - p->pos;

+  UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;

+  if (limit2 < limit)

+    limit = limit2;

+  limit2 = p->streamPos - p->pos;

+  if (limit2 <= p->keepSizeAfter)

+  {

+    if (limit2 > 0)

+      limit2 = 1;

+  }

+  else

+    limit2 -= p->keepSizeAfter;

+  if (limit2 < limit)

+    limit = limit2;

+  {

+    UInt32 lenLimit = p->streamPos - p->pos;

+    if (lenLimit > p->matchMaxLen)

+      lenLimit = p->matchMaxLen;

+    p->lenLimit = lenLimit;

+  }

+  p->posLimit = p->pos + limit;

+}

+

+void MatchFinder_Init(CMatchFinder *p)

+{

+  UInt32 i;

+  for (i = 0; i < p->hashSizeSum; i++)

+    p->hash[i] = kEmptyHashValue;

+  p->cyclicBufferPos = 0;

+  p->buffer = p->bufferBase;

+  p->pos = p->streamPos = p->cyclicBufferSize;

+  p->result = SZ_OK;

+  p->streamEndWasReached = 0;

+  MatchFinder_ReadBlock(p);

+  MatchFinder_SetLimits(p);

+}

+

+static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)

+{

+  return (p->pos - p->historySize - 1) & kNormalizeMask;

+}

+

+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)

+{

+  UInt32 i;

+  for (i = 0; i < numItems; i++)

+  {

+    UInt32 value = items[i];

+    if (value <= subValue)

+      value = kEmptyHashValue;

+    else

+      value -= subValue;

+    items[i] = value;

+  }

+}

+

+static void MatchFinder_Normalize(CMatchFinder *p)

+{

+  UInt32 subValue = MatchFinder_GetSubValue(p);

+  MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);

+  MatchFinder_ReduceOffsets(p, subValue);

+}

+

+static void MatchFinder_CheckLimits(CMatchFinder *p)

+{

+  if (p->pos == kMaxValForNormalize)

+    MatchFinder_Normalize(p);

+  if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)

+    MatchFinder_CheckAndMoveAndRead(p);

+  if (p->cyclicBufferPos == p->cyclicBufferSize)

+    p->cyclicBufferPos = 0;

+  MatchFinder_SetLimits(p);

+}

+

+static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,

+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,

+    UInt32 *distances, UInt32 maxLen)

+{

+  son[_cyclicBufferPos] = curMatch;

+  for (;;)

+  {

+    UInt32 delta = pos - curMatch;

+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)

+      return distances;

+    {

+      const Byte *pb = cur - delta;

+      curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];

+      if (pb[maxLen] == cur[maxLen] && *pb == *cur)

+      {

+        UInt32 len = 0;

+        while (++len != lenLimit)

+          if (pb[len] != cur[len])

+            break;

+        if (maxLen < len)

+        {

+          *distances++ = maxLen = len;

+          *distances++ = delta - 1;

+          if (len == lenLimit)

+            return distances;

+        }

+      }

+    }

+  }

+}

+

+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,

+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,

+    UInt32 *distances, UInt32 maxLen)

+{

+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;

+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);

+  UInt32 len0 = 0, len1 = 0;

+  for (;;)

+  {

+    UInt32 delta = pos - curMatch;

+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)

+    {

+      *ptr0 = *ptr1 = kEmptyHashValue;

+      return distances;

+    }

+    {

+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);

+      const Byte *pb = cur - delta;

+      UInt32 len = (len0 < len1 ? len0 : len1);

+      if (pb[len] == cur[len])

+      {

+        if (++len != lenLimit && pb[len] == cur[len])

+          while (++len != lenLimit)

+            if (pb[len] != cur[len])

+              break;

+        if (maxLen < len)

+        {

+          *distances++ = maxLen = len;

+          *distances++ = delta - 1;

+          if (len == lenLimit)

+          {

+            *ptr1 = pair[0];

+            *ptr0 = pair[1];

+            return distances;

+          }

+        }

+      }

+      if (pb[len] < cur[len])

+      {

+        *ptr1 = curMatch;

+        ptr1 = pair + 1;

+        curMatch = *ptr1;

+        len1 = len;

+      }

+      else

+      {

+        *ptr0 = curMatch;

+        ptr0 = pair;

+        curMatch = *ptr0;

+        len0 = len;

+      }

+    }

+  }

+}

+

+static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,

+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)

+{

+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;

+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);

+  UInt32 len0 = 0, len1 = 0;

+  for (;;)

+  {

+    UInt32 delta = pos - curMatch;

+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)

+    {

+      *ptr0 = *ptr1 = kEmptyHashValue;

+      return;

+    }

+    {

+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);

+      const Byte *pb = cur - delta;

+      UInt32 len = (len0 < len1 ? len0 : len1);

+      if (pb[len] == cur[len])

+      {

+        while (++len != lenLimit)

+          if (pb[len] != cur[len])

+            break;

+        {

+          if (len == lenLimit)

+          {

+            *ptr1 = pair[0];

+            *ptr0 = pair[1];

+            return;

+          }

+        }

+      }

+      if (pb[len] < cur[len])

+      {

+        *ptr1 = curMatch;

+        ptr1 = pair + 1;

+        curMatch = *ptr1;

+        len1 = len;

+      }

+      else

+      {

+        *ptr0 = curMatch;

+        ptr0 = pair;

+        curMatch = *ptr0;

+        len0 = len;

+      }

+    }

+  }

+}

+

+#define MOVE_POS \

+  ++p->cyclicBufferPos; \

+  p->buffer++; \

+  if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);

+

+#define MOVE_POS_RET MOVE_POS return offset;

+

+static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }

+

+#define GET_MATCHES_HEADER2(minLen, ret_op) \

+  UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \

+  lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \

+  cur = p->buffer;

+

+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)

+#define SKIP_HEADER(minLen)        GET_MATCHES_HEADER2(minLen, continue)

+

+#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue

+

+#define GET_MATCHES_FOOTER(offset, maxLen) \

+  offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \

+  distances + offset, maxLen) - distances); MOVE_POS_RET;

+

+#define SKIP_FOOTER \

+  SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;

+

+static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

+{

+  UInt32 offset;

+  GET_MATCHES_HEADER(2)

+  HASH2_CALC;

+  curMatch = p->hash[hashValue];

+  p->hash[hashValue] = p->pos;

+  offset = 0;

+  GET_MATCHES_FOOTER(offset, 1)

+}

+

+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

+{

+  UInt32 offset;

+  GET_MATCHES_HEADER(3)

+  HASH_ZIP_CALC;

+  curMatch = p->hash[hashValue];

+  p->hash[hashValue] = p->pos;

+  offset = 0;

+  GET_MATCHES_FOOTER(offset, 2)

+}

+

+static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

+{

+  UInt32 hash2Value, delta2, maxLen, offset;

+  GET_MATCHES_HEADER(3)

+

+  HASH3_CALC;

+

+  delta2 = p->pos - p->hash[hash2Value];

+  curMatch = p->hash[kFix3HashSize + hashValue];

+  

+  p->hash[hash2Value] =

+  p->hash[kFix3HashSize + hashValue] = p->pos;

+

+

+  maxLen = 2;

+  offset = 0;

+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)

+  {

+    for (; maxLen != lenLimit; maxLen++)

+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])

+        break;

+    distances[0] = maxLen;

+    distances[1] = delta2 - 1;

+    offset = 2;

+    if (maxLen == lenLimit)

+    {

+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));

+      MOVE_POS_RET;

+    }

+  }

+  GET_MATCHES_FOOTER(offset, maxLen)

+}

+

+static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

+{

+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;

+  GET_MATCHES_HEADER(4)

+

+  HASH4_CALC;

+

+  delta2 = p->pos - p->hash[                hash2Value];

+  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];

+  curMatch = p->hash[kFix4HashSize + hashValue];

+  

+  p->hash[                hash2Value] =

+  p->hash[kFix3HashSize + hash3Value] =

+  p->hash[kFix4HashSize + hashValue] = p->pos;

+

+  maxLen = 1;

+  offset = 0;

+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)

+  {

+    distances[0] = maxLen = 2;

+    distances[1] = delta2 - 1;

+    offset = 2;

+  }

+  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)

+  {

+    maxLen = 3;

+    distances[offset + 1] = delta3 - 1;

+    offset += 2;

+    delta2 = delta3;

+  }

+  if (offset != 0)

+  {

+    for (; maxLen != lenLimit; maxLen++)

+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])

+        break;

+    distances[offset - 2] = maxLen;

+    if (maxLen == lenLimit)

+    {

+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));

+      MOVE_POS_RET;

+    }

+  }

+  if (maxLen < 3)

+    maxLen = 3;

+  GET_MATCHES_FOOTER(offset, maxLen)

+}

+

+static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

+{

+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;

+  GET_MATCHES_HEADER(4)

+

+  HASH4_CALC;

+

+  delta2 = p->pos - p->hash[                hash2Value];

+  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];

+  curMatch = p->hash[kFix4HashSize + hashValue];

+

+  p->hash[                hash2Value] =

+  p->hash[kFix3HashSize + hash3Value] =

+  p->hash[kFix4HashSize + hashValue] = p->pos;

+

+  maxLen = 1;

+  offset = 0;

+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)

+  {

+    distances[0] = maxLen = 2;

+    distances[1] = delta2 - 1;

+    offset = 2;

+  }

+  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)

+  {

+    maxLen = 3;

+    distances[offset + 1] = delta3 - 1;

+    offset += 2;

+    delta2 = delta3;

+  }

+  if (offset != 0)

+  {

+    for (; maxLen != lenLimit; maxLen++)

+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])

+        break;

+    distances[offset - 2] = maxLen;

+    if (maxLen == lenLimit)

+    {

+      p->son[p->cyclicBufferPos] = curMatch;

+      MOVE_POS_RET;

+    }

+  }

+  if (maxLen < 3)

+    maxLen = 3;

+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),

+    distances + offset, maxLen) - (distances));

+  MOVE_POS_RET

+}

+

+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)

+{

+  UInt32 offset;

+  GET_MATCHES_HEADER(3)

+  HASH_ZIP_CALC;

+  curMatch = p->hash[hashValue];

+  p->hash[hashValue] = p->pos;

+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),

+    distances, 2) - (distances));

+  MOVE_POS_RET

+}

+

+static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

+{

+  do

+  {

+    SKIP_HEADER(2)

+    HASH2_CALC;

+    curMatch = p->hash[hashValue];

+    p->hash[hashValue] = p->pos;

+    SKIP_FOOTER

+  }

+  while (--num != 0);

+}

+

+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

+{

+  do

+  {

+    SKIP_HEADER(3)

+    HASH_ZIP_CALC;

+    curMatch = p->hash[hashValue];

+    p->hash[hashValue] = p->pos;

+    SKIP_FOOTER

+  }

+  while (--num != 0);

+}

+

+static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

+{

+  do

+  {

+    UInt32 hash2Value;

+    SKIP_HEADER(3)

+    HASH3_CALC;

+    curMatch = p->hash[kFix3HashSize + hashValue];

+    p->hash[hash2Value] =

+    p->hash[kFix3HashSize + hashValue] = p->pos;

+    SKIP_FOOTER

+  }

+  while (--num != 0);

+}

+

+static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

+{

+  do

+  {

+    UInt32 hash2Value, hash3Value;

+    SKIP_HEADER(4)

+    HASH4_CALC;

+    curMatch = p->hash[kFix4HashSize + hashValue];

+    p->hash[                hash2Value] =

+    p->hash[kFix3HashSize + hash3Value] = p->pos;

+    p->hash[kFix4HashSize + hashValue] = p->pos;

+    SKIP_FOOTER

+  }

+  while (--num != 0);

+}

+

+static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

+{

+  do

+  {

+    UInt32 hash2Value, hash3Value;

+    SKIP_HEADER(4)

+    HASH4_CALC;

+    curMatch = p->hash[kFix4HashSize + hashValue];

+    p->hash[                hash2Value] =

+    p->hash[kFix3HashSize + hash3Value] =

+    p->hash[kFix4HashSize + hashValue] = p->pos;

+    p->son[p->cyclicBufferPos] = curMatch;

+    MOVE_POS

+  }

+  while (--num != 0);

+}

+

+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)

+{

+  do

+  {

+    SKIP_HEADER(3)

+    HASH_ZIP_CALC;

+    curMatch = p->hash[hashValue];

+    p->hash[hashValue] = p->pos;

+    p->son[p->cyclicBufferPos] = curMatch;

+    MOVE_POS

+  }

+  while (--num != 0);

+}

+

+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)

+{

+  vTable->Init = (Mf_Init_Func)MatchFinder_Init;

+  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;

+  vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;

+  vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;

+  if (!p->btMode)

+  {

+    vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;

+    vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;

+  }

+  else if (p->numHashBytes == 2)

+  {

+    vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;

+    vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;

+  }

+  else if (p->numHashBytes == 3)

+  {

+    vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;

+    vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;

+  }

+  else

+  {

+    vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;

+    vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;

+  }

+}

diff --git a/C/LzFind.h b/C/LzFind.h
new file mode 100755
index 0000000..7ebdfa4
--- /dev/null
+++ b/C/LzFind.h
@@ -0,0 +1,115 @@
+/* LzFind.h -- Match finder for LZ algorithms

+2009-04-22 : Igor Pavlov : Public domain */

+

+#ifndef __LZ_FIND_H

+#define __LZ_FIND_H

+

+#include "Types.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+typedef UInt32 CLzRef;

+

+typedef struct _CMatchFinder

+{

+  Byte *buffer;

+  UInt32 pos;

+  UInt32 posLimit;

+  UInt32 streamPos;

+  UInt32 lenLimit;

+

+  UInt32 cyclicBufferPos;

+  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */

+

+  UInt32 matchMaxLen;

+  CLzRef *hash;

+  CLzRef *son;

+  UInt32 hashMask;

+  UInt32 cutValue;

+

+  Byte *bufferBase;

+  ISeqInStream *stream;

+  int streamEndWasReached;

+

+  UInt32 blockSize;

+  UInt32 keepSizeBefore;

+  UInt32 keepSizeAfter;

+

+  UInt32 numHashBytes;

+  int directInput;

+  size_t directInputRem;

+  int btMode;

+  int bigHash;

+  UInt32 historySize;

+  UInt32 fixedHashSize;

+  UInt32 hashSizeSum;

+  UInt32 numSons;

+  SRes result;

+  UInt32 crc[256];

+} CMatchFinder;

+

+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)

+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])

+

+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)

+

+int MatchFinder_NeedMove(CMatchFinder *p);

+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);

+void MatchFinder_MoveBlock(CMatchFinder *p);

+void MatchFinder_ReadIfRequired(CMatchFinder *p);

+

+void MatchFinder_Construct(CMatchFinder *p);

+

+/* Conditions:

+     historySize <= 3 GB

+     keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB

+*/

+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,

+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,

+    ISzAlloc *alloc);

+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);

+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);

+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);

+

+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,

+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,

+    UInt32 *distances, UInt32 maxLen);

+

+/*

+Conditions:

+  Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.

+  Mf_GetPointerToCurrentPos_Func's result must be used only before any other function

+*/

+

+typedef void (*Mf_Init_Func)(void *object);

+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);

+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);

+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);

+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);

+typedef void (*Mf_Skip_Func)(void *object, UInt32);

+

+typedef struct _IMatchFinder

+{

+  Mf_Init_Func Init;

+  Mf_GetIndexByte_Func GetIndexByte;

+  Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;

+  Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;

+  Mf_GetMatches_Func GetMatches;

+  Mf_Skip_Func Skip;

+} IMatchFinder;

+

+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);

+

+void MatchFinder_Init(CMatchFinder *p);

+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);

+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);

+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);

+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/LzFindMt.c b/C/LzFindMt.c
new file mode 100755
index 0000000..db95590
--- /dev/null
+++ b/C/LzFindMt.c
@@ -0,0 +1,793 @@
+/* LzFindMt.c -- multithreaded Match finder for LZ algorithms

+2009-09-20 : Igor Pavlov : Public domain */

+

+#include "LzHash.h"

+

+#include "LzFindMt.h"

+

+void MtSync_Construct(CMtSync *p)

+{

+  p->wasCreated = False;

+  p->csWasInitialized = False;

+  p->csWasEntered = False;

+  Thread_Construct(&p->thread);

+  Event_Construct(&p->canStart);

+  Event_Construct(&p->wasStarted);

+  Event_Construct(&p->wasStopped);

+  Semaphore_Construct(&p->freeSemaphore);

+  Semaphore_Construct(&p->filledSemaphore);

+}

+

+void MtSync_GetNextBlock(CMtSync *p)

+{

+  if (p->needStart)

+  {

+    p->numProcessedBlocks = 1;

+    p->needStart = False;

+    p->stopWriting = False;

+    p->exit = False;

+    Event_Reset(&p->wasStarted);

+    Event_Reset(&p->wasStopped);

+

+    Event_Set(&p->canStart);

+    Event_Wait(&p->wasStarted);

+  }

+  else

+  {

+    CriticalSection_Leave(&p->cs);

+    p->csWasEntered = False;

+    p->numProcessedBlocks++;

+    Semaphore_Release1(&p->freeSemaphore);

+  }

+  Semaphore_Wait(&p->filledSemaphore);

+  CriticalSection_Enter(&p->cs);

+  p->csWasEntered = True;

+}

+

+/* MtSync_StopWriting must be called if Writing was started */

+

+void MtSync_StopWriting(CMtSync *p)

+{

+  UInt32 myNumBlocks = p->numProcessedBlocks;

+  if (!Thread_WasCreated(&p->thread) || p->needStart)

+    return;

+  p->stopWriting = True;

+  if (p->csWasEntered)

+  {

+    CriticalSection_Leave(&p->cs);

+    p->csWasEntered = False;

+  }

+  Semaphore_Release1(&p->freeSemaphore);

+ 

+  Event_Wait(&p->wasStopped);

+

+  while (myNumBlocks++ != p->numProcessedBlocks)

+  {

+    Semaphore_Wait(&p->filledSemaphore);

+    Semaphore_Release1(&p->freeSemaphore);

+  }

+  p->needStart = True;

+}

+

+void MtSync_Destruct(CMtSync *p)

+{

+  if (Thread_WasCreated(&p->thread))

+  {

+    MtSync_StopWriting(p);

+    p->exit = True;

+    if (p->needStart)

+      Event_Set(&p->canStart);

+    Thread_Wait(&p->thread);

+    Thread_Close(&p->thread);

+  }

+  if (p->csWasInitialized)

+  {

+    CriticalSection_Delete(&p->cs);

+    p->csWasInitialized = False;

+  }

+

+  Event_Close(&p->canStart);

+  Event_Close(&p->wasStarted);

+  Event_Close(&p->wasStopped);

+  Semaphore_Close(&p->freeSemaphore);

+  Semaphore_Close(&p->filledSemaphore);

+

+  p->wasCreated = False;

+}

+

+#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }

+

+static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)

+{

+  if (p->wasCreated)

+    return SZ_OK;

+

+  RINOK_THREAD(CriticalSection_Init(&p->cs));

+  p->csWasInitialized = True;

+

+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart));

+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted));

+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped));

+  

+  RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));

+  RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));

+

+  p->needStart = True;

+  

+  RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj));

+  p->wasCreated = True;

+  return SZ_OK;

+}

+

+static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)

+{

+  SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);

+  if (res != SZ_OK)

+    MtSync_Destruct(p);

+  return res;

+}

+

+void MtSync_Init(CMtSync *p) { p->needStart = True; }

+

+#define kMtMaxValForNormalize 0xFFFFFFFF

+

+#define DEF_GetHeads2(name, v, action) \

+static void GetHeads ## name(const Byte *p, UInt32 pos, \

+UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \

+{ action; for (; numHeads != 0; numHeads--) { \

+const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++;  } }

+

+#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)

+

+DEF_GetHeads2(2,  (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )

+DEF_GetHeads(3,  (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)

+DEF_GetHeads(4,  (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)

+DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)

+/* DEF_GetHeads(5,  (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */

+

+void HashThreadFunc(CMatchFinderMt *mt)

+{

+  CMtSync *p = &mt->hashSync;

+  for (;;)

+  {

+    UInt32 numProcessedBlocks = 0;

+    Event_Wait(&p->canStart);

+    Event_Set(&p->wasStarted);

+    for (;;)

+    {

+      if (p->exit)

+        return;

+      if (p->stopWriting)

+      {

+        p->numProcessedBlocks = numProcessedBlocks;

+        Event_Set(&p->wasStopped);

+        break;

+      }

+

+      {

+        CMatchFinder *mf = mt->MatchFinder;

+        if (MatchFinder_NeedMove(mf))

+        {

+          CriticalSection_Enter(&mt->btSync.cs);

+          CriticalSection_Enter(&mt->hashSync.cs);

+          {

+            const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);

+            const Byte *afterPtr;

+            MatchFinder_MoveBlock(mf);

+            afterPtr = MatchFinder_GetPointerToCurrentPos(mf);

+            mt->pointerToCurPos -= beforePtr - afterPtr;

+            mt->buffer -= beforePtr - afterPtr;

+          }

+          CriticalSection_Leave(&mt->btSync.cs);

+          CriticalSection_Leave(&mt->hashSync.cs);

+          continue;

+        }

+

+        Semaphore_Wait(&p->freeSemaphore);

+

+        MatchFinder_ReadIfRequired(mf);

+        if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))

+        {

+          UInt32 subValue = (mf->pos - mf->historySize - 1);

+          MatchFinder_ReduceOffsets(mf, subValue);

+          MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);

+        }

+        {

+          UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;

+          UInt32 num = mf->streamPos - mf->pos;

+          heads[0] = 2;

+          heads[1] = num;

+          if (num >= mf->numHashBytes)

+          {

+            num = num - mf->numHashBytes + 1;

+            if (num > kMtHashBlockSize - 2)

+              num = kMtHashBlockSize - 2;

+            mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);

+            heads[0] += num;

+          }

+          mf->pos += num;

+          mf->buffer += num;

+        }

+      }

+

+      Semaphore_Release1(&p->filledSemaphore);

+    }

+  }

+}

+

+void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)

+{

+  MtSync_GetNextBlock(&p->hashSync);

+  p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;

+  p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];

+  p->hashNumAvail = p->hashBuf[p->hashBufPos++];

+}

+

+#define kEmptyHashValue 0

+

+/* #define MFMT_GM_INLINE */

+

+#ifdef MFMT_GM_INLINE

+

+#define NO_INLINE MY_FAST_CALL

+

+Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,

+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,

+    UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)

+{

+  do

+  {

+  UInt32 *distances = _distances + 1;

+  UInt32 curMatch = pos - *hash++;

+

+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;

+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);

+  UInt32 len0 = 0, len1 = 0;

+  UInt32 cutValue = _cutValue;

+  UInt32 maxLen = _maxLen;

+  for (;;)

+  {

+    UInt32 delta = pos - curMatch;

+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)

+    {

+      *ptr0 = *ptr1 = kEmptyHashValue;

+      break;

+    }

+    {

+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);

+      const Byte *pb = cur - delta;

+      UInt32 len = (len0 < len1 ? len0 : len1);

+      if (pb[len] == cur[len])

+      {

+        if (++len != lenLimit && pb[len] == cur[len])

+          while (++len != lenLimit)

+            if (pb[len] != cur[len])

+              break;

+        if (maxLen < len)

+        {

+          *distances++ = maxLen = len;

+          *distances++ = delta - 1;

+          if (len == lenLimit)

+          {

+            *ptr1 = pair[0];

+            *ptr0 = pair[1];

+            break;

+          }

+        }

+      }

+      if (pb[len] < cur[len])

+      {

+        *ptr1 = curMatch;

+        ptr1 = pair + 1;

+        curMatch = *ptr1;

+        len1 = len;

+      }

+      else

+      {

+        *ptr0 = curMatch;

+        ptr0 = pair;

+        curMatch = *ptr0;

+        len0 = len;

+      }

+    }

+  }

+  pos++;

+  _cyclicBufferPos++;

+  cur++;

+  {

+    UInt32 num = (UInt32)(distances - _distances);

+    *_distances = num - 1;

+    _distances += num;

+    limit -= num;

+  }

+  }

+  while (limit > 0 && --size != 0);

+  *posRes = pos;

+  return limit;

+}

+

+#endif

+

+void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)

+{

+  UInt32 numProcessed = 0;

+  UInt32 curPos = 2;

+  UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);

+  distances[1] = p->hashNumAvail;

+  while (curPos < limit)

+  {

+    if (p->hashBufPos == p->hashBufPosLimit)

+    {

+      MatchFinderMt_GetNextBlock_Hash(p);

+      distances[1] = numProcessed + p->hashNumAvail;

+      if (p->hashNumAvail >= p->numHashBytes)

+        continue;

+      for (; p->hashNumAvail != 0; p->hashNumAvail--)

+        distances[curPos++] = 0;

+      break;

+    }

+    {

+      UInt32 size = p->hashBufPosLimit - p->hashBufPos;

+      UInt32 lenLimit = p->matchMaxLen;

+      UInt32 pos = p->pos;

+      UInt32 cyclicBufferPos = p->cyclicBufferPos;

+      if (lenLimit >= p->hashNumAvail)

+        lenLimit = p->hashNumAvail;

+      {

+        UInt32 size2 = p->hashNumAvail - lenLimit + 1;

+        if (size2 < size)

+          size = size2;

+        size2 = p->cyclicBufferSize - cyclicBufferPos;

+        if (size2 < size)

+          size = size2;

+      }

+      #ifndef MFMT_GM_INLINE

+      while (curPos < limit && size-- != 0)

+      {

+        UInt32 *startDistances = distances + curPos;

+        UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],

+          pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,

+          startDistances + 1, p->numHashBytes - 1) - startDistances);

+        *startDistances = num - 1;

+        curPos += num;

+        cyclicBufferPos++;

+        pos++;

+        p->buffer++;

+      }

+      #else

+      {

+        UInt32 posRes;

+        curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,

+          distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);

+        p->hashBufPos += posRes - pos;

+        cyclicBufferPos += posRes - pos;

+        p->buffer += posRes - pos;

+        pos = posRes;

+      }

+      #endif

+

+      numProcessed += pos - p->pos;

+      p->hashNumAvail -= pos - p->pos;

+      p->pos = pos;

+      if (cyclicBufferPos == p->cyclicBufferSize)

+        cyclicBufferPos = 0;

+      p->cyclicBufferPos = cyclicBufferPos;

+    }

+  }

+  distances[0] = curPos;

+}

+

+void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)

+{

+  CMtSync *sync = &p->hashSync;

+  if (!sync->needStart)

+  {

+    CriticalSection_Enter(&sync->cs);

+    sync->csWasEntered = True;

+  }

+  

+  BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);

+

+  if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)

+  {

+    UInt32 subValue = p->pos - p->cyclicBufferSize;

+    MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);

+    p->pos -= subValue;

+  }

+

+  if (!sync->needStart)

+  {

+    CriticalSection_Leave(&sync->cs);

+    sync->csWasEntered = False;

+  }

+}

+

+void BtThreadFunc(CMatchFinderMt *mt)

+{

+  CMtSync *p = &mt->btSync;

+  for (;;)

+  {

+    UInt32 blockIndex = 0;

+    Event_Wait(&p->canStart);

+    Event_Set(&p->wasStarted);

+    for (;;)

+    {

+      if (p->exit)

+        return;

+      if (p->stopWriting)

+      {

+        p->numProcessedBlocks = blockIndex;

+        MtSync_StopWriting(&mt->hashSync);

+        Event_Set(&p->wasStopped);

+        break;

+      }

+      Semaphore_Wait(&p->freeSemaphore);

+      BtFillBlock(mt, blockIndex++);

+      Semaphore_Release1(&p->filledSemaphore);

+    }

+  }

+}

+

+void MatchFinderMt_Construct(CMatchFinderMt *p)

+{

+  p->hashBuf = 0;

+  MtSync_Construct(&p->hashSync);

+  MtSync_Construct(&p->btSync);

+}

+

+void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, p->hashBuf);

+  p->hashBuf = 0;

+}

+

+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)

+{

+  MtSync_Destruct(&p->hashSync);

+  MtSync_Destruct(&p->btSync);

+  MatchFinderMt_FreeMem(p, alloc);

+}

+

+#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)

+#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)

+

+static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p);  return 0; }

+static unsigned MY_STD_CALL BtThreadFunc2(void *p)

+{

+  Byte allocaDummy[0x180];

+  int i = 0;

+  for (i = 0; i < 16; i++)

+    allocaDummy[i] = (Byte)i;

+  BtThreadFunc((CMatchFinderMt *)p);

+  return 0;

+}

+

+SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,

+    UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)

+{

+  CMatchFinder *mf = p->MatchFinder;

+  p->historySize = historySize;

+  if (kMtBtBlockSize <= matchMaxLen * 4)

+    return SZ_ERROR_PARAM;

+  if (p->hashBuf == 0)

+  {

+    p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));

+    if (p->hashBuf == 0)

+      return SZ_ERROR_MEM;

+    p->btBuf = p->hashBuf + kHashBufferSize;

+  }

+  keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);

+  keepAddBufferAfter += kMtHashBlockSize;

+  if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))

+    return SZ_ERROR_MEM;

+

+  RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));

+  RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));

+  return SZ_OK;

+}

+

+/* Call it after ReleaseStream / SetStream */

+void MatchFinderMt_Init(CMatchFinderMt *p)

+{

+  CMatchFinder *mf = p->MatchFinder;

+  p->btBufPos = p->btBufPosLimit = 0;

+  p->hashBufPos = p->hashBufPosLimit = 0;

+  MatchFinder_Init(mf);

+  p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);

+  p->btNumAvailBytes = 0;

+  p->lzPos = p->historySize + 1;

+

+  p->hash = mf->hash;

+  p->fixedHashSize = mf->fixedHashSize;

+  p->crc = mf->crc;

+

+  p->son = mf->son;

+  p->matchMaxLen = mf->matchMaxLen;

+  p->numHashBytes = mf->numHashBytes;

+  p->pos = mf->pos;

+  p->buffer = mf->buffer;

+  p->cyclicBufferPos = mf->cyclicBufferPos;

+  p->cyclicBufferSize = mf->cyclicBufferSize;

+  p->cutValue = mf->cutValue;

+}

+

+/* ReleaseStream is required to finish multithreading */

+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)

+{

+  MtSync_StopWriting(&p->btSync);

+  /* p->MatchFinder->ReleaseStream(); */

+}

+

+void MatchFinderMt_Normalize(CMatchFinderMt *p)

+{

+  MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);

+  p->lzPos = p->historySize + 1;

+}

+

+void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)

+{

+  UInt32 blockIndex;

+  MtSync_GetNextBlock(&p->btSync);

+  blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);

+  p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;

+  p->btBufPosLimit += p->btBuf[p->btBufPos++];

+  p->btNumAvailBytes = p->btBuf[p->btBufPos++];

+  if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)

+    MatchFinderMt_Normalize(p);

+}

+

+const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)

+{

+  return p->pointerToCurPos;

+}

+

+#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);

+

+UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)

+{

+  GET_NEXT_BLOCK_IF_REQUIRED;

+  return p->btNumAvailBytes;

+}

+

+Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)

+{

+  return p->pointerToCurPos[index];

+}

+

+UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)

+{

+  UInt32 hash2Value, curMatch2;

+  UInt32 *hash = p->hash;

+  const Byte *cur = p->pointerToCurPos;

+  UInt32 lzPos = p->lzPos;

+  MT_HASH2_CALC

+      

+  curMatch2 = hash[hash2Value];

+  hash[hash2Value] = lzPos;

+

+  if (curMatch2 >= matchMinPos)

+    if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])

+    {

+      *distances++ = 2;

+      *distances++ = lzPos - curMatch2 - 1;

+    }

+  return distances;

+}

+

+UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)

+{

+  UInt32 hash2Value, hash3Value, curMatch2, curMatch3;

+  UInt32 *hash = p->hash;

+  const Byte *cur = p->pointerToCurPos;

+  UInt32 lzPos = p->lzPos;

+  MT_HASH3_CALC

+

+  curMatch2 = hash[                hash2Value];

+  curMatch3 = hash[kFix3HashSize + hash3Value];

+  

+  hash[                hash2Value] =

+  hash[kFix3HashSize + hash3Value] =

+    lzPos;

+

+  if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])

+  {

+    distances[1] = lzPos - curMatch2 - 1;

+    if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])

+    {

+      distances[0] = 3;

+      return distances + 2;

+    }

+    distances[0] = 2;

+    distances += 2;

+  }

+  if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])

+  {

+    *distances++ = 3;

+    *distances++ = lzPos - curMatch3 - 1;

+  }

+  return distances;

+}

+

+/*

+UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)

+{

+  UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;

+  UInt32 *hash = p->hash;

+  const Byte *cur = p->pointerToCurPos;

+  UInt32 lzPos = p->lzPos;

+  MT_HASH4_CALC

+      

+  curMatch2 = hash[                hash2Value];

+  curMatch3 = hash[kFix3HashSize + hash3Value];

+  curMatch4 = hash[kFix4HashSize + hash4Value];

+  

+  hash[                hash2Value] =

+  hash[kFix3HashSize + hash3Value] =

+  hash[kFix4HashSize + hash4Value] =

+    lzPos;

+

+  if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])

+  {

+    distances[1] = lzPos - curMatch2 - 1;

+    if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])

+    {

+      distances[0] =  (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;

+      return distances + 2;

+    }

+    distances[0] = 2;

+    distances += 2;

+  }

+  if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])

+  {

+    distances[1] = lzPos - curMatch3 - 1;

+    if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])

+    {

+      distances[0] = 4;

+      return distances + 2;

+    }

+    distances[0] = 3;

+    distances += 2;

+  }

+

+  if (curMatch4 >= matchMinPos)

+    if (

+      cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&

+      cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]

+      )

+    {

+      *distances++ = 4;

+      *distances++ = lzPos - curMatch4 - 1;

+    }

+  return distances;

+}

+*/

+

+#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;

+

+UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)

+{

+  const UInt32 *btBuf = p->btBuf + p->btBufPos;

+  UInt32 len = *btBuf++;

+  p->btBufPos += 1 + len;

+  p->btNumAvailBytes--;

+  {

+    UInt32 i;

+    for (i = 0; i < len; i += 2)

+    {

+      *distances++ = *btBuf++;

+      *distances++ = *btBuf++;

+    }

+  }

+  INCREASE_LZ_POS

+  return len;

+}

+

+UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)

+{

+  const UInt32 *btBuf = p->btBuf + p->btBufPos;

+  UInt32 len = *btBuf++;

+  p->btBufPos += 1 + len;

+

+  if (len == 0)

+  {

+    if (p->btNumAvailBytes-- >= 4)

+      len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));

+  }

+  else

+  {

+    /* Condition: there are matches in btBuf with length < p->numHashBytes */

+    UInt32 *distances2;

+    p->btNumAvailBytes--;

+    distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);

+    do

+    {

+      *distances2++ = *btBuf++;

+      *distances2++ = *btBuf++;

+    }

+    while ((len -= 2) != 0);

+    len  = (UInt32)(distances2 - (distances));

+  }

+  INCREASE_LZ_POS

+  return len;

+}

+

+#define SKIP_HEADER2_MT  do { GET_NEXT_BLOCK_IF_REQUIRED

+#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;

+#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);

+

+void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)

+{

+  SKIP_HEADER2_MT { p->btNumAvailBytes--;

+  SKIP_FOOTER_MT

+}

+

+void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)

+{

+  SKIP_HEADER_MT(2)

+      UInt32 hash2Value;

+      MT_HASH2_CALC

+      hash[hash2Value] = p->lzPos;

+  SKIP_FOOTER_MT

+}

+

+void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)

+{

+  SKIP_HEADER_MT(3)

+      UInt32 hash2Value, hash3Value;

+      MT_HASH3_CALC

+      hash[kFix3HashSize + hash3Value] =

+      hash[                hash2Value] =

+        p->lzPos;

+  SKIP_FOOTER_MT

+}

+

+/*

+void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)

+{

+  SKIP_HEADER_MT(4)

+      UInt32 hash2Value, hash3Value, hash4Value;

+      MT_HASH4_CALC

+      hash[kFix4HashSize + hash4Value] =

+      hash[kFix3HashSize + hash3Value] =

+      hash[                hash2Value] =

+        p->lzPos;

+  SKIP_FOOTER_MT

+}

+*/

+

+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)

+{

+  vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;

+  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;

+  vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;

+  vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;

+  vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;

+  switch(p->MatchFinder->numHashBytes)

+  {

+    case 2:

+      p->GetHeadsFunc = GetHeads2;

+      p->MixMatchesFunc = (Mf_Mix_Matches)0;

+      vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;

+      vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;

+      break;

+    case 3:

+      p->GetHeadsFunc = GetHeads3;

+      p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;

+      vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;

+      break;

+    default:

+    /* case 4: */

+      p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;

+      /* p->GetHeadsFunc = GetHeads4; */

+      p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;

+      vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;

+      break;

+    /*

+    default:

+      p->GetHeadsFunc = GetHeads5;

+      p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;

+      vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;

+      break;

+    */

+  }

+}

diff --git a/C/LzFindMt.h b/C/LzFindMt.h
new file mode 100755
index 0000000..17ed237
--- /dev/null
+++ b/C/LzFindMt.h
@@ -0,0 +1,105 @@
+/* LzFindMt.h -- multithreaded Match finder for LZ algorithms

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __LZ_FIND_MT_H

+#define __LZ_FIND_MT_H

+

+#include "LzFind.h"

+#include "Threads.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#define kMtHashBlockSize (1 << 13)

+#define kMtHashNumBlocks (1 << 3)

+#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)

+

+#define kMtBtBlockSize (1 << 14)

+#define kMtBtNumBlocks (1 << 6)

+#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)

+

+typedef struct _CMtSync

+{

+  Bool wasCreated;

+  Bool needStart;

+  Bool exit;

+  Bool stopWriting;

+

+  CThread thread;

+  CAutoResetEvent canStart;

+  CAutoResetEvent wasStarted;

+  CAutoResetEvent wasStopped;

+  CSemaphore freeSemaphore;

+  CSemaphore filledSemaphore;

+  Bool csWasInitialized;

+  Bool csWasEntered;

+  CCriticalSection cs;

+  UInt32 numProcessedBlocks;

+} CMtSync;

+

+typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);

+

+/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */

+#define kMtCacheLineDummy 128

+

+typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,

+  UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);

+

+typedef struct _CMatchFinderMt

+{

+  /* LZ */

+  const Byte *pointerToCurPos;

+  UInt32 *btBuf;

+  UInt32 btBufPos;

+  UInt32 btBufPosLimit;

+  UInt32 lzPos;

+  UInt32 btNumAvailBytes;

+

+  UInt32 *hash;

+  UInt32 fixedHashSize;

+  UInt32 historySize;

+  const UInt32 *crc;

+

+  Mf_Mix_Matches MixMatchesFunc;

+  

+  /* LZ + BT */

+  CMtSync btSync;

+  Byte btDummy[kMtCacheLineDummy];

+

+  /* BT */

+  UInt32 *hashBuf;

+  UInt32 hashBufPos;

+  UInt32 hashBufPosLimit;

+  UInt32 hashNumAvail;

+

+  CLzRef *son;

+  UInt32 matchMaxLen;

+  UInt32 numHashBytes;

+  UInt32 pos;

+  Byte *buffer;

+  UInt32 cyclicBufferPos;

+  UInt32 cyclicBufferSize; /* it must be historySize + 1 */

+  UInt32 cutValue;

+

+  /* BT + Hash */

+  CMtSync hashSync;

+  /* Byte hashDummy[kMtCacheLineDummy]; */

+  

+  /* Hash */

+  Mf_GetHeads GetHeadsFunc;

+  CMatchFinder *MatchFinder;

+} CMatchFinderMt;

+

+void MatchFinderMt_Construct(CMatchFinderMt *p);

+void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);

+SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,

+    UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);

+void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);

+void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/LzHash.h b/C/LzHash.h
new file mode 100755
index 0000000..b2f0e3c
--- /dev/null
+++ b/C/LzHash.h
@@ -0,0 +1,54 @@
+/* LzHash.h -- HASH functions for LZ algorithms

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __LZ_HASH_H

+#define __LZ_HASH_H

+

+#define kHash2Size (1 << 10)

+#define kHash3Size (1 << 16)

+#define kHash4Size (1 << 20)

+

+#define kFix3HashSize (kHash2Size)

+#define kFix4HashSize (kHash2Size + kHash3Size)

+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)

+

+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);

+

+#define HASH3_CALC { \

+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

+  hash2Value = temp & (kHash2Size - 1); \

+  hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }

+

+#define HASH4_CALC { \

+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

+  hash2Value = temp & (kHash2Size - 1); \

+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \

+  hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }

+

+#define HASH5_CALC { \

+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

+  hash2Value = temp & (kHash2Size - 1); \

+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \

+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \

+  hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \

+  hash4Value &= (kHash4Size - 1); }

+

+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */

+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;

+

+

+#define MT_HASH2_CALC \

+  hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);

+

+#define MT_HASH3_CALC { \

+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

+  hash2Value = temp & (kHash2Size - 1); \

+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }

+

+#define MT_HASH4_CALC { \

+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \

+  hash2Value = temp & (kHash2Size - 1); \

+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \

+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }

+

+#endif

diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c
new file mode 100755
index 0000000..8f24067
--- /dev/null
+++ b/C/Lzma2Dec.c
@@ -0,0 +1,356 @@
+/* Lzma2Dec.c -- LZMA2 Decoder

+2009-05-03 : Igor Pavlov : Public domain */

+

+/* #define SHOW_DEBUG_INFO */

+

+#ifdef SHOW_DEBUG_INFO

+#include <stdio.h>

+#endif

+

+#include <string.h>

+

+#include "Lzma2Dec.h"

+

+/*

+00000000  -  EOS

+00000001 U U  -  Uncompressed Reset Dic

+00000010 U U  -  Uncompressed No Reset

+100uuuuu U U P P  -  LZMA no reset

+101uuuuu U U P P  -  LZMA reset state

+110uuuuu U U P P S  -  LZMA reset state + new prop

+111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic

+

+  u, U - Unpack Size

+  P - Pack Size

+  S - Props

+*/

+

+#define LZMA2_CONTROL_LZMA (1 << 7)

+#define LZMA2_CONTROL_COPY_NO_RESET 2

+#define LZMA2_CONTROL_COPY_RESET_DIC 1

+#define LZMA2_CONTROL_EOF 0

+

+#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)

+

+#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)

+#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)

+

+#define LZMA2_LCLP_MAX 4

+#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))

+

+#ifdef SHOW_DEBUG_INFO

+#define PRF(x) x

+#else

+#define PRF(x)

+#endif

+

+typedef enum

+{

+  LZMA2_STATE_CONTROL,

+  LZMA2_STATE_UNPACK0,

+  LZMA2_STATE_UNPACK1,

+  LZMA2_STATE_PACK0,

+  LZMA2_STATE_PACK1,

+  LZMA2_STATE_PROP,

+  LZMA2_STATE_DATA,

+  LZMA2_STATE_DATA_CONT,

+  LZMA2_STATE_FINISHED,

+  LZMA2_STATE_ERROR

+} ELzma2State;

+

+static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)

+{

+  UInt32 dicSize;

+  if (prop > 40)

+    return SZ_ERROR_UNSUPPORTED;

+  dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);

+  props[0] = (Byte)LZMA2_LCLP_MAX;

+  props[1] = (Byte)(dicSize);

+  props[2] = (Byte)(dicSize >> 8);

+  props[3] = (Byte)(dicSize >> 16);

+  props[4] = (Byte)(dicSize >> 24);

+  return SZ_OK;

+}

+

+SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)

+{

+  Byte props[LZMA_PROPS_SIZE];

+  RINOK(Lzma2Dec_GetOldProps(prop, props));

+  return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);

+}

+

+SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)

+{

+  Byte props[LZMA_PROPS_SIZE];

+  RINOK(Lzma2Dec_GetOldProps(prop, props));

+  return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);

+}

+

+void Lzma2Dec_Init(CLzma2Dec *p)

+{

+  p->state = LZMA2_STATE_CONTROL;

+  p->needInitDic = True;

+  p->needInitState = True;

+  p->needInitProp = True;

+  LzmaDec_Init(&p->decoder);

+}

+

+static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)

+{

+  switch(p->state)

+  {

+    case LZMA2_STATE_CONTROL:

+      p->control = b;

+      PRF(printf("\n %4X ", p->decoder.dicPos));

+      PRF(printf(" %2X", b));

+      if (p->control == 0)

+        return LZMA2_STATE_FINISHED;

+      if (LZMA2_IS_UNCOMPRESSED_STATE(p))

+      {

+        if ((p->control & 0x7F) > 2)

+          return LZMA2_STATE_ERROR;

+        p->unpackSize = 0;

+      }

+      else

+        p->unpackSize = (UInt32)(p->control & 0x1F) << 16;

+      return LZMA2_STATE_UNPACK0;

+    

+    case LZMA2_STATE_UNPACK0:

+      p->unpackSize |= (UInt32)b << 8;

+      return LZMA2_STATE_UNPACK1;

+    

+    case LZMA2_STATE_UNPACK1:

+      p->unpackSize |= (UInt32)b;

+      p->unpackSize++;

+      PRF(printf(" %8d", p->unpackSize));

+      return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;

+    

+    case LZMA2_STATE_PACK0:

+      p->packSize = (UInt32)b << 8;

+      return LZMA2_STATE_PACK1;

+

+    case LZMA2_STATE_PACK1:

+      p->packSize |= (UInt32)b;

+      p->packSize++;

+      PRF(printf(" %8d", p->packSize));

+      return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:

+        (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);

+

+    case LZMA2_STATE_PROP:

+    {

+      int lc, lp;

+      if (b >= (9 * 5 * 5))

+        return LZMA2_STATE_ERROR;

+      lc = b % 9;

+      b /= 9;

+      p->decoder.prop.pb = b / 5;

+      lp = b % 5;

+      if (lc + lp > LZMA2_LCLP_MAX)

+        return LZMA2_STATE_ERROR;

+      p->decoder.prop.lc = lc;

+      p->decoder.prop.lp = lp;

+      p->needInitProp = False;

+      return LZMA2_STATE_DATA;

+    }

+  }

+  return LZMA2_STATE_ERROR;

+}

+

+static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)

+{

+  memcpy(p->dic + p->dicPos, src, size);

+  p->dicPos += size;

+  if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)

+    p->checkDicSize = p->prop.dicSize;

+  p->processedPos += (UInt32)size;

+}

+

+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);

+

+SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,

+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)

+{

+  SizeT inSize = *srcLen;

+  *srcLen = 0;

+  *status = LZMA_STATUS_NOT_SPECIFIED;

+

+  while (p->state != LZMA2_STATE_FINISHED)

+  {

+    SizeT dicPos = p->decoder.dicPos;

+    if (p->state == LZMA2_STATE_ERROR)

+      return SZ_ERROR_DATA;

+    if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)

+    {

+      *status = LZMA_STATUS_NOT_FINISHED;

+      return SZ_OK;

+    }

+    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)

+    {

+      if (*srcLen == inSize)

+      {

+        *status = LZMA_STATUS_NEEDS_MORE_INPUT;

+        return SZ_OK;

+      }

+      (*srcLen)++;

+      p->state = Lzma2Dec_UpdateState(p, *src++);

+      continue;

+    }

+    {

+      SizeT destSizeCur = dicLimit - dicPos;

+      SizeT srcSizeCur = inSize - *srcLen;

+      ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;

+      

+      if (p->unpackSize <= destSizeCur)

+      {

+        destSizeCur = (SizeT)p->unpackSize;

+        curFinishMode = LZMA_FINISH_END;

+      }

+

+      if (LZMA2_IS_UNCOMPRESSED_STATE(p))

+      {

+        if (*srcLen == inSize)

+        {

+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;

+          return SZ_OK;

+        }

+

+        if (p->state == LZMA2_STATE_DATA)

+        {

+          Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);

+          if (initDic)

+            p->needInitProp = p->needInitState = True;

+          else if (p->needInitDic)

+            return SZ_ERROR_DATA;

+          p->needInitDic = False;

+          LzmaDec_InitDicAndState(&p->decoder, initDic, False);

+        }

+

+        if (srcSizeCur > destSizeCur)

+          srcSizeCur = destSizeCur;

+

+        if (srcSizeCur == 0)

+          return SZ_ERROR_DATA;

+

+        LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);

+

+        src += srcSizeCur;

+        *srcLen += srcSizeCur;

+        p->unpackSize -= (UInt32)srcSizeCur;

+        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;

+      }

+      else

+      {

+        SizeT outSizeProcessed;

+        SRes res;

+

+        if (p->state == LZMA2_STATE_DATA)

+        {

+          int mode = LZMA2_GET_LZMA_MODE(p);

+          Bool initDic = (mode == 3);

+          Bool initState = (mode > 0);

+          if ((!initDic && p->needInitDic) || (!initState && p->needInitState))

+            return SZ_ERROR_DATA;

+          

+          LzmaDec_InitDicAndState(&p->decoder, initDic, initState);

+          p->needInitDic = False;

+          p->needInitState = False;

+          p->state = LZMA2_STATE_DATA_CONT;

+        }

+        if (srcSizeCur > p->packSize)

+          srcSizeCur = (SizeT)p->packSize;

+          

+        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);

+        

+        src += srcSizeCur;

+        *srcLen += srcSizeCur;

+        p->packSize -= (UInt32)srcSizeCur;

+

+        outSizeProcessed = p->decoder.dicPos - dicPos;

+        p->unpackSize -= (UInt32)outSizeProcessed;

+

+        RINOK(res);

+        if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)

+          return res;

+

+        if (srcSizeCur == 0 && outSizeProcessed == 0)

+        {

+          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||

+              p->unpackSize != 0 || p->packSize != 0)

+            return SZ_ERROR_DATA;

+          p->state = LZMA2_STATE_CONTROL;

+        }

+        if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)

+          *status = LZMA_STATUS_NOT_FINISHED;

+      }

+    }

+  }

+  *status = LZMA_STATUS_FINISHED_WITH_MARK;

+  return SZ_OK;

+}

+

+SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)

+{

+  SizeT outSize = *destLen, inSize = *srcLen;

+  *srcLen = *destLen = 0;

+  for (;;)

+  {

+    SizeT srcSizeCur = inSize, outSizeCur, dicPos;

+    ELzmaFinishMode curFinishMode;

+    SRes res;

+    if (p->decoder.dicPos == p->decoder.dicBufSize)

+      p->decoder.dicPos = 0;

+    dicPos = p->decoder.dicPos;

+    if (outSize > p->decoder.dicBufSize - dicPos)

+    {

+      outSizeCur = p->decoder.dicBufSize;

+      curFinishMode = LZMA_FINISH_ANY;

+    }

+    else

+    {

+      outSizeCur = dicPos + outSize;

+      curFinishMode = finishMode;

+    }

+

+    res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);

+    src += srcSizeCur;

+    inSize -= srcSizeCur;

+    *srcLen += srcSizeCur;

+    outSizeCur = p->decoder.dicPos - dicPos;

+    memcpy(dest, p->decoder.dic + dicPos, outSizeCur);

+    dest += outSizeCur;

+    outSize -= outSizeCur;

+    *destLen += outSizeCur;

+    if (res != 0)

+      return res;

+    if (outSizeCur == 0 || outSize == 0)

+      return SZ_OK;

+  }

+}

+

+SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)

+{

+  CLzma2Dec decoder;

+  SRes res;

+  SizeT outSize = *destLen, inSize = *srcLen;

+  Byte props[LZMA_PROPS_SIZE];

+

+  Lzma2Dec_Construct(&decoder);

+

+  *destLen = *srcLen = 0;

+  *status = LZMA_STATUS_NOT_SPECIFIED;

+  decoder.decoder.dic = dest;

+  decoder.decoder.dicBufSize = outSize;

+

+  RINOK(Lzma2Dec_GetOldProps(prop, props));

+  RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));

+  

+  *srcLen = inSize;

+  res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);

+  *destLen = decoder.decoder.dicPos;

+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)

+    res = SZ_ERROR_INPUT_EOF;

+

+  LzmaDec_FreeProbs(&decoder.decoder, alloc);

+  return res;

+}

diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h
new file mode 100755
index 0000000..827698d
--- /dev/null
+++ b/C/Lzma2Dec.h
@@ -0,0 +1,84 @@
+/* Lzma2Dec.h -- LZMA2 Decoder

+2009-05-03 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA2_DEC_H

+#define __LZMA2_DEC_H

+

+#include "LzmaDec.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+/* ---------- State Interface ---------- */

+

+typedef struct

+{

+  CLzmaDec decoder;

+  UInt32 packSize;

+  UInt32 unpackSize;

+  int state;

+  Byte control;

+  Bool needInitDic;

+  Bool needInitState;

+  Bool needInitProp;

+} CLzma2Dec;

+

+#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)

+#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);

+#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);

+

+SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);

+SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);

+void Lzma2Dec_Init(CLzma2Dec *p);

+

+

+/*

+finishMode:

+  It has meaning only if the decoding reaches output limit (*destLen or dicLimit).

+  LZMA_FINISH_ANY - use smallest number of input bytes

+  LZMA_FINISH_END - read EndOfStream marker after decoding

+

+Returns:

+  SZ_OK

+    status:

+      LZMA_STATUS_FINISHED_WITH_MARK

+      LZMA_STATUS_NOT_FINISHED

+      LZMA_STATUS_NEEDS_MORE_INPUT

+  SZ_ERROR_DATA - Data error

+*/

+

+SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,

+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);

+

+SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,

+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);

+

+

+/* ---------- One Call Interface ---------- */

+

+/*

+finishMode:

+  It has meaning only if the decoding reaches output limit (*destLen).

+  LZMA_FINISH_ANY - use smallest number of input bytes

+  LZMA_FINISH_END - read EndOfStream marker after decoding

+

+Returns:

+  SZ_OK

+    status:

+      LZMA_STATUS_FINISHED_WITH_MARK

+      LZMA_STATUS_NOT_FINISHED

+  SZ_ERROR_DATA - Data error

+  SZ_ERROR_MEM  - Memory allocation error

+  SZ_ERROR_UNSUPPORTED - Unsupported properties

+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).

+*/

+

+SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c
new file mode 100755
index 0000000..35f6ed7
--- /dev/null
+++ b/C/Lzma2Enc.c
@@ -0,0 +1,477 @@
+/* Lzma2Enc.c -- LZMA2 Encoder

+2010-09-24 : Igor Pavlov : Public domain */

+

+/* #include <stdio.h> */

+#include <string.h>

+

+/* #define _7ZIP_ST */

+

+#include "Lzma2Enc.h"

+

+#ifndef _7ZIP_ST

+#include "MtCoder.h"

+#else

+#define NUM_MT_CODER_THREADS_MAX 1

+#endif

+

+#define LZMA2_CONTROL_LZMA (1 << 7)

+#define LZMA2_CONTROL_COPY_NO_RESET 2

+#define LZMA2_CONTROL_COPY_RESET_DIC 1

+#define LZMA2_CONTROL_EOF 0

+

+#define LZMA2_LCLP_MAX 4

+

+#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))

+

+#define LZMA2_PACK_SIZE_MAX (1 << 16)

+#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX

+#define LZMA2_UNPACK_SIZE_MAX (1 << 21)

+#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX

+

+#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)

+

+

+#define PRF(x) /* x */

+

+/* ---------- CLzma2EncInt ---------- */

+

+typedef struct

+{

+  CLzmaEncHandle enc;

+  UInt64 srcPos;

+  Byte props;

+  Bool needInitState;

+  Bool needInitProp;

+} CLzma2EncInt;

+

+static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)

+{

+  Byte propsEncoded[LZMA_PROPS_SIZE];

+  SizeT propsSize = LZMA_PROPS_SIZE;

+  RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));

+  RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));

+  p->srcPos = 0;

+  p->props = propsEncoded[0];

+  p->needInitState = True;

+  p->needInitProp = True;

+  return SZ_OK;

+}

+

+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,

+    ISzAlloc *alloc, ISzAlloc *allocBig);

+SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,

+    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);

+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,

+    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);

+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);

+void LzmaEnc_Finish(CLzmaEncHandle pp);

+void LzmaEnc_SaveState(CLzmaEncHandle pp);

+void LzmaEnc_RestoreState(CLzmaEncHandle pp);

+

+

+static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,

+    size_t *packSizeRes, ISeqOutStream *outStream)

+{

+  size_t packSizeLimit = *packSizeRes;

+  size_t packSize = packSizeLimit;

+  UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;

+  unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);

+  Bool useCopyBlock;

+  SRes res;

+

+  *packSizeRes = 0;

+  if (packSize < lzHeaderSize)

+    return SZ_ERROR_OUTPUT_EOF;

+  packSize -= lzHeaderSize;

+  

+  LzmaEnc_SaveState(p->enc);

+  res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,

+      outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);

+  

+  PRF(printf("\npackSize = %7d unpackSize = %7d  ", packSize, unpackSize));

+

+  if (unpackSize == 0)

+    return res;

+

+  if (res == SZ_OK)

+    useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));

+  else

+  {

+    if (res != SZ_ERROR_OUTPUT_EOF)

+      return res;

+    res = SZ_OK;

+    useCopyBlock = True;

+  }

+

+  if (useCopyBlock)

+  {

+    size_t destPos = 0;

+    PRF(printf("################# COPY           "));

+    while (unpackSize > 0)

+    {

+      UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;

+      if (packSizeLimit - destPos < u + 3)

+        return SZ_ERROR_OUTPUT_EOF;

+      outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);

+      outBuf[destPos++] = (Byte)((u - 1) >> 8);

+      outBuf[destPos++] = (Byte)(u - 1);

+      memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);

+      unpackSize -= u;

+      destPos += u;

+      p->srcPos += u;

+      if (outStream)

+      {

+        *packSizeRes += destPos;

+        if (outStream->Write(outStream, outBuf, destPos) != destPos)

+          return SZ_ERROR_WRITE;

+        destPos = 0;

+      }

+      else

+        *packSizeRes = destPos;

+      /* needInitState = True; */

+    }

+    LzmaEnc_RestoreState(p->enc);

+    return SZ_OK;

+  }

+  {

+    size_t destPos = 0;

+    UInt32 u = unpackSize - 1;

+    UInt32 pm = (UInt32)(packSize - 1);

+    unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);

+

+    PRF(printf("               "));

+

+    outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));

+    outBuf[destPos++] = (Byte)(u >> 8);

+    outBuf[destPos++] = (Byte)u;

+    outBuf[destPos++] = (Byte)(pm >> 8);

+    outBuf[destPos++] = (Byte)pm;

+    

+    if (p->needInitProp)

+      outBuf[destPos++] = p->props;

+    

+    p->needInitProp = False;

+    p->needInitState = False;

+    destPos += packSize;

+    p->srcPos += unpackSize;

+

+    if (outStream)

+      if (outStream->Write(outStream, outBuf, destPos) != destPos)

+        return SZ_ERROR_WRITE;

+    *packSizeRes = destPos;

+    return SZ_OK;

+  }

+}

+

+/* ---------- Lzma2 Props ---------- */

+

+void Lzma2EncProps_Init(CLzma2EncProps *p)

+{

+  LzmaEncProps_Init(&p->lzmaProps);

+  p->numTotalThreads = -1;

+  p->numBlockThreads = -1;

+  p->blockSize = 0;

+}

+

+void Lzma2EncProps_Normalize(CLzma2EncProps *p)

+{

+  int t1, t1n, t2, t3;

+  {

+    CLzmaEncProps lzmaProps = p->lzmaProps;

+    LzmaEncProps_Normalize(&lzmaProps);

+    t1n = lzmaProps.numThreads;

+  }

+

+  t1 = p->lzmaProps.numThreads;

+  t2 = p->numBlockThreads;

+  t3 = p->numTotalThreads;

+

+  if (t2 > NUM_MT_CODER_THREADS_MAX)

+    t2 = NUM_MT_CODER_THREADS_MAX;

+

+  if (t3 <= 0)

+  {

+    if (t2 <= 0)

+      t2 = 1;

+    t3 = t1n * t2;

+  }

+  else if (t2 <= 0)

+  {

+    t2 = t3 / t1n;

+    if (t2 == 0)

+    {

+      t1 = 1;

+      t2 = t3;

+    }

+    if (t2 > NUM_MT_CODER_THREADS_MAX)

+      t2 = NUM_MT_CODER_THREADS_MAX;

+  }

+  else if (t1 <= 0)

+  {

+    t1 = t3 / t2;

+    if (t1 == 0)

+      t1 = 1;

+  }

+  else

+    t3 = t1n * t2;

+

+  p->lzmaProps.numThreads = t1;

+  p->numBlockThreads = t2;

+  p->numTotalThreads = t3;

+  LzmaEncProps_Normalize(&p->lzmaProps);

+

+  if (p->blockSize == 0)

+  {

+    UInt32 dictSize = p->lzmaProps.dictSize;

+    UInt64 blockSize = (UInt64)dictSize << 2;

+    const UInt32 kMinSize = (UInt32)1 << 20;

+    const UInt32 kMaxSize = (UInt32)1 << 28;

+    if (blockSize < kMinSize) blockSize = kMinSize;

+    if (blockSize > kMaxSize) blockSize = kMaxSize;

+    if (blockSize < dictSize) blockSize = dictSize;

+    p->blockSize = (size_t)blockSize;

+  }

+}

+

+static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)

+{

+  return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;

+}

+

+/* ---------- Lzma2 ---------- */

+

+typedef struct

+{

+  Byte propEncoded;

+  CLzma2EncProps props;

+  

+  Byte *outBuf;

+

+  ISzAlloc *alloc;

+  ISzAlloc *allocBig;

+

+  CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];

+

+  #ifndef _7ZIP_ST

+  CMtCoder mtCoder;

+  #endif

+

+} CLzma2Enc;

+

+

+/* ---------- Lzma2EncThread ---------- */

+

+static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,

+  ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)

+{

+  UInt64 packTotal = 0;

+  SRes res = SZ_OK;

+

+  if (mainEncoder->outBuf == 0)

+  {

+    mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);

+    if (mainEncoder->outBuf == 0)

+      return SZ_ERROR_MEM;

+  }

+  RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));

+  RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,

+      mainEncoder->alloc, mainEncoder->allocBig));

+  for (;;)

+  {

+    size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;

+    res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);

+    if (res != SZ_OK)

+      break;

+    packTotal += packSize;

+    res = Progress(progress, p->srcPos, packTotal);

+    if (res != SZ_OK)

+      break;

+    if (packSize == 0)

+      break;

+  }

+  LzmaEnc_Finish(p->enc);

+  if (res == SZ_OK)

+  {

+    Byte b = 0;

+    if (outStream->Write(outStream, &b, 1) != 1)

+      return SZ_ERROR_WRITE;

+  }

+  return res;

+}

+

+#ifndef _7ZIP_ST

+

+typedef struct

+{

+  IMtCoderCallback funcTable;

+  CLzma2Enc *lzma2Enc;

+} CMtCallbackImp;

+

+static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,

+      const Byte *src, size_t srcSize, int finished)

+{

+  CMtCallbackImp *imp = (CMtCallbackImp *)pp;

+  CLzma2Enc *mainEncoder = imp->lzma2Enc;

+  CLzma2EncInt *p = &mainEncoder->coders[index];

+

+  SRes res = SZ_OK;

+  {

+    size_t destLim = *destSize;

+    *destSize = 0;

+

+    if (srcSize != 0)

+    {

+      RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));

+     

+      RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,

+          mainEncoder->alloc, mainEncoder->allocBig));

+     

+      while (p->srcPos < srcSize)

+      {

+        size_t packSize = destLim - *destSize;

+        res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);

+        if (res != SZ_OK)

+          break;

+        *destSize += packSize;

+

+        if (packSize == 0)

+        {

+          res = SZ_ERROR_FAIL;

+          break;

+        }

+

+        if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)

+        {

+          res = SZ_ERROR_PROGRESS;

+          break;

+        }

+      }

+      LzmaEnc_Finish(p->enc);

+      if (res != SZ_OK)

+        return res;

+    }

+    if (finished)

+    {

+      if (*destSize == destLim)

+        return SZ_ERROR_OUTPUT_EOF;

+      dest[(*destSize)++] = 0;

+    }

+  }

+  return res;

+}

+

+#endif

+

+/* ---------- Lzma2Enc ---------- */

+

+CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));

+  if (p == 0)

+    return NULL;

+  Lzma2EncProps_Init(&p->props);

+  Lzma2EncProps_Normalize(&p->props);

+  p->outBuf = 0;

+  p->alloc = alloc;

+  p->allocBig = allocBig;

+  {

+    unsigned i;

+    for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)

+      p->coders[i].enc = 0;

+  }

+  #ifndef _7ZIP_ST

+  MtCoder_Construct(&p->mtCoder);

+  #endif

+

+  return p;

+}

+

+void Lzma2Enc_Destroy(CLzma2EncHandle pp)

+{

+  CLzma2Enc *p = (CLzma2Enc *)pp;

+  unsigned i;

+  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)

+  {

+    CLzma2EncInt *t = &p->coders[i];

+    if (t->enc)

+    {

+      LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);

+      t->enc = 0;

+    }

+  }

+

+  #ifndef _7ZIP_ST

+  MtCoder_Destruct(&p->mtCoder);

+  #endif

+

+  IAlloc_Free(p->alloc, p->outBuf);

+  IAlloc_Free(p->alloc, pp);

+}

+

+SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)

+{

+  CLzma2Enc *p = (CLzma2Enc *)pp;

+  CLzmaEncProps lzmaProps = props->lzmaProps;

+  LzmaEncProps_Normalize(&lzmaProps);

+  if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)

+    return SZ_ERROR_PARAM;

+  p->props = *props;

+  Lzma2EncProps_Normalize(&p->props);

+  return SZ_OK;

+}

+

+Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)

+{

+  CLzma2Enc *p = (CLzma2Enc *)pp;

+  unsigned i;

+  UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);

+  for (i = 0; i < 40; i++)

+    if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))

+      break;

+  return (Byte)i;

+}

+

+SRes Lzma2Enc_Encode(CLzma2EncHandle pp,

+    ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)

+{

+  CLzma2Enc *p = (CLzma2Enc *)pp;

+  int i;

+

+  for (i = 0; i < p->props.numBlockThreads; i++)

+  {

+    CLzma2EncInt *t = &p->coders[i];

+    if (t->enc == NULL)

+    {

+      t->enc = LzmaEnc_Create(p->alloc);

+      if (t->enc == NULL)

+        return SZ_ERROR_MEM;

+    }

+  }

+

+  #ifndef _7ZIP_ST

+  if (p->props.numBlockThreads <= 1)

+  #endif

+    return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);

+

+  #ifndef _7ZIP_ST

+

+  {

+    CMtCallbackImp mtCallback;

+

+    mtCallback.funcTable.Code = MtCallbackImp_Code;

+    mtCallback.lzma2Enc = p;

+    

+    p->mtCoder.progress = progress;

+    p->mtCoder.inStream = inStream;

+    p->mtCoder.outStream = outStream;

+    p->mtCoder.alloc = p->alloc;

+    p->mtCoder.mtCallback = &mtCallback.funcTable;

+

+    p->mtCoder.blockSize = p->props.blockSize;

+    p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;

+    p->mtCoder.numThreads = p->props.numBlockThreads;

+    

+    return MtCoder_Code(&p->mtCoder);

+  }

+  #endif

+}

diff --git a/C/Lzma2Enc.h b/C/Lzma2Enc.h
new file mode 100755
index 0000000..38830e5
--- /dev/null
+++ b/C/Lzma2Enc.h
@@ -0,0 +1,66 @@
+/* Lzma2Enc.h -- LZMA2 Encoder

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA2_ENC_H

+#define __LZMA2_ENC_H

+

+#include "LzmaEnc.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+typedef struct

+{

+  CLzmaEncProps lzmaProps;

+  size_t blockSize;

+  int numBlockThreads;

+  int numTotalThreads;

+} CLzma2EncProps;

+

+void Lzma2EncProps_Init(CLzma2EncProps *p);

+void Lzma2EncProps_Normalize(CLzma2EncProps *p);

+

+/* ---------- CLzmaEnc2Handle Interface ---------- */

+

+/* Lzma2Enc_* functions can return the following exit codes:

+Returns:

+  SZ_OK           - OK

+  SZ_ERROR_MEM    - Memory allocation error

+  SZ_ERROR_PARAM  - Incorrect paramater in props

+  SZ_ERROR_WRITE  - Write callback error

+  SZ_ERROR_PROGRESS - some break from progress callback

+  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)

+*/

+

+typedef void * CLzma2EncHandle;

+

+CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);

+void Lzma2Enc_Destroy(CLzma2EncHandle p);

+SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);

+Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);

+SRes Lzma2Enc_Encode(CLzma2EncHandle p,

+    ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);

+

+/* ---------- One Call Interface ---------- */

+

+/* Lzma2Encode

+Return code:

+  SZ_OK               - OK

+  SZ_ERROR_MEM        - Memory allocation error

+  SZ_ERROR_PARAM      - Incorrect paramater

+  SZ_ERROR_OUTPUT_EOF - output buffer overflow

+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)

+*/

+

+/*

+SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,

+    const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,

+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

+*/

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/Lzma86.h b/C/Lzma86.h
new file mode 100755
index 0000000..6425bb8
--- /dev/null
+++ b/C/Lzma86.h
@@ -0,0 +1,111 @@
+/* Lzma86.h -- LZMA + x86 (BCJ) Filter

+2009-08-14 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA86_H

+#define __LZMA86_H

+

+#include "Types.h"

+

+EXTERN_C_BEGIN

+

+#define LZMA86_SIZE_OFFSET (1 + 5)

+#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)

+

+/*

+It's an example for LZMA + x86 Filter use.

+You can use .lzma86 extension, if you write that stream to file.

+.lzma86 header adds one additional byte to standard .lzma header.

+.lzma86 header (14 bytes):

+  Offset Size  Description

+    0     1    = 0 - no filter, pure LZMA

+               = 1 - x86 filter + LZMA

+    1     1    lc, lp and pb in encoded form

+    2     4    dictSize (little endian)

+    6     8    uncompressed size (little endian)

+

+

+Lzma86_Encode

+-------------

+level - compression level: 0 <= level <= 9, the default value for "level" is 5.

+

+dictSize - The dictionary size in bytes. The maximum value is

+        128 MB = (1 << 27) bytes for 32-bit version

+          1 GB = (1 << 30) bytes for 64-bit version

+     The default value is 16 MB = (1 << 24) bytes, for level = 5.

+     It's recommended to use the dictionary that is larger than 4 KB and

+     that can be calculated as (1 << N) or (3 << N) sizes.

+     For better compression ratio dictSize must be >= inSize.

+

+filterMode:

+    SZ_FILTER_NO   - no Filter

+    SZ_FILTER_YES  - x86 Filter

+    SZ_FILTER_AUTO - it tries both alternatives to select best.

+              Encoder will use 2 or 3 passes:

+              2 passes when FILTER_NO provides better compression.

+              3 passes when FILTER_YES provides better compression.

+

+Lzma86Encode allocates Data with MyAlloc functions.

+RAM Requirements for compressing:

+  RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize

+      filterMode     FilterBlockSize

+     SZ_FILTER_NO         0

+     SZ_FILTER_YES      inSize

+     SZ_FILTER_AUTO     inSize

+

+

+Return code:

+  SZ_OK               - OK

+  SZ_ERROR_MEM        - Memory allocation error

+  SZ_ERROR_PARAM      - Incorrect paramater

+  SZ_ERROR_OUTPUT_EOF - output buffer overflow

+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)

+*/

+

+enum ESzFilterMode

+{

+  SZ_FILTER_NO,

+  SZ_FILTER_YES,

+  SZ_FILTER_AUTO

+};

+

+SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,

+    int level, UInt32 dictSize, int filterMode);

+

+

+/*

+Lzma86_GetUnpackSize:

+  In:

+    src      - input data

+    srcLen   - input data size

+  Out:

+    unpackSize - size of uncompressed stream

+  Return code:

+    SZ_OK               - OK

+    SZ_ERROR_INPUT_EOF  - Error in headers

+*/

+

+SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);

+

+/*

+Lzma86_Decode:

+  In:

+    dest     - output data

+    destLen  - output data size

+    src      - input data

+    srcLen   - input data size

+  Out:

+    destLen  - processed output size

+    srcLen   - processed input size

+  Return code:

+    SZ_OK           - OK

+    SZ_ERROR_DATA  - Data error

+    SZ_ERROR_MEM   - Memory allocation error

+    SZ_ERROR_UNSUPPORTED - unsupported file

+    SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer

+*/

+

+SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);

+

+EXTERN_C_END

+

+#endif

diff --git a/C/Lzma86Dec.c b/C/Lzma86Dec.c
new file mode 100755
index 0000000..760a447
--- /dev/null
+++ b/C/Lzma86Dec.c
@@ -0,0 +1,56 @@
+/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder

+2009-08-14 : Igor Pavlov : Public domain */

+

+#include "Lzma86.h"

+

+#include "Alloc.h"

+#include "Bra.h"

+#include "LzmaDec.h"

+

+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

+static void SzFree(void *p, void *address) { p = p; MyFree(address); }

+

+SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)

+{

+  unsigned i;

+  if (srcLen < LZMA86_HEADER_SIZE)

+    return SZ_ERROR_INPUT_EOF;

+  *unpackSize = 0;

+  for (i = 0; i < sizeof(UInt64); i++)

+    *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i);

+  return SZ_OK;

+}

+

+SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)

+{

+  ISzAlloc g_Alloc = { SzAlloc, SzFree };

+  SRes res;

+  int useFilter;

+  SizeT inSizePure;

+  ELzmaStatus status;

+

+  if (*srcLen < LZMA86_HEADER_SIZE)

+    return SZ_ERROR_INPUT_EOF;

+

+  useFilter = src[0];

+

+  if (useFilter > 1)

+  {

+    *destLen = 0;

+    return SZ_ERROR_UNSUPPORTED;

+  }

+

+  inSizePure = *srcLen - LZMA86_HEADER_SIZE;

+  res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure,

+      src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc);

+  *srcLen = inSizePure + LZMA86_HEADER_SIZE;

+  if (res != SZ_OK)

+    return res;

+  if (useFilter == 1)

+  {

+    UInt32 x86State;

+    x86_Convert_Init(x86State);

+    x86_Convert(dest, *destLen, 0, &x86State, 0);

+  }

+  return SZ_OK;

+}

diff --git a/C/Lzma86Enc.c b/C/Lzma86Enc.c
new file mode 100755
index 0000000..a29c605
--- /dev/null
+++ b/C/Lzma86Enc.c
@@ -0,0 +1,108 @@
+/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder

+2009-08-14 : Igor Pavlov : Public domain */

+

+#include <string.h>

+

+#include "Lzma86.h"

+

+#include "Alloc.h"

+#include "Bra.h"

+#include "LzmaEnc.h"

+

+#define SZE_OUT_OVERFLOW SZE_DATA_ERROR

+

+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

+static void SzFree(void *p, void *address) { p = p; MyFree(address); }

+

+int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,

+    int level, UInt32 dictSize, int filterMode)

+{

+  ISzAlloc g_Alloc = { SzAlloc, SzFree };

+  size_t outSize2 = *destLen;

+  Byte *filteredStream;

+  Bool useFilter;

+  int mainResult = SZ_ERROR_OUTPUT_EOF;

+  CLzmaEncProps props;

+  LzmaEncProps_Init(&props);

+  props.level = level;

+  props.dictSize = dictSize;

+  

+  *destLen = 0;

+  if (outSize2 < LZMA86_HEADER_SIZE)

+    return SZ_ERROR_OUTPUT_EOF;

+

+  {

+    int i;

+    UInt64 t = srcLen;

+    for (i = 0; i < 8; i++, t >>= 8)

+      dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;

+  }

+

+  filteredStream = 0;

+  useFilter = (filterMode != SZ_FILTER_NO);

+  if (useFilter)

+  {

+    if (srcLen != 0)

+    {

+      filteredStream = (Byte *)MyAlloc(srcLen);

+      if (filteredStream == 0)

+        return SZ_ERROR_MEM;

+      memcpy(filteredStream, src, srcLen);

+    }

+    {

+      UInt32 x86State;

+      x86_Convert_Init(x86State);

+      x86_Convert(filteredStream, srcLen, 0, &x86State, 1);

+    }

+  }

+

+  {

+    size_t minSize = 0;

+    Bool bestIsFiltered = False;

+

+    /* passes for SZ_FILTER_AUTO:

+        0 - BCJ + LZMA

+        1 - LZMA

+        2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.

+    */

+    int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;

+

+    int i;

+    for (i = 0; i < numPasses; i++)

+    {

+      size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;

+      size_t outPropsSize = 5;

+      SRes curRes;

+      Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);

+      if (curModeIsFiltered && !bestIsFiltered)

+        break;

+      if (useFilter && i == 0)

+        curModeIsFiltered = True;

+      

+      curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,

+          curModeIsFiltered ? filteredStream : src, srcLen,

+          &props, dest + 1, &outPropsSize, 0,

+          NULL, &g_Alloc, &g_Alloc);

+      

+      if (curRes != SZ_ERROR_OUTPUT_EOF)

+      {

+        if (curRes != SZ_OK)

+        {

+          mainResult = curRes;

+          break;

+        }

+        if (outSizeProcessed <= minSize || mainResult != SZ_OK)

+        {

+          minSize = outSizeProcessed;

+          bestIsFiltered = curModeIsFiltered;

+          mainResult = SZ_OK;

+        }

+      }

+    }

+    dest[0] = (bestIsFiltered ? 1 : 0);

+    *destLen = LZMA86_HEADER_SIZE + minSize;

+  }

+  if (useFilter)

+    MyFree(filteredStream);

+  return mainResult;

+}

diff --git a/C/LzmaDec.c b/C/LzmaDec.c
new file mode 100755
index 0000000..4fdc11d
--- /dev/null
+++ b/C/LzmaDec.c
@@ -0,0 +1,999 @@
+/* LzmaDec.c -- LZMA Decoder

+2009-09-20 : Igor Pavlov : Public domain */

+

+#include "LzmaDec.h"

+

+#include <string.h>

+

+#define kNumTopBits 24

+#define kTopValue ((UInt32)1 << kNumTopBits)

+

+#define kNumBitModelTotalBits 11

+#define kBitModelTotal (1 << kNumBitModelTotalBits)

+#define kNumMoveBits 5

+

+#define RC_INIT_SIZE 5

+

+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }

+

+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)

+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));

+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));

+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \

+  { UPDATE_0(p); i = (i + i); A0; } else \

+  { UPDATE_1(p); i = (i + i) + 1; A1; }

+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)

+

+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }

+#define TREE_DECODE(probs, limit, i) \

+  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }

+

+/* #define _LZMA_SIZE_OPT */

+

+#ifdef _LZMA_SIZE_OPT

+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)

+#else

+#define TREE_6_DECODE(probs, i) \

+  { i = 1; \

+  TREE_GET_BIT(probs, i); \

+  TREE_GET_BIT(probs, i); \

+  TREE_GET_BIT(probs, i); \

+  TREE_GET_BIT(probs, i); \

+  TREE_GET_BIT(probs, i); \

+  TREE_GET_BIT(probs, i); \

+  i -= 0x40; }

+#endif

+

+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }

+

+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)

+#define UPDATE_0_CHECK range = bound;

+#define UPDATE_1_CHECK range -= bound; code -= bound;

+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \

+  { UPDATE_0_CHECK; i = (i + i); A0; } else \

+  { UPDATE_1_CHECK; i = (i + i) + 1; A1; }

+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)

+#define TREE_DECODE_CHECK(probs, limit, i) \

+  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }

+

+

+#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 kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)

+

+#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)

+

+#define LZMA_BASE_SIZE 1846

+#define LZMA_LIT_SIZE 768

+

+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))

+

+#if Literal != LZMA_BASE_SIZE

+StopCompilingDueBUG

+#endif

+

+#define LZMA_DIC_MIN (1 << 12)

+

+/* First LZMA-symbol is always decoded.

+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization

+Out:

+  Result:

+    SZ_OK - OK

+    SZ_ERROR_DATA - Error

+  p->remainLen:

+    < kMatchSpecLenStart : normal remain

+    = kMatchSpecLenStart : finished

+    = kMatchSpecLenStart + 1 : Flush marker

+    = kMatchSpecLenStart + 2 : State Init Marker

+*/

+

+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)

+{

+  CLzmaProb *probs = p->probs;

+

+  unsigned state = p->state;

+  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];

+  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;

+  unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;

+  unsigned lc = p->prop.lc;

+

+  Byte *dic = p->dic;

+  SizeT dicBufSize = p->dicBufSize;

+  SizeT dicPos = p->dicPos;

+  

+  UInt32 processedPos = p->processedPos;

+  UInt32 checkDicSize = p->checkDicSize;

+  unsigned len = 0;

+

+  const Byte *buf = p->buf;

+  UInt32 range = p->range;

+  UInt32 code = p->code;

+

+  do

+  {

+    CLzmaProb *prob;

+    UInt32 bound;

+    unsigned ttt;

+    unsigned posState = processedPos & pbMask;

+

+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;

+    IF_BIT_0(prob)

+    {

+      unsigned symbol;

+      UPDATE_0(prob);

+      prob = probs + Literal;

+      if (checkDicSize != 0 || processedPos != 0)

+        prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +

+        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));

+

+      if (state < kNumLitStates)

+      {

+        state -= (state < 4) ? state : 3;

+        symbol = 1;

+        do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);

+      }

+      else

+      {

+        unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];

+        unsigned offs = 0x100;

+        state -= (state < 10) ? 3 : 6;

+        symbol = 1;

+        do

+        {

+          unsigned bit;

+          CLzmaProb *probLit;

+          matchByte <<= 1;

+          bit = (matchByte & offs);

+          probLit = prob + offs + bit + symbol;

+          GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)

+        }

+        while (symbol < 0x100);

+      }

+      dic[dicPos++] = (Byte)symbol;

+      processedPos++;

+      continue;

+    }

+    else

+    {

+      UPDATE_1(prob);

+      prob = probs + IsRep + state;

+      IF_BIT_0(prob)

+      {

+        UPDATE_0(prob);

+        state += kNumStates;

+        prob = probs + LenCoder;

+      }

+      else

+      {

+        UPDATE_1(prob);

+        if (checkDicSize == 0 && processedPos == 0)

+          return SZ_ERROR_DATA;

+        prob = probs + IsRepG0 + state;

+        IF_BIT_0(prob)

+        {

+          UPDATE_0(prob);

+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;

+          IF_BIT_0(prob)

+          {

+            UPDATE_0(prob);

+            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];

+            dicPos++;

+            processedPos++;

+            state = state < kNumLitStates ? 9 : 11;

+            continue;

+          }

+          UPDATE_1(prob);

+        }

+        else

+        {

+          UInt32 distance;

+          UPDATE_1(prob);

+          prob = probs + IsRepG1 + state;

+          IF_BIT_0(prob)

+          {

+            UPDATE_0(prob);

+            distance = rep1;

+          }

+          else

+          {

+            UPDATE_1(prob);

+            prob = probs + IsRepG2 + state;

+            IF_BIT_0(prob)

+            {

+              UPDATE_0(prob);

+              distance = rep2;

+            }

+            else

+            {

+              UPDATE_1(prob);

+              distance = rep3;

+              rep3 = rep2;

+            }

+            rep2 = rep1;

+          }

+          rep1 = rep0;

+          rep0 = distance;

+        }

+        state = state < kNumLitStates ? 8 : 11;

+        prob = probs + RepLenCoder;

+      }

+      {

+        unsigned limit, offset;

+        CLzmaProb *probLen = prob + LenChoice;

+        IF_BIT_0(probLen)

+        {

+          UPDATE_0(probLen);

+          probLen = prob + LenLow + (posState << kLenNumLowBits);

+          offset = 0;

+          limit = (1 << kLenNumLowBits);

+        }

+        else

+        {

+          UPDATE_1(probLen);

+          probLen = prob + LenChoice2;

+          IF_BIT_0(probLen)

+          {

+            UPDATE_0(probLen);

+            probLen = prob + LenMid + (posState << kLenNumMidBits);

+            offset = kLenNumLowSymbols;

+            limit = (1 << kLenNumMidBits);

+          }

+          else

+          {

+            UPDATE_1(probLen);

+            probLen = prob + LenHigh;

+            offset = kLenNumLowSymbols + kLenNumMidSymbols;

+            limit = (1 << kLenNumHighBits);

+          }

+        }

+        TREE_DECODE(probLen, limit, len);

+        len += offset;

+      }

+

+      if (state >= kNumStates)

+      {

+        UInt32 distance;

+        prob = probs + PosSlot +

+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);

+        TREE_6_DECODE(prob, distance);

+        if (distance >= kStartPosModelIndex)

+        {

+          unsigned posSlot = (unsigned)distance;

+          int numDirectBits = (int)(((distance >> 1) - 1));

+          distance = (2 | (distance & 1));

+          if (posSlot < kEndPosModelIndex)

+          {

+            distance <<= numDirectBits;

+            prob = probs + SpecPos + distance - posSlot - 1;

+            {

+              UInt32 mask = 1;

+              unsigned i = 1;

+              do

+              {

+                GET_BIT2(prob + i, i, ; , distance |= mask);

+                mask <<= 1;

+              }

+              while (--numDirectBits != 0);

+            }

+          }

+          else

+          {

+            numDirectBits -= kNumAlignBits;

+            do

+            {

+              NORMALIZE

+              range >>= 1;

+              

+              {

+                UInt32 t;

+                code -= range;

+                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */

+                distance = (distance << 1) + (t + 1);

+                code += range & t;

+              }

+              /*

+              distance <<= 1;

+              if (code >= range)

+              {

+                code -= range;

+                distance |= 1;

+              }

+              */

+            }

+            while (--numDirectBits != 0);

+            prob = probs + Align;

+            distance <<= kNumAlignBits;

+            {

+              unsigned i = 1;

+              GET_BIT2(prob + i, i, ; , distance |= 1);

+              GET_BIT2(prob + i, i, ; , distance |= 2);

+              GET_BIT2(prob + i, i, ; , distance |= 4);

+              GET_BIT2(prob + i, i, ; , distance |= 8);

+            }

+            if (distance == (UInt32)0xFFFFFFFF)

+            {

+              len += kMatchSpecLenStart;

+              state -= kNumStates;

+              break;

+            }

+          }

+        }

+        rep3 = rep2;

+        rep2 = rep1;

+        rep1 = rep0;

+        rep0 = distance + 1;

+        if (checkDicSize == 0)

+        {

+          if (distance >= processedPos)

+            return SZ_ERROR_DATA;

+        }

+        else if (distance >= checkDicSize)

+          return SZ_ERROR_DATA;

+        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;

+      }

+

+      len += kMatchMinLen;

+

+      if (limit == dicPos)

+        return SZ_ERROR_DATA;

+      {

+        SizeT rem = limit - dicPos;

+        unsigned curLen = ((rem < len) ? (unsigned)rem : len);

+        SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);

+

+        processedPos += curLen;

+

+        len -= curLen;

+        if (pos + curLen <= dicBufSize)

+        {

+          Byte *dest = dic + dicPos;

+          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;

+          const Byte *lim = dest + curLen;

+          dicPos += curLen;

+          do

+            *(dest) = (Byte)*(dest + src);

+          while (++dest != lim);

+        }

+        else

+        {

+          do

+          {

+            dic[dicPos++] = dic[pos];

+            if (++pos == dicBufSize)

+              pos = 0;

+          }

+          while (--curLen != 0);

+        }

+      }

+    }

+  }

+  while (dicPos < limit && buf < bufLimit);

+  NORMALIZE;

+  p->buf = buf;

+  p->range = range;

+  p->code = code;

+  p->remainLen = len;

+  p->dicPos = dicPos;

+  p->processedPos = processedPos;

+  p->reps[0] = rep0;

+  p->reps[1] = rep1;

+  p->reps[2] = rep2;

+  p->reps[3] = rep3;

+  p->state = state;

+

+  return SZ_OK;

+}

+

+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)

+{

+  if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)

+  {

+    Byte *dic = p->dic;

+    SizeT dicPos = p->dicPos;

+    SizeT dicBufSize = p->dicBufSize;

+    unsigned len = p->remainLen;

+    UInt32 rep0 = p->reps[0];

+    if (limit - dicPos < len)

+      len = (unsigned)(limit - dicPos);

+

+    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)

+      p->checkDicSize = p->prop.dicSize;

+

+    p->processedPos += len;

+    p->remainLen -= len;

+    while (len-- != 0)

+    {

+      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];

+      dicPos++;

+    }

+    p->dicPos = dicPos;

+  }

+}

+

+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)

+{

+  do

+  {

+    SizeT limit2 = limit;

+    if (p->checkDicSize == 0)

+    {

+      UInt32 rem = p->prop.dicSize - p->processedPos;

+      if (limit - p->dicPos > rem)

+        limit2 = p->dicPos + rem;

+    }

+    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));

+    if (p->processedPos >= p->prop.dicSize)

+      p->checkDicSize = p->prop.dicSize;

+    LzmaDec_WriteRem(p, limit);

+  }

+  while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);

+

+  if (p->remainLen > kMatchSpecLenStart)

+  {

+    p->remainLen = kMatchSpecLenStart;

+  }

+  return 0;

+}

+

+typedef enum

+{

+  DUMMY_ERROR, /* unexpected end of input stream */

+  DUMMY_LIT,

+  DUMMY_MATCH,

+  DUMMY_REP

+} ELzmaDummy;

+

+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)

+{

+  UInt32 range = p->range;

+  UInt32 code = p->code;

+  const Byte *bufLimit = buf + inSize;

+  CLzmaProb *probs = p->probs;

+  unsigned state = p->state;

+  ELzmaDummy res;

+

+  {

+    CLzmaProb *prob;

+    UInt32 bound;

+    unsigned ttt;

+    unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);

+

+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;

+    IF_BIT_0_CHECK(prob)

+    {

+      UPDATE_0_CHECK

+

+      /* if (bufLimit - buf >= 7) return DUMMY_LIT; */

+

+      prob = probs + Literal;

+      if (p->checkDicSize != 0 || p->processedPos != 0)

+        prob += (LZMA_LIT_SIZE *

+          ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +

+          (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));

+

+      if (state < kNumLitStates)

+      {

+        unsigned symbol = 1;

+        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);

+      }

+      else

+      {

+        unsigned matchByte = p->dic[p->dicPos - p->reps[0] +

+            ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];

+        unsigned offs = 0x100;

+        unsigned symbol = 1;

+        do

+        {

+          unsigned bit;

+          CLzmaProb *probLit;

+          matchByte <<= 1;

+          bit = (matchByte & offs);

+          probLit = prob + offs + bit + symbol;

+          GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)

+        }

+        while (symbol < 0x100);

+      }

+      res = DUMMY_LIT;

+    }

+    else

+    {

+      unsigned len;

+      UPDATE_1_CHECK;

+

+      prob = probs + IsRep + state;

+      IF_BIT_0_CHECK(prob)

+      {

+        UPDATE_0_CHECK;

+        state = 0;

+        prob = probs + LenCoder;

+        res = DUMMY_MATCH;

+      }

+      else

+      {

+        UPDATE_1_CHECK;

+        res = DUMMY_REP;

+        prob = probs + IsRepG0 + state;

+        IF_BIT_0_CHECK(prob)

+        {

+          UPDATE_0_CHECK;

+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;

+          IF_BIT_0_CHECK(prob)

+          {

+            UPDATE_0_CHECK;

+            NORMALIZE_CHECK;

+            return DUMMY_REP;

+          }

+          else

+          {

+            UPDATE_1_CHECK;

+          }

+        }

+        else

+        {

+          UPDATE_1_CHECK;

+          prob = probs + IsRepG1 + state;

+          IF_BIT_0_CHECK(prob)

+          {

+            UPDATE_0_CHECK;

+          }

+          else

+          {

+            UPDATE_1_CHECK;

+            prob = probs + IsRepG2 + state;

+            IF_BIT_0_CHECK(prob)

+            {

+              UPDATE_0_CHECK;

+            }

+            else

+            {

+              UPDATE_1_CHECK;

+            }

+          }

+        }

+        state = kNumStates;

+        prob = probs + RepLenCoder;

+      }

+      {

+        unsigned limit, offset;

+        CLzmaProb *probLen = prob + LenChoice;

+        IF_BIT_0_CHECK(probLen)

+        {

+          UPDATE_0_CHECK;

+          probLen = prob + LenLow + (posState << kLenNumLowBits);

+          offset = 0;

+          limit = 1 << kLenNumLowBits;

+        }

+        else

+        {

+          UPDATE_1_CHECK;

+          probLen = prob + LenChoice2;

+          IF_BIT_0_CHECK(probLen)

+          {

+            UPDATE_0_CHECK;

+            probLen = prob + LenMid + (posState << kLenNumMidBits);

+            offset = kLenNumLowSymbols;

+            limit = 1 << kLenNumMidBits;

+          }

+          else

+          {

+            UPDATE_1_CHECK;

+            probLen = prob + LenHigh;

+            offset = kLenNumLowSymbols + kLenNumMidSymbols;

+            limit = 1 << kLenNumHighBits;

+          }

+        }

+        TREE_DECODE_CHECK(probLen, limit, len);

+        len += offset;

+      }

+

+      if (state < 4)

+      {

+        unsigned posSlot;

+        prob = probs + PosSlot +

+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<

+            kNumPosSlotBits);

+        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);

+        if (posSlot >= kStartPosModelIndex)

+        {

+          int numDirectBits = ((posSlot >> 1) - 1);

+

+          /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */

+

+          if (posSlot < kEndPosModelIndex)

+          {

+            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;

+          }

+          else

+          {

+            numDirectBits -= kNumAlignBits;

+            do

+            {

+              NORMALIZE_CHECK

+              range >>= 1;

+              code -= range & (((code - range) >> 31) - 1);

+              /* if (code >= range) code -= range; */

+            }

+            while (--numDirectBits != 0);

+            prob = probs + Align;

+            numDirectBits = kNumAlignBits;

+          }

+          {

+            unsigned i = 1;

+            do

+            {

+              GET_BIT_CHECK(prob + i, i);

+            }

+            while (--numDirectBits != 0);

+          }

+        }

+      }

+    }

+  }

+  NORMALIZE_CHECK;

+  return res;

+}

+

+

+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)

+{

+  p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);

+  p->range = 0xFFFFFFFF;

+  p->needFlush = 0;

+}

+

+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)

+{

+  p->needFlush = 1;

+  p->remainLen = 0;

+  p->tempBufSize = 0;

+

+  if (initDic)

+  {

+    p->processedPos = 0;

+    p->checkDicSize = 0;

+    p->needInitState = 1;

+  }

+  if (initState)

+    p->needInitState = 1;

+}

+

+void LzmaDec_Init(CLzmaDec *p)

+{

+  p->dicPos = 0;

+  LzmaDec_InitDicAndState(p, True, True);

+}

+

+static void LzmaDec_InitStateReal(CLzmaDec *p)

+{

+  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));

+  UInt32 i;

+  CLzmaProb *probs = p->probs;

+  for (i = 0; i < numProbs; i++)

+    probs[i] = kBitModelTotal >> 1;

+  p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;

+  p->state = 0;

+  p->needInitState = 0;

+}

+

+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,

+    ELzmaFinishMode finishMode, ELzmaStatus *status)

+{

+  SizeT inSize = *srcLen;

+  (*srcLen) = 0;

+  LzmaDec_WriteRem(p, dicLimit);

+  

+  *status = LZMA_STATUS_NOT_SPECIFIED;

+

+  while (p->remainLen != kMatchSpecLenStart)

+  {

+      int checkEndMarkNow;

+

+      if (p->needFlush != 0)

+      {

+        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)

+          p->tempBuf[p->tempBufSize++] = *src++;

+        if (p->tempBufSize < RC_INIT_SIZE)

+        {

+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;

+          return SZ_OK;

+        }

+        if (p->tempBuf[0] != 0)

+          return SZ_ERROR_DATA;

+

+        LzmaDec_InitRc(p, p->tempBuf);

+        p->tempBufSize = 0;

+      }

+

+      checkEndMarkNow = 0;

+      if (p->dicPos >= dicLimit)

+      {

+        if (p->remainLen == 0 && p->code == 0)

+        {

+          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;

+          return SZ_OK;

+        }

+        if (finishMode == LZMA_FINISH_ANY)

+        {

+          *status = LZMA_STATUS_NOT_FINISHED;

+          return SZ_OK;

+        }

+        if (p->remainLen != 0)

+        {

+          *status = LZMA_STATUS_NOT_FINISHED;

+          return SZ_ERROR_DATA;

+        }

+        checkEndMarkNow = 1;

+      }

+

+      if (p->needInitState)

+        LzmaDec_InitStateReal(p);

+  

+      if (p->tempBufSize == 0)

+      {

+        SizeT processed;

+        const Byte *bufLimit;

+        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)

+        {

+          int dummyRes = LzmaDec_TryDummy(p, src, inSize);

+          if (dummyRes == DUMMY_ERROR)

+          {

+            memcpy(p->tempBuf, src, inSize);

+            p->tempBufSize = (unsigned)inSize;

+            (*srcLen) += inSize;

+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;

+            return SZ_OK;

+          }

+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)

+          {

+            *status = LZMA_STATUS_NOT_FINISHED;

+            return SZ_ERROR_DATA;

+          }

+          bufLimit = src;

+        }

+        else

+          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;

+        p->buf = src;

+        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)

+          return SZ_ERROR_DATA;

+        processed = (SizeT)(p->buf - src);

+        (*srcLen) += processed;

+        src += processed;

+        inSize -= processed;

+      }

+      else

+      {

+        unsigned rem = p->tempBufSize, lookAhead = 0;

+        while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)

+          p->tempBuf[rem++] = src[lookAhead++];

+        p->tempBufSize = rem;

+        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)

+        {

+          int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);

+          if (dummyRes == DUMMY_ERROR)

+          {

+            (*srcLen) += lookAhead;

+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;

+            return SZ_OK;

+          }

+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)

+          {

+            *status = LZMA_STATUS_NOT_FINISHED;

+            return SZ_ERROR_DATA;

+          }

+        }

+        p->buf = p->tempBuf;

+        if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)

+          return SZ_ERROR_DATA;

+        lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));

+        (*srcLen) += lookAhead;

+        src += lookAhead;

+        inSize -= lookAhead;

+        p->tempBufSize = 0;

+      }

+  }

+  if (p->code == 0)

+    *status = LZMA_STATUS_FINISHED_WITH_MARK;

+  return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;

+}

+

+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)

+{

+  SizeT outSize = *destLen;

+  SizeT inSize = *srcLen;

+  *srcLen = *destLen = 0;

+  for (;;)

+  {

+    SizeT inSizeCur = inSize, outSizeCur, dicPos;

+    ELzmaFinishMode curFinishMode;

+    SRes res;

+    if (p->dicPos == p->dicBufSize)

+      p->dicPos = 0;

+    dicPos = p->dicPos;

+    if (outSize > p->dicBufSize - dicPos)

+    {

+      outSizeCur = p->dicBufSize;

+      curFinishMode = LZMA_FINISH_ANY;

+    }

+    else

+    {

+      outSizeCur = dicPos + outSize;

+      curFinishMode = finishMode;

+    }

+

+    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);

+    src += inSizeCur;

+    inSize -= inSizeCur;

+    *srcLen += inSizeCur;

+    outSizeCur = p->dicPos - dicPos;

+    memcpy(dest, p->dic + dicPos, outSizeCur);

+    dest += outSizeCur;

+    outSize -= outSizeCur;

+    *destLen += outSizeCur;

+    if (res != 0)

+      return res;

+    if (outSizeCur == 0 || outSize == 0)

+      return SZ_OK;

+  }

+}

+

+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, p->probs);

+  p->probs = 0;

+}

+

+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, p->dic);

+  p->dic = 0;

+}

+

+void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)

+{

+  LzmaDec_FreeProbs(p, alloc);

+  LzmaDec_FreeDict(p, alloc);

+}

+

+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)

+{

+  UInt32 dicSize;

+  Byte d;

+  

+  if (size < LZMA_PROPS_SIZE)

+    return SZ_ERROR_UNSUPPORTED;

+  else

+    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);

+ 

+  if (dicSize < LZMA_DIC_MIN)

+    dicSize = LZMA_DIC_MIN;

+  p->dicSize = dicSize;

+

+  d = data[0];

+  if (d >= (9 * 5 * 5))

+    return SZ_ERROR_UNSUPPORTED;

+

+  p->lc = d % 9;

+  d /= 9;

+  p->pb = d / 5;

+  p->lp = d % 5;

+

+  return SZ_OK;

+}

+

+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)

+{

+  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);

+  if (p->probs == 0 || numProbs != p->numProbs)

+  {

+    LzmaDec_FreeProbs(p, alloc);

+    p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));

+    p->numProbs = numProbs;

+    if (p->probs == 0)

+      return SZ_ERROR_MEM;

+  }

+  return SZ_OK;

+}

+

+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)

+{

+  CLzmaProps propNew;

+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));

+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));

+  p->prop = propNew;

+  return SZ_OK;

+}

+

+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)

+{

+  CLzmaProps propNew;

+  SizeT dicBufSize;

+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));

+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));

+  dicBufSize = propNew.dicSize;

+  if (p->dic == 0 || dicBufSize != p->dicBufSize)

+  {

+    LzmaDec_FreeDict(p, alloc);

+    p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);

+    if (p->dic == 0)

+    {

+      LzmaDec_FreeProbs(p, alloc);

+      return SZ_ERROR_MEM;

+    }

+  }

+  p->dicBufSize = dicBufSize;

+  p->prop = propNew;

+  return SZ_OK;

+}

+

+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,

+    ELzmaStatus *status, ISzAlloc *alloc)

+{

+  CLzmaDec p;

+  SRes res;

+  SizeT inSize = *srcLen;

+  SizeT outSize = *destLen;

+  *srcLen = *destLen = 0;

+  if (inSize < RC_INIT_SIZE)

+    return SZ_ERROR_INPUT_EOF;

+

+  LzmaDec_Construct(&p);

+  res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);

+  if (res != 0)

+    return res;

+  p.dic = dest;

+  p.dicBufSize = outSize;

+

+  LzmaDec_Init(&p);

+  

+  *srcLen = inSize;

+  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);

+

+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)

+    res = SZ_ERROR_INPUT_EOF;

+

+  (*destLen) = p.dicPos;

+  LzmaDec_FreeProbs(&p, alloc);

+  return res;

+}

diff --git a/C/LzmaDec.h b/C/LzmaDec.h
new file mode 100755
index 0000000..6741a64
--- /dev/null
+++ b/C/LzmaDec.h
@@ -0,0 +1,231 @@
+/* LzmaDec.h -- LZMA Decoder

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA_DEC_H

+#define __LZMA_DEC_H

+

+#include "Types.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+/* #define _LZMA_PROB32 */

+/* _LZMA_PROB32 can increase the speed on some CPUs,

+   but memory usage for CLzmaDec::probs will be doubled in that case */

+

+#ifdef _LZMA_PROB32

+#define CLzmaProb UInt32

+#else

+#define CLzmaProb UInt16

+#endif

+

+

+/* ---------- LZMA Properties ---------- */

+

+#define LZMA_PROPS_SIZE 5

+

+typedef struct _CLzmaProps

+{

+  unsigned lc, lp, pb;

+  UInt32 dicSize;

+} CLzmaProps;

+

+/* LzmaProps_Decode - decodes properties

+Returns:

+  SZ_OK

+  SZ_ERROR_UNSUPPORTED - Unsupported properties

+*/

+

+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);

+

+

+/* ---------- LZMA Decoder state ---------- */

+

+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.

+   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */

+

+#define LZMA_REQUIRED_INPUT_MAX 20

+

+typedef struct

+{

+  CLzmaProps prop;

+  CLzmaProb *probs;

+  Byte *dic;

+  const Byte *buf;

+  UInt32 range, code;

+  SizeT dicPos;

+  SizeT dicBufSize;

+  UInt32 processedPos;

+  UInt32 checkDicSize;

+  unsigned state;

+  UInt32 reps[4];

+  unsigned remainLen;

+  int needFlush;

+  int needInitState;

+  UInt32 numProbs;

+  unsigned tempBufSize;

+  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];

+} CLzmaDec;

+

+#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }

+

+void LzmaDec_Init(CLzmaDec *p);

+

+/* There are two types of LZMA streams:

+     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.

+     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */

+

+typedef enum

+{

+  LZMA_FINISH_ANY,   /* finish at any point */

+  LZMA_FINISH_END    /* block must be finished at the end */

+} ELzmaFinishMode;

+

+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!

+

+   You must use LZMA_FINISH_END, when you know that current output buffer

+   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.

+

+   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,

+   and output value of destLen will be less than output buffer size limit.

+   You can check status result also.

+

+   You can use multiple checks to test data integrity after full decompression:

+     1) Check Result and "status" variable.

+     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.

+     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.

+        You must use correct finish mode in that case. */

+

+typedef enum

+{

+  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */

+  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */

+  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */

+  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */

+  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */

+} ELzmaStatus;

+

+/* ELzmaStatus is used only as output value for function call */

+

+

+/* ---------- Interfaces ---------- */

+

+/* There are 3 levels of interfaces:

+     1) Dictionary Interface

+     2) Buffer Interface

+     3) One Call Interface

+   You can select any of these interfaces, but don't mix functions from different

+   groups for same object. */

+

+

+/* There are two variants to allocate state for Dictionary Interface:

+     1) LzmaDec_Allocate / LzmaDec_Free

+     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs

+   You can use variant 2, if you set dictionary buffer manually.

+   For Buffer Interface you must always use variant 1.

+

+LzmaDec_Allocate* can return:

+  SZ_OK

+  SZ_ERROR_MEM         - Memory allocation error

+  SZ_ERROR_UNSUPPORTED - Unsupported properties

+*/

+   

+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);

+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);

+

+SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);

+void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);

+

+/* ---------- Dictionary Interface ---------- */

+

+/* You can use it, if you want to eliminate the overhead for data copying from

+   dictionary to some other external buffer.

+   You must work with CLzmaDec variables directly in this interface.

+

+   STEPS:

+     LzmaDec_Constr()

+     LzmaDec_Allocate()

+     for (each new stream)

+     {

+       LzmaDec_Init()

+       while (it needs more decompression)

+       {

+         LzmaDec_DecodeToDic()

+         use data from CLzmaDec::dic and update CLzmaDec::dicPos

+       }

+     }

+     LzmaDec_Free()

+*/

+

+/* LzmaDec_DecodeToDic

+   

+   The decoding to internal dictionary buffer (CLzmaDec::dic).

+   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!

+

+finishMode:

+  It has meaning only if the decoding reaches output limit (dicLimit).

+  LZMA_FINISH_ANY - Decode just dicLimit bytes.

+  LZMA_FINISH_END - Stream must be finished after dicLimit.

+

+Returns:

+  SZ_OK

+    status:

+      LZMA_STATUS_FINISHED_WITH_MARK

+      LZMA_STATUS_NOT_FINISHED

+      LZMA_STATUS_NEEDS_MORE_INPUT

+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK

+  SZ_ERROR_DATA - Data error

+*/

+

+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,

+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);

+

+

+/* ---------- Buffer Interface ---------- */

+

+/* It's zlib-like interface.

+   See LzmaDec_DecodeToDic description for information about STEPS and return results,

+   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need

+   to work with CLzmaDec variables manually.

+

+finishMode:

+  It has meaning only if the decoding reaches output limit (*destLen).

+  LZMA_FINISH_ANY - Decode just destLen bytes.

+  LZMA_FINISH_END - Stream must be finished after (*destLen).

+*/

+

+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,

+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);

+

+

+/* ---------- One Call Interface ---------- */

+

+/* LzmaDecode

+

+finishMode:

+  It has meaning only if the decoding reaches output limit (*destLen).

+  LZMA_FINISH_ANY - Decode just destLen bytes.

+  LZMA_FINISH_END - Stream must be finished after (*destLen).

+

+Returns:

+  SZ_OK

+    status:

+      LZMA_STATUS_FINISHED_WITH_MARK

+      LZMA_STATUS_NOT_FINISHED

+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK

+  SZ_ERROR_DATA - Data error

+  SZ_ERROR_MEM  - Memory allocation error

+  SZ_ERROR_UNSUPPORTED - Unsupported properties

+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).

+*/

+

+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,

+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,

+    ELzmaStatus *status, ISzAlloc *alloc);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c
new file mode 100755
index 0000000..9e6dbdb
--- /dev/null
+++ b/C/LzmaEnc.c
@@ -0,0 +1,2268 @@
+/* LzmaEnc.c -- LZMA Encoder

+2010-04-16 : Igor Pavlov : Public domain */

+

+#include <string.h>

+

+/* #define SHOW_STAT */

+/* #define SHOW_STAT2 */

+

+#if defined(SHOW_STAT) || defined(SHOW_STAT2)

+#include <stdio.h>

+#endif

+

+#include "LzmaEnc.h"

+

+#include "LzFind.h"

+#ifndef _7ZIP_ST

+#include "LzFindMt.h"

+#endif

+

+#ifdef SHOW_STAT

+static int ttt = 0;

+#endif

+

+#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)

+

+#define kBlockSize (9 << 10)

+#define kUnpackBlockSize (1 << 18)

+#define kMatchArraySize (1 << 21)

+#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)

+

+#define kNumMaxDirectBits (31)

+

+#define kNumTopBits 24

+#define kTopValue ((UInt32)1 << kNumTopBits)

+

+#define kNumBitModelTotalBits 11

+#define kBitModelTotal (1 << kNumBitModelTotalBits)

+#define kNumMoveBits 5

+#define kProbInitValue (kBitModelTotal >> 1)

+

+#define kNumMoveReducingBits 4

+#define kNumBitPriceShiftBits 4

+#define kBitPrice (1 << kNumBitPriceShiftBits)

+

+void LzmaEncProps_Init(CLzmaEncProps *p)

+{

+  p->level = 5;

+  p->dictSize = p->mc = 0;

+  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;

+  p->writeEndMark = 0;

+}

+

+void LzmaEncProps_Normalize(CLzmaEncProps *p)

+{

+  int level = p->level;

+  if (level < 0) level = 5;

+  p->level = level;

+  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));

+  if (p->lc < 0) p->lc = 3;

+  if (p->lp < 0) p->lp = 0;

+  if (p->pb < 0) p->pb = 2;

+  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);

+  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);

+  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);

+  if (p->numHashBytes < 0) p->numHashBytes = 4;

+  if (p->mc == 0)  p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);

+  if (p->numThreads < 0)

+    p->numThreads =

+      #ifndef _7ZIP_ST

+      ((p->btMode && p->algo) ? 2 : 1);

+      #else

+      1;

+      #endif

+}

+

+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)

+{

+  CLzmaEncProps props = *props2;

+  LzmaEncProps_Normalize(&props);

+  return props.dictSize;

+}

+

+/* #define LZMA_LOG_BSR */

+/* Define it for Intel's CPU */

+

+

+#ifdef LZMA_LOG_BSR

+

+#define kDicLogSizeMaxCompress 30

+

+#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }

+

+UInt32 GetPosSlot1(UInt32 pos)

+{

+  UInt32 res;

+  BSR2_RET(pos, res);

+  return res;

+}

+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }

+#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }

+

+#else

+

+#define kNumLogBits (9 + (int)sizeof(size_t) / 2)

+#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)

+

+void LzmaEnc_FastPosInit(Byte *g_FastPos)

+{

+  int c = 2, slotFast;

+  g_FastPos[0] = 0;

+  g_FastPos[1] = 1;

+  

+  for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)

+  {

+    UInt32 k = (1 << ((slotFast >> 1) - 1));

+    UInt32 j;

+    for (j = 0; j < k; j++, c++)

+      g_FastPos[c] = (Byte)slotFast;

+  }

+}

+

+#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \

+  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \

+  res = p->g_FastPos[pos >> i] + (i * 2); }

+/*

+#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \

+  p->g_FastPos[pos >> 6] + 12 : \

+  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }

+*/

+

+#define GetPosSlot1(pos) p->g_FastPos[pos]

+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }

+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }

+

+#endif

+

+

+#define LZMA_NUM_REPS 4

+

+typedef unsigned CState;

+

+typedef struct

+{

+  UInt32 price;

+

+  CState state;

+  int prev1IsChar;

+  int prev2;

+

+  UInt32 posPrev2;

+  UInt32 backPrev2;

+

+  UInt32 posPrev;

+  UInt32 backPrev;

+  UInt32 backs[LZMA_NUM_REPS];

+} COptimal;

+

+#define kNumOpts (1 << 12)

+

+#define kNumLenToPosStates 4

+#define kNumPosSlotBits 6

+#define kDicLogSizeMin 0

+#define kDicLogSizeMax 32

+#define kDistTableSizeMax (kDicLogSizeMax * 2)

+

+

+#define kNumAlignBits 4

+#define kAlignTableSize (1 << kNumAlignBits)

+#define kAlignMask (kAlignTableSize - 1)

+

+#define kStartPosModelIndex 4

+#define kEndPosModelIndex 14

+#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)

+

+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))

+

+#ifdef _LZMA_PROB32

+#define CLzmaProb UInt32

+#else

+#define CLzmaProb UInt16

+#endif

+

+#define LZMA_PB_MAX 4

+#define LZMA_LC_MAX 8

+#define LZMA_LP_MAX 4

+

+#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)

+

+

+#define kLenNumLowBits 3

+#define kLenNumLowSymbols (1 << kLenNumLowBits)

+#define kLenNumMidBits 3

+#define kLenNumMidSymbols (1 << kLenNumMidBits)

+#define kLenNumHighBits 8

+#define kLenNumHighSymbols (1 << kLenNumHighBits)

+

+#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)

+

+#define LZMA_MATCH_LEN_MIN 2

+#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)

+

+#define kNumStates 12

+

+typedef struct

+{

+  CLzmaProb choice;

+  CLzmaProb choice2;

+  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];

+  CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];

+  CLzmaProb high[kLenNumHighSymbols];

+} CLenEnc;

+

+typedef struct

+{

+  CLenEnc p;

+  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];

+  UInt32 tableSize;

+  UInt32 counters[LZMA_NUM_PB_STATES_MAX];

+} CLenPriceEnc;

+

+typedef struct

+{

+  UInt32 range;

+  Byte cache;

+  UInt64 low;

+  UInt64 cacheSize;

+  Byte *buf;

+  Byte *bufLim;

+  Byte *bufBase;

+  ISeqOutStream *outStream;

+  UInt64 processed;

+  SRes res;

+} CRangeEnc;

+

+typedef struct

+{

+  CLzmaProb *litProbs;

+

+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];

+  CLzmaProb isRep[kNumStates];

+  CLzmaProb isRepG0[kNumStates];

+  CLzmaProb isRepG1[kNumStates];

+  CLzmaProb isRepG2[kNumStates];

+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];

+

+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];

+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];

+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];

+  

+  CLenPriceEnc lenEnc;

+  CLenPriceEnc repLenEnc;

+

+  UInt32 reps[LZMA_NUM_REPS];

+  UInt32 state;

+} CSaveState;

+

+typedef struct

+{

+  IMatchFinder matchFinder;

+  void *matchFinderObj;

+

+  #ifndef _7ZIP_ST

+  Bool mtMode;

+  CMatchFinderMt matchFinderMt;

+  #endif

+

+  CMatchFinder matchFinderBase;

+

+  #ifndef _7ZIP_ST

+  Byte pad[128];

+  #endif

+  

+  UInt32 optimumEndIndex;

+  UInt32 optimumCurrentIndex;

+

+  UInt32 longestMatchLength;

+  UInt32 numPairs;

+  UInt32 numAvail;

+  COptimal opt[kNumOpts];

+  

+  #ifndef LZMA_LOG_BSR

+  Byte g_FastPos[1 << kNumLogBits];

+  #endif

+

+  UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];

+  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];

+  UInt32 numFastBytes;

+  UInt32 additionalOffset;

+  UInt32 reps[LZMA_NUM_REPS];

+  UInt32 state;

+

+  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];

+  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];

+  UInt32 alignPrices[kAlignTableSize];

+  UInt32 alignPriceCount;

+

+  UInt32 distTableSize;

+

+  unsigned lc, lp, pb;

+  unsigned lpMask, pbMask;

+

+  CLzmaProb *litProbs;

+

+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];

+  CLzmaProb isRep[kNumStates];

+  CLzmaProb isRepG0[kNumStates];

+  CLzmaProb isRepG1[kNumStates];

+  CLzmaProb isRepG2[kNumStates];

+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];

+

+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];

+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];

+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];

+  

+  CLenPriceEnc lenEnc;

+  CLenPriceEnc repLenEnc;

+

+  unsigned lclp;

+

+  Bool fastMode;

+  

+  CRangeEnc rc;

+

+  Bool writeEndMark;

+  UInt64 nowPos64;

+  UInt32 matchPriceCount;

+  Bool finished;

+  Bool multiThread;

+

+  SRes result;

+  UInt32 dictSize;

+  UInt32 matchFinderCycles;

+

+  int needInit;

+

+  CSaveState saveState;

+} CLzmaEnc;

+

+void LzmaEnc_SaveState(CLzmaEncHandle pp)

+{

+  CLzmaEnc *p = (CLzmaEnc *)pp;

+  CSaveState *dest = &p->saveState;

+  int i;

+  dest->lenEnc = p->lenEnc;

+  dest->repLenEnc = p->repLenEnc;

+  dest->state = p->state;

+

+  for (i = 0; i < kNumStates; i++)

+  {

+    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));

+    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));

+  }

+  for (i = 0; i < kNumLenToPosStates; i++)

+    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));

+  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));

+  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));

+  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));

+  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));

+  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));

+  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));

+  memcpy(dest->reps, p->reps, sizeof(p->reps));

+  memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));

+}

+

+void LzmaEnc_RestoreState(CLzmaEncHandle pp)

+{

+  CLzmaEnc *dest = (CLzmaEnc *)pp;

+  const CSaveState *p = &dest->saveState;

+  int i;

+  dest->lenEnc = p->lenEnc;

+  dest->repLenEnc = p->repLenEnc;

+  dest->state = p->state;

+

+  for (i = 0; i < kNumStates; i++)

+  {

+    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));

+    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));

+  }

+  for (i = 0; i < kNumLenToPosStates; i++)

+    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));

+  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));

+  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));

+  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));

+  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));

+  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));

+  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));

+  memcpy(dest->reps, p->reps, sizeof(p->reps));

+  memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));

+}

+

+SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)

+{

+  CLzmaEnc *p = (CLzmaEnc *)pp;

+  CLzmaEncProps props = *props2;

+  LzmaEncProps_Normalize(&props);

+

+  if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||

+      props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30))

+    return SZ_ERROR_PARAM;

+  p->dictSize = props.dictSize;

+  p->matchFinderCycles = props.mc;

+  {

+    unsigned fb = props.fb;

+    if (fb < 5)

+      fb = 5;

+    if (fb > LZMA_MATCH_LEN_MAX)

+      fb = LZMA_MATCH_LEN_MAX;

+    p->numFastBytes = fb;

+  }

+  p->lc = props.lc;

+  p->lp = props.lp;

+  p->pb = props.pb;

+  p->fastMode = (props.algo == 0);

+  p->matchFinderBase.btMode = props.btMode;

+  {

+    UInt32 numHashBytes = 4;

+    if (props.btMode)

+    {

+      if (props.numHashBytes < 2)

+        numHashBytes = 2;

+      else if (props.numHashBytes < 4)

+        numHashBytes = props.numHashBytes;

+    }

+    p->matchFinderBase.numHashBytes = numHashBytes;

+  }

+

+  p->matchFinderBase.cutValue = props.mc;

+

+  p->writeEndMark = props.writeEndMark;

+

+  #ifndef _7ZIP_ST

+  /*

+  if (newMultiThread != _multiThread)

+  {

+    ReleaseMatchFinder();

+    _multiThread = newMultiThread;

+  }

+  */

+  p->multiThread = (props.numThreads > 1);

+  #endif

+

+  return SZ_OK;

+}

+

+static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};

+static const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};

+static const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};

+static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};

+

+#define IsCharState(s) ((s) < 7)

+

+#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)

+

+#define kInfinityPrice (1 << 30)

+

+static void RangeEnc_Construct(CRangeEnc *p)

+{

+  p->outStream = 0;

+  p->bufBase = 0;

+}

+

+#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)

+

+#define RC_BUF_SIZE (1 << 16)

+static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)

+{

+  if (p->bufBase == 0)

+  {

+    p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);

+    if (p->bufBase == 0)

+      return 0;

+    p->bufLim = p->bufBase + RC_BUF_SIZE;

+  }

+  return 1;

+}

+

+static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, p->bufBase);

+  p->bufBase = 0;

+}

+

+static void RangeEnc_Init(CRangeEnc *p)

+{

+  /* Stream.Init(); */

+  p->low = 0;

+  p->range = 0xFFFFFFFF;

+  p->cacheSize = 1;

+  p->cache = 0;

+

+  p->buf = p->bufBase;

+

+  p->processed = 0;

+  p->res = SZ_OK;

+}

+

+static void RangeEnc_FlushStream(CRangeEnc *p)

+{

+  size_t num;

+  if (p->res != SZ_OK)

+    return;

+  num = p->buf - p->bufBase;

+  if (num != p->outStream->Write(p->outStream, p->bufBase, num))

+    p->res = SZ_ERROR_WRITE;

+  p->processed += num;

+  p->buf = p->bufBase;

+}

+

+static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)

+{

+  if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)

+  {

+    Byte temp = p->cache;

+    do

+    {

+      Byte *buf = p->buf;

+      *buf++ = (Byte)(temp + (Byte)(p->low >> 32));

+      p->buf = buf;

+      if (buf == p->bufLim)

+        RangeEnc_FlushStream(p);

+      temp = 0xFF;

+    }

+    while (--p->cacheSize != 0);

+    p->cache = (Byte)((UInt32)p->low >> 24);

+  }

+  p->cacheSize++;

+  p->low = (UInt32)p->low << 8;

+}

+

+static void RangeEnc_FlushData(CRangeEnc *p)

+{

+  int i;

+  for (i = 0; i < 5; i++)

+    RangeEnc_ShiftLow(p);

+}

+

+static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)

+{

+  do

+  {

+    p->range >>= 1;

+    p->low += p->range & (0 - ((value >> --numBits) & 1));

+    if (p->range < kTopValue)

+    {

+      p->range <<= 8;

+      RangeEnc_ShiftLow(p);

+    }

+  }

+  while (numBits != 0);

+}

+

+static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)

+{

+  UInt32 ttt = *prob;

+  UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;

+  if (symbol == 0)

+  {

+    p->range = newBound;

+    ttt += (kBitModelTotal - ttt) >> kNumMoveBits;

+  }

+  else

+  {

+    p->low += newBound;

+    p->range -= newBound;

+    ttt -= ttt >> kNumMoveBits;

+  }

+  *prob = (CLzmaProb)ttt;

+  if (p->range < kTopValue)

+  {

+    p->range <<= 8;

+    RangeEnc_ShiftLow(p);

+  }

+}

+

+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)

+{

+  symbol |= 0x100;

+  do

+  {

+    RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);

+    symbol <<= 1;

+  }

+  while (symbol < 0x10000);

+}

+

+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)

+{

+  UInt32 offs = 0x100;

+  symbol |= 0x100;

+  do

+  {

+    matchByte <<= 1;

+    RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);

+    symbol <<= 1;

+    offs &= ~(matchByte ^ symbol);

+  }

+  while (symbol < 0x10000);

+}

+

+void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)

+{

+  UInt32 i;

+  for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))

+  {

+    const int kCyclesBits = kNumBitPriceShiftBits;

+    UInt32 w = i;

+    UInt32 bitCount = 0;

+    int j;

+    for (j = 0; j < kCyclesBits; j++)

+    {

+      w = w * w;

+      bitCount <<= 1;

+      while (w >= ((UInt32)1 << 16))

+      {

+        w >>= 1;

+        bitCount++;

+      }

+    }

+    ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);

+  }

+}

+

+

+#define GET_PRICE(prob, symbol) \

+  p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];

+

+#define GET_PRICEa(prob, symbol) \

+  ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];

+

+#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]

+#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]

+

+#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]

+#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]

+

+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)

+{

+  UInt32 price = 0;

+  symbol |= 0x100;

+  do

+  {

+    price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);

+    symbol <<= 1;

+  }

+  while (symbol < 0x10000);

+  return price;

+}

+

+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)

+{

+  UInt32 price = 0;

+  UInt32 offs = 0x100;

+  symbol |= 0x100;

+  do

+  {

+    matchByte <<= 1;

+    price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);

+    symbol <<= 1;

+    offs &= ~(matchByte ^ symbol);

+  }

+  while (symbol < 0x10000);

+  return price;

+}

+

+

+static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)

+{

+  UInt32 m = 1;

+  int i;

+  for (i = numBitLevels; i != 0;)

+  {

+    UInt32 bit;

+    i--;

+    bit = (symbol >> i) & 1;

+    RangeEnc_EncodeBit(rc, probs + m, bit);

+    m = (m << 1) | bit;

+  }

+}

+

+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)

+{

+  UInt32 m = 1;

+  int i;

+  for (i = 0; i < numBitLevels; i++)

+  {

+    UInt32 bit = symbol & 1;

+    RangeEnc_EncodeBit(rc, probs + m, bit);

+    m = (m << 1) | bit;

+    symbol >>= 1;

+  }

+}

+

+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)

+{

+  UInt32 price = 0;

+  symbol |= (1 << numBitLevels);

+  while (symbol != 1)

+  {

+    price += GET_PRICEa(probs[symbol >> 1], symbol & 1);

+    symbol >>= 1;

+  }

+  return price;

+}

+

+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)

+{

+  UInt32 price = 0;

+  UInt32 m = 1;

+  int i;

+  for (i = numBitLevels; i != 0; i--)

+  {

+    UInt32 bit = symbol & 1;

+    symbol >>= 1;

+    price += GET_PRICEa(probs[m], bit);

+    m = (m << 1) | bit;

+  }

+  return price;

+}

+

+

+static void LenEnc_Init(CLenEnc *p)

+{

+  unsigned i;

+  p->choice = p->choice2 = kProbInitValue;

+  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)

+    p->low[i] = kProbInitValue;

+  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)

+    p->mid[i] = kProbInitValue;

+  for (i = 0; i < kLenNumHighSymbols; i++)

+    p->high[i] = kProbInitValue;

+}

+

+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)

+{

+  if (symbol < kLenNumLowSymbols)

+  {

+    RangeEnc_EncodeBit(rc, &p->choice, 0);

+    RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);

+  }

+  else

+  {

+    RangeEnc_EncodeBit(rc, &p->choice, 1);

+    if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)

+    {

+      RangeEnc_EncodeBit(rc, &p->choice2, 0);

+      RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);

+    }

+    else

+    {

+      RangeEnc_EncodeBit(rc, &p->choice2, 1);

+      RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);

+    }

+  }

+}

+

+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)

+{

+  UInt32 a0 = GET_PRICE_0a(p->choice);

+  UInt32 a1 = GET_PRICE_1a(p->choice);

+  UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);

+  UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);

+  UInt32 i = 0;

+  for (i = 0; i < kLenNumLowSymbols; i++)

+  {

+    if (i >= numSymbols)

+      return;

+    prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);

+  }

+  for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)

+  {

+    if (i >= numSymbols)

+      return;

+    prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);

+  }

+  for (; i < numSymbols; i++)

+    prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);

+}

+

+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)

+{

+  LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);

+  p->counters[posState] = p->tableSize;

+}

+

+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)

+{

+  UInt32 posState;

+  for (posState = 0; posState < numPosStates; posState++)

+    LenPriceEnc_UpdateTable(p, posState, ProbPrices);

+}

+

+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)

+{

+  LenEnc_Encode(&p->p, rc, symbol, posState);

+  if (updatePrice)

+    if (--p->counters[posState] == 0)

+      LenPriceEnc_UpdateTable(p, posState, ProbPrices);

+}

+

+

+

+

+static void MovePos(CLzmaEnc *p, UInt32 num)

+{

+  #ifdef SHOW_STAT

+  ttt += num;

+  printf("\n MovePos %d", num);

+  #endif

+  if (num != 0)

+  {

+    p->additionalOffset += num;

+    p->matchFinder.Skip(p->matchFinderObj, num);

+  }

+}

+

+static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)

+{

+  UInt32 lenRes = 0, numPairs;

+  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);

+  numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);

+  #ifdef SHOW_STAT

+  printf("\n i = %d numPairs = %d    ", ttt, numPairs / 2);

+  ttt++;

+  {

+    UInt32 i;

+    for (i = 0; i < numPairs; i += 2)

+      printf("%2d %6d   | ", p->matches[i], p->matches[i + 1]);

+  }

+  #endif

+  if (numPairs > 0)

+  {

+    lenRes = p->matches[numPairs - 2];

+    if (lenRes == p->numFastBytes)

+    {

+      const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;

+      UInt32 distance = p->matches[numPairs - 1] + 1;

+      UInt32 numAvail = p->numAvail;

+      if (numAvail > LZMA_MATCH_LEN_MAX)

+        numAvail = LZMA_MATCH_LEN_MAX;

+      {

+        const Byte *pby2 = pby - distance;

+        for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);

+      }

+    }

+  }

+  p->additionalOffset++;

+  *numDistancePairsRes = numPairs;

+  return lenRes;

+}

+

+

+#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;

+#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;

+#define IsShortRep(p) ((p)->backPrev == 0)

+

+static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)

+{

+  return

+    GET_PRICE_0(p->isRepG0[state]) +

+    GET_PRICE_0(p->isRep0Long[state][posState]);

+}

+

+static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)

+{

+  UInt32 price;

+  if (repIndex == 0)

+  {

+    price = GET_PRICE_0(p->isRepG0[state]);

+    price += GET_PRICE_1(p->isRep0Long[state][posState]);

+  }

+  else

+  {

+    price = GET_PRICE_1(p->isRepG0[state]);

+    if (repIndex == 1)

+      price += GET_PRICE_0(p->isRepG1[state]);

+    else

+    {

+      price += GET_PRICE_1(p->isRepG1[state]);

+      price += GET_PRICE(p->isRepG2[state], repIndex - 2);

+    }

+  }

+  return price;

+}

+

+static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)

+{

+  return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +

+    GetPureRepPrice(p, repIndex, state, posState);

+}

+

+static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)

+{

+  UInt32 posMem = p->opt[cur].posPrev;

+  UInt32 backMem = p->opt[cur].backPrev;

+  p->optimumEndIndex = cur;

+  do

+  {

+    if (p->opt[cur].prev1IsChar)

+    {

+      MakeAsChar(&p->opt[posMem])

+      p->opt[posMem].posPrev = posMem - 1;

+      if (p->opt[cur].prev2)

+      {

+        p->opt[posMem - 1].prev1IsChar = False;

+        p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;

+        p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;

+      }

+    }

+    {

+      UInt32 posPrev = posMem;

+      UInt32 backCur = backMem;

+      

+      backMem = p->opt[posPrev].backPrev;

+      posMem = p->opt[posPrev].posPrev;

+      

+      p->opt[posPrev].backPrev = backCur;

+      p->opt[posPrev].posPrev = cur;

+      cur = posPrev;

+    }

+  }

+  while (cur != 0);

+  *backRes = p->opt[0].backPrev;

+  p->optimumCurrentIndex  = p->opt[0].posPrev;

+  return p->optimumCurrentIndex;

+}

+

+#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)

+

+static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)

+{

+  UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;

+  UInt32 matchPrice, repMatchPrice, normalMatchPrice;

+  UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];

+  UInt32 *matches;

+  const Byte *data;

+  Byte curByte, matchByte;

+  if (p->optimumEndIndex != p->optimumCurrentIndex)

+  {

+    const COptimal *opt = &p->opt[p->optimumCurrentIndex];

+    UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;

+    *backRes = opt->backPrev;

+    p->optimumCurrentIndex = opt->posPrev;

+    return lenRes;

+  }

+  p->optimumCurrentIndex = p->optimumEndIndex = 0;

+  

+  if (p->additionalOffset == 0)

+    mainLen = ReadMatchDistances(p, &numPairs);

+  else

+  {

+    mainLen = p->longestMatchLength;

+    numPairs = p->numPairs;

+  }

+

+  numAvail = p->numAvail;

+  if (numAvail < 2)

+  {

+    *backRes = (UInt32)(-1);

+    return 1;

+  }

+  if (numAvail > LZMA_MATCH_LEN_MAX)

+    numAvail = LZMA_MATCH_LEN_MAX;

+

+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;

+  repMaxIndex = 0;

+  for (i = 0; i < LZMA_NUM_REPS; i++)

+  {

+    UInt32 lenTest;

+    const Byte *data2;

+    reps[i] = p->reps[i];

+    data2 = data - (reps[i] + 1);

+    if (data[0] != data2[0] || data[1] != data2[1])

+    {

+      repLens[i] = 0;

+      continue;

+    }

+    for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);

+    repLens[i] = lenTest;

+    if (lenTest > repLens[repMaxIndex])

+      repMaxIndex = i;

+  }

+  if (repLens[repMaxIndex] >= p->numFastBytes)

+  {

+    UInt32 lenRes;

+    *backRes = repMaxIndex;

+    lenRes = repLens[repMaxIndex];

+    MovePos(p, lenRes - 1);

+    return lenRes;

+  }

+

+  matches = p->matches;

+  if (mainLen >= p->numFastBytes)

+  {

+    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;

+    MovePos(p, mainLen - 1);

+    return mainLen;

+  }

+  curByte = *data;

+  matchByte = *(data - (reps[0] + 1));

+

+  if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)

+  {

+    *backRes = (UInt32)-1;

+    return 1;

+  }

+

+  p->opt[0].state = (CState)p->state;

+

+  posState = (position & p->pbMask);

+

+  {

+    const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));

+    p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +

+        (!IsCharState(p->state) ?

+          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :

+          LitEnc_GetPrice(probs, curByte, p->ProbPrices));

+  }

+

+  MakeAsChar(&p->opt[1]);

+

+  matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);

+  repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);

+

+  if (matchByte == curByte)

+  {

+    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);

+    if (shortRepPrice < p->opt[1].price)

+    {

+      p->opt[1].price = shortRepPrice;

+      MakeAsShortRep(&p->opt[1]);

+    }

+  }

+  lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);

+

+  if (lenEnd < 2)

+  {

+    *backRes = p->opt[1].backPrev;

+    return 1;

+  }

+

+  p->opt[1].posPrev = 0;

+  for (i = 0; i < LZMA_NUM_REPS; i++)

+    p->opt[0].backs[i] = reps[i];

+

+  len = lenEnd;

+  do

+    p->opt[len--].price = kInfinityPrice;

+  while (len >= 2);

+

+  for (i = 0; i < LZMA_NUM_REPS; i++)

+  {

+    UInt32 repLen = repLens[i];

+    UInt32 price;

+    if (repLen < 2)

+      continue;

+    price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);

+    do

+    {

+      UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];

+      COptimal *opt = &p->opt[repLen];

+      if (curAndLenPrice < opt->price)

+      {

+        opt->price = curAndLenPrice;

+        opt->posPrev = 0;

+        opt->backPrev = i;

+        opt->prev1IsChar = False;

+      }

+    }

+    while (--repLen >= 2);

+  }

+

+  normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);

+

+  len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);

+  if (len <= mainLen)

+  {

+    UInt32 offs = 0;

+    while (len > matches[offs])

+      offs += 2;

+    for (; ; len++)

+    {

+      COptimal *opt;

+      UInt32 distance = matches[offs + 1];

+

+      UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];

+      UInt32 lenToPosState = GetLenToPosState(len);

+      if (distance < kNumFullDistances)

+        curAndLenPrice += p->distancesPrices[lenToPosState][distance];

+      else

+      {

+        UInt32 slot;

+        GetPosSlot2(distance, slot);

+        curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];

+      }

+      opt = &p->opt[len];

+      if (curAndLenPrice < opt->price)

+      {

+        opt->price = curAndLenPrice;

+        opt->posPrev = 0;

+        opt->backPrev = distance + LZMA_NUM_REPS;

+        opt->prev1IsChar = False;

+      }

+      if (len == matches[offs])

+      {

+        offs += 2;

+        if (offs == numPairs)

+          break;

+      }

+    }

+  }

+

+  cur = 0;

+

+    #ifdef SHOW_STAT2

+    if (position >= 0)

+    {

+      unsigned i;

+      printf("\n pos = %4X", position);

+      for (i = cur; i <= lenEnd; i++)

+      printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);

+    }

+    #endif

+

+  for (;;)

+  {

+    UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;

+    UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;

+    Bool nextIsChar;

+    Byte curByte, matchByte;

+    const Byte *data;

+    COptimal *curOpt;

+    COptimal *nextOpt;

+

+    cur++;

+    if (cur == lenEnd)

+      return Backward(p, backRes, cur);

+

+    newLen = ReadMatchDistances(p, &numPairs);

+    if (newLen >= p->numFastBytes)

+    {

+      p->numPairs = numPairs;

+      p->longestMatchLength = newLen;

+      return Backward(p, backRes, cur);

+    }

+    position++;

+    curOpt = &p->opt[cur];

+    posPrev = curOpt->posPrev;

+    if (curOpt->prev1IsChar)

+    {

+      posPrev--;

+      if (curOpt->prev2)

+      {

+        state = p->opt[curOpt->posPrev2].state;

+        if (curOpt->backPrev2 < LZMA_NUM_REPS)

+          state = kRepNextStates[state];

+        else

+          state = kMatchNextStates[state];

+      }

+      else

+        state = p->opt[posPrev].state;

+      state = kLiteralNextStates[state];

+    }

+    else

+      state = p->opt[posPrev].state;

+    if (posPrev == cur - 1)

+    {

+      if (IsShortRep(curOpt))

+        state = kShortRepNextStates[state];

+      else

+        state = kLiteralNextStates[state];

+    }

+    else

+    {

+      UInt32 pos;

+      const COptimal *prevOpt;

+      if (curOpt->prev1IsChar && curOpt->prev2)

+      {

+        posPrev = curOpt->posPrev2;

+        pos = curOpt->backPrev2;

+        state = kRepNextStates[state];

+      }

+      else

+      {

+        pos = curOpt->backPrev;

+        if (pos < LZMA_NUM_REPS)

+          state = kRepNextStates[state];

+        else

+          state = kMatchNextStates[state];

+      }

+      prevOpt = &p->opt[posPrev];

+      if (pos < LZMA_NUM_REPS)

+      {

+        UInt32 i;

+        reps[0] = prevOpt->backs[pos];

+        for (i = 1; i <= pos; i++)

+          reps[i] = prevOpt->backs[i - 1];

+        for (; i < LZMA_NUM_REPS; i++)

+          reps[i] = prevOpt->backs[i];

+      }

+      else

+      {

+        UInt32 i;

+        reps[0] = (pos - LZMA_NUM_REPS);

+        for (i = 1; i < LZMA_NUM_REPS; i++)

+          reps[i] = prevOpt->backs[i - 1];

+      }

+    }

+    curOpt->state = (CState)state;

+

+    curOpt->backs[0] = reps[0];

+    curOpt->backs[1] = reps[1];

+    curOpt->backs[2] = reps[2];

+    curOpt->backs[3] = reps[3];

+

+    curPrice = curOpt->price;

+    nextIsChar = False;

+    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;

+    curByte = *data;

+    matchByte = *(data - (reps[0] + 1));

+

+    posState = (position & p->pbMask);

+

+    curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);

+    {

+      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));

+      curAnd1Price +=

+        (!IsCharState(state) ?

+          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :

+          LitEnc_GetPrice(probs, curByte, p->ProbPrices));

+    }

+

+    nextOpt = &p->opt[cur + 1];

+

+    if (curAnd1Price < nextOpt->price)

+    {

+      nextOpt->price = curAnd1Price;

+      nextOpt->posPrev = cur;

+      MakeAsChar(nextOpt);

+      nextIsChar = True;

+    }

+

+    matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);

+    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);

+    

+    if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))

+    {

+      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);

+      if (shortRepPrice <= nextOpt->price)

+      {

+        nextOpt->price = shortRepPrice;

+        nextOpt->posPrev = cur;

+        MakeAsShortRep(nextOpt);

+        nextIsChar = True;

+      }

+    }

+    numAvailFull = p->numAvail;

+    {

+      UInt32 temp = kNumOpts - 1 - cur;

+      if (temp < numAvailFull)

+        numAvailFull = temp;

+    }

+

+    if (numAvailFull < 2)

+      continue;

+    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);

+

+    if (!nextIsChar && matchByte != curByte) /* speed optimization */

+    {

+      /* try Literal + rep0 */

+      UInt32 temp;

+      UInt32 lenTest2;

+      const Byte *data2 = data - (reps[0] + 1);

+      UInt32 limit = p->numFastBytes + 1;

+      if (limit > numAvailFull)

+        limit = numAvailFull;

+

+      for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);

+      lenTest2 = temp - 1;

+      if (lenTest2 >= 2)

+      {

+        UInt32 state2 = kLiteralNextStates[state];

+        UInt32 posStateNext = (position + 1) & p->pbMask;

+        UInt32 nextRepMatchPrice = curAnd1Price +

+            GET_PRICE_1(p->isMatch[state2][posStateNext]) +

+            GET_PRICE_1(p->isRep[state2]);

+        /* for (; lenTest2 >= 2; lenTest2--) */

+        {

+          UInt32 curAndLenPrice;

+          COptimal *opt;

+          UInt32 offset = cur + 1 + lenTest2;

+          while (lenEnd < offset)

+            p->opt[++lenEnd].price = kInfinityPrice;

+          curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);

+          opt = &p->opt[offset];

+          if (curAndLenPrice < opt->price)

+          {

+            opt->price = curAndLenPrice;

+            opt->posPrev = cur + 1;

+            opt->backPrev = 0;

+            opt->prev1IsChar = True;

+            opt->prev2 = False;

+          }

+        }

+      }

+    }

+    

+    startLen = 2; /* speed optimization */

+    {

+    UInt32 repIndex;

+    for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)

+    {

+      UInt32 lenTest;

+      UInt32 lenTestTemp;

+      UInt32 price;

+      const Byte *data2 = data - (reps[repIndex] + 1);

+      if (data[0] != data2[0] || data[1] != data2[1])

+        continue;

+      for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);

+      while (lenEnd < cur + lenTest)

+        p->opt[++lenEnd].price = kInfinityPrice;

+      lenTestTemp = lenTest;

+      price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);

+      do

+      {

+        UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];

+        COptimal *opt = &p->opt[cur + lenTest];

+        if (curAndLenPrice < opt->price)

+        {

+          opt->price = curAndLenPrice;

+          opt->posPrev = cur;

+          opt->backPrev = repIndex;

+          opt->prev1IsChar = False;

+        }

+      }

+      while (--lenTest >= 2);

+      lenTest = lenTestTemp;

+      

+      if (repIndex == 0)

+        startLen = lenTest + 1;

+        

+      /* if (_maxMode) */

+        {

+          UInt32 lenTest2 = lenTest + 1;

+          UInt32 limit = lenTest2 + p->numFastBytes;

+          UInt32 nextRepMatchPrice;

+          if (limit > numAvailFull)

+            limit = numAvailFull;

+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);

+          lenTest2 -= lenTest + 1;

+          if (lenTest2 >= 2)

+          {

+            UInt32 state2 = kRepNextStates[state];

+            UInt32 posStateNext = (position + lenTest) & p->pbMask;

+            UInt32 curAndLenCharPrice =

+                price + p->repLenEnc.prices[posState][lenTest - 2] +

+                GET_PRICE_0(p->isMatch[state2][posStateNext]) +

+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),

+                    data[lenTest], data2[lenTest], p->ProbPrices);

+            state2 = kLiteralNextStates[state2];

+            posStateNext = (position + lenTest + 1) & p->pbMask;

+            nextRepMatchPrice = curAndLenCharPrice +

+                GET_PRICE_1(p->isMatch[state2][posStateNext]) +

+                GET_PRICE_1(p->isRep[state2]);

+            

+            /* for (; lenTest2 >= 2; lenTest2--) */

+            {

+              UInt32 curAndLenPrice;

+              COptimal *opt;

+              UInt32 offset = cur + lenTest + 1 + lenTest2;

+              while (lenEnd < offset)

+                p->opt[++lenEnd].price = kInfinityPrice;

+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);

+              opt = &p->opt[offset];

+              if (curAndLenPrice < opt->price)

+              {

+                opt->price = curAndLenPrice;

+                opt->posPrev = cur + lenTest + 1;

+                opt->backPrev = 0;

+                opt->prev1IsChar = True;

+                opt->prev2 = True;

+                opt->posPrev2 = cur;

+                opt->backPrev2 = repIndex;

+              }

+            }

+          }

+        }

+    }

+    }

+    /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */

+    if (newLen > numAvail)

+    {

+      newLen = numAvail;

+      for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);

+      matches[numPairs] = newLen;

+      numPairs += 2;

+    }

+    if (newLen >= startLen)

+    {

+      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);

+      UInt32 offs, curBack, posSlot;

+      UInt32 lenTest;

+      while (lenEnd < cur + newLen)

+        p->opt[++lenEnd].price = kInfinityPrice;

+

+      offs = 0;

+      while (startLen > matches[offs])

+        offs += 2;

+      curBack = matches[offs + 1];

+      GetPosSlot2(curBack, posSlot);

+      for (lenTest = /*2*/ startLen; ; lenTest++)

+      {

+        UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];

+        UInt32 lenToPosState = GetLenToPosState(lenTest);

+        COptimal *opt;

+        if (curBack < kNumFullDistances)

+          curAndLenPrice += p->distancesPrices[lenToPosState][curBack];

+        else

+          curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];

+        

+        opt = &p->opt[cur + lenTest];

+        if (curAndLenPrice < opt->price)

+        {

+          opt->price = curAndLenPrice;

+          opt->posPrev = cur;

+          opt->backPrev = curBack + LZMA_NUM_REPS;

+          opt->prev1IsChar = False;

+        }

+

+        if (/*_maxMode && */lenTest == matches[offs])

+        {

+          /* Try Match + Literal + Rep0 */

+          const Byte *data2 = data - (curBack + 1);

+          UInt32 lenTest2 = lenTest + 1;

+          UInt32 limit = lenTest2 + p->numFastBytes;

+          UInt32 nextRepMatchPrice;

+          if (limit > numAvailFull)

+            limit = numAvailFull;

+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);

+          lenTest2 -= lenTest + 1;

+          if (lenTest2 >= 2)

+          {

+            UInt32 state2 = kMatchNextStates[state];

+            UInt32 posStateNext = (position + lenTest) & p->pbMask;

+            UInt32 curAndLenCharPrice = curAndLenPrice +

+                GET_PRICE_0(p->isMatch[state2][posStateNext]) +

+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),

+                    data[lenTest], data2[lenTest], p->ProbPrices);

+            state2 = kLiteralNextStates[state2];

+            posStateNext = (posStateNext + 1) & p->pbMask;

+            nextRepMatchPrice = curAndLenCharPrice +

+                GET_PRICE_1(p->isMatch[state2][posStateNext]) +

+                GET_PRICE_1(p->isRep[state2]);

+            

+            /* for (; lenTest2 >= 2; lenTest2--) */

+            {

+              UInt32 offset = cur + lenTest + 1 + lenTest2;

+              UInt32 curAndLenPrice;

+              COptimal *opt;

+              while (lenEnd < offset)

+                p->opt[++lenEnd].price = kInfinityPrice;

+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);

+              opt = &p->opt[offset];

+              if (curAndLenPrice < opt->price)

+              {

+                opt->price = curAndLenPrice;

+                opt->posPrev = cur + lenTest + 1;

+                opt->backPrev = 0;

+                opt->prev1IsChar = True;

+                opt->prev2 = True;

+                opt->posPrev2 = cur;

+                opt->backPrev2 = curBack + LZMA_NUM_REPS;

+              }

+            }

+          }

+          offs += 2;

+          if (offs == numPairs)

+            break;

+          curBack = matches[offs + 1];

+          if (curBack >= kNumFullDistances)

+            GetPosSlot2(curBack, posSlot);

+        }

+      }

+    }

+  }

+}

+

+#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))

+

+static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)

+{

+  UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;

+  const Byte *data;

+  const UInt32 *matches;

+

+  if (p->additionalOffset == 0)

+    mainLen = ReadMatchDistances(p, &numPairs);

+  else

+  {

+    mainLen = p->longestMatchLength;

+    numPairs = p->numPairs;

+  }

+

+  numAvail = p->numAvail;

+  *backRes = (UInt32)-1;

+  if (numAvail < 2)

+    return 1;

+  if (numAvail > LZMA_MATCH_LEN_MAX)

+    numAvail = LZMA_MATCH_LEN_MAX;

+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;

+

+  repLen = repIndex = 0;

+  for (i = 0; i < LZMA_NUM_REPS; i++)

+  {

+    UInt32 len;

+    const Byte *data2 = data - (p->reps[i] + 1);

+    if (data[0] != data2[0] || data[1] != data2[1])

+      continue;

+    for (len = 2; len < numAvail && data[len] == data2[len]; len++);

+    if (len >= p->numFastBytes)

+    {

+      *backRes = i;

+      MovePos(p, len - 1);

+      return len;

+    }

+    if (len > repLen)

+    {

+      repIndex = i;

+      repLen = len;

+    }

+  }

+

+  matches = p->matches;

+  if (mainLen >= p->numFastBytes)

+  {

+    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;

+    MovePos(p, mainLen - 1);

+    return mainLen;

+  }

+

+  mainDist = 0; /* for GCC */

+  if (mainLen >= 2)

+  {

+    mainDist = matches[numPairs - 1];

+    while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)

+    {

+      if (!ChangePair(matches[numPairs - 3], mainDist))

+        break;

+      numPairs -= 2;

+      mainLen = matches[numPairs - 2];

+      mainDist = matches[numPairs - 1];

+    }

+    if (mainLen == 2 && mainDist >= 0x80)

+      mainLen = 1;

+  }

+

+  if (repLen >= 2 && (

+        (repLen + 1 >= mainLen) ||

+        (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||

+        (repLen + 3 >= mainLen && mainDist >= (1 << 15))))

+  {

+    *backRes = repIndex;

+    MovePos(p, repLen - 1);

+    return repLen;

+  }

+  

+  if (mainLen < 2 || numAvail <= 2)

+    return 1;

+

+  p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);

+  if (p->longestMatchLength >= 2)

+  {

+    UInt32 newDistance = matches[p->numPairs - 1];

+    if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||

+        (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||

+        (p->longestMatchLength > mainLen + 1) ||

+        (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))

+      return 1;

+  }

+  

+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;

+  for (i = 0; i < LZMA_NUM_REPS; i++)

+  {

+    UInt32 len, limit;

+    const Byte *data2 = data - (p->reps[i] + 1);

+    if (data[0] != data2[0] || data[1] != data2[1])

+      continue;

+    limit = mainLen - 1;

+    for (len = 2; len < limit && data[len] == data2[len]; len++);

+    if (len >= limit)

+      return 1;

+  }

+  *backRes = mainDist + LZMA_NUM_REPS;

+  MovePos(p, mainLen - 2);

+  return mainLen;

+}

+

+static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)

+{

+  UInt32 len;

+  RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);

+  RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);

+  p->state = kMatchNextStates[p->state];

+  len = LZMA_MATCH_LEN_MIN;

+  LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);

+  RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);

+  RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);

+  RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);

+}

+

+static SRes CheckErrors(CLzmaEnc *p)

+{

+  if (p->result != SZ_OK)

+    return p->result;

+  if (p->rc.res != SZ_OK)

+    p->result = SZ_ERROR_WRITE;

+  if (p->matchFinderBase.result != SZ_OK)

+    p->result = SZ_ERROR_READ;

+  if (p->result != SZ_OK)

+    p->finished = True;

+  return p->result;

+}

+

+static SRes Flush(CLzmaEnc *p, UInt32 nowPos)

+{

+  /* ReleaseMFStream(); */

+  p->finished = True;

+  if (p->writeEndMark)

+    WriteEndMarker(p, nowPos & p->pbMask);

+  RangeEnc_FlushData(&p->rc);

+  RangeEnc_FlushStream(&p->rc);

+  return CheckErrors(p);

+}

+

+static void FillAlignPrices(CLzmaEnc *p)

+{

+  UInt32 i;

+  for (i = 0; i < kAlignTableSize; i++)

+    p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);

+  p->alignPriceCount = 0;

+}

+

+static void FillDistancesPrices(CLzmaEnc *p)

+{

+  UInt32 tempPrices[kNumFullDistances];

+  UInt32 i, lenToPosState;

+  for (i = kStartPosModelIndex; i < kNumFullDistances; i++)

+  {

+    UInt32 posSlot = GetPosSlot1(i);

+    UInt32 footerBits = ((posSlot >> 1) - 1);

+    UInt32 base = ((2 | (posSlot & 1)) << footerBits);

+    tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);

+  }

+

+  for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)

+  {

+    UInt32 posSlot;

+    const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];

+    UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];

+    for (posSlot = 0; posSlot < p->distTableSize; posSlot++)

+      posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);

+    for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)

+      posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);

+

+    {

+      UInt32 *distancesPrices = p->distancesPrices[lenToPosState];

+      UInt32 i;

+      for (i = 0; i < kStartPosModelIndex; i++)

+        distancesPrices[i] = posSlotPrices[i];

+      for (; i < kNumFullDistances; i++)

+        distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];

+    }

+  }

+  p->matchPriceCount = 0;

+}

+

+void LzmaEnc_Construct(CLzmaEnc *p)

+{

+  RangeEnc_Construct(&p->rc);

+  MatchFinder_Construct(&p->matchFinderBase);

+  #ifndef _7ZIP_ST

+  MatchFinderMt_Construct(&p->matchFinderMt);

+  p->matchFinderMt.MatchFinder = &p->matchFinderBase;

+  #endif

+

+  {

+    CLzmaEncProps props;

+    LzmaEncProps_Init(&props);

+    LzmaEnc_SetProps(p, &props);

+  }

+

+  #ifndef LZMA_LOG_BSR

+  LzmaEnc_FastPosInit(p->g_FastPos);

+  #endif

+

+  LzmaEnc_InitPriceTables(p->ProbPrices);

+  p->litProbs = 0;

+  p->saveState.litProbs = 0;

+}

+

+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)

+{

+  void *p;

+  p = alloc->Alloc(alloc, sizeof(CLzmaEnc));

+  if (p != 0)

+    LzmaEnc_Construct((CLzmaEnc *)p);

+  return p;

+}

+

+void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, p->litProbs);

+  alloc->Free(alloc, p->saveState.litProbs);

+  p->litProbs = 0;

+  p->saveState.litProbs = 0;

+}

+

+void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  #ifndef _7ZIP_ST

+  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);

+  #endif

+  MatchFinder_Free(&p->matchFinderBase, allocBig);

+  LzmaEnc_FreeLits(p, alloc);

+  RangeEnc_Free(&p->rc, alloc);

+}

+

+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);

+  alloc->Free(alloc, p);

+}

+

+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)

+{

+  UInt32 nowPos32, startPos32;

+  if (p->needInit)

+  {

+    p->matchFinder.Init(p->matchFinderObj);

+    p->needInit = 0;

+  }

+

+  if (p->finished)

+    return p->result;

+  RINOK(CheckErrors(p));

+

+  nowPos32 = (UInt32)p->nowPos64;

+  startPos32 = nowPos32;

+

+  if (p->nowPos64 == 0)

+  {

+    UInt32 numPairs;

+    Byte curByte;

+    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)

+      return Flush(p, nowPos32);

+    ReadMatchDistances(p, &numPairs);

+    RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);

+    p->state = kLiteralNextStates[p->state];

+    curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);

+    LitEnc_Encode(&p->rc, p->litProbs, curByte);

+    p->additionalOffset--;

+    nowPos32++;

+  }

+

+  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)

+  for (;;)

+  {

+    UInt32 pos, len, posState;

+

+    if (p->fastMode)

+      len = GetOptimumFast(p, &pos);

+    else

+      len = GetOptimum(p, nowPos32, &pos);

+

+    #ifdef SHOW_STAT2

+    printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);

+    #endif

+

+    posState = nowPos32 & p->pbMask;

+    if (len == 1 && pos == (UInt32)-1)

+    {

+      Byte curByte;

+      CLzmaProb *probs;

+      const Byte *data;

+

+      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);

+      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;

+      curByte = *data;

+      probs = LIT_PROBS(nowPos32, *(data - 1));

+      if (IsCharState(p->state))

+        LitEnc_Encode(&p->rc, probs, curByte);

+      else

+        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));

+      p->state = kLiteralNextStates[p->state];

+    }

+    else

+    {

+      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);

+      if (pos < LZMA_NUM_REPS)

+      {

+        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);

+        if (pos == 0)

+        {

+          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);

+          RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));

+        }

+        else

+        {

+          UInt32 distance = p->reps[pos];

+          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);

+          if (pos == 1)

+            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);

+          else

+          {

+            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);

+            RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);

+            if (pos == 3)

+              p->reps[3] = p->reps[2];

+            p->reps[2] = p->reps[1];

+          }

+          p->reps[1] = p->reps[0];

+          p->reps[0] = distance;

+        }

+        if (len == 1)

+          p->state = kShortRepNextStates[p->state];

+        else

+        {

+          LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);

+          p->state = kRepNextStates[p->state];

+        }

+      }

+      else

+      {

+        UInt32 posSlot;

+        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);

+        p->state = kMatchNextStates[p->state];

+        LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);

+        pos -= LZMA_NUM_REPS;

+        GetPosSlot(pos, posSlot);

+        RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);

+        

+        if (posSlot >= kStartPosModelIndex)

+        {

+          UInt32 footerBits = ((posSlot >> 1) - 1);

+          UInt32 base = ((2 | (posSlot & 1)) << footerBits);

+          UInt32 posReduced = pos - base;

+

+          if (posSlot < kEndPosModelIndex)

+            RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);

+          else

+          {

+            RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);

+            RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);

+            p->alignPriceCount++;

+          }

+        }

+        p->reps[3] = p->reps[2];

+        p->reps[2] = p->reps[1];

+        p->reps[1] = p->reps[0];

+        p->reps[0] = pos;

+        p->matchPriceCount++;

+      }

+    }

+    p->additionalOffset -= len;

+    nowPos32 += len;

+    if (p->additionalOffset == 0)

+    {

+      UInt32 processed;

+      if (!p->fastMode)

+      {

+        if (p->matchPriceCount >= (1 << 7))

+          FillDistancesPrices(p);

+        if (p->alignPriceCount >= kAlignTableSize)

+          FillAlignPrices(p);

+      }

+      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)

+        break;

+      processed = nowPos32 - startPos32;

+      if (useLimits)

+      {

+        if (processed + kNumOpts + 300 >= maxUnpackSize ||

+            RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)

+          break;

+      }

+      else if (processed >= (1 << 15))

+      {

+        p->nowPos64 += nowPos32 - startPos32;

+        return CheckErrors(p);

+      }

+    }

+  }

+  p->nowPos64 += nowPos32 - startPos32;

+  return Flush(p, nowPos32);

+}

+

+#define kBigHashDicLimit ((UInt32)1 << 24)

+

+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  UInt32 beforeSize = kNumOpts;

+  Bool btMode;

+  if (!RangeEnc_Alloc(&p->rc, alloc))

+    return SZ_ERROR_MEM;

+  btMode = (p->matchFinderBase.btMode != 0);

+  #ifndef _7ZIP_ST

+  p->mtMode = (p->multiThread && !p->fastMode && btMode);

+  #endif

+

+  {

+    unsigned lclp = p->lc + p->lp;

+    if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)

+    {

+      LzmaEnc_FreeLits(p, alloc);

+      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));

+      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));

+      if (p->litProbs == 0 || p->saveState.litProbs == 0)

+      {

+        LzmaEnc_FreeLits(p, alloc);

+        return SZ_ERROR_MEM;

+      }

+      p->lclp = lclp;

+    }

+  }

+

+  p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);

+

+  if (beforeSize + p->dictSize < keepWindowSize)

+    beforeSize = keepWindowSize - p->dictSize;

+

+  #ifndef _7ZIP_ST

+  if (p->mtMode)

+  {

+    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));

+    p->matchFinderObj = &p->matchFinderMt;

+    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);

+  }

+  else

+  #endif

+  {

+    if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))

+      return SZ_ERROR_MEM;

+    p->matchFinderObj = &p->matchFinderBase;

+    MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);

+  }

+  return SZ_OK;

+}

+

+void LzmaEnc_Init(CLzmaEnc *p)

+{

+  UInt32 i;

+  p->state = 0;

+  for (i = 0 ; i < LZMA_NUM_REPS; i++)

+    p->reps[i] = 0;

+

+  RangeEnc_Init(&p->rc);

+

+

+  for (i = 0; i < kNumStates; i++)

+  {

+    UInt32 j;

+    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)

+    {

+      p->isMatch[i][j] = kProbInitValue;

+      p->isRep0Long[i][j] = kProbInitValue;

+    }

+    p->isRep[i] = kProbInitValue;

+    p->isRepG0[i] = kProbInitValue;

+    p->isRepG1[i] = kProbInitValue;

+    p->isRepG2[i] = kProbInitValue;

+  }

+

+  {

+    UInt32 num = 0x300 << (p->lp + p->lc);

+    for (i = 0; i < num; i++)

+      p->litProbs[i] = kProbInitValue;

+  }

+

+  {

+    for (i = 0; i < kNumLenToPosStates; i++)

+    {

+      CLzmaProb *probs = p->posSlotEncoder[i];

+      UInt32 j;

+      for (j = 0; j < (1 << kNumPosSlotBits); j++)

+        probs[j] = kProbInitValue;

+    }

+  }

+  {

+    for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)

+      p->posEncoders[i] = kProbInitValue;

+  }

+

+  LenEnc_Init(&p->lenEnc.p);

+  LenEnc_Init(&p->repLenEnc.p);

+

+  for (i = 0; i < (1 << kNumAlignBits); i++)

+    p->posAlignEncoder[i] = kProbInitValue;

+

+  p->optimumEndIndex = 0;

+  p->optimumCurrentIndex = 0;

+  p->additionalOffset = 0;

+

+  p->pbMask = (1 << p->pb) - 1;

+  p->lpMask = (1 << p->lp) - 1;

+}

+

+void LzmaEnc_InitPrices(CLzmaEnc *p)

+{

+  if (!p->fastMode)

+  {

+    FillDistancesPrices(p);

+    FillAlignPrices(p);

+  }

+

+  p->lenEnc.tableSize =

+  p->repLenEnc.tableSize =

+      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;

+  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);

+  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);

+}

+

+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  UInt32 i;

+  for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)

+    if (p->dictSize <= ((UInt32)1 << i))

+      break;

+  p->distTableSize = i * 2;

+

+  p->finished = False;

+  p->result = SZ_OK;

+  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));

+  LzmaEnc_Init(p);

+  LzmaEnc_InitPrices(p);

+  p->nowPos64 = 0;

+  return SZ_OK;

+}

+

+static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,

+    ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  CLzmaEnc *p = (CLzmaEnc *)pp;

+  p->matchFinderBase.stream = inStream;

+  p->needInit = 1;

+  p->rc.outStream = outStream;

+  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);

+}

+

+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,

+    ISeqInStream *inStream, UInt32 keepWindowSize,

+    ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  CLzmaEnc *p = (CLzmaEnc *)pp;

+  p->matchFinderBase.stream = inStream;

+  p->needInit = 1;

+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);

+}

+

+static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)

+{

+  p->matchFinderBase.directInput = 1;

+  p->matchFinderBase.bufferBase = (Byte *)src;

+  p->matchFinderBase.directInputRem = srcLen;

+}

+

+SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,

+    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  CLzmaEnc *p = (CLzmaEnc *)pp;

+  LzmaEnc_SetInputBuf(p, src, srcLen);

+  p->needInit = 1;

+

+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);

+}

+

+void LzmaEnc_Finish(CLzmaEncHandle pp)

+{

+  #ifndef _7ZIP_ST

+  CLzmaEnc *p = (CLzmaEnc *)pp;

+  if (p->mtMode)

+    MatchFinderMt_ReleaseStream(&p->matchFinderMt);

+  #else

+  pp = pp;

+  #endif

+}

+

+typedef struct

+{

+  ISeqOutStream funcTable;

+  Byte *data;

+  SizeT rem;

+  Bool overflow;

+} CSeqOutStreamBuf;

+

+static size_t MyWrite(void *pp, const void *data, size_t size)

+{

+  CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;

+  if (p->rem < size)

+  {

+    size = p->rem;

+    p->overflow = True;

+  }

+  memcpy(p->data, data, size);

+  p->rem -= size;

+  p->data += size;

+  return size;

+}

+

+

+UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)

+{

+  const CLzmaEnc *p = (CLzmaEnc *)pp;

+  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);

+}

+

+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)

+{

+  const CLzmaEnc *p = (CLzmaEnc *)pp;

+  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;

+}

+

+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,

+    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)

+{

+  CLzmaEnc *p = (CLzmaEnc *)pp;

+  UInt64 nowPos64;

+  SRes res;

+  CSeqOutStreamBuf outStream;

+

+  outStream.funcTable.Write = MyWrite;

+  outStream.data = dest;

+  outStream.rem = *destLen;

+  outStream.overflow = False;

+

+  p->writeEndMark = False;

+  p->finished = False;

+  p->result = SZ_OK;

+

+  if (reInit)

+    LzmaEnc_Init(p);

+  LzmaEnc_InitPrices(p);

+  nowPos64 = p->nowPos64;

+  RangeEnc_Init(&p->rc);

+  p->rc.outStream = &outStream.funcTable;

+

+  res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);

+  

+  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);

+  *destLen -= outStream.rem;

+  if (outStream.overflow)

+    return SZ_ERROR_OUTPUT_EOF;

+

+  return res;

+}

+

+static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)

+{

+  SRes res = SZ_OK;

+

+  #ifndef _7ZIP_ST

+  Byte allocaDummy[0x300];

+  int i = 0;

+  for (i = 0; i < 16; i++)

+    allocaDummy[i] = (Byte)i;

+  #endif

+

+  for (;;)

+  {

+    res = LzmaEnc_CodeOneBlock(p, False, 0, 0);

+    if (res != SZ_OK || p->finished != 0)

+      break;

+    if (progress != 0)

+    {

+      res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));

+      if (res != SZ_OK)

+      {

+        res = SZ_ERROR_PROGRESS;

+        break;

+      }

+    }

+  }

+  LzmaEnc_Finish(p);

+  return res;

+}

+

+SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,

+    ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));

+  return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);

+}

+

+SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)

+{

+  CLzmaEnc *p = (CLzmaEnc *)pp;

+  int i;

+  UInt32 dictSize = p->dictSize;

+  if (*size < LZMA_PROPS_SIZE)

+    return SZ_ERROR_PARAM;

+  *size = LZMA_PROPS_SIZE;

+  props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);

+

+  for (i = 11; i <= 30; i++)

+  {

+    if (dictSize <= ((UInt32)2 << i))

+    {

+      dictSize = (2 << i);

+      break;

+    }

+    if (dictSize <= ((UInt32)3 << i))

+    {

+      dictSize = (3 << i);

+      break;

+    }

+  }

+

+  for (i = 0; i < 4; i++)

+    props[1 + i] = (Byte)(dictSize >> (8 * i));

+  return SZ_OK;

+}

+

+SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,

+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  SRes res;

+  CLzmaEnc *p = (CLzmaEnc *)pp;

+

+  CSeqOutStreamBuf outStream;

+

+  LzmaEnc_SetInputBuf(p, src, srcLen);

+

+  outStream.funcTable.Write = MyWrite;

+  outStream.data = dest;

+  outStream.rem = *destLen;

+  outStream.overflow = False;

+

+  p->writeEndMark = writeEndMark;

+

+  p->rc.outStream = &outStream.funcTable;

+  res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);

+  if (res == SZ_OK)

+    res = LzmaEnc_Encode2(p, progress);

+

+  *destLen -= outStream.rem;

+  if (outStream.overflow)

+    return SZ_ERROR_OUTPUT_EOF;

+  return res;

+}

+

+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,

+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,

+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)

+{

+  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);

+  SRes res;

+  if (p == 0)

+    return SZ_ERROR_MEM;

+

+  res = LzmaEnc_SetProps(p, props);

+  if (res == SZ_OK)

+  {

+    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);

+    if (res == SZ_OK)

+      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,

+          writeEndMark, progress, alloc, allocBig);

+  }

+

+  LzmaEnc_Destroy(p, alloc, allocBig);

+  return res;

+}

diff --git a/C/LzmaEnc.h b/C/LzmaEnc.h
new file mode 100755
index 0000000..999f5af
--- /dev/null
+++ b/C/LzmaEnc.h
@@ -0,0 +1,80 @@
+/*  LzmaEnc.h -- LZMA Encoder

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA_ENC_H

+#define __LZMA_ENC_H

+

+#include "Types.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#define LZMA_PROPS_SIZE 5

+

+typedef struct _CLzmaEncProps

+{

+  int level;       /*  0 <= level <= 9 */

+  UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version

+                      (1 << 12) <= dictSize <= (1 << 30) for 64-bit version

+                       default = (1 << 24) */

+  int lc;          /* 0 <= lc <= 8, default = 3 */

+  int lp;          /* 0 <= lp <= 4, default = 0 */

+  int pb;          /* 0 <= pb <= 4, default = 2 */

+  int algo;        /* 0 - fast, 1 - normal, default = 1 */

+  int fb;          /* 5 <= fb <= 273, default = 32 */

+  int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */

+  int numHashBytes; /* 2, 3 or 4, default = 4 */

+  UInt32 mc;        /* 1 <= mc <= (1 << 30), default = 32 */

+  unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */

+  int numThreads;  /* 1 or 2, default = 2 */

+} CLzmaEncProps;

+

+void LzmaEncProps_Init(CLzmaEncProps *p);

+void LzmaEncProps_Normalize(CLzmaEncProps *p);

+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);

+

+

+/* ---------- CLzmaEncHandle Interface ---------- */

+

+/* LzmaEnc_* functions can return the following exit codes:

+Returns:

+  SZ_OK           - OK

+  SZ_ERROR_MEM    - Memory allocation error

+  SZ_ERROR_PARAM  - Incorrect paramater in props

+  SZ_ERROR_WRITE  - Write callback error.

+  SZ_ERROR_PROGRESS - some break from progress callback

+  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)

+*/

+

+typedef void * CLzmaEncHandle;

+

+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);

+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);

+SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);

+SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);

+SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,

+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

+SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,

+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

+

+/* ---------- One Call Interface ---------- */

+

+/* LzmaEncode

+Return code:

+  SZ_OK               - OK

+  SZ_ERROR_MEM        - Memory allocation error

+  SZ_ERROR_PARAM      - Incorrect paramater

+  SZ_ERROR_OUTPUT_EOF - output buffer overflow

+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)

+*/

+

+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,

+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,

+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/LzmaLib.c b/C/LzmaLib.c
new file mode 100755
index 0000000..3e3cf40
--- /dev/null
+++ b/C/LzmaLib.c
@@ -0,0 +1,46 @@
+/* LzmaLib.c -- LZMA library wrapper

+2008-08-05

+Igor Pavlov

+Public domain */

+

+#include "LzmaEnc.h"

+#include "LzmaDec.h"

+#include "Alloc.h"

+#include "LzmaLib.h"

+

+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

+static void SzFree(void *p, void *address) { p = p; MyFree(address); }

+static ISzAlloc g_Alloc = { SzAlloc, SzFree };

+

+MY_STDAPI LzmaCompress(unsigned char *dest, size_t  *destLen, const unsigned char *src, size_t  srcLen,

+  unsigned char *outProps, size_t *outPropsSize,

+  int level, /* 0 <= level <= 9, default = 5 */

+  unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */

+  int lc, /* 0 <= lc <= 8, default = 3  */

+  int lp, /* 0 <= lp <= 4, default = 0  */

+  int pb, /* 0 <= pb <= 4, default = 2  */

+  int fb,  /* 5 <= fb <= 273, default = 32 */

+  int numThreads /* 1 or 2, default = 2 */

+)

+{

+  CLzmaEncProps props;

+  LzmaEncProps_Init(&props);

+  props.level = level;

+  props.dictSize = dictSize;

+  props.lc = lc;

+  props.lp = lp;

+  props.pb = pb;

+  props.fb = fb;

+  props.numThreads = numThreads;

+

+  return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0,

+      NULL, &g_Alloc, &g_Alloc);

+}

+

+

+MY_STDAPI LzmaUncompress(unsigned char *dest, size_t  *destLen, const unsigned char *src, size_t  *srcLen,

+  const unsigned char *props, size_t propsSize)

+{

+  ELzmaStatus status;

+  return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc);

+}

diff --git a/C/LzmaLib.h b/C/LzmaLib.h
new file mode 100755
index 0000000..55e1e11
--- /dev/null
+++ b/C/LzmaLib.h
@@ -0,0 +1,135 @@
+/* LzmaLib.h -- LZMA library interface

+2009-04-07 : Igor Pavlov : Public domain */

+

+#ifndef __LZMA_LIB_H

+#define __LZMA_LIB_H

+

+#include "Types.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#define MY_STDAPI int MY_STD_CALL

+

+#define LZMA_PROPS_SIZE 5

+

+/*

+RAM requirements for LZMA:

+  for compression:   (dictSize * 11.5 + 6 MB) + state_size

+  for decompression: dictSize + state_size

+    state_size = (4 + (1.5 << (lc + lp))) KB

+    by default (lc=3, lp=0), state_size = 16 KB.

+

+LZMA properties (5 bytes) format

+    Offset Size  Description

+      0     1    lc, lp and pb in encoded form.

+      1     4    dictSize (little endian).

+*/

+

+/*

+LzmaCompress

+------------

+

+outPropsSize -

+     In:  the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.

+     Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.

+

+  LZMA Encoder will use defult values for any parameter, if it is

+  -1  for any from: level, loc, lp, pb, fb, numThreads

+   0  for dictSize

+  

+level - compression level: 0 <= level <= 9;

+

+  level dictSize algo  fb

+    0:    16 KB   0    32

+    1:    64 KB   0    32

+    2:   256 KB   0    32

+    3:     1 MB   0    32

+    4:     4 MB   0    32

+    5:    16 MB   1    32

+    6:    32 MB   1    32

+    7+:   64 MB   1    64

+ 

+  The default value for "level" is 5.

+

+  algo = 0 means fast method

+  algo = 1 means normal method

+

+dictSize - The dictionary size in bytes. The maximum value is

+        128 MB = (1 << 27) bytes for 32-bit version

+          1 GB = (1 << 30) bytes for 64-bit version

+     The default value is 16 MB = (1 << 24) bytes.

+     It's recommended to use the dictionary that is larger than 4 KB and

+     that can be calculated as (1 << N) or (3 << N) sizes.

+

+lc - The number of literal context bits (high bits of previous literal).

+     It can be in the range from 0 to 8. The default value is 3.

+     Sometimes lc=4 gives the gain for big files.

+

+lp - The number of literal pos bits (low bits of current position for literals).

+     It can be in the range from 0 to 4. The default value is 0.

+     The lp switch is intended for periodical data when the period is equal to 2^lp.

+     For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's

+     better to set lc=0, if you change lp switch.

+

+pb - The number of pos bits (low bits of current position).

+     It can be in the range from 0 to 4. The default value is 2.

+     The pb switch is intended for periodical data when the period is equal 2^pb.

+

+fb - Word size (the number of fast bytes).

+     It can be in the range from 5 to 273. The default value is 32.

+     Usually, a big number gives a little bit better compression ratio and

+     slower compression process.

+

+numThreads - The number of thereads. 1 or 2. The default value is 2.

+     Fast mode (algo = 0) can use only 1 thread.

+

+Out:

+  destLen  - processed output size

+Returns:

+  SZ_OK               - OK

+  SZ_ERROR_MEM        - Memory allocation error

+  SZ_ERROR_PARAM      - Incorrect paramater

+  SZ_ERROR_OUTPUT_EOF - output buffer overflow

+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)

+*/

+

+MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,

+  unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */

+  int level,      /* 0 <= level <= 9, default = 5 */

+  unsigned dictSize,  /* default = (1 << 24) */

+  int lc,        /* 0 <= lc <= 8, default = 3  */

+  int lp,        /* 0 <= lp <= 4, default = 0  */

+  int pb,        /* 0 <= pb <= 4, default = 2  */

+  int fb,        /* 5 <= fb <= 273, default = 32 */

+  int numThreads /* 1 or 2, default = 2 */

+  );

+

+/*

+LzmaUncompress

+--------------

+In:

+  dest     - output data

+  destLen  - output data size

+  src      - input data

+  srcLen   - input data size

+Out:

+  destLen  - processed output size

+  srcLen   - processed input size

+Returns:

+  SZ_OK                - OK

+  SZ_ERROR_DATA        - Data error

+  SZ_ERROR_MEM         - Memory allocation arror

+  SZ_ERROR_UNSUPPORTED - Unsupported properties

+  SZ_ERROR_INPUT_EOF   - it needs more bytes in input buffer (src)

+*/

+

+MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,

+  const unsigned char *props, size_t propsSize);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/MtCoder.c b/C/MtCoder.c
new file mode 100755
index 0000000..9f0d268
--- /dev/null
+++ b/C/MtCoder.c
@@ -0,0 +1,327 @@
+/* MtCoder.c -- Multi-thread Coder

+2010-09-24 : Igor Pavlov : Public domain */

+

+#include <stdio.h>

+

+#include "MtCoder.h"

+

+void LoopThread_Construct(CLoopThread *p)

+{

+  Thread_Construct(&p->thread);

+  Event_Construct(&p->startEvent);

+  Event_Construct(&p->finishedEvent);

+}

+

+void LoopThread_Close(CLoopThread *p)

+{

+  Thread_Close(&p->thread);

+  Event_Close(&p->startEvent);

+  Event_Close(&p->finishedEvent);

+}

+

+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)

+{

+  CLoopThread *p = (CLoopThread *)pp;

+  for (;;)

+  {

+    if (Event_Wait(&p->startEvent) != 0)

+      return SZ_ERROR_THREAD;

+    if (p->stop)

+      return 0;

+    p->res = p->func(p->param);

+    if (Event_Set(&p->finishedEvent) != 0)

+      return SZ_ERROR_THREAD;

+  }

+}

+

+WRes LoopThread_Create(CLoopThread *p)

+{

+  p->stop = 0;

+  RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));

+  RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));

+  return Thread_Create(&p->thread, LoopThreadFunc, p);

+}

+

+WRes LoopThread_StopAndWait(CLoopThread *p)

+{

+  p->stop = 1;

+  if (Event_Set(&p->startEvent) != 0)

+    return SZ_ERROR_THREAD;

+  return Thread_Wait(&p->thread);

+}

+

+WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }

+WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }

+

+static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)

+{

+  return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;

+}

+

+static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)

+{

+  unsigned i;

+  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)

+    p->inSizes[i] = p->outSizes[i] = 0;

+  p->totalInSize = p->totalOutSize = 0;

+  p->progress = progress;

+  p->res = SZ_OK;

+}

+

+static void MtProgress_Reinit(CMtProgress *p, unsigned index)

+{

+  p->inSizes[index] = 0;

+  p->outSizes[index] = 0;

+}

+

+#define UPDATE_PROGRESS(size, prev, total) \

+  if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }

+

+SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)

+{

+  SRes res;

+  CriticalSection_Enter(&p->cs);

+  UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)

+  UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)

+  if (p->res == SZ_OK)

+    p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);

+  res = p->res;

+  CriticalSection_Leave(&p->cs);

+  return res;

+}

+

+static void MtProgress_SetError(CMtProgress *p, SRes res)

+{

+  CriticalSection_Enter(&p->cs);

+  if (p->res == SZ_OK)

+    p->res = res;

+  CriticalSection_Leave(&p->cs);

+}

+

+static void MtCoder_SetError(CMtCoder* p, SRes res)

+{

+  CriticalSection_Enter(&p->cs);

+  if (p->res == SZ_OK)

+    p->res = res;

+  CriticalSection_Leave(&p->cs);

+}

+

+/* ---------- MtThread ---------- */

+

+void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)

+{

+  p->mtCoder = mtCoder;

+  p->outBuf = 0;

+  p->inBuf = 0;

+  Event_Construct(&p->canRead);

+  Event_Construct(&p->canWrite);

+  LoopThread_Construct(&p->thread);

+}

+

+#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }

+

+static void CMtThread_CloseEvents(CMtThread *p)

+{

+  Event_Close(&p->canRead);

+  Event_Close(&p->canWrite);

+}

+

+static void CMtThread_Destruct(CMtThread *p)

+{

+  CMtThread_CloseEvents(p);

+

+  if (Thread_WasCreated(&p->thread.thread))

+  {

+    LoopThread_StopAndWait(&p->thread);

+    LoopThread_Close(&p->thread);

+  }

+

+  if (p->mtCoder->alloc)

+    IAlloc_Free(p->mtCoder->alloc, p->outBuf);

+  p->outBuf = 0;

+

+  if (p->mtCoder->alloc)

+    IAlloc_Free(p->mtCoder->alloc, p->inBuf);

+  p->inBuf = 0;

+}

+

+#define MY_BUF_ALLOC(buf, size, newSize) \

+  if (buf == 0 || size != newSize) \

+  { IAlloc_Free(p->mtCoder->alloc, buf); \

+    size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \

+    if (buf == 0) return SZ_ERROR_MEM; }

+

+static SRes CMtThread_Prepare(CMtThread *p)

+{

+  MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)

+  MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)

+

+  p->stopReading = False;

+  p->stopWriting = False;

+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));

+  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));

+

+  return SZ_OK;

+}

+

+static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)

+{

+  size_t size = *processedSize;

+  *processedSize = 0;

+  while (size != 0)

+  {

+    size_t curSize = size;

+    SRes res = stream->Read(stream, data, &curSize);

+    *processedSize += curSize;

+    data += curSize;

+    size -= curSize;

+    RINOK(res);

+    if (curSize == 0)

+      return SZ_OK;

+  }

+  return SZ_OK;

+}

+

+#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads  - 1 ? 0 : p->index + 1]

+

+static SRes MtThread_Process(CMtThread *p, Bool *stop)

+{

+  CMtThread *next;

+  *stop = True;

+  if (Event_Wait(&p->canRead) != 0)

+    return SZ_ERROR_THREAD;

+  

+  next = GET_NEXT_THREAD(p);

+  

+  if (p->stopReading)

+  {

+    next->stopReading = True;

+    return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;

+  }

+

+  {

+    size_t size = p->mtCoder->blockSize;

+    size_t destSize = p->outBufSize;

+

+    RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));

+    next->stopReading = *stop = (size != p->mtCoder->blockSize);

+    if (Event_Set(&next->canRead) != 0)

+      return SZ_ERROR_THREAD;

+

+    RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,

+        p->outBuf, &destSize, p->inBuf, size, *stop));

+

+    MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);

+

+    if (Event_Wait(&p->canWrite) != 0)

+      return SZ_ERROR_THREAD;

+    if (p->stopWriting)

+      return SZ_ERROR_FAIL;

+    if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)

+      return SZ_ERROR_WRITE;

+    return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;

+  }

+}

+

+static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)

+{

+  CMtThread *p = (CMtThread *)pp;

+  for (;;)

+  {

+    Bool stop;

+    CMtThread *next = GET_NEXT_THREAD(p);

+    SRes res = MtThread_Process(p, &stop);

+    if (res != SZ_OK)

+    {

+      MtCoder_SetError(p->mtCoder, res);

+      MtProgress_SetError(&p->mtCoder->mtProgress, res);

+      next->stopReading = True;

+      next->stopWriting = True;

+      Event_Set(&next->canRead);

+      Event_Set(&next->canWrite);

+      return res;

+    }

+    if (stop)

+      return 0;

+  }

+}

+

+void MtCoder_Construct(CMtCoder* p)

+{

+  unsigned i;

+  p->alloc = 0;

+  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)

+  {

+    CMtThread *t = &p->threads[i];

+    t->index = i;

+    CMtThread_Construct(t, p);

+  }

+  CriticalSection_Init(&p->cs);

+  CriticalSection_Init(&p->mtProgress.cs);

+}

+

+void MtCoder_Destruct(CMtCoder* p)

+{

+  unsigned i;

+  for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)

+    CMtThread_Destruct(&p->threads[i]);

+  CriticalSection_Delete(&p->cs);

+  CriticalSection_Delete(&p->mtProgress.cs);

+}

+

+SRes MtCoder_Code(CMtCoder *p)

+{

+  unsigned i, numThreads = p->numThreads;

+  SRes res = SZ_OK;

+  p->res = SZ_OK;

+

+  MtProgress_Init(&p->mtProgress, p->progress);

+

+  for (i = 0; i < numThreads; i++)

+  {

+    RINOK(CMtThread_Prepare(&p->threads[i]));

+  }

+

+  for (i = 0; i < numThreads; i++)

+  {

+    CMtThread *t = &p->threads[i];

+    CLoopThread *lt = &t->thread;

+

+    if (!Thread_WasCreated(&lt->thread))

+    {

+      lt->func = ThreadFunc;

+      lt->param = t;

+

+      if (LoopThread_Create(lt) != SZ_OK)

+      {

+        res = SZ_ERROR_THREAD;

+        break;

+      }

+    }

+  }

+

+  if (res == SZ_OK)

+  {

+    unsigned j;

+    for (i = 0; i < numThreads; i++)

+    {

+      CMtThread *t = &p->threads[i];

+      if (LoopThread_StartSubThread(&t->thread) != SZ_OK)

+      {

+        res = SZ_ERROR_THREAD;

+        p->threads[0].stopReading = True;

+        break;

+      }

+    }

+

+    Event_Set(&p->threads[0].canWrite);

+    Event_Set(&p->threads[0].canRead);

+

+    for (j = 0; j < i; j++)

+      LoopThread_WaitSubThread(&p->threads[j].thread);

+  }

+

+  for (i = 0; i < numThreads; i++)

+    CMtThread_CloseEvents(&p->threads[i]);

+  return (res == SZ_OK) ? p->res : res;

+}

diff --git a/C/MtCoder.h b/C/MtCoder.h
new file mode 100755
index 0000000..705208e
--- /dev/null
+++ b/C/MtCoder.h
@@ -0,0 +1,98 @@
+/* MtCoder.h -- Multi-thread Coder

+2009-11-19 : Igor Pavlov : Public domain */

+

+#ifndef __MT_CODER_H

+#define __MT_CODER_H

+

+#include "Threads.h"

+

+EXTERN_C_BEGIN

+

+typedef struct

+{

+  CThread thread;

+  CAutoResetEvent startEvent;

+  CAutoResetEvent finishedEvent;

+  int stop;

+  

+  THREAD_FUNC_TYPE func;

+  LPVOID param;

+  THREAD_FUNC_RET_TYPE res;

+} CLoopThread;

+

+void LoopThread_Construct(CLoopThread *p);

+void LoopThread_Close(CLoopThread *p);

+WRes LoopThread_Create(CLoopThread *p);

+WRes LoopThread_StopAndWait(CLoopThread *p);

+WRes LoopThread_StartSubThread(CLoopThread *p);

+WRes LoopThread_WaitSubThread(CLoopThread *p);

+

+#ifndef _7ZIP_ST

+#define NUM_MT_CODER_THREADS_MAX 32

+#else

+#define NUM_MT_CODER_THREADS_MAX 1

+#endif

+

+typedef struct

+{

+  UInt64 totalInSize;

+  UInt64 totalOutSize;

+  ICompressProgress *progress;

+  SRes res;

+  CCriticalSection cs;

+  UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];

+  UInt64 outSizes[NUM_MT_CODER_THREADS_MAX];

+} CMtProgress;

+

+SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);

+

+struct _CMtCoder;

+

+typedef struct

+{

+  struct _CMtCoder *mtCoder;

+  Byte *outBuf;

+  size_t outBufSize;

+  Byte *inBuf;

+  size_t inBufSize;

+  unsigned index;

+  CLoopThread thread;

+

+  Bool stopReading;

+  Bool stopWriting;

+  CAutoResetEvent canRead;

+  CAutoResetEvent canWrite;

+} CMtThread;

+

+typedef struct

+{

+  SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize,

+      const Byte *src, size_t srcSize, int finished);

+} IMtCoderCallback;

+

+typedef struct _CMtCoder

+{

+  size_t blockSize;

+  size_t destBlockSize;

+  unsigned numThreads;

+  

+  ISeqInStream *inStream;

+  ISeqOutStream *outStream;

+  ICompressProgress *progress;

+  ISzAlloc *alloc;

+

+  IMtCoderCallback *mtCallback;

+  CCriticalSection cs;

+  SRes res;

+

+  CMtProgress mtProgress;

+  CMtThread threads[NUM_MT_CODER_THREADS_MAX];

+} CMtCoder;

+

+void MtCoder_Construct(CMtCoder* p);

+void MtCoder_Destruct(CMtCoder* p);

+SRes MtCoder_Code(CMtCoder *p);

+

+EXTERN_C_END

+

+#endif

diff --git a/C/Ppmd.h b/C/Ppmd.h
new file mode 100755
index 0000000..14344a7
--- /dev/null
+++ b/C/Ppmd.h
@@ -0,0 +1,81 @@
+/* Ppmd.h -- PPMD codec common code

+2010-03-12 : Igor Pavlov : Public domain

+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

+

+#ifndef __PPMD_H

+#define __PPMD_H

+

+#include "Types.h"

+#include "CpuArch.h"

+

+EXTERN_C_BEGIN

+

+#ifdef MY_CPU_32BIT

+  #define PPMD_32BIT

+#endif

+

+#define PPMD_INT_BITS 7

+#define PPMD_PERIOD_BITS 7

+#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))

+

+#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))

+#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)

+#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))

+#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))

+

+#define PPMD_N1 4

+#define PPMD_N2 4

+#define PPMD_N3 4

+#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)

+#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)

+

+/* SEE-contexts for PPM-contexts with masked symbols */

+typedef struct

+{

+  UInt16 Summ; /* Freq */

+  Byte Shift;  /* Speed of Freq change; low Shift is for fast change */

+  Byte Count;  /* Count to next change of Shift */

+} CPpmd_See;

+

+#define Ppmd_See_Update(p)  if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \

+    { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }

+

+typedef struct

+{

+  Byte Symbol;

+  Byte Freq;

+  UInt16 SuccessorLow;

+  UInt16 SuccessorHigh;

+} CPpmd_State;

+

+typedef

+  #ifdef PPMD_32BIT

+    CPpmd_State *

+  #else

+    UInt32

+  #endif

+  CPpmd_State_Ref;

+

+typedef

+  #ifdef PPMD_32BIT

+    void *

+  #else

+    UInt32

+  #endif

+  CPpmd_Void_Ref;

+

+typedef

+  #ifdef PPMD_32BIT

+    Byte *

+  #else

+    UInt32

+  #endif

+  CPpmd_Byte_Ref;

+

+#define PPMD_SetAllBitsIn256Bytes(p) \

+  { unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \

+  p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}

+

+EXTERN_C_END

+ 

+#endif

diff --git a/C/Ppmd7.c b/C/Ppmd7.c
new file mode 100755
index 0000000..4b160cf
--- /dev/null
+++ b/C/Ppmd7.c
@@ -0,0 +1,708 @@
+/* Ppmd7.c -- PPMdH codec

+2010-03-12 : Igor Pavlov : Public domain

+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

+

+#include <memory.h>

+

+#include "Ppmd7.h"

+

+const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };

+static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};

+

+#define MAX_FREQ 124

+#define UNIT_SIZE 12

+

+#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)

+#define U2I(nu) (p->Units2Indx[(nu) - 1])

+#define I2U(indx) (p->Indx2Units[indx])

+

+#ifdef PPMD_32BIT

+  #define REF(ptr) (ptr)

+#else

+  #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))

+#endif

+

+#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))

+

+#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))

+#define STATS(ctx) Ppmd7_GetStats(p, ctx)

+#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)

+#define SUFFIX(ctx) CTX((ctx)->Suffix)

+

+typedef CPpmd7_Context * CTX_PTR;

+

+struct CPpmd7_Node_;

+

+typedef

+  #ifdef PPMD_32BIT

+    struct CPpmd7_Node_ *

+  #else

+    UInt32

+  #endif

+  CPpmd7_Node_Ref;

+

+typedef struct CPpmd7_Node_

+{

+  UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */

+  UInt16 NU;

+  CPpmd7_Node_Ref Next; /* must be at offset >= 4 */

+  CPpmd7_Node_Ref Prev;

+} CPpmd7_Node;

+

+#ifdef PPMD_32BIT

+  #define NODE(ptr) (ptr)

+#else

+  #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))

+#endif

+

+void Ppmd7_Construct(CPpmd7 *p)

+{

+  unsigned i, k, m;

+

+  p->Base = 0;

+

+  for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)

+  {

+    unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);

+    do { p->Units2Indx[k++] = (Byte)i; } while(--step);

+    p->Indx2Units[i] = (Byte)k;

+  }

+

+  p->NS2BSIndx[0] = (0 << 1);

+  p->NS2BSIndx[1] = (1 << 1);

+  memset(p->NS2BSIndx + 2, (2 << 1), 9);

+  memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);

+

+  for (i = 0; i < 3; i++)

+    p->NS2Indx[i] = (Byte)i;

+  for (m = i, k = 1; i < 256; i++)

+  {

+    p->NS2Indx[i] = (Byte)m;

+    if (--k == 0)

+      k = (++m) - 2;

+  }

+

+  memset(p->HB2Flag, 0, 0x40);

+  memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);

+}

+

+void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)

+{

+  alloc->Free(alloc, p->Base);

+  p->Size = 0;

+  p->Base = 0;

+}

+

+Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)

+{

+  if (p->Base == 0 || p->Size != size)

+  {

+    Ppmd7_Free(p, alloc);

+    p->AlignOffset =

+      #ifdef PPMD_32BIT

+        (4 - size) & 3;

+      #else

+        4 - (size & 3);

+      #endif

+    if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size

+        #ifndef PPMD_32BIT

+        + UNIT_SIZE

+        #endif

+        )) == 0)

+      return False;

+    p->Size = size;

+  }

+  return True;

+}

+

+static void InsertNode(CPpmd7 *p, void *node, unsigned indx)

+{

+  *((CPpmd_Void_Ref *)node) = p->FreeList[indx];

+  p->FreeList[indx] = REF(node);

+}

+

+static void *RemoveNode(CPpmd7 *p, unsigned indx)

+{

+  CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);

+  p->FreeList[indx] = *node;

+  return node;

+}

+

+static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)

+{

+  unsigned i, nu = I2U(oldIndx) - I2U(newIndx);

+  ptr = (Byte *)ptr + U2B(I2U(newIndx));

+  if (I2U(i = U2I(nu)) != nu)

+  {

+    unsigned k = I2U(--i);

+    InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);

+  }

+  InsertNode(p, ptr, i);

+}

+

+static void GlueFreeBlocks(CPpmd7 *p)

+{

+  #ifdef PPMD_32BIT

+  CPpmd7_Node headItem;

+  CPpmd7_Node_Ref head = &headItem;

+  #else

+  CPpmd7_Node_Ref head = p->AlignOffset + p->Size;

+  #endif

+  

+  CPpmd7_Node_Ref n = head;

+  unsigned i;

+

+  p->GlueCount = 255;

+

+  /* create doubly-linked list of free blocks */

+  for (i = 0; i < PPMD_NUM_INDEXES; i++)

+  {

+    UInt16 nu = I2U(i);

+    CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];

+    p->FreeList[i] = 0;

+    while (next != 0)

+    {

+      CPpmd7_Node *node = NODE(next);

+      node->Next = n;

+      n = NODE(n)->Prev = next;

+      next = *(const CPpmd7_Node_Ref *)node;

+      node->Stamp = 0;

+      node->NU = (UInt16)nu;

+    }

+  }

+  NODE(head)->Stamp = 1;

+  NODE(head)->Next = n;

+  NODE(n)->Prev = head;

+  if (p->LoUnit != p->HiUnit)

+    ((CPpmd7_Node *)p->LoUnit)->Stamp = 1;

+  

+  /* Glue free blocks */

+  while (n != head)

+  {

+    CPpmd7_Node *node = NODE(n);

+    UInt32 nu = (UInt32)node->NU;

+    for (;;)

+    {

+      CPpmd7_Node *node2 = NODE(n) + nu;

+      nu += node2->NU;

+      if (node2->Stamp != 0 || nu >= 0x10000)

+        break;

+      NODE(node2->Prev)->Next = node2->Next;

+      NODE(node2->Next)->Prev = node2->Prev;

+      node->NU = (UInt16)nu;

+    }

+    n = node->Next;

+  }

+  

+  /* Fill lists of free blocks */

+  for (n = NODE(head)->Next; n != head;)

+  {

+    CPpmd7_Node *node = NODE(n);

+    unsigned nu;

+    CPpmd7_Node_Ref next = node->Next;

+    for (nu = node->NU; nu > 128; nu -= 128, node += 128)

+      InsertNode(p, node, PPMD_NUM_INDEXES - 1);

+    if (I2U(i = U2I(nu)) != nu)

+    {

+      unsigned k = I2U(--i);

+      InsertNode(p, node + k, nu - k - 1);

+    }

+    InsertNode(p, node, i);

+    n = next;

+  }

+}

+

+static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)

+{

+  unsigned i;

+  void *retVal;

+  if (p->GlueCount == 0)

+  {

+    GlueFreeBlocks(p);

+    if (p->FreeList[indx] != 0)

+      return RemoveNode(p, indx);

+  }

+  i = indx;

+  do

+  {

+    if (++i == PPMD_NUM_INDEXES)

+    {

+      UInt32 numBytes = U2B(I2U(indx));

+      p->GlueCount--;

+      return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);

+    }

+  }

+  while (p->FreeList[i] == 0);

+  retVal = RemoveNode(p, i);

+  SplitBlock(p, retVal, i, indx);

+  return retVal;

+}

+

+static void *AllocUnits(CPpmd7 *p, unsigned indx)

+{

+  UInt32 numBytes;

+  if (p->FreeList[indx] != 0)

+    return RemoveNode(p, indx);

+  numBytes = U2B(I2U(indx));

+  if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))

+  {

+    void *retVal = p->LoUnit;

+    p->LoUnit += numBytes;

+    return retVal;

+  }

+  return AllocUnitsRare(p, indx);

+}

+

+#define MyMem12Cpy(dest, src, num) \

+  { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \

+    do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }

+

+static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)

+{

+  unsigned i0 = U2I(oldNU);

+  unsigned i1 = U2I(newNU);

+  if (i0 == i1)

+    return oldPtr;

+  if (p->FreeList[i1] != 0)

+  {

+    void *ptr = RemoveNode(p, i1);

+    MyMem12Cpy(ptr, oldPtr, newNU);

+    InsertNode(p, oldPtr, i0);

+    return ptr;

+  }

+  SplitBlock(p, oldPtr, i0, i1);

+  return oldPtr;

+}

+

+#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))

+

+static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)

+{

+  (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);

+  (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);

+}

+

+static void RestartModel(CPpmd7 *p)

+{

+  unsigned i, k, m;

+

+  memset(p->FreeList, 0, sizeof(p->FreeList));

+  p->Text = p->Base + p->AlignOffset;

+  p->HiUnit = p->Text + p->Size;

+  p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;

+  p->GlueCount = 0;

+

+  p->OrderFall = p->MaxOrder;

+  p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;

+  p->PrevSuccess = 0;

+

+  p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */

+  p->MinContext->Suffix = 0;

+  p->MinContext->NumStats = 256;

+  p->MinContext->SummFreq = 256 + 1;

+  p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */

+  p->LoUnit += U2B(256 / 2);

+  p->MinContext->Stats = REF(p->FoundState);

+  for (i = 0; i < 256; i++)

+  {

+    CPpmd_State *s = &p->FoundState[i];

+    s->Symbol = (Byte)i;

+    s->Freq = 1;

+    SetSuccessor(s, 0);

+  }

+

+  for (i = 0; i < 128; i++)

+    for (k = 0; k < 8; k++)

+    {

+      UInt16 *dest = p->BinSumm[i] + k;

+      UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));

+      for (m = 0; m < 64; m += 8)

+        dest[m] = val;

+    }

+  

+  for (i = 0; i < 25; i++)

+    for (k = 0; k < 16; k++)

+    {

+      CPpmd_See *s = &p->See[i][k];

+      s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));

+      s->Count = 4;

+    }

+}

+

+void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)

+{

+  p->MaxOrder = maxOrder;

+  RestartModel(p);

+  p->DummySee.Shift = PPMD_PERIOD_BITS;

+  p->DummySee.Summ = 0; /* unused */

+  p->DummySee.Count = 64; /* unused */

+}

+

+static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)

+{

+  CPpmd_State upState;

+  CTX_PTR c = p->MinContext;

+  CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);

+  CPpmd_State *ps[PPMD7_MAX_ORDER];

+  unsigned numPs = 0;

+  

+  if (!skip)

+    ps[numPs++] = p->FoundState;

+  

+  while (c->Suffix)

+  {

+    CPpmd_Void_Ref successor;

+    CPpmd_State *s;

+    c = SUFFIX(c);

+    if (c->NumStats != 1)

+    {

+      for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);

+    }

+    else

+      s = ONE_STATE(c);

+    successor = SUCCESSOR(s);

+    if (successor != upBranch)

+    {

+      c = CTX(successor);

+      if (numPs == 0)

+        return c;

+      break;

+    }

+    ps[numPs++] = s;

+  }

+  

+  upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);

+  SetSuccessor(&upState, upBranch + 1);

+  

+  if (c->NumStats == 1)

+    upState.Freq = ONE_STATE(c)->Freq;

+  else

+  {

+    UInt32 cf, s0;

+    CPpmd_State *s;

+    for (s = STATS(c); s->Symbol != upState.Symbol; s++);

+    cf = s->Freq - 1;

+    s0 = c->SummFreq - c->NumStats - cf;

+    upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));

+  }

+

+  do

+  {

+    /* Create Child */

+    CTX_PTR c1; /* = AllocContext(p); */

+    if (p->HiUnit != p->LoUnit)

+      c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);

+    else if (p->FreeList[0] != 0)

+      c1 = (CTX_PTR)RemoveNode(p, 0);

+    else

+    {

+      c1 = (CTX_PTR)AllocUnitsRare(p, 0);

+      if (!c1)

+        return NULL;

+    }

+    c1->NumStats = 1;

+    *ONE_STATE(c1) = upState;

+    c1->Suffix = REF(c);

+    SetSuccessor(ps[--numPs], REF(c1));

+    c = c1;

+  }

+  while (numPs != 0);

+  

+  return c;

+}

+

+static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)

+{

+  CPpmd_State tmp = *t1;

+  *t1 = *t2;

+  *t2 = tmp;

+}

+

+static void UpdateModel(CPpmd7 *p)

+{

+  CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);

+  CTX_PTR c;

+  unsigned s0, ns;

+  

+  if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)

+  {

+    c = SUFFIX(p->MinContext);

+    

+    if (c->NumStats == 1)

+    {

+      CPpmd_State *s = ONE_STATE(c);

+      if (s->Freq < 32)

+        s->Freq++;

+    }

+    else

+    {

+      CPpmd_State *s = STATS(c);

+      if (s->Symbol != p->FoundState->Symbol)

+      {

+        do { s++; } while (s->Symbol != p->FoundState->Symbol);

+        if (s[0].Freq >= s[-1].Freq)

+        {

+          SwapStates(&s[0], &s[-1]);

+          s--;

+        }

+      }

+      if (s->Freq < MAX_FREQ - 9)

+      {

+        s->Freq += 2;

+        c->SummFreq += 2;

+      }

+    }

+  }

+

+  if (p->OrderFall == 0)

+  {

+    p->MinContext = p->MaxContext = CreateSuccessors(p, True);

+    if (p->MinContext == 0)

+    {

+      RestartModel(p);

+      return;

+    }

+    SetSuccessor(p->FoundState, REF(p->MinContext));

+    return;

+  }

+  

+  *p->Text++ = p->FoundState->Symbol;

+  successor = REF(p->Text);

+  if (p->Text >= p->UnitsStart)

+  {

+    RestartModel(p);

+    return;

+  }

+  

+  if (fSuccessor)

+  {

+    if (fSuccessor <= successor)

+    {

+      CTX_PTR cs = CreateSuccessors(p, False);

+      if (cs == NULL)

+      {

+        RestartModel(p);

+        return;

+      }

+      fSuccessor = REF(cs);

+    }

+    if (--p->OrderFall == 0)

+    {

+      successor = fSuccessor;

+      p->Text -= (p->MaxContext != p->MinContext);

+    }

+  }

+  else

+  {

+    SetSuccessor(p->FoundState, successor);

+    fSuccessor = REF(p->MinContext);

+  }

+  

+  s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);

+  

+  for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))

+  {

+    unsigned ns1;

+    UInt32 cf, sf;

+    if ((ns1 = c->NumStats) != 1)

+    {

+      if ((ns1 & 1) == 0)

+      {

+        /* Expand for one UNIT */

+        unsigned oldNU = ns1 >> 1;

+        unsigned i = U2I(oldNU);

+        if (i != U2I(oldNU + 1))

+        {

+          void *ptr = AllocUnits(p, i + 1);

+          void *oldPtr;

+          if (!ptr)

+          {

+            RestartModel(p);

+            return;

+          }

+          oldPtr = STATS(c);

+          MyMem12Cpy(ptr, oldPtr, oldNU);

+          InsertNode(p, oldPtr, i);

+          c->Stats = STATS_REF(ptr);

+        }

+      }

+      c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));

+    }

+    else

+    {

+      CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);

+      if (!s)

+      {

+        RestartModel(p);

+        return;

+      }

+      *s = *ONE_STATE(c);

+      c->Stats = REF(s);

+      if (s->Freq < MAX_FREQ / 4 - 1)

+        s->Freq <<= 1;

+      else

+        s->Freq = MAX_FREQ - 4;

+      c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));

+    }

+    cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);

+    sf = (UInt32)s0 + c->SummFreq;

+    if (cf < 6 * sf)

+    {

+      cf = 1 + (cf > sf) + (cf >= 4 * sf);

+      c->SummFreq += 3;

+    }

+    else

+    {

+      cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);

+      c->SummFreq = (UInt16)(c->SummFreq + cf);

+    }

+    {

+      CPpmd_State *s = STATS(c) + ns1;

+      SetSuccessor(s, successor);

+      s->Symbol = p->FoundState->Symbol;

+      s->Freq = (Byte)cf;

+      c->NumStats = (UInt16)(ns1 + 1);

+    }

+  }

+  p->MaxContext = p->MinContext = CTX(fSuccessor);

+}

+  

+static void Rescale(CPpmd7 *p)

+{

+  unsigned i, adder, sumFreq, escFreq;

+  CPpmd_State *stats = STATS(p->MinContext);

+  CPpmd_State *s = p->FoundState;

+  {

+    CPpmd_State tmp = *s;

+    for (; s != stats; s--)

+      s[0] = s[-1];

+    *s = tmp;

+  }

+  escFreq = p->MinContext->SummFreq - s->Freq;

+  s->Freq += 4;

+  adder = (p->OrderFall != 0);

+  s->Freq = (Byte)((s->Freq + adder) >> 1);

+  sumFreq = s->Freq;

+  

+  i = p->MinContext->NumStats - 1;

+  do

+  {

+    escFreq -= (++s)->Freq;

+    s->Freq = (Byte)((s->Freq + adder) >> 1);

+    sumFreq += s->Freq;

+    if (s[0].Freq > s[-1].Freq)

+    {

+      CPpmd_State *s1 = s;

+      CPpmd_State tmp = *s1;

+      do

+        s1[0] = s1[-1];

+      while (--s1 != stats && tmp.Freq > s1[-1].Freq);

+      *s1 = tmp;

+    }

+  }

+  while (--i);

+  

+  if (s->Freq == 0)

+  {

+    unsigned numStats = p->MinContext->NumStats;

+    unsigned n0, n1;

+    do { i++; } while ((--s)->Freq == 0);

+    escFreq += i;

+    p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);

+    if (p->MinContext->NumStats == 1)

+    {

+      CPpmd_State tmp = *stats;

+      do

+      {

+        tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));

+        escFreq >>= 1;

+      }

+      while (escFreq > 1);

+      InsertNode(p, stats, U2I(((numStats + 1) >> 1)));

+      *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;

+      return;

+    }

+    n0 = (numStats + 1) >> 1;

+    n1 = (p->MinContext->NumStats + 1) >> 1;

+    if (n0 != n1)

+      p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));

+  }

+  p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));

+  p->FoundState = STATS(p->MinContext);

+}

+

+CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)

+{

+  CPpmd_See *see;

+  unsigned nonMasked = p->MinContext->NumStats - numMasked;

+  if (p->MinContext->NumStats != 256)

+  {

+    see = p->See[p->NS2Indx[nonMasked - 1]] +

+        (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +

+        2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +

+        4 * (numMasked > nonMasked) +

+        p->HiBitsFlag;

+    {

+      unsigned r = (see->Summ >> see->Shift);

+      see->Summ = (UInt16)(see->Summ - r);

+      *escFreq = r + (r == 0);

+    }

+  }

+  else

+  {

+    see = &p->DummySee;

+    *escFreq = 1;

+  }

+  return see;

+}

+

+static void NextContext(CPpmd7 *p)

+{

+  CTX_PTR c = CTX(SUCCESSOR(p->FoundState));

+  if (p->OrderFall == 0 && (Byte *)c > p->Text)

+    p->MinContext = p->MaxContext = c;

+  else

+    UpdateModel(p);

+}

+

+void Ppmd7_Update1(CPpmd7 *p)

+{

+  CPpmd_State *s = p->FoundState;

+  s->Freq += 4;

+  p->MinContext->SummFreq += 4;

+  if (s[0].Freq > s[-1].Freq)

+  {

+    SwapStates(&s[0], &s[-1]);

+    p->FoundState = --s;

+    if (s->Freq > MAX_FREQ)

+      Rescale(p);

+  }

+  NextContext(p);

+}

+

+void Ppmd7_Update1_0(CPpmd7 *p)

+{

+  p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);

+  p->RunLength += p->PrevSuccess;

+  p->MinContext->SummFreq += 4;

+  if ((p->FoundState->Freq += 4) > MAX_FREQ)

+    Rescale(p);

+  NextContext(p);

+}

+

+void Ppmd7_UpdateBin(CPpmd7 *p)

+{

+  p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));

+  p->PrevSuccess = 1;

+  p->RunLength++;

+  NextContext(p);

+}

+

+void Ppmd7_Update2(CPpmd7 *p)

+{

+  p->MinContext->SummFreq += 4;

+  if ((p->FoundState->Freq += 4) > MAX_FREQ)

+    Rescale(p);

+  p->RunLength = p->InitRL;

+  UpdateModel(p);

+}

diff --git a/C/Ppmd7.h b/C/Ppmd7.h
new file mode 100755
index 0000000..56e81eb
--- /dev/null
+++ b/C/Ppmd7.h
@@ -0,0 +1,140 @@
+/* Ppmd7.h -- PPMdH compression codec

+2010-03-12 : Igor Pavlov : Public domain

+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

+

+/* This code supports virtual RangeDecoder and includes the implementation

+of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.

+If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */

+

+#ifndef __PPMD7_H

+#define __PPMD7_H

+

+#include "Ppmd.h"

+

+EXTERN_C_BEGIN

+

+#define PPMD7_MIN_ORDER 2

+#define PPMD7_MAX_ORDER 64

+

+#define PPMD7_MIN_MEM_SIZE (1 << 11)

+#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)

+

+struct CPpmd7_Context_;

+

+typedef

+  #ifdef PPMD_32BIT

+    struct CPpmd7_Context_ *

+  #else

+    UInt32

+  #endif

+  CPpmd7_Context_Ref;

+

+typedef struct CPpmd7_Context_

+{

+  UInt16 NumStats;

+  UInt16 SummFreq;

+  CPpmd_State_Ref Stats;

+  CPpmd7_Context_Ref Suffix;

+} CPpmd7_Context;

+

+#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)

+

+typedef struct

+{

+  CPpmd7_Context *MinContext, *MaxContext;

+  CPpmd_State *FoundState;

+  unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;

+  Int32 RunLength, InitRL; /* must be 32-bit at least */

+

+  UInt32 Size;

+  UInt32 GlueCount;

+  Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;

+  UInt32 AlignOffset;

+

+  Byte Indx2Units[PPMD_NUM_INDEXES];

+  Byte Units2Indx[128];

+  CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];

+  Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];

+  CPpmd_See DummySee, See[25][16];

+  UInt16 BinSumm[128][64];

+} CPpmd7;

+

+void Ppmd7_Construct(CPpmd7 *p);

+Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);

+void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc);

+void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);

+#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)

+

+

+/* ---------- Internal Functions ---------- */

+

+extern const Byte PPMD7_kExpEscape[16];

+

+#ifdef PPMD_32BIT

+  #define Ppmd7_GetPtr(p, ptr) (ptr)

+  #define Ppmd7_GetContext(p, ptr) (ptr)

+  #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)

+#else

+  #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))

+  #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))

+  #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))

+#endif

+

+void Ppmd7_Update1(CPpmd7 *p);

+void Ppmd7_Update1_0(CPpmd7 *p);

+void Ppmd7_Update2(CPpmd7 *p);

+void Ppmd7_UpdateBin(CPpmd7 *p);

+

+#define Ppmd7_GetBinSumm(p) \

+    &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \

+    p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \

+    (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \

+    2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \

+    ((p->RunLength >> 26) & 0x20)]

+

+CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);

+

+

+/* ---------- Decode ---------- */

+

+typedef struct

+{

+  UInt32 (*GetThreshold)(void *p, UInt32 total);

+  void (*Decode)(void *p, UInt32 start, UInt32 size);

+  UInt32 (*DecodeBit)(void *p, UInt32 size0);

+} IPpmd7_RangeDec;

+

+typedef struct

+{

+  IPpmd7_RangeDec p;

+  UInt32 Range;

+  UInt32 Code;

+  IByteIn *Stream;

+} CPpmd7z_RangeDec;

+

+void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);

+Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);

+#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)

+

+int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc);

+

+

+/* ---------- Encode ---------- */

+

+typedef struct

+{

+  UInt64 Low;

+  UInt32 Range;

+  Byte Cache;

+  UInt64 CacheSize;

+  IByteOut *Stream;

+} CPpmd7z_RangeEnc;

+

+void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p);

+void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p);

+

+void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);

+

+EXTERN_C_END

+ 

+#endif

diff --git a/C/Ppmd7Dec.c b/C/Ppmd7Dec.c
new file mode 100755
index 0000000..d6608e8
--- /dev/null
+++ b/C/Ppmd7Dec.c
@@ -0,0 +1,187 @@
+/* Ppmd7Dec.c -- PPMdH Decoder

+2010-03-12 : Igor Pavlov : Public domain

+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

+

+#include "Ppmd7.h"

+

+#define kTopValue (1 << 24)

+

+Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)

+{

+  unsigned i;

+  p->Code = 0;

+  p->Range = 0xFFFFFFFF;

+  if (p->Stream->Read((void *)p->Stream) != 0)

+    return False;

+  for (i = 0; i < 4; i++)

+    p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);

+  return (p->Code < 0xFFFFFFFF);

+}

+

+static UInt32 Range_GetThreshold(void *pp, UInt32 total)

+{

+  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;

+  return (p->Code) / (p->Range /= total);

+}

+

+static void Range_Normalize(CPpmd7z_RangeDec *p)

+{

+  if (p->Range < kTopValue)

+  {

+    p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);

+    p->Range <<= 8;

+    if (p->Range < kTopValue)

+    {

+      p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);

+      p->Range <<= 8;

+    }

+  }

+}

+

+static void Range_Decode(void *pp, UInt32 start, UInt32 size)

+{

+  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;

+  p->Code -= start * p->Range;

+  p->Range *= size;

+  Range_Normalize(p);

+}

+

+static UInt32 Range_DecodeBit(void *pp, UInt32 size0)

+{

+  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;

+  UInt32 newBound = (p->Range >> 14) * size0;

+  UInt32 symbol;

+  if (p->Code < newBound)

+  {

+    symbol = 0;

+    p->Range = newBound;

+  }

+  else

+  {

+    symbol = 1;

+    p->Code -= newBound;

+    p->Range -= newBound;

+  }

+  Range_Normalize(p);

+  return symbol;

+}

+

+void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)

+{

+  p->p.GetThreshold = Range_GetThreshold;

+  p->p.Decode = Range_Decode;

+  p->p.DecodeBit = Range_DecodeBit;

+}

+

+

+#define MASK(sym) ((signed char *)charMask)[sym]

+

+int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)

+{

+  size_t charMask[256 / sizeof(size_t)];

+  if (p->MinContext->NumStats != 1)

+  {

+    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);

+    unsigned i;

+    UInt32 count, hiCnt;

+    if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))

+    {

+      Byte symbol;

+      rc->Decode(rc, 0, s->Freq);

+      p->FoundState = s;

+      symbol = s->Symbol;

+      Ppmd7_Update1_0(p);

+      return symbol;

+    }

+    p->PrevSuccess = 0;

+    i = p->MinContext->NumStats - 1;

+    do

+    {

+      if ((hiCnt += (++s)->Freq) > count)

+      {

+        Byte symbol;

+        rc->Decode(rc, hiCnt - s->Freq, s->Freq);

+        p->FoundState = s;

+        symbol = s->Symbol;

+        Ppmd7_Update1(p);

+        return symbol;

+      }

+    }

+    while (--i);

+    if (count >= p->MinContext->SummFreq)

+      return -2;

+    p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];

+    rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);

+    PPMD_SetAllBitsIn256Bytes(charMask);

+    MASK(s->Symbol) = 0;

+    i = p->MinContext->NumStats - 1;

+    do { MASK((--s)->Symbol) = 0; } while (--i);

+  }

+  else

+  {

+    UInt16 *prob = Ppmd7_GetBinSumm(p);

+    if (rc->DecodeBit(rc, *prob) == 0)

+    {

+      Byte symbol;

+      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);

+      symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;

+      Ppmd7_UpdateBin(p);

+      return symbol;

+    }

+    *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);

+    p->InitEsc = PPMD7_kExpEscape[*prob >> 10];

+    PPMD_SetAllBitsIn256Bytes(charMask);

+    MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;

+    p->PrevSuccess = 0;

+  }

+  for (;;)

+  {

+    CPpmd_State *ps[256], *s;

+    UInt32 freqSum, count, hiCnt;

+    CPpmd_See *see;

+    unsigned i, num, numMasked = p->MinContext->NumStats;

+    do

+    {

+      p->OrderFall++;

+      if (!p->MinContext->Suffix)

+        return -1;

+      p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);

+    }

+    while (p->MinContext->NumStats == numMasked);

+    hiCnt = 0;

+    s = Ppmd7_GetStats(p, p->MinContext);

+    i = 0;

+    num = p->MinContext->NumStats - numMasked;

+    do

+    {

+      int k = (int)(MASK(s->Symbol));

+      hiCnt += (s->Freq & k);

+      ps[i] = s++;

+      i -= k;

+    }

+    while (i != num);

+    

+    see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);

+    freqSum += hiCnt;

+    count = rc->GetThreshold(rc, freqSum);

+    

+    if (count < hiCnt)

+    {

+      Byte symbol;

+      CPpmd_State **pps = ps;

+      for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);

+      s = *pps;

+      rc->Decode(rc, hiCnt - s->Freq, s->Freq);

+      Ppmd_See_Update(see);

+      p->FoundState = s;

+      symbol = s->Symbol;

+      Ppmd7_Update2(p);

+      return symbol;

+    }

+    if (count >= freqSum)

+      return -2;

+    rc->Decode(rc, hiCnt, freqSum - hiCnt);

+    see->Summ = (UInt16)(see->Summ + freqSum);

+    do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);

+  }

+}

diff --git a/C/Ppmd7Enc.c b/C/Ppmd7Enc.c
new file mode 100755
index 0000000..b1fecae
--- /dev/null
+++ b/C/Ppmd7Enc.c
@@ -0,0 +1,185 @@
+/* Ppmd7Enc.c -- PPMdH Encoder

+2010-03-12 : Igor Pavlov : Public domain

+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */

+

+#include "Ppmd7.h"

+

+#define kTopValue (1 << 24)

+

+void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)

+{

+  p->Low = 0;

+  p->Range = 0xFFFFFFFF;

+  p->Cache = 0;

+  p->CacheSize = 1;

+}

+

+static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)

+{

+  if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)

+  {

+    Byte temp = p->Cache;

+    do

+    {

+      p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));

+      temp = 0xFF;

+    }

+    while(--p->CacheSize != 0);

+    p->Cache = (Byte)((UInt32)p->Low >> 24);

+  }

+  p->CacheSize++;

+  p->Low = (UInt32)p->Low << 8;

+}

+

+static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)

+{

+  p->Low += start * (p->Range /= total);

+  p->Range *= size;

+  while (p->Range < kTopValue)

+  {

+    p->Range <<= 8;

+    RangeEnc_ShiftLow(p);

+  }

+}

+

+static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)

+{

+  p->Range = (p->Range >> 14) * size0;

+  while (p->Range < kTopValue)

+  {

+    p->Range <<= 8;

+    RangeEnc_ShiftLow(p);

+  }

+}

+

+static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)

+{

+  UInt32 newBound = (p->Range >> 14) * size0;

+  p->Low += newBound;

+  p->Range -= newBound;

+  while (p->Range < kTopValue)

+  {

+    p->Range <<= 8;

+    RangeEnc_ShiftLow(p);

+  }

+}

+

+void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)

+{

+  unsigned i;

+  for (i = 0; i < 5; i++)

+    RangeEnc_ShiftLow(p);

+}

+

+

+#define MASK(sym) ((signed char *)charMask)[sym]

+

+void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)

+{

+  size_t charMask[256 / sizeof(size_t)];

+  if (p->MinContext->NumStats != 1)

+  {

+    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);

+    UInt32 sum;

+    unsigned i;

+    if (s->Symbol == symbol)

+    {

+      RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);

+      p->FoundState = s;

+      Ppmd7_Update1_0(p);

+      return;

+    }

+    p->PrevSuccess = 0;

+    sum = s->Freq;

+    i = p->MinContext->NumStats - 1;

+    do

+    {

+      if ((++s)->Symbol == symbol)

+      {

+        RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);

+        p->FoundState = s;

+        Ppmd7_Update1(p);

+        return;

+      }

+      sum += s->Freq;

+    }

+    while (--i);

+    

+    p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];

+    PPMD_SetAllBitsIn256Bytes(charMask);

+    MASK(s->Symbol) = 0;

+    i = p->MinContext->NumStats - 1;

+    do { MASK((--s)->Symbol) = 0; } while (--i);

+    RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);

+  }

+  else

+  {

+    UInt16 *prob = Ppmd7_GetBinSumm(p);

+    CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);

+    if (s->Symbol == symbol)

+    {

+      RangeEnc_EncodeBit_0(rc, *prob);

+      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);

+      p->FoundState = s;

+      Ppmd7_UpdateBin(p);

+      return;

+    }

+    else

+    {

+      RangeEnc_EncodeBit_1(rc, *prob);

+      *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);

+      p->InitEsc = PPMD7_kExpEscape[*prob >> 10];

+      PPMD_SetAllBitsIn256Bytes(charMask);

+      MASK(s->Symbol) = 0;

+      p->PrevSuccess = 0;

+    }

+  }

+  for (;;)

+  {

+    UInt32 escFreq;

+    CPpmd_See *see;

+    CPpmd_State *s;

+    UInt32 sum;

+    unsigned i, numMasked = p->MinContext->NumStats;

+    do

+    {

+      p->OrderFall++;

+      if (!p->MinContext->Suffix)

+        return; /* EndMarker (symbol = -1) */

+      p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);

+    }

+    while (p->MinContext->NumStats == numMasked);

+    

+    see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);

+    s = Ppmd7_GetStats(p, p->MinContext);

+    sum = 0;

+    i = p->MinContext->NumStats;

+    do

+    {

+      int cur = s->Symbol;

+      if (cur == symbol)

+      {

+        UInt32 low = sum;

+        CPpmd_State *s1 = s;

+        do

+        {

+          sum += (s->Freq & (int)(MASK(s->Symbol)));

+          s++;

+        }

+        while (--i);

+        RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);

+        Ppmd_See_Update(see);

+        p->FoundState = s1;

+        Ppmd7_Update2(p);

+        return;

+      }

+      sum += (s->Freq & (int)(MASK(cur)));

+      MASK(cur) = 0;

+      s++;

+    }

+    while (--i);

+    

+    RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);

+    see->Summ = (UInt16)(see->Summ + sum + escFreq);

+  }

+}

diff --git a/C/RotateDefs.h b/C/RotateDefs.h
new file mode 100755
index 0000000..ff9b722
--- /dev/null
+++ b/C/RotateDefs.h
@@ -0,0 +1,20 @@
+/* RotateDefs.h -- Rotate functions

+2009-02-07 : Igor Pavlov : Public domain */

+

+#ifndef __ROTATE_DEFS_H

+#define __ROTATE_DEFS_H

+

+#ifdef _MSC_VER

+

+#include <stdlib.h>

+#define rotlFixed(x, n) _rotl((x), (n))

+#define rotrFixed(x, n) _rotr((x), (n))

+

+#else

+

+#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))

+#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))

+

+#endif

+

+#endif

diff --git a/C/Sha256.c b/C/Sha256.c
new file mode 100755
index 0000000..cfb9eac
--- /dev/null
+++ b/C/Sha256.c
@@ -0,0 +1,204 @@
+/* Crypto/Sha256.c -- SHA-256 Hash

+2010-06-11 : Igor Pavlov : Public domain

+This code is based on public domain code from Wei Dai's Crypto++ library. */

+

+#include "RotateDefs.h"

+#include "Sha256.h"

+

+/* define it for speed optimization */

+/* #define _SHA256_UNROLL */

+/* #define _SHA256_UNROLL2 */

+

+void Sha256_Init(CSha256 *p)

+{

+  p->state[0] = 0x6a09e667;

+  p->state[1] = 0xbb67ae85;

+  p->state[2] = 0x3c6ef372;

+  p->state[3] = 0xa54ff53a;

+  p->state[4] = 0x510e527f;

+  p->state[5] = 0x9b05688c;

+  p->state[6] = 0x1f83d9ab;

+  p->state[7] = 0x5be0cd19;

+  p->count = 0;

+}

+

+#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22))

+#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25))

+#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3))

+#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10))

+

+#define blk0(i) (W[i] = data[i])

+#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15]))

+

+#define Ch(x,y,z) (z^(x&(y^z)))

+#define Maj(x,y,z) ((x&y)|(z&(x|y)))

+

+#define a(i) T[(0-(i))&7]

+#define b(i) T[(1-(i))&7]

+#define c(i) T[(2-(i))&7]

+#define d(i) T[(3-(i))&7]

+#define e(i) T[(4-(i))&7]

+#define f(i) T[(5-(i))&7]

+#define g(i) T[(6-(i))&7]

+#define h(i) T[(7-(i))&7]

+

+

+#ifdef _SHA256_UNROLL2

+

+#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\

+  d += h; h += S0(a) + Maj(a, b, c)

+

+#define RX_8(i) \

+  R(a,b,c,d,e,f,g,h, i); \

+  R(h,a,b,c,d,e,f,g, i+1); \

+  R(g,h,a,b,c,d,e,f, i+2); \

+  R(f,g,h,a,b,c,d,e, i+3); \

+  R(e,f,g,h,a,b,c,d, i+4); \

+  R(d,e,f,g,h,a,b,c, i+5); \

+  R(c,d,e,f,g,h,a,b, i+6); \

+  R(b,c,d,e,f,g,h,a, i+7)

+

+#else

+

+#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\

+  d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))

+

+#ifdef _SHA256_UNROLL

+

+#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);

+

+#endif

+

+#endif

+

+static const UInt32 K[64] = {

+  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,

+  0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,

+  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,

+  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,

+  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,

+  0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,

+  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,

+  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,

+  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,

+  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,

+  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,

+  0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,

+  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,

+  0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,

+  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,

+  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2

+};

+

+static void Sha256_Transform(UInt32 *state, const UInt32 *data)

+{

+  UInt32 W[16];

+  unsigned j;

+  #ifdef _SHA256_UNROLL2

+  UInt32 a,b,c,d,e,f,g,h;

+  a = state[0];

+  b = state[1];

+  c = state[2];

+  d = state[3];

+  e = state[4];

+  f = state[5];

+  g = state[6];

+  h = state[7];

+  #else

+  UInt32 T[8];

+  for (j = 0; j < 8; j++)

+    T[j] = state[j];

+  #endif

+

+  for (j = 0; j < 64; j += 16)

+  {

+    #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2)

+    RX_8(0); RX_8(8);

+    #else

+    unsigned i;

+    for (i = 0; i < 16; i++) { R(i); }

+    #endif

+  }

+

+  #ifdef _SHA256_UNROLL2

+  state[0] += a;

+  state[1] += b;

+  state[2] += c;

+  state[3] += d;

+  state[4] += e;

+  state[5] += f;

+  state[6] += g;

+  state[7] += h;

+  #else

+  for (j = 0; j < 8; j++)

+    state[j] += T[j];

+  #endif

+  

+  /* Wipe variables */

+  /* memset(W, 0, sizeof(W)); */

+  /* memset(T, 0, sizeof(T)); */

+}

+

+#undef S0

+#undef S1

+#undef s0

+#undef s1

+

+static void Sha256_WriteByteBlock(CSha256 *p)

+{

+  UInt32 data32[16];

+  unsigned i;

+  for (i = 0; i < 16; i++)

+    data32[i] =

+      ((UInt32)(p->buffer[i * 4    ]) << 24) +

+      ((UInt32)(p->buffer[i * 4 + 1]) << 16) +

+      ((UInt32)(p->buffer[i * 4 + 2]) <<  8) +

+      ((UInt32)(p->buffer[i * 4 + 3]));

+  Sha256_Transform(p->state, data32);

+}

+

+void Sha256_Update(CSha256 *p, const Byte *data, size_t size)

+{

+  UInt32 curBufferPos = (UInt32)p->count & 0x3F;

+  while (size > 0)

+  {

+    p->buffer[curBufferPos++] = *data++;

+    p->count++;

+    size--;

+    if (curBufferPos == 64)

+    {

+      curBufferPos = 0;

+      Sha256_WriteByteBlock(p);

+    }

+  }

+}

+

+void Sha256_Final(CSha256 *p, Byte *digest)

+{

+  UInt64 lenInBits = (p->count << 3);

+  UInt32 curBufferPos = (UInt32)p->count & 0x3F;

+  unsigned i;

+  p->buffer[curBufferPos++] = 0x80;

+  while (curBufferPos != (64 - 8))

+  {

+    curBufferPos &= 0x3F;

+    if (curBufferPos == 0)

+      Sha256_WriteByteBlock(p);

+    p->buffer[curBufferPos++] = 0;

+  }

+  for (i = 0; i < 8; i++)

+  {

+    p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56);

+    lenInBits <<= 8;

+  }

+  Sha256_WriteByteBlock(p);

+

+  for (i = 0; i < 8; i++)

+  {

+    *digest++ = (Byte)(p->state[i] >> 24);

+    *digest++ = (Byte)(p->state[i] >> 16);

+    *digest++ = (Byte)(p->state[i] >> 8);

+    *digest++ = (Byte)(p->state[i]);

+  }

+  Sha256_Init(p);

+}

diff --git a/C/Sha256.h b/C/Sha256.h
new file mode 100755
index 0000000..26d1e3a
--- /dev/null
+++ b/C/Sha256.h
@@ -0,0 +1,26 @@
+/* Sha256.h -- SHA-256 Hash

+2010-06-11 : Igor Pavlov : Public domain */

+

+#ifndef __CRYPTO_SHA256_H

+#define __CRYPTO_SHA256_H

+

+#include "Types.h"

+

+EXTERN_C_BEGIN

+

+#define SHA256_DIGEST_SIZE 32

+

+typedef struct

+{

+  UInt32 state[8];

+  UInt64 count;

+  Byte buffer[64];

+} CSha256;

+

+void Sha256_Init(CSha256 *p);

+void Sha256_Update(CSha256 *p, const Byte *data, size_t size);

+void Sha256_Final(CSha256 *p, Byte *digest);

+

+EXTERN_C_END

+

+#endif

diff --git a/C/Threads.c b/C/Threads.c
new file mode 100755
index 0000000..4be44fb
--- /dev/null
+++ b/C/Threads.c
@@ -0,0 +1,84 @@
+/* Threads.c -- multithreading library

+2009-09-20 : Igor Pavlov : Public domain */

+

+#ifndef _WIN32_WCE

+#include <process.h>

+#endif

+

+#include "Threads.h"

+

+static WRes GetError()

+{

+  DWORD res = GetLastError();

+  return (res) ? (WRes)(res) : 1;

+}

+

+WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }

+WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }

+

+WRes HandlePtr_Close(HANDLE *p)

+{

+  if (*p != NULL)

+    if (!CloseHandle(*p))

+      return GetError();

+  *p = NULL;

+  return 0;

+}

+

+WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }

+

+WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)

+{

+  unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */

+  *p =

+    #ifdef UNDER_CE

+    CreateThread(0, 0, func, param, 0, &threadId);

+    #else

+    (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);

+    #endif

+    /* maybe we must use errno here, but probably GetLastError() is also OK. */

+  return HandleToWRes(*p);

+}

+

+WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)

+{

+  *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);

+  return HandleToWRes(*p);

+}

+

+WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }

+WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }

+

+WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }

+WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }

+WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }

+WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }

+

+

+WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)

+{

+  *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);

+  return HandleToWRes(*p);

+}

+

+static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)

+  { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }

+WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)

+  { return Semaphore_Release(p, (LONG)num, NULL); }

+WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }

+

+WRes CriticalSection_Init(CCriticalSection *p)

+{

+  /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */

+  #ifdef _MSC_VER

+  __try

+  #endif

+  {

+    InitializeCriticalSection(p);

+    /* InitializeCriticalSectionAndSpinCount(p, 0); */

+  }

+  #ifdef _MSC_VER

+  __except (EXCEPTION_EXECUTE_HANDLER) { return 1; }

+  #endif

+  return 0;

+}

diff --git a/C/Threads.h b/C/Threads.h
new file mode 100755
index 0000000..6a7afa8
--- /dev/null
+++ b/C/Threads.h
@@ -0,0 +1,59 @@
+/* Threads.h -- multithreading library

+2009-03-27 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_THREADS_H

+#define __7Z_THREADS_H

+

+#include "Types.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+WRes HandlePtr_Close(HANDLE *h);

+WRes Handle_WaitObject(HANDLE h);

+

+typedef HANDLE CThread;

+#define Thread_Construct(p) *(p) = NULL

+#define Thread_WasCreated(p) (*(p) != NULL)

+#define Thread_Close(p) HandlePtr_Close(p)

+#define Thread_Wait(p) Handle_WaitObject(*(p))

+typedef unsigned THREAD_FUNC_RET_TYPE;

+#define THREAD_FUNC_CALL_TYPE MY_STD_CALL

+#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE

+typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);

+WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);

+

+typedef HANDLE CEvent;

+typedef CEvent CAutoResetEvent;

+typedef CEvent CManualResetEvent;

+#define Event_Construct(p) *(p) = NULL

+#define Event_IsCreated(p) (*(p) != NULL)

+#define Event_Close(p) HandlePtr_Close(p)

+#define Event_Wait(p) Handle_WaitObject(*(p))

+WRes Event_Set(CEvent *p);

+WRes Event_Reset(CEvent *p);

+WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);

+WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);

+WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);

+WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);

+

+typedef HANDLE CSemaphore;

+#define Semaphore_Construct(p) (*p) = NULL

+#define Semaphore_Close(p) HandlePtr_Close(p)

+#define Semaphore_Wait(p) Handle_WaitObject(*(p))

+WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);

+WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);

+WRes Semaphore_Release1(CSemaphore *p);

+

+typedef CRITICAL_SECTION CCriticalSection;

+WRes CriticalSection_Init(CCriticalSection *p);

+#define CriticalSection_Delete(p) DeleteCriticalSection(p)

+#define CriticalSection_Enter(p) EnterCriticalSection(p)

+#define CriticalSection_Leave(p) LeaveCriticalSection(p)

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/C/Types.h b/C/Types.h
new file mode 100755
index 0000000..f193ce2
--- /dev/null
+++ b/C/Types.h
@@ -0,0 +1,254 @@
+/* Types.h -- Basic types

+2010-10-09 : Igor Pavlov : Public domain */

+

+#ifndef __7Z_TYPES_H

+#define __7Z_TYPES_H

+

+#include <stddef.h>

+

+#ifdef _WIN32

+#include <windows.h>

+#endif

+

+#ifndef EXTERN_C_BEGIN

+#ifdef __cplusplus

+#define EXTERN_C_BEGIN extern "C" {

+#define EXTERN_C_END }

+#else

+#define EXTERN_C_BEGIN

+#define EXTERN_C_END

+#endif

+#endif

+

+EXTERN_C_BEGIN

+

+#define SZ_OK 0

+

+#define SZ_ERROR_DATA 1

+#define SZ_ERROR_MEM 2

+#define SZ_ERROR_CRC 3

+#define SZ_ERROR_UNSUPPORTED 4

+#define SZ_ERROR_PARAM 5

+#define SZ_ERROR_INPUT_EOF 6

+#define SZ_ERROR_OUTPUT_EOF 7

+#define SZ_ERROR_READ 8

+#define SZ_ERROR_WRITE 9

+#define SZ_ERROR_PROGRESS 10

+#define SZ_ERROR_FAIL 11

+#define SZ_ERROR_THREAD 12

+

+#define SZ_ERROR_ARCHIVE 16

+#define SZ_ERROR_NO_ARCHIVE 17

+

+typedef int SRes;

+

+#ifdef _WIN32

+typedef DWORD WRes;

+#else

+typedef int WRes;

+#endif

+

+#ifndef RINOK

+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }

+#endif

+

+typedef unsigned char Byte;

+typedef short Int16;

+typedef unsigned short UInt16;

+

+#ifdef _LZMA_UINT32_IS_ULONG

+typedef long Int32;

+typedef unsigned long UInt32;

+#else

+typedef int Int32;

+typedef unsigned int UInt32;

+#endif

+

+#ifdef _SZ_NO_INT_64

+

+/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.

+   NOTES: Some code will work incorrectly in that case! */

+

+typedef long Int64;

+typedef unsigned long UInt64;

+

+#else

+

+#if defined(_MSC_VER) || defined(__BORLANDC__)

+typedef __int64 Int64;

+typedef unsigned __int64 UInt64;

+#define UINT64_CONST(n) n

+#else

+typedef long long int Int64;

+typedef unsigned long long int UInt64;

+#define UINT64_CONST(n) n ## ULL

+#endif

+

+#endif

+

+#ifdef _LZMA_NO_SYSTEM_SIZE_T

+typedef UInt32 SizeT;

+#else

+typedef size_t SizeT;

+#endif

+

+typedef int Bool;

+#define True 1

+#define False 0

+

+

+#ifdef _WIN32

+#define MY_STD_CALL __stdcall

+#else

+#define MY_STD_CALL

+#endif

+

+#ifdef _MSC_VER

+

+#if _MSC_VER >= 1300

+#define MY_NO_INLINE __declspec(noinline)

+#else

+#define MY_NO_INLINE

+#endif

+

+#define MY_CDECL __cdecl

+#define MY_FAST_CALL __fastcall

+

+#else

+

+#define MY_CDECL

+#define MY_FAST_CALL

+

+#endif

+

+

+/* The following interfaces use first parameter as pointer to structure */

+

+typedef struct

+{

+  Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */

+} IByteIn;

+

+typedef struct

+{

+  void (*Write)(void *p, Byte b);

+} IByteOut;

+

+typedef struct

+{

+  SRes (*Read)(void *p, void *buf, size_t *size);

+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.

+       (output(*size) < input(*size)) is allowed */

+} ISeqInStream;

+

+/* it can return SZ_ERROR_INPUT_EOF */

+SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);

+SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);

+SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);

+

+typedef struct

+{

+  size_t (*Write)(void *p, const void *buf, size_t size);

+    /* Returns: result - the number of actually written bytes.

+       (result < size) means error */

+} ISeqOutStream;

+

+typedef enum

+{

+  SZ_SEEK_SET = 0,

+  SZ_SEEK_CUR = 1,

+  SZ_SEEK_END = 2

+} ESzSeek;

+

+typedef struct

+{

+  SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */

+  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);

+} ISeekInStream;

+

+typedef struct

+{

+  SRes (*Look)(void *p, const void **buf, size_t *size);

+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.

+       (output(*size) > input(*size)) is not allowed

+       (output(*size) < input(*size)) is allowed */

+  SRes (*Skip)(void *p, size_t offset);

+    /* offset must be <= output(*size) of Look */

+

+  SRes (*Read)(void *p, void *buf, size_t *size);

+    /* reads directly (without buffer). It's same as ISeqInStream::Read */

+  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);

+} ILookInStream;

+

+SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);

+SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);

+

+/* reads via ILookInStream::Read */

+SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);

+SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);

+

+#define LookToRead_BUF_SIZE (1 << 14)

+

+typedef struct

+{

+  ILookInStream s;

+  ISeekInStream *realStream;

+  size_t pos;

+  size_t size;

+  Byte buf[LookToRead_BUF_SIZE];

+} CLookToRead;

+

+void LookToRead_CreateVTable(CLookToRead *p, int lookahead);

+void LookToRead_Init(CLookToRead *p);

+

+typedef struct

+{

+  ISeqInStream s;

+  ILookInStream *realStream;

+} CSecToLook;

+

+void SecToLook_CreateVTable(CSecToLook *p);

+

+typedef struct

+{

+  ISeqInStream s;

+  ILookInStream *realStream;

+} CSecToRead;

+

+void SecToRead_CreateVTable(CSecToRead *p);

+

+typedef struct

+{

+  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);

+    /* Returns: result. (result != SZ_OK) means break.

+       Value (UInt64)(Int64)-1 for size means unknown value. */

+} ICompressProgress;

+

+typedef struct

+{

+  void *(*Alloc)(void *p, size_t size);

+  void (*Free)(void *p, void *address); /* address can be 0 */

+} ISzAlloc;

+

+#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)

+#define IAlloc_Free(p, a) (p)->Free((p), a)

+

+#ifdef _WIN32

+

+#define CHAR_PATH_SEPARATOR '\\'

+#define WCHAR_PATH_SEPARATOR L'\\'

+#define STRING_PATH_SEPARATOR "\\"

+#define WSTRING_PATH_SEPARATOR L"\\"

+

+#else

+

+#define CHAR_PATH_SEPARATOR '/'

+#define WCHAR_PATH_SEPARATOR L'/'

+#define STRING_PATH_SEPARATOR "/"

+#define WSTRING_PATH_SEPARATOR L"/"

+

+#endif

+

+EXTERN_C_END

+

+#endif

diff --git a/C/Util/7z/7z.dsp b/C/Util/7z/7z.dsp
new file mode 100755
index 0000000..9f5806b
--- /dev/null
+++ b/C/Util/7z/7z.dsp
@@ -0,0 +1,214 @@
+# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Console Application" 0x0103

+

+CFG=7z - Win32 Debug

+!MESSAGE This is not a valid makefile. To build this project using NMAKE,

+!MESSAGE use the Export Makefile command and run

+!MESSAGE 

+!MESSAGE NMAKE /f "7z.mak".

+!MESSAGE 

+!MESSAGE You can specify a configuration when running NMAKE

+!MESSAGE by defining the macro CFG on the command line. For example:

+!MESSAGE 

+!MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application")

+!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""

+# PROP Scc_LocalPath ""

+CPP=cl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "7z - Win32 Release"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "Release"

+# PROP BASE Intermediate_Dir "Release"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "Release"

+# PROP Intermediate_Dir "Release"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c

+# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /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" /opt:NOWIN98

+# SUBTRACT LINK32 /pdb:none

+

+!ELSEIF  "$(CFG)" == "7z - Win32 Debug"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir "Debug"

+# PROP BASE Intermediate_Dir "Debug"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir "Debug"

+# PROP Intermediate_Dir "Debug"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c

+# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /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 - Win32 Release"

+# Name "7z - Win32 Debug"

+# Begin Group "Common"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=..\..\7z.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zAlloc.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zAlloc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zBuf.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zBuf.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zCrc.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zCrc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zCrcOpt.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zDec.c

+# ADD CPP /D "_7ZIP_PPMD_SUPPPORT"

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zFile.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zFile.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zIn.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zStream.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Bcj2.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Bcj2.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Bra.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Bra.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Bra86.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\CpuArch.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\CpuArch.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Lzma2Dec.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Lzma2Dec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaDec.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaDec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Ppmd.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Ppmd7.c

+# SUBTRACT CPP /YX

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Ppmd7.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Ppmd7Dec.c

+# SUBTRACT CPP /YX

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Types.h

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=.\7zMain.c

+# End Source File

+# End Target

+# End Project

diff --git a/C/Util/7z/7z.dsw b/C/Util/7z/7z.dsw
new file mode 100755
index 0000000..23089fb
--- /dev/null
+++ b/C/Util/7z/7z.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"=.\7z.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c
new file mode 100755
index 0000000..f217340
--- /dev/null
+++ b/C/Util/7z/7zMain.c
@@ -0,0 +1,501 @@
+/* 7zMain.c - Test application for 7z Decoder

+2010-10-28 : Igor Pavlov : Public domain */

+

+#include <stdio.h>

+#include <string.h>

+

+#include "../../7z.h"

+#include "../../7zAlloc.h"

+#include "../../7zCrc.h"

+#include "../../7zFile.h"

+#include "../../7zVersion.h"

+

+#ifndef USE_WINDOWS_FILE

+/* for mkdir */

+#ifdef _WIN32

+#include <direct.h>

+#else

+#include <sys/stat.h>

+#include <errno.h>

+#endif

+#endif

+

+static ISzAlloc g_Alloc = { SzAlloc, SzFree };

+

+static int Buf_EnsureSize(CBuf *dest, size_t size)

+{

+  if (dest->size >= size)

+    return 1;

+  Buf_Free(dest, &g_Alloc);

+  return Buf_Create(dest, size, &g_Alloc);

+}

+

+#ifndef _WIN32

+

+static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };

+

+static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen)

+{

+  size_t destPos = 0, srcPos = 0;

+  for (;;)

+  {

+    unsigned numAdds;

+    UInt32 value;

+    if (srcPos == srcLen)

+    {

+      *destLen = destPos;

+      return True;

+    }

+    value = src[srcPos++];

+    if (value < 0x80)

+    {

+      if (dest)

+        dest[destPos] = (char)value;

+      destPos++;

+      continue;

+    }

+    if (value >= 0xD800 && value < 0xE000)

+    {

+      UInt32 c2;

+      if (value >= 0xDC00 || srcPos == srcLen)

+        break;

+      c2 = src[srcPos++];

+      if (c2 < 0xDC00 || c2 >= 0xE000)

+        break;

+      value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;

+    }

+    for (numAdds = 1; numAdds < 5; numAdds++)

+      if (value < (((UInt32)1) << (numAdds * 5 + 6)))

+        break;

+    if (dest)

+      dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));

+    destPos++;

+    do

+    {

+      numAdds--;

+      if (dest)

+        dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));

+      destPos++;

+    }

+    while (numAdds != 0);

+  }

+  *destLen = destPos;

+  return False;

+}

+

+static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)

+{

+  size_t destLen = 0;

+  Bool res;

+  Utf16_To_Utf8(NULL, &destLen, src, srcLen);

+  destLen += 1;

+  if (!Buf_EnsureSize(dest, destLen))

+    return SZ_ERROR_MEM;

+  res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen);

+  dest->data[destLen] = 0;

+  return res ? SZ_OK : SZ_ERROR_FAIL;

+}

+#endif

+

+static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s, int fileMode)

+{

+  int len = 0;

+  for (len = 0; s[len] != '\0'; len++);

+

+  #ifdef _WIN32

+  {

+    int size = len * 3 + 100;

+    if (!Buf_EnsureSize(buf, size))

+      return SZ_ERROR_MEM;

+    {

+      char defaultChar = '_';

+      BOOL defUsed;

+      int numChars = WideCharToMultiByte(fileMode ?

+          (

+          #ifdef UNDER_CE

+          CP_ACP

+          #else

+          AreFileApisANSI() ? CP_ACP : CP_OEMCP

+          #endif

+          ) : CP_OEMCP,

+          0, s, len, (char *)buf->data, size, &defaultChar, &defUsed);

+      if (numChars == 0 || numChars >= size)

+        return SZ_ERROR_FAIL;

+      buf->data[numChars] = 0;

+      return SZ_OK;

+    }

+  }

+  #else

+  fileMode = fileMode;

+  return Utf16_To_Utf8Buf(buf, s, len);

+  #endif

+}

+

+static WRes MyCreateDir(const UInt16 *name)

+{

+  #ifdef USE_WINDOWS_FILE

+  

+  return CreateDirectoryW(name, NULL) ? 0 : GetLastError();

+  

+  #else

+

+  CBuf buf;

+  WRes res;

+  Buf_Init(&buf);

+  RINOK(Utf16_To_Char(&buf, name, 1));

+

+  res =

+  #ifdef _WIN32

+  _mkdir((const char *)buf.data)

+  #else

+  mkdir((const char *)buf.data, 0777)

+  #endif

+  == 0 ? 0 : errno;

+  Buf_Free(&buf, &g_Alloc);

+  return res;

+  

+  #endif

+}

+

+static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name)

+{

+  #ifdef USE_WINDOWS_FILE

+  return OutFile_OpenW(p, name);

+  #else

+  CBuf buf;

+  WRes res;

+  Buf_Init(&buf);

+  RINOK(Utf16_To_Char(&buf, name, 1));

+  res = OutFile_Open(p, (const char *)buf.data);

+  Buf_Free(&buf, &g_Alloc);

+  return res;

+  #endif

+}

+

+static SRes PrintString(const UInt16 *s)

+{

+  CBuf buf;

+  SRes res;

+  Buf_Init(&buf);

+  res = Utf16_To_Char(&buf, s, 0);

+  if (res == SZ_OK)

+    fputs((const char *)buf.data, stdout);

+  Buf_Free(&buf, &g_Alloc);

+  return res;

+}

+

+static void UInt64ToStr(UInt64 value, char *s)

+{

+  char temp[32];

+  int pos = 0;

+  do

+  {

+    temp[pos++] = (char)('0' + (unsigned)(value % 10));

+    value /= 10;

+  }

+  while (value != 0);

+  do

+    *s++ = temp[--pos];

+  while (pos);

+  *s = '\0';

+}

+

+static char *UIntToStr(char *s, unsigned value, int numDigits)

+{

+  char temp[16];

+  int pos = 0;

+  do

+    temp[pos++] = (char)('0' + (value % 10));

+  while (value /= 10);

+  for (numDigits -= pos; numDigits > 0; numDigits--)

+    *s++ = '0';

+  do

+    *s++ = temp[--pos];

+  while (pos);

+  *s = '\0';

+  return s;

+}

+

+#define PERIOD_4 (4 * 365 + 1)

+#define PERIOD_100 (PERIOD_4 * 25 - 1)

+#define PERIOD_400 (PERIOD_100 * 4 + 1)

+

+static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s)

+{

+  unsigned year, mon, day, hour, min, sec;

+  UInt64 v64 = (ft->Low | ((UInt64)ft->High << 32)) / 10000000;

+  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

+  unsigned t;

+  UInt32 v;

+  sec = (unsigned)(v64 % 60); v64 /= 60;

+  min = (unsigned)(v64 % 60); v64 /= 60;

+  hour = (unsigned)(v64 % 24); v64 /= 24;

+

+  v = (UInt32)v64;

+

+  year = (unsigned)(1601 + v / PERIOD_400 * 400);

+  v %= PERIOD_400;

+

+  t = v / PERIOD_100; if (t ==  4) t =  3; year += t * 100; v -= t * PERIOD_100;

+  t = v / PERIOD_4;   if (t == 25) t = 24; year += t * 4;   v -= t * PERIOD_4;

+  t = v / 365;        if (t ==  4) t =  3; year += t;       v -= t * 365;

+

+  if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))

+    ms[1] = 29;

+  for (mon = 1; mon <= 12; mon++)

+  {

+    unsigned s = ms[mon - 1];

+    if (v < s)

+      break;

+    v -= s;

+  }

+  day = (unsigned)v + 1;

+  s = UIntToStr(s, year, 4); *s++ = '-';

+  s = UIntToStr(s, mon, 2);  *s++ = '-';

+  s = UIntToStr(s, day, 2);  *s++ = ' ';

+  s = UIntToStr(s, hour, 2); *s++ = ':';

+  s = UIntToStr(s, min, 2);  *s++ = ':';

+  s = UIntToStr(s, sec, 2);

+}

+

+void PrintError(char *sz)

+{

+  printf("\nERROR: %s\n", sz);

+}

+

+#ifdef USE_WINDOWS_FILE

+#define kEmptyAttribChar '.'

+static void GetAttribString(UInt32 wa, Bool isDir, char *s)

+{

+  s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar);

+  s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar);

+  s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar);

+  s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar);

+  s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar);

+  s[5] = '\0';

+}

+#else

+static void GetAttribString(UInt32, Bool, char *s)

+{

+  s[0] = '\0';

+}

+#endif

+

+int MY_CDECL main(int numargs, char *args[])

+{

+  CFileInStream archiveStream;

+  CLookToRead lookStream;

+  CSzArEx db;

+  SRes res;

+  ISzAlloc allocImp;

+  ISzAlloc allocTempImp;

+  UInt16 *temp = NULL;

+  size_t tempSize = 0;

+

+  printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");

+  if (numargs == 1)

+  {

+    printf(

+      "Usage: 7zDec <command> <archive_name>\n\n"

+      "<Commands>\n"

+      "  e: Extract files from archive (without using directory names)\n"

+      "  l: List contents of archive\n"

+      "  t: Test integrity of archive\n"

+      "  x: eXtract files with full paths\n");

+    return 0;

+  }

+  if (numargs < 3)

+  {

+    PrintError("incorrect command");

+    return 1;

+  }

+

+  allocImp.Alloc = SzAlloc;

+  allocImp.Free = SzFree;

+

+  allocTempImp.Alloc = SzAllocTemp;

+  allocTempImp.Free = SzFreeTemp;

+

+  if (InFile_Open(&archiveStream.file, args[2]))

+  {

+    PrintError("can not open input file");

+    return 1;

+  }

+

+  FileInStream_CreateVTable(&archiveStream);

+  LookToRead_CreateVTable(&lookStream, False);

+  

+  lookStream.realStream = &archiveStream.s;

+  LookToRead_Init(&lookStream);

+

+  CrcGenerateTable();

+

+  SzArEx_Init(&db);

+  res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);

+  if (res == SZ_OK)

+  {

+    char *command = args[1];

+    int listCommand = 0, testCommand = 0, extractCommand = 0, fullPaths = 0;

+    if (strcmp(command, "l") == 0) listCommand = 1;

+    else if (strcmp(command, "t") == 0) testCommand = 1;

+    else if (strcmp(command, "e") == 0) extractCommand = 1;

+    else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; }

+    else

+    {

+      PrintError("incorrect command");

+      res = SZ_ERROR_FAIL;

+    }

+

+    if (res == SZ_OK)

+    {

+      UInt32 i;

+

+      /*

+      if you need cache, use these 3 variables.

+      if you use external function, you can make these variable as static.

+      */

+      UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */

+      Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */

+      size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */

+

+      for (i = 0; i < db.db.NumFiles; i++)

+      {

+        size_t offset = 0;

+        size_t outSizeProcessed = 0;

+        const CSzFileItem *f = db.db.Files + i;

+        size_t len;

+        if (listCommand == 0 && f->IsDir && !fullPaths)

+          continue;

+        len = SzArEx_GetFileNameUtf16(&db, i, NULL);

+

+        if (len > tempSize)

+        {

+          SzFree(NULL, temp);

+          tempSize = len;

+          temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));

+          if (temp == 0)

+          {

+            res = SZ_ERROR_MEM;

+            break;

+          }

+        }

+

+        SzArEx_GetFileNameUtf16(&db, i, temp);

+        if (listCommand)

+        {

+          char attr[8], s[32], t[32];

+

+          GetAttribString(f->AttribDefined ? f->Attrib : 0, f->IsDir, attr);

+

+          UInt64ToStr(f->Size, s);

+          if (f->MTimeDefined)

+            ConvertFileTimeToString(&f->MTime, t);

+          else

+          {

+            size_t j;

+            for (j = 0; j < 19; j++)

+              t[j] = ' ';

+            t[j] = '\0';

+          }

+          

+          printf("%s %s %10s  ", t, attr, s);

+          res = PrintString(temp);

+          if (res != SZ_OK)

+            break;

+          if (f->IsDir)

+            printf("/");

+          printf("\n");

+          continue;

+        }

+        fputs(testCommand ?

+            "Testing    ":

+            "Extracting ",

+            stdout);

+        res = PrintString(temp);

+        if (res != SZ_OK)

+          break;

+        if (f->IsDir)

+          printf("/");

+        else

+        {

+          res = SzArEx_Extract(&db, &lookStream.s, i,

+              &blockIndex, &outBuffer, &outBufferSize,

+              &offset, &outSizeProcessed,

+              &allocImp, &allocTempImp);

+          if (res != SZ_OK)

+            break;

+        }

+        if (!testCommand)

+        {

+          CSzFile outFile;

+          size_t processedSize;

+          size_t j;

+          UInt16 *name = (UInt16 *)temp;

+          const UInt16 *destPath = (const UInt16 *)name;

+          for (j = 0; name[j] != 0; j++)

+            if (name[j] == '/')

+            {

+              if (fullPaths)

+              {

+                name[j] = 0;

+                MyCreateDir(name);

+                name[j] = CHAR_PATH_SEPARATOR;

+              }

+              else

+                destPath = name + j + 1;

+            }

+    

+          if (f->IsDir)

+          {

+            MyCreateDir(destPath);

+            printf("\n");

+            continue;

+          }

+          else if (OutFile_OpenUtf16(&outFile, destPath))

+          {

+            PrintError("can not open output file");

+            res = SZ_ERROR_FAIL;

+            break;

+          }

+          processedSize = outSizeProcessed;

+          if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)

+          {

+            PrintError("can not write output file");

+            res = SZ_ERROR_FAIL;

+            break;

+          }

+          if (File_Close(&outFile))

+          {

+            PrintError("can not close output file");

+            res = SZ_ERROR_FAIL;

+            break;

+          }

+          #ifdef USE_WINDOWS_FILE

+          if (f->AttribDefined)

+            SetFileAttributesW(destPath, f->Attrib);

+          #endif

+        }

+        printf("\n");

+      }

+      IAlloc_Free(&allocImp, outBuffer);

+    }

+  }

+  SzArEx_Free(&db, &allocImp);

+  SzFree(NULL, temp);

+

+  File_Close(&archiveStream.file);

+  if (res == SZ_OK)

+  {

+    printf("\nEverything is Ok\n");

+    return 0;

+  }

+  if (res == SZ_ERROR_UNSUPPORTED)

+    PrintError("decoder doesn't support this archive");

+  else if (res == SZ_ERROR_MEM)

+    PrintError("can not allocate memory");

+  else if (res == SZ_ERROR_CRC)

+    PrintError("CRC error");

+  else

+    printf("\nERROR #%d\n", res);

+  return 1;

+}

diff --git a/C/Util/7z/makefile b/C/Util/7z/makefile
new file mode 100755
index 0000000..3b85364
--- /dev/null
+++ b/C/Util/7z/makefile
@@ -0,0 +1,37 @@
+MY_STATIC_LINK=1

+CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT

+

+PROG = 7zDec.exe

+

+C_OBJS = \

+  $O\7zAlloc.obj \

+  $O\7zBuf.obj \

+  $O\7zBuf2.obj \

+  $O\7zCrc.obj \

+  $O\7zCrcOpt.obj \

+  $O\7zFile.obj \

+  $O\7zDec.obj \

+  $O\7zIn.obj \

+  $O\7zStream.obj \

+  $O\Bcj2.obj \

+  $O\Bra.obj \

+  $O\Bra86.obj \

+  $O\CpuArch.obj \

+  $O\Lzma2Dec.obj \

+  $O\LzmaDec.obj \

+  $O\Ppmd7.obj \

+  $O\Ppmd7Dec.obj \

+

+7Z_OBJS = \

+  $O\7zMain.obj \

+

+OBJS = \

+  $(7Z_OBJS) \

+  $(C_OBJS) \

+

+!include "../../../CPP/Build.mak"

+

+$(7Z_OBJS): $(*B).c

+	$(COMPL_O1)

+$(C_OBJS): ../../$(*B).c

+	$(COMPL_O2)

diff --git a/C/Util/7z/makefile.gcc b/C/Util/7z/makefile.gcc
new file mode 100755
index 0000000..2fb1576
--- /dev/null
+++ b/C/Util/7z/makefile.gcc
@@ -0,0 +1,70 @@
+PROG = 7zDec

+CXX = g++

+LIB =

+RM = rm -f

+CFLAGS = -c -O2 -Wall

+

+OBJS = 7zMain.o 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zIn.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o

+

+all: $(PROG)

+

+$(PROG): $(OBJS)

+	$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)

+

+7zMain.o: 7zMain.c

+	$(CXX) $(CFLAGS) 7zMain.c

+

+7zAlloc.o: 7zAlloc.c

+	$(CXX) $(CFLAGS) ../../7zAlloc.c

+

+7zBuf.o: ../../7zBuf.c

+	$(CXX) $(CFLAGS) ../../7zBuf.c

+

+7zBuf2.o: ../../7zBuf2.c

+	$(CXX) $(CFLAGS) ../../7zBuf2.c

+

+7zCrc.o: ../../7zCrc.c

+	$(CXX) $(CFLAGS) ../../7zCrc.c

+

+7zCrcOpt.o: ../../7zCrc.c

+	$(CXX) $(CFLAGS) ../../7zCrcOpt.c

+

+7zDec.o: ../../7zDec.c

+	$(CXX) $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT ../../7zDec.c

+

+7zIn.o: ../../7zIn.c

+	$(CXX) $(CFLAGS) ../../7zIn.c

+

+CpuArch.o: ../../CpuArch.c

+	$(CXX) $(CFLAGS) ../../CpuArch.c

+

+LzmaDec.o: ../../LzmaDec.c

+	$(CXX) $(CFLAGS) ../../LzmaDec.c

+

+Lzma2Dec.o: ../../Lzma2Dec.c

+	$(CXX) $(CFLAGS) ../../Lzma2Dec.c

+

+Bra.o: ../../Bra.c

+	$(CXX) $(CFLAGS) ../../Bra.c

+

+Bra86.o: ../../Bra86.c

+	$(CXX) $(CFLAGS) ../../Bra86.c

+

+Bcj2.o: ../../Bcj2.c

+	$(CXX) $(CFLAGS) ../../Bcj2.c

+

+Ppmd7.o: ../../Ppmd7.c

+	$(CXX) $(CFLAGS) ../../Ppmd7.c

+

+Ppmd7Dec.o: ../../Ppmd7Dec.c

+	$(CXX) $(CFLAGS) ../../Ppmd7Dec.c

+

+7zFile.o: ../../7zFile.c

+	$(CXX) $(CFLAGS) ../../7zFile.c

+

+7zStream.o: ../../7zStream.c

+	$(CXX) $(CFLAGS) ../../7zStream.c

+

+clean:

+	-$(RM) $(PROG) $(OBJS)

+

diff --git a/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c
new file mode 100755
index 0000000..f8de4a2
--- /dev/null
+++ b/C/Util/Lzma/LzmaUtil.c
@@ -0,0 +1,254 @@
+/* LzmaUtil.c -- Test application for LZMA compression

+2010-09-20 : Igor Pavlov : Public domain */

+

+#define _CRT_SECURE_NO_WARNINGS

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+

+#include "../../Alloc.h"

+#include "../../7zFile.h"

+#include "../../7zVersion.h"

+#include "../../LzmaDec.h"

+#include "../../LzmaEnc.h"

+

+const char *kCantReadMessage = "Can not read input file";

+const char *kCantWriteMessage = "Can not write output file";

+const char *kCantAllocateMessage = "Can not allocate memory";

+const char *kDataErrorMessage = "Data error";

+

+static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }

+static void SzFree(void *p, void *address) { p = p; MyFree(address); }

+static ISzAlloc g_Alloc = { SzAlloc, SzFree };

+

+void PrintHelp(char *buffer)

+{

+  strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"

+      "\nUsage:  lzma <e|d> inputFile outputFile\n"

+             "  e: encode file\n"

+             "  d: decode file\n");

+}

+

+int PrintError(char *buffer, const char *message)

+{

+  strcat(buffer, "\nError: ");

+  strcat(buffer, message);

+  strcat(buffer, "\n");

+  return 1;

+}

+

+int PrintErrorNumber(char *buffer, SRes val)

+{

+  sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);

+  return 1;

+}

+

+int PrintUserError(char *buffer)

+{

+  return PrintError(buffer, "Incorrect command");

+}

+

+#define IN_BUF_SIZE (1 << 16)

+#define OUT_BUF_SIZE (1 << 16)

+

+static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,

+    UInt64 unpackSize)

+{

+  int thereIsSize = (unpackSize != (UInt64)(Int64)-1);

+  Byte inBuf[IN_BUF_SIZE];

+  Byte outBuf[OUT_BUF_SIZE];

+  size_t inPos = 0, inSize = 0, outPos = 0;

+  LzmaDec_Init(state);

+  for (;;)

+  {

+    if (inPos == inSize)

+    {

+      inSize = IN_BUF_SIZE;

+      RINOK(inStream->Read(inStream, inBuf, &inSize));

+      inPos = 0;

+    }

+    {

+      SRes res;

+      SizeT inProcessed = inSize - inPos;

+      SizeT outProcessed = OUT_BUF_SIZE - outPos;

+      ELzmaFinishMode finishMode = LZMA_FINISH_ANY;

+      ELzmaStatus status;

+      if (thereIsSize && outProcessed > unpackSize)

+      {

+        outProcessed = (SizeT)unpackSize;

+        finishMode = LZMA_FINISH_END;

+      }

+      

+      res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,

+        inBuf + inPos, &inProcessed, finishMode, &status);

+      inPos += inProcessed;

+      outPos += outProcessed;

+      unpackSize -= outProcessed;

+      

+      if (outStream)

+        if (outStream->Write(outStream, outBuf, outPos) != outPos)

+          return SZ_ERROR_WRITE;

+        

+      outPos = 0;

+      

+      if (res != SZ_OK || thereIsSize && unpackSize == 0)

+        return res;

+      

+      if (inProcessed == 0 && outProcessed == 0)

+      {

+        if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)

+          return SZ_ERROR_DATA;

+        return res;

+      }

+    }

+  }

+}

+

+static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)

+{

+  UInt64 unpackSize;

+  int i;

+  SRes res = 0;

+

+  CLzmaDec state;

+

+  /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */

+  unsigned char header[LZMA_PROPS_SIZE + 8];

+

+  /* Read and parse header */

+

+  RINOK(SeqInStream_Read(inStream, header, sizeof(header)));

+

+  unpackSize = 0;

+  for (i = 0; i < 8; i++)

+    unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);

+

+  LzmaDec_Construct(&state);

+  RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));

+  res = Decode2(&state, outStream, inStream, unpackSize);

+  LzmaDec_Free(&state, &g_Alloc);

+  return res;

+}

+

+static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)

+{

+  CLzmaEncHandle enc;

+  SRes res;

+  CLzmaEncProps props;

+

+  rs = rs;

+

+  enc = LzmaEnc_Create(&g_Alloc);

+  if (enc == 0)

+    return SZ_ERROR_MEM;

+

+  LzmaEncProps_Init(&props);

+  res = LzmaEnc_SetProps(enc, &props);

+

+  if (res == SZ_OK)

+  {

+    Byte header[LZMA_PROPS_SIZE + 8];

+    size_t headerSize = LZMA_PROPS_SIZE;

+    int i;

+

+    res = LzmaEnc_WriteProperties(enc, header, &headerSize);

+    for (i = 0; i < 8; i++)

+      header[headerSize++] = (Byte)(fileSize >> (8 * i));

+    if (outStream->Write(outStream, header, headerSize) != headerSize)

+      res = SZ_ERROR_WRITE;

+    else

+    {

+      if (res == SZ_OK)

+        res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);

+    }

+  }

+  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);

+  return res;

+}

+

+int main2(int numArgs, const char *args[], char *rs)

+{

+  CFileSeqInStream inStream;

+  CFileOutStream outStream;

+  char c;

+  int res;

+  int encodeMode;

+  Bool useOutFile = False;

+

+  FileSeqInStream_CreateVTable(&inStream);

+  File_Construct(&inStream.file);

+

+  FileOutStream_CreateVTable(&outStream);

+  File_Construct(&outStream.file);

+

+  if (numArgs == 1)

+  {

+    PrintHelp(rs);

+    return 0;

+  }

+

+  if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)

+    return PrintUserError(rs);

+

+  c = args[1][0];

+  encodeMode = (c == 'e' || c == 'E');

+  if (!encodeMode && c != 'd' && c != 'D')

+    return PrintUserError(rs);

+

+  {

+    size_t t4 = sizeof(UInt32);

+    size_t t8 = sizeof(UInt64);

+    if (t4 != 4 || t8 != 8)

+      return PrintError(rs, "Incorrect UInt32 or UInt64");

+  }

+

+  if (InFile_Open(&inStream.file, args[2]) != 0)

+    return PrintError(rs, "Can not open input file");

+

+  if (numArgs > 3)

+  {

+    useOutFile = True;

+    if (OutFile_Open(&outStream.file, args[3]) != 0)

+      return PrintError(rs, "Can not open output file");

+  }

+  else if (encodeMode)

+    PrintUserError(rs);

+

+  if (encodeMode)

+  {

+    UInt64 fileSize;

+    File_GetLength(&inStream.file, &fileSize);

+    res = Encode(&outStream.s, &inStream.s, fileSize, rs);

+  }

+  else

+  {

+    res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL);

+  }

+

+  if (useOutFile)

+    File_Close(&outStream.file);

+  File_Close(&inStream.file);

+

+  if (res != SZ_OK)

+  {

+    if (res == SZ_ERROR_MEM)

+      return PrintError(rs, kCantAllocateMessage);

+    else if (res == SZ_ERROR_DATA)

+      return PrintError(rs, kDataErrorMessage);

+    else if (res == SZ_ERROR_WRITE)

+      return PrintError(rs, kCantWriteMessage);

+    else if (res == SZ_ERROR_READ)

+      return PrintError(rs, kCantReadMessage);

+    return PrintErrorNumber(rs, res);

+  }

+  return 0;

+}

+

+int MY_CDECL main(int numArgs, const char *args[])

+{

+  char rs[800] = { 0 };

+  int res = main2(numArgs, args, rs);

+  fputs(rs, stdout);

+  return res;

+}

diff --git a/C/Util/Lzma/LzmaUtil.dsp b/C/Util/Lzma/LzmaUtil.dsp
new file mode 100755
index 0000000..4815511
--- /dev/null
+++ b/C/Util/Lzma/LzmaUtil.dsp
@@ -0,0 +1,168 @@
+# Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Console Application" 0x0103

+

+CFG=LzmaUtil - Win32 Debug

+!MESSAGE This is not a valid makefile. To build this project using NMAKE,

+!MESSAGE use the Export Makefile command and run

+!MESSAGE 

+!MESSAGE NMAKE /f "LzmaUtil.mak".

+!MESSAGE 

+!MESSAGE You can specify a configuration when running NMAKE

+!MESSAGE by defining the macro CFG on the command line. For example:

+!MESSAGE 

+!MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application")

+!MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""

+# PROP Scc_LocalPath ""

+CPP=cl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "LzmaUtil - Win32 Release"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "Release"

+# PROP BASE Intermediate_Dir "Release"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "Release"

+# PROP Intermediate_Dir "Release"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c

+# ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c

+# SUBTRACT CPP /YX

+# ADD BASE RSC /l 0x419 /d "NDEBUG"

+# ADD RSC /l 0x419 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7lzma.exe"

+

+!ELSEIF  "$(CFG)" == "LzmaUtil - Win32 Debug"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir "Debug"

+# PROP BASE Intermediate_Dir "Debug"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir "Debug"

+# PROP Intermediate_Dir "Debug"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c

+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c

+# SUBTRACT CPP /YX

+# ADD BASE RSC /l 0x419 /d "_DEBUG"

+# ADD RSC /l 0x419 /d "_DEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7lzma.exe" /pdbtype:sept

+

+!ENDIF 

+

+# Begin Target

+

+# Name "LzmaUtil - Win32 Release"

+# Name "LzmaUtil - Win32 Debug"

+# Begin Source File

+

+SOURCE=..\..\7zFile.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zFile.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zStream.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\7zVersion.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Alloc.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Alloc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\CpuArch.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzFind.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzFind.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzFindMt.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzFindMt.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzHash.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaDec.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaDec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaEnc.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaEnc.h

+# End Source File

+# Begin Source File

+

+SOURCE=.\LzmaUtil.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Threads.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Threads.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Types.h

+# End Source File

+# End Target

+# End Project

diff --git a/C/Util/Lzma/LzmaUtil.dsw b/C/Util/Lzma/LzmaUtil.dsw
new file mode 100755
index 0000000..f435487
--- /dev/null
+++ b/C/Util/Lzma/LzmaUtil.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00

+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

+

+###############################################################################

+

+Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/C/Util/Lzma/makefile b/C/Util/Lzma/makefile
new file mode 100755
index 0000000..e99e098
--- /dev/null
+++ b/C/Util/Lzma/makefile
@@ -0,0 +1,28 @@
+MY_STATIC_LINK=1

+PROG = LZMAc.exe

+

+CFLAGS = $(CFLAGS) \

+

+LIB_OBJS = \

+  $O\LzmaUtil.obj \

+

+C_OBJS = \

+  $O\Alloc.obj \

+  $O\LzFind.obj \

+  $O\LzFindMt.obj \

+  $O\LzmaDec.obj \

+  $O\LzmaEnc.obj \

+  $O\7zFile.obj \

+  $O\7zStream.obj \

+  $O\Threads.obj \

+

+OBJS = \

+  $(LIB_OBJS) \

+  $(C_OBJS) \

+

+!include "../../../CPP/Build.mak"

+

+$(LIB_OBJS): $(*B).c

+	$(COMPL_O2)

+$(C_OBJS): ../../$(*B).c

+	$(COMPL_O2)

diff --git a/C/Util/Lzma/makefile.gcc b/C/Util/Lzma/makefile.gcc
new file mode 100755
index 0000000..12a72bb
--- /dev/null
+++ b/C/Util/Lzma/makefile.gcc
@@ -0,0 +1,44 @@
+PROG = lzma

+CXX = g++

+LIB =

+RM = rm -f

+CFLAGS = -c -O2 -Wall -D_7ZIP_ST

+

+OBJS = \

+  LzmaUtil.o \

+  Alloc.o \

+  LzFind.o \

+  LzmaDec.o \

+  LzmaEnc.o \

+  7zFile.o \

+  7zStream.o \

+

+

+all: $(PROG)

+

+$(PROG): $(OBJS)

+	$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)

+

+LzmaUtil.o: LzmaUtil.c

+	$(CXX) $(CFLAGS) LzmaUtil.c

+

+Alloc.o: ../../Alloc.c

+	$(CXX) $(CFLAGS) ../../Alloc.c

+

+LzFind.o: ../../LzFind.c

+	$(CXX) $(CFLAGS) ../../LzFind.c

+

+LzmaDec.o: ../../LzmaDec.c

+	$(CXX) $(CFLAGS) ../../LzmaDec.c

+

+LzmaEnc.o: ../../LzmaEnc.c

+	$(CXX) $(CFLAGS) ../../LzmaEnc.c

+

+7zFile.o: ../../7zFile.c

+	$(CXX) $(CFLAGS) ../../7zFile.c

+

+7zStream.o: ../../7zStream.c

+	$(CXX) $(CFLAGS) ../../7zStream.c

+

+clean:

+	-$(RM) $(PROG) $(OBJS)

diff --git a/C/Util/LzmaLib/LzmaLib.def b/C/Util/LzmaLib/LzmaLib.def
new file mode 100755
index 0000000..43b9597
--- /dev/null
+++ b/C/Util/LzmaLib/LzmaLib.def
@@ -0,0 +1,4 @@
+EXPORTS

+  LzmaCompress

+  LzmaUncompress

+

diff --git a/C/Util/LzmaLib/LzmaLib.dsp b/C/Util/LzmaLib/LzmaLib.dsp
new file mode 100755
index 0000000..bf52b63
--- /dev/null
+++ b/C/Util/LzmaLib/LzmaLib.dsp
@@ -0,0 +1,178 @@
+# Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4>

+# Microsoft Developer Studio Generated Build File, Format Version 6.00

+# ** DO NOT EDIT **

+

+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102

+

+CFG=LzmaLib - Win32 Debug

+!MESSAGE This is not a valid makefile. To build this project using NMAKE,

+!MESSAGE use the Export Makefile command and run

+!MESSAGE 

+!MESSAGE NMAKE /f "LzmaLib.mak".

+!MESSAGE 

+!MESSAGE You can specify a configuration when running NMAKE

+!MESSAGE by defining the macro CFG on the command line. For example:

+!MESSAGE 

+!MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug"

+!MESSAGE 

+!MESSAGE Possible choices for configuration are:

+!MESSAGE 

+!MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")

+!MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")

+!MESSAGE 

+

+# Begin Project

+# PROP AllowPerConfigDependencies 0

+# PROP Scc_ProjName ""

+# PROP Scc_LocalPath ""

+CPP=cl.exe

+MTL=midl.exe

+RSC=rc.exe

+

+!IF  "$(CFG)" == "LzmaLib - Win32 Release"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 0

+# PROP BASE Output_Dir "Release"

+# PROP BASE Intermediate_Dir "Release"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 0

+# PROP Output_Dir "Release"

+# PROP Intermediate_Dir "Release"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c

+# ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /FD /c

+# SUBTRACT CPP /YX

+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32

+# ADD BASE RSC /l 0x419 /d "NDEBUG"

+# ADD RSC /l 0x419 /d "NDEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98

+# SUBTRACT LINK32 /pdb:none

+

+!ELSEIF  "$(CFG)" == "LzmaLib - Win32 Debug"

+

+# PROP BASE Use_MFC 0

+# PROP BASE Use_Debug_Libraries 1

+# PROP BASE Output_Dir "Debug"

+# PROP BASE Intermediate_Dir "Debug"

+# PROP BASE Target_Dir ""

+# PROP Use_MFC 0

+# PROP Use_Debug_Libraries 1

+# PROP Output_Dir "Debug"

+# PROP Intermediate_Dir "Debug"

+# PROP Ignore_Export_Lib 0

+# PROP Target_Dir ""

+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c

+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c

+# SUBTRACT CPP /YX

+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32

+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32

+# ADD BASE RSC /l 0x419 /d "_DEBUG"

+# ADD RSC /l 0x419 /d "_DEBUG"

+BSC32=bscmake.exe

+# ADD BASE BSC32 /nologo

+# ADD BSC32 /nologo

+LINK32=link.exe

+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept

+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept

+

+!ENDIF 

+

+# Begin Target

+

+# Name "LzmaLib - Win32 Release"

+# Name "LzmaLib - Win32 Debug"

+# Begin Group "Spec"

+

+# PROP Default_Filter ""

+# Begin Source File

+

+SOURCE=.\LzmaLib.def

+# End Source File

+# Begin Source File

+

+SOURCE=.\LzmaLibExports.c

+# End Source File

+# End Group

+# Begin Source File

+

+SOURCE=..\..\Alloc.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Alloc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\IStream.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzFind.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzFind.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzFindMt.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzFindMt.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzHash.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaDec.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaDec.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaEnc.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaEnc.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaLib.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\LzmaLib.h

+# End Source File

+# Begin Source File

+

+SOURCE=.\resource.rc

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Threads.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Threads.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\Types.h

+# End Source File

+# End Target

+# End Project

diff --git a/C/Util/LzmaLib/LzmaLib.dsw b/C/Util/LzmaLib/LzmaLib.dsw
new file mode 100755
index 0000000..f6c5559
--- /dev/null
+++ b/C/Util/LzmaLib/LzmaLib.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00

+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

+

+###############################################################################

+

+Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4>

+

+Package=<5>

+{{{

+}}}

+

+Package=<4>

+{{{

+}}}

+

+###############################################################################

+

+Global:

+

+Package=<5>

+{{{

+}}}

+

+Package=<3>

+{{{

+}}}

+

+###############################################################################

+

diff --git a/C/Util/LzmaLib/LzmaLibExports.c b/C/Util/LzmaLib/LzmaLibExports.c
new file mode 100755
index 0000000..7434536
--- /dev/null
+++ b/C/Util/LzmaLib/LzmaLibExports.c
@@ -0,0 +1,12 @@
+/* LzmaLibExports.c -- LZMA library DLL Entry point

+2008-10-04 : Igor Pavlov : Public domain */

+

+#include <windows.h>

+

+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

+{

+  hInstance = hInstance;

+  dwReason = dwReason;

+  lpReserved = lpReserved;

+  return TRUE;

+}

diff --git a/C/Util/LzmaLib/makefile b/C/Util/LzmaLib/makefile
new file mode 100755
index 0000000..e0f3114
--- /dev/null
+++ b/C/Util/LzmaLib/makefile
@@ -0,0 +1,34 @@
+MY_STATIC_LINK=1

+SLIB = sLZMA.lib

+PROG = LZMA.dll

+SLIBPATH = $O\$(SLIB)

+

+DEF_FILE = LzmaLib.def

+CFLAGS = $(CFLAGS) \

+

+LIB_OBJS = \

+  $O\LzmaLibExports.obj \

+

+C_OBJS = \

+  $O\Alloc.obj \

+  $O\LzFind.obj \

+  $O\LzFindMt.obj \

+  $O\LzmaDec.obj \

+  $O\LzmaEnc.obj \

+  $O\LzmaLib.obj \

+  $O\Threads.obj \

+

+OBJS = \

+  $(LIB_OBJS) \

+  $(C_OBJS) \

+  $O\resource.res

+

+!include "../../../CPP/Build.mak"

+

+$(SLIBPATH): $O $(OBJS)

+	lib -out:$(SLIBPATH) $(OBJS) $(LIBS)

+

+$(LIB_OBJS): $(*B).c

+	$(COMPL_O2)

+$(C_OBJS): ../../$(*B).c

+	$(COMPL_O2)

diff --git a/C/Util/LzmaLib/resource.rc b/C/Util/LzmaLib/resource.rc
new file mode 100755
index 0000000..cb62ed9
--- /dev/null
+++ b/C/Util/LzmaLib/resource.rc
@@ -0,0 +1,4 @@
+#include "../../../CPP/7zip/MyVersionInfo.rc"

+

+MY_VERSION_INFO_DLL("LZMA library", "LZMA")

+

diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c
new file mode 100755
index 0000000..d4eb5c4
--- /dev/null
+++ b/C/Util/SfxSetup/SfxSetup.c
@@ -0,0 +1,592 @@
+/* SfxSetup.c - 7z SFX Setup

+2010-11-11 : Igor Pavlov : Public domain */

+

+#ifndef UNICODE

+#define UNICODE

+#endif

+

+#ifndef _UNICODE

+#define _UNICODE

+#endif

+

+#ifdef _CONSOLE

+#include <stdio.h>

+#endif

+

+#include "../../7z.h"

+#include "../../7zAlloc.h"

+#include "../../7zCrc.h"

+#include "../../7zFile.h"

+#include "../../CpuArch.h"

+

+#define k_EXE_ExtIndex 1

+

+static const char *kExts[] =

+{

+  "bat",

+  "exe",

+  "inf",

+  "msi",

+  #ifdef UNDER_CE

+  "cab",

+  #endif

+  "html",

+  "htm"

+};

+

+static const char *kNames[] =

+{

+  "setup",

+  "install",

+  "run",

+  "start"

+};

+

+static unsigned FindExt(const wchar_t *s, unsigned *extLen)

+{

+  unsigned len = (unsigned)wcslen(s);

+  unsigned i;

+  for (i = len; i > 0; i--)

+  {

+    if (s[i - 1] == '.')

+    {

+      *extLen = len - i;

+      return i - 1;

+    }

+  }

+  *extLen = 0;

+  return len;

+}

+

+#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))

+

+static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len)

+{

+  unsigned i;

+  for (i = 0; i < num; i++)

+  {

+    const char *item = items[i];

+    unsigned itemLen = (unsigned)strlen(item);

+    unsigned j;

+    if (len != itemLen)

+      continue;

+    for (j = 0; j < len; j++)

+    {

+      unsigned c = item[j];

+      if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j])

+        break;

+    }

+    if (j == len)

+      return i;

+  }

+  return i;

+}

+

+#ifdef _CONSOLE

+static BOOL WINAPI HandlerRoutine(DWORD ctrlType)

+{

+  ctrlType = ctrlType;

+  return TRUE;

+}

+#endif

+

+static void PrintErrorMessage(const char *message)

+{

+  #ifdef _CONSOLE

+  printf("\n7-Zip Error: %s\n", message);

+  #else

+  #ifdef UNDER_CE

+  WCHAR messageW[256 + 4];

+  unsigned i;

+  for (i = 0; i < 256 && message[i] != 0; i++)

+    messageW[i] = message[i];

+  messageW[i] = 0;

+  MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR);

+  #else

+  MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR);

+  #endif

+  #endif

+}

+

+static WRes MyCreateDir(const WCHAR *name)

+{

+  return CreateDirectoryW(name, NULL) ? 0 : GetLastError();

+}

+

+#ifdef UNDER_CE

+#define kBufferSize (1 << 13)

+#else

+#define kBufferSize (1 << 15)

+#endif

+

+#define kSignatureSearchLimit (1 << 22)

+

+static Bool FindSignature(CSzFile *stream, UInt64 *resPos)

+{

+  Byte buf[kBufferSize];

+  size_t numPrevBytes = 0;

+  *resPos = 0;

+  for (;;)

+  {

+    size_t numTests, pos;

+    if (*resPos > kSignatureSearchLimit)

+      return False;

+    

+    do

+    {

+      size_t processed = kBufferSize - numPrevBytes;

+      if (File_Read(stream, buf + numPrevBytes, &processed) != 0)

+        return False;

+      if (processed == 0)

+        return False;

+      numPrevBytes += processed;

+    }

+    while (numPrevBytes <= k7zStartHeaderSize);

+    

+    numTests = numPrevBytes - k7zStartHeaderSize;

+    for (pos = 0; pos < numTests; pos++)

+    {

+      for (; buf[pos] != '7' && pos < numTests; pos++);

+      if (pos == numTests)

+        break;

+      if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)

+        if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8))

+        {

+          *resPos += pos;

+          return True;

+        }

+    }

+    *resPos += numTests;

+    numPrevBytes -= numTests;

+    memmove(buf, buf + numTests, numPrevBytes);

+  }

+}

+

+static Bool DoesFileOrDirExist(const WCHAR *path)

+{

+  WIN32_FIND_DATAW fd;

+  HANDLE handle;

+  handle = FindFirstFileW(path, &fd);

+  if (handle == INVALID_HANDLE_VALUE)

+    return False;

+  FindClose(handle);

+  return True;

+}

+

+static WRes RemoveDirWithSubItems(WCHAR *path)

+{

+  WIN32_FIND_DATAW fd;

+  HANDLE handle;

+  WRes res = 0;

+  size_t len = wcslen(path);

+  wcscpy(path + len, L"*");

+  handle = FindFirstFileW(path, &fd);

+  path[len] = L'\0';

+  if (handle == INVALID_HANDLE_VALUE)

+    return GetLastError();

+  for (;;)

+  {

+    if (wcscmp(fd.cFileName, L".") != 0 &&

+        wcscmp(fd.cFileName, L"..") != 0)

+    {

+      wcscpy(path + len, fd.cFileName);

+      if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)

+      {

+        wcscat(path, L"\\");

+        res = RemoveDirWithSubItems(path);

+      }

+      else

+      {

+        SetFileAttributesW(path, 0);

+        if (DeleteFileW(path) == 0)

+          res = GetLastError();

+      }

+      if (res != 0)

+        break;

+    }

+    if (!FindNextFileW(handle, &fd))

+    {

+      res = GetLastError();

+      if (res == ERROR_NO_MORE_FILES)

+        res = 0;

+      break;

+    }

+  }

+  path[len] = L'\0';

+  FindClose(handle);

+  if (res == 0)

+  {

+    if (!RemoveDirectoryW(path))

+      res = GetLastError();

+  }

+  return res;

+}

+

+#ifdef _CONSOLE

+int MY_CDECL main()

+#else

+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

+  #ifdef UNDER_CE

+  LPWSTR

+  #else

+  LPSTR

+  #endif

+  lpCmdLine, int nCmdShow)

+#endif

+{

+  CFileInStream archiveStream;

+  CLookToRead lookStream;

+  CSzArEx db;

+  SRes res = SZ_OK;

+  ISzAlloc allocImp;

+  ISzAlloc allocTempImp;

+  WCHAR sfxPath[MAX_PATH + 2];

+  WCHAR path[MAX_PATH * 3 + 2];

+  size_t pathLen;

+  DWORD winRes;

+  const wchar_t *cmdLineParams;

+  const char *errorMessage = NULL;

+  Bool useShellExecute = True;

+

+  #ifdef _CONSOLE

+  SetConsoleCtrlHandler(HandlerRoutine, TRUE);

+  #else

+  hInstance = hInstance;

+  hPrevInstance = hPrevInstance;

+  lpCmdLine = lpCmdLine;

+  nCmdShow = nCmdShow;

+  #endif

+

+  CrcGenerateTable();

+

+  allocImp.Alloc = SzAlloc;

+  allocImp.Free = SzFree;

+

+  allocTempImp.Alloc = SzAllocTemp;

+  allocTempImp.Free = SzFreeTemp;

+

+  FileInStream_CreateVTable(&archiveStream);

+  LookToRead_CreateVTable(&lookStream, False);

+ 

+  winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH);

+  if (winRes == 0 || winRes > MAX_PATH)

+    return 1;

+  {

+    cmdLineParams = GetCommandLineW();

+    #ifndef UNDER_CE

+    {

+      Bool quoteMode = False;

+      for (;; cmdLineParams++)

+      {

+        wchar_t c = *cmdLineParams;

+        if (c == L'\"')

+          quoteMode = !quoteMode;

+        else if (c == 0 || (c == L' ' && !quoteMode))

+          break;

+      }

+    }

+    #endif

+  }

+

+  {

+    unsigned i;

+    DWORD d;

+    winRes = GetTempPathW(MAX_PATH, path);

+    if (winRes == 0 || winRes > MAX_PATH)

+      return 1;

+    pathLen = wcslen(path);

+    d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();

+    for (i = 0;; i++, d += GetTickCount())

+    {

+      if (i >= 100)

+      {

+        res = SZ_ERROR_FAIL;

+        break;

+      }

+      wcscpy(path + pathLen, L"7z");

+

+      {

+        wchar_t *s = path + wcslen(path);

+        UInt32 value = d;

+        unsigned k;

+        for (k = 0; k < 8; k++)

+        {

+          unsigned t = value & 0xF;

+          value >>= 4;

+          s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));

+        }

+        s[k] = '\0';

+      }

+

+      if (DoesFileOrDirExist(path))

+        continue;

+      if (CreateDirectoryW(path, NULL))

+      {

+        wcscat(path, L"\\");

+        pathLen = wcslen(path);

+        break;

+      }

+      if (GetLastError() != ERROR_ALREADY_EXISTS)

+      {

+        res = SZ_ERROR_FAIL;

+        break;

+      }

+    }

+    if (res != SZ_OK)

+      errorMessage = "Can't create temp folder";

+  }

+

+  if (res != SZ_OK)

+  {

+    if (!errorMessage)

+      errorMessage = "Error";

+    PrintErrorMessage(errorMessage);

+    return 1;

+  }

+

+  if (InFile_OpenW(&archiveStream.file, sfxPath) != 0)

+  {

+    errorMessage = "can not open input file";

+    res = SZ_ERROR_FAIL;

+  }

+  else

+  {

+    UInt64 pos = 0;

+    if (!FindSignature(&archiveStream.file, &pos))

+      res = SZ_ERROR_FAIL;

+    else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0)

+      res = SZ_ERROR_FAIL;

+    if (res != 0)

+      errorMessage = "Can't find 7z archive";

+  }

+

+  if (res == SZ_OK)

+  {

+    lookStream.realStream = &archiveStream.s;

+    LookToRead_Init(&lookStream);

+  }

+

+  SzArEx_Init(&db);

+  if (res == SZ_OK)

+  {

+    res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);

+  }

+  if (res == SZ_OK)

+  {

+    UInt32 executeFileIndex = (UInt32)(Int32)-1;

+    UInt32 minPrice = 1 << 30;

+    UInt32 i;

+    UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */

+    Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */

+    size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */

+    

+    for (i = 0; i < db.db.NumFiles; i++)

+    {

+      size_t offset = 0;